AstroToolkit 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,168 @@
1
+ import pandas as pd
2
+ import astropy.coordinates as coord
3
+ from astroquery.vizier import Vizier
4
+ import astropy.units as u
5
+
6
+ catalogue_names=['I/345/gaia2','I/355/gaiadr3']
7
+
8
+ row_limit=Vizier.ROW_LIMIT = -1
9
+
10
+ def renameHeadersDR3(data):
11
+ #Manually rename all columns to their original column names. This one line is 6849 characters long.
12
+ data.rename(columns={'RA_ICRS':'ra','DE_ICRS':'dec','Source':'source_id','e_RA_ICRS':'ra_error','e_DE_ICRS':'dec_error','Plx':'parallax','e_Plx':'parallax_error','PM':'pm','pmRA':'pmra','e_pmRA':'pmra_error','pmDE':'pmdec','e_pmDE':'pmdec_error','RUWE':'ruwe','FG':'phot_g_mean_flux','e_FG':'phot_g_mean_flux_error','Gmag':'phot_g_mean_mag','FBP':'phot_bp_mean_flux','e_FBP':'phot_bp_mean_flux_error','BPmag':'phot_bp_mean_mag','FRP':'phot_rp_mean_flux','e_FRP':'phot_rp_mean_flux_error','RPmag':'phot_rp_mean_mag','BP-RP':'bp_rp','RV':'radial_velocity','e_RV':'radial_velocity_error','Vbroad':'vbroad','GRVSmag':'grvs_mag','QSO':'in_qso_candidates','Gal':'in_galaxy_candidates','NSS':'in_galaxy_candidates','XPcont':'has_xp_continuous','XPsamp':'has_xp_sampled','RVS':'has_rvs','EpochPh':'has_epoch_photometry','EpochRV':'has_epoch_photometry','MCMCGSP':'has_mcmc_gspphot','MCMCMSC':'has_mcmc_msc','And':'in_andromeda_survey','Teff':'teff_gspphot','logg':'logg_gspphot','__Fe_H_':'mh_gspphot','Dist':'distance_gspphot','A0':'distance_gspphot','HIP':'hip_original_ext_source_id','PS1':'ps1_original_ext_source_id','SDSS13':'sdss13_ext_source_id','SKYM2':'skym2_original_ext_source_id','TYC2':'tyc2_original_ext_source_id','URAT1':'urat1_original_ext_source_id','ALLWISE':'allwise_original_ext_source_id','APASS9':'apass9_original_ext_source_id','GSC23':'gsc23_original_ext_source_id','RAVE5':'gsc23_original_ext_source_id','_2MASS':'twomass_original_ext_source_id','RAVE6':'rave6_original_ext_source_id','RAJ2000':'ra2000','DEJ2000':'dec2000','DR3Name':'designation','SolID':'solution_id','RandomI':'random_index','RPlx':'parallax_over_error','RADEcor':'ra_dec_corr','RAPlxcor':'ra_parallax_corr','RApmRAcor':'ra_pmra_corr','RApmDEcor':'ra_pmdec_corr','DEPlxcor':'dec_parallax_corr','DEpmRAcor':'dec_pmra_corr','DEpmDEcor':'dec_pmdec_corr','PlxpmRAcor':'parallax_pmra_corr','PlxpmDEcor':'parallax_pmdec_corr','pmRApmDEcor':'pmra_pmdec_corr','NAL':'astrometric_n_obs_al','NAC':'astrometric_n_obs_ac','NgAL':'astrometric_n_good_obs_al','NbAL':'astrometric_n_bad_obs_al','gofAL':'astrometric_gof_al','chi2AL':'astrometric_chi2_al','epsi':'astrometric_chi2_al','sepsi':'astrometric_chi2_al','Solved':'astrometric_params_solved','APF':'astrometric_primary_flag','nueff':'nu_eff_used_in_astrometry','pscol':'pseudocolour','e_pscol':'pseudocolour_error','RApscolCorr':'ra_pseudocolour_corr','DEpscolCorr':'dec_pseudocolour_corr','PlxpscolCorr':'parallax_pseudocolour_corr','pmRApscolCorr':'pmra_pseudocolour_corr','pmDEpscolCorr':'pmdec_pseudocolour_corr','MatchObsA':'astrometric_matched_transits','Nper':'visibility_periods_used','amax':'astrometric_sigma5d_max','MatchObs':'matched_transits','NewMatchObs':'new_matched_transits','MatchObsrm':'matched_transits_removed','IPDgofha':'ipd_gof_harmonic_amplitude','IPDgofhp':'ipd_gof_harmonic_phase','IPDfmp':'ipd_frac_multi_peak','IPDfow':'ipd_frac_odd_win','SDSk1':'scan_direction_strength_k1','SDSk2':'scan_direction_strength_k2','SDSk3':'scan_direction_strength_k3','SDSk4':'scan_direction_strength_k4','SDMk1':'scan_direction_mean_k1','SDMk2':'scan_direction_mean_k2','SDMk3':'scan_direction_mean_k3','SDMk4':'scan_direction_mean_k4','Dup':'duplicated_source','o_Gmag':'phot_g_n_obs','RFG':'phot_g_mean_flux_over_error','e_Gmag':'phot_g_mean_mag_error','o_BPmag':'phot_bp_n_obs','RFBP':'phot_bp_mean_flux_over_error','e_BPmag':'phot_bp_mean_mag_error','o_RPmag':'phot_rp_n_obs','RFRP':'phot_rp_mean_flux_over_error','e_RPmag':'phot_rp_mean_mag_error','E_BP_RP_':'phot_bp_rp_excess_factor','NBPcont':'phot_bp_n_contaminated_transits','NBPblend':'phot_bp_n_blended_transits','NRPcont':'phot_rp_n_contaminated_transits','NRPblend':'phot_rp_n_blended_transits','Mode':'phot_proc_mode','BP-G':'bp_g','G-RP':'g_rp','n_RV':'rv_method_used','o_RV':'rv_nb_transits','o_RVd':'rv_nb_deblended_transits','RVNper':'rv_visibility_periods_used','RVS_N':'rv_expected_sig_to_noise','RVgof':'rv_renormalised_gof','RVchi2':'rv_chisq_pvalue','RVTdur':'rv_time_duration','RVamp':'rv_amplitude_robust','RVtempTeff':'rv_template_teff','RVtemplogg':'rv_template_logg','RVtemp_Fe_H_':'rv_template_fe_h','Vatmparam':'rv_atm_param_origin','e_Vbroad':'vbroad_error','o_Vbroad':'vbroad_nb_transits','e_GRVSmag':'grvs_mag_error','o_GRVSmag':'grvs_mag_nb_transits','RVSS_N':'rvs_spec_sig_to_noise','GLON':'l','GLAT':'b','ELON':'ecl_lon','ELAT':'ecl_lat','PQSO':'classprob_dsc_combmod_quasar','PGal':'classprob_dsc_combmod_galaxy','PSS':'classprob_dsc_combmod_star','b_Teff':'teff_gspphot_lower','B_Teff':'teff_gspphot_upper','b_logg':'logg_gspphot_lower','B_logg':'logg_gspphot_upper','b__Fe_H_':'mh_gspphot_lower','B__Fe_H_':'mh_gspphot_upper','b_Dist':'distance_gspphot_lower','B_Dist':'distance_gspphot_upper','b_A0':'azero_gspphot_lower','B_A0':'azero_gspphot_upper','AG':'ag_bspphot','b_AG':'ag_gspphot_lower','B_AG':'ag_gspphot_upper','E_BP-RP_':'ebpminrp_gspphot','b_E_BP-RP_':'ebpminrp_gspphot_lower','B_E_BP-RP_':'ebpminrp_gspphot_upper','Lib':'libname_gspphot','dHIP':'hip_angular_distance','nHIP':'hip_number_of_neighbours','f_HIP':'hip_xm_flag','PS1coid':'clean_panstarrs1_oid','dPS1':'ps1_angular_distance','nPS1':'ps1_number_of_neighbours','mPS1':'ps1_number_of_mates','f_PS1':'ps1_xm_flag','SDSS13coid':'clean_sdssdr13_oid','dSDSS13':'sdss13_angular_distance','nSDSS13':'sdss13_number_of_neighbours','mSDSS13':'sdss13_number_of_mates','f_SDSS13':'sdss13_xm_flag','dSKYM2':'skym2_angular_distance','nSKYM2':'skym2_number_of_neighbours','mSKYM2':'skym2_number_of_mates','f_SKYM2':'skym2_xm_flag','dTYC2':'tyc2_angular_distance','f_TYC2':'tyc2_xm_flag','TYC2moid':'tycho2tdsc_merge_oid','nTYC2':'tyc2_number_of_neighbours','dURAT1':'urat1_angular_distance','f_URAT1':'urat1_xm_flag','URAT1oid':'urat1_oid','nURAT1':'urat1_number_of_neighbours','mURAT1':'urat1_number_of_mates','dAllWISE':'allwise_angular_distance','f_AllWISE':'allwise_xm_flag','AllWISEoid':'allwise_oid','nAllWISE':'allwise_number_of_neighbours','mAllWISE':'allwise_number_of_mates','APASS9coid':'clean_apassdr9_oid','dAPASS9':'apass9_angular_distance','nAPASS9':'apass9_number_of_neighbours','mAPASS9':'apass9_number_of_mates','f_APASS9':'apass9_xm_flag','dGSC23':'gsc23_angular_distance','f_GSC23':'gsc23_xm_flag','GSC23coid':'clean_gsc23_oid','nGSC23':'gsc23_number_of_neighbours','mGSC23':'gsc23_number_of_mates','dRAVE5':'rave5_angular_distance','f_RAVE5':'rave5_xm_flag','RAVE5coid':'clean_ravedr5_oid','nRAVE5':'rave5_number_of_neighbours','d2MASS':'twomass_angular_distance','f_2MASS':'twomass_xm_flag','_2MASScoid':'clean_tmass_psc_xsc_oid','n2MASS':'twomass_number_of_neighbours','m2MASS':'twomass_number_of_mates','dRAVE6':'rave6_angular_distance','f_RAVE6':'rave6_xm_flag','RAVE6oid':'ravedr6_oid','nRAVE6':'rave6_number_of_neighbours','e_RAJ2000':'ra2000_error','e_DEJ2000':'dec2000_error','RADEcorJ2000':'ra2000_de2000_corr'}, inplace=True)
13
+ return data
14
+
15
+ #Returns all Gaia data from a given data release for an object, given its Gaia designation
16
+ def GaiaQueryDesignation(Designation,catalogue='dr3'):
17
+ #Raises an exception if multiple designations are given, added since GaiaGetDesignation can return a tuple which then breaks if immediately passed back into this function without parsing first.
18
+ if isinstance(Designation,list):
19
+ raise Exception('multiple designations given')
20
+ #'GAIA DR...' prefix in object designations is not present in returned tables, but is required for Vizier query. Therefore need to create two separate parameters, one with the prefix (Search Designation) and one without (Designation)
21
+ if isinstance(Designation,str):
22
+ Designation=Designation.upper()
23
+ catalogue=catalogue.lower()
24
+ if catalogue!='dr2' and catalogue!='dr3':
25
+ raise Exception('invalid catalogue')
26
+ exit()
27
+
28
+ if 'GAIA DR3 ' in str(Designation) or 'GAIA DR2 ' in str(Designation):
29
+ SearchDesignation=Designation
30
+ if 'GAIA DR3' in str(Designation):
31
+ catalogue='dr3'
32
+ elif 'GAIA DR2' in str(Designation):
33
+ catalogue='dr2'
34
+ Designation=Designation[9:]
35
+ else:
36
+ if catalogue=='dr2':
37
+ SearchDesignation='GAIA DR2 '+str(Designation)
38
+ elif catalogue=='dr3':
39
+ SearchDesignation='GAIA DR3 '+str(Designation)
40
+
41
+ data=[]
42
+
43
+ #Sends Vizier query for given designation. Returns multiple objects within a radius, but as you are searching with a GAIA designation it is assumed that you already know the exact object that want and so all others are removed.
44
+ v=Vizier(columns=['**'],column_filters={"Source":"=="+str(Designation)},row_limit=row_limit)
45
+
46
+ if catalogue=='dr2':
47
+ data.append(v.query_object(SearchDesignation,catalog=catalogue_names[0]))
48
+ if len(data[0])==0:
49
+ print('[Gaia: GaiaQueryDesignation] Error: no Gaia data found for given designation')
50
+ return None
51
+ data=data[0][0].to_pandas()
52
+ data=renameHeadersDR3(data)
53
+ return data
54
+ elif catalogue=='dr3':
55
+ data.append(v.query_object(SearchDesignation,catalog=catalogue_names[1],))
56
+ if len(data[0])==0:
57
+ print('[Gaia: GaiaQueryDesignation] Error: no Gaia data found for given designation')
58
+ return None
59
+ data=data[0][0].to_pandas()
60
+ data=renameHeadersDR3(data)
61
+ return data
62
+
63
+ #Returns all Gaia data from a given data release for an object, given its coordinates
64
+ def GaiaQueryCoords(ObjRa,ObjDec,radius=3,catalogue='dr3'):
65
+ catalogue=catalogue.lower()
66
+
67
+ if not isinstance(radius,int) and not isinstance(radius,float):
68
+ raise Exception('search radius must be a float or an integer')
69
+
70
+ if not isinstance(ObjRa,float):
71
+ try:
72
+ ObjRa=float(ObjRa)
73
+ except:
74
+ raise Exception('object RA must be a float or an integer')
75
+ if not isinstance(ObjDec,float):
76
+ try:
77
+ ObjDec=float(ObjDec)
78
+ except:
79
+ raise Exception('object DEC must be a float or an integer')
80
+
81
+ if catalogue!='dr2' and catalogue!='dr3':
82
+ raise Exception('invalid catalogue')
83
+
84
+ data=[]
85
+
86
+ #Get all columns
87
+ v=Vizier(columns=['**'],row_limit=row_limit)
88
+
89
+ #Sends Vizier query, can return multiple objects in given search radius
90
+ if catalogue=='dr2':
91
+ data.append(v.query_region(coord.SkyCoord(ra=ObjRa,dec=ObjDec,unit=(u.deg,u.deg),frame='icrs'),width=radius*u.arcsec,catalog=catalogue_names[0]))
92
+ if len(data[0])==0:
93
+ print('[Gaia: GaiaQueryCoords] Error: no Gaia data found at given coordinates')
94
+ return None
95
+ data=data[0][0].to_pandas()
96
+ data=data.reset_index(drop=True)
97
+ data=renameHeadersDR3(data)
98
+ return data
99
+ if catalogue=='dr3':
100
+ data.append(v.query_region(coord.SkyCoord(ra=ObjRa,dec=ObjDec,unit=(u.deg,u.deg),frame='icrs'),width=radius*u.arcsec,catalog=catalogue_names[1]))
101
+ if len(data[0])==0:
102
+ print('[Gaia: GaiaQueryCoords] Error: no Gaia data found at given coordinates')
103
+ return None
104
+ data=data[0][0].to_pandas()
105
+ data=data.reset_index(drop=True)
106
+ data=renameHeadersDR3(data)
107
+ return data
108
+
109
+ #Returns an objects Gaia designation given its coordinates. Designations are given the prefix 'GAIA DR2' or 'GAIA DR3' depending on the catalogue given, as this is the format used by Vizier.
110
+ def GaiaGetDesignation(ObjRa,ObjDec,radius=3,catalogue='dr3'):
111
+ data=GaiaQueryCoords(ObjRa,ObjDec,radius,catalogue)
112
+
113
+ catalogue=catalogue.lower()
114
+
115
+ Designation=data['source_id']
116
+ #Returns designation if only one object is found
117
+ if len(data)==1:
118
+ if catalogue=='dr2':
119
+ Designation='GAIA DR2 '+str(Designation[0])
120
+ elif catalogue=='dr3':
121
+ Designation='GAIA DR3 '+str(Designation[0])
122
+ #Returns designation as a tuple if multiple objects are found
123
+ if len(data)>1:
124
+ print('[Gaia: GaiaGetDesignation] Note: '+len(data), 'objects detected within search radius.')
125
+ Designation=Designation.to_list()
126
+ if not isinstance(data,pd.DataFrame):
127
+ return None
128
+ return Designation
129
+
130
+ #Returns an object's coordinates in a given data release given a Gaia designation, returns them as tuple [RA,DEC]
131
+ def GaiaGetCoords(Designation,catalogue='dr3'):
132
+ data=GaiaQueryDesignation(Designation,catalogue)
133
+ if not isinstance(data,pd.DataFrame) or data.empty:
134
+ return None
135
+
136
+ #If used correctly this should never trigger as each object should have a unique Gaia designation
137
+ if len(data)>1:
138
+ raise Exception('too many objects returned by search')
139
+
140
+ objRa=data['ra']
141
+ objDec=data['dec']
142
+ Coords=[objRa[0],objDec[0]]
143
+
144
+ return Coords
145
+
146
+ def GaiaGetPhotometryDesignation(Designation,catalogue='dr3'):
147
+ data=GaiaQueryDesignation(Designation,catalogue)
148
+ if not isinstance(data,pd.DataFrame) or data.empty:
149
+ return None
150
+
151
+ photometry=data[['ra','dec','source_id','phot_g_mean_mag','phot_g_mean_mag_error','phot_bp_mean_mag','phot_bp_mean_mag_error','phot_rp_mean_mag','phot_rp_mean_mag_error']].copy()
152
+
153
+ return photometry
154
+
155
+ def GaiaGetPhotometryCoords(ObjRa,ObjDec,radius=3):
156
+ data=GaiaQueryCoords(ObjRa,ObjDec,radius=radius)
157
+
158
+ if not isinstance(data,pd.DataFrame) or data.empty:
159
+ return None
160
+
161
+ photometry=data[['ra','dec','source_id','phot_g_mean_mag','phot_g_mean_mag_error','phot_bp_mean_mag','phot_bp_mean_mag_error','phot_rp_mean_mag','phot_rp_mean_mag_error']].copy()
162
+
163
+ return photometry
164
+
165
+ if __name__=='__main__':
166
+ print(GaiaQueryDesignation(6050296829033196032))
167
+
168
+
@@ -0,0 +1,221 @@
1
+ from astropy.table import Table
2
+ from astropy.io import fits
3
+ import astropy
4
+ from astropy.visualization import PercentileInterval, AsinhStretch
5
+ from astropy.wcs import WCS
6
+ import PIL
7
+ from PIL import Image
8
+ from io import BytesIO
9
+ import numpy as np
10
+ import requests
11
+ import re
12
+ import warnings
13
+ from astropy.utils.exceptions import AstropyWarning
14
+ import pandas as pd
15
+ from bokeh.plotting import figure
16
+ from bokeh.models import Range1d
17
+
18
+ #Ignore warning about deprecated header
19
+ warnings.simplefilter('ignore', category=AstropyWarning)
20
+
21
+ def get_image(ra,dec,size=30,band='g'):
22
+ # Construct URL for fetching a list of image urls
23
+ service='https://ps1images.stsci.edu/cgi-bin/ps1filenames.py'
24
+ url=f'{service}?ra={ra}&dec={dec}&band={band}'
25
+
26
+ # Try to read the resulting table
27
+ try:
28
+ table=Table.read(url, format='ascii')
29
+ except:
30
+ print('[PanSTARRS: get_image_data] Error: experiencing issues with Pan-STARRS.')
31
+ return None, None, None
32
+
33
+ if not len(table)>0:
34
+ print('[PanSTARRS: get_image_data] Error: no PanSTARRS images found using given fields.')
35
+ return None, None, None
36
+
37
+ # Finds any missing filters in returned data and removes them from the 'band' string to signify this
38
+ shortnames=[]
39
+ for i in range(0,len(table)):
40
+ shortnames.append(table['shortname'][i])
41
+
42
+ missing_filters=[]
43
+ if len(table)!=len(band):
44
+ for i in range(0,len(band)):
45
+ filterCheck='.'+band[i]+'.'
46
+ if any(filterCheck in shortname for shortname in shortnames):
47
+ pass
48
+ else:
49
+ print('[PanSTARRS: get_image_data] Note: no PanSTARRS data in '+band[i]+' band')
50
+ missing_filters.append(band[i])
51
+
52
+ for i in range(0,len(missing_filters)):
53
+ band=band.replace(missing_filters[i],'')
54
+
55
+ # Constructs the URL used to fetch the images
56
+ url=(f'https://ps1images.stsci.edu/cgi-bin/fitscut.cgi?ra={ra}&dec={dec}&size={size}&format=fits')
57
+
58
+ filterList=['yzirg'.find(x) for x in table['filter']]
59
+ table=table[np.argsort(filterList)]
60
+
61
+ urlbase=url+'&red='
62
+ url=[]
63
+ for filename in table['filename']:
64
+ url.append(urlbase+filename)
65
+
66
+ # Grab images using constructed URL
67
+ try:
68
+ r=requests.get(url[0],timeout=15)
69
+ if r.status_code!=200:
70
+ print('[PanSTARRS: getFitsImage] Error: experiencing issues with Pan-STARRS.')
71
+ return None, None, None
72
+ except:
73
+ print('[PanSTARRS: get_image_data] Error: experiencing issues with Pan-STARRS.')
74
+ return None, None, None
75
+
76
+ # Read and format image data
77
+ try:
78
+ fh=fits.open(BytesIO(r.content))
79
+ fitsImage=fh[0].data
80
+ image_header=fh[0].header
81
+ fitsImage[np.isnan(fitsImage)]=0.0
82
+ transform=AsinhStretch()+PercentileInterval(95)
83
+ image=transform(fitsImage)
84
+
85
+ return image, image_header, band
86
+ except:
87
+ print('[PanSTARRS: get_image_data] Error: no PanSTARRS images found using given fields. 2')
88
+ return None, None, None
89
+
90
+ '''
91
+ Function for returning the wcs (transformation) and mjd of an image
92
+ '''
93
+ def get_info(ra,dec,size=30,band='g'):
94
+ # Verify inputs
95
+ ra,dec,size,sizeAS,band=input_management(ra=ra,dec=dec,size=size,band=band)
96
+ # Get image header
97
+ image_data=get_image(ra=ra,dec=dec,size=size,band=band)[1]
98
+
99
+ if not isinstance(image_data,astropy.io.fits.header.Header):
100
+ return None, None
101
+
102
+ wcs=WCS(image_data)
103
+ mjd=image_data['MJD-OBS']
104
+
105
+ return wcs, mjd
106
+
107
+ '''
108
+ Verifies all inputs and transforms them into the units required by queries
109
+ '''
110
+ def input_management(ra,dec,size=30,band='g'):
111
+ if len(band)!=len(set(band)):
112
+ raise Exception('duplicate detected in filter selection')
113
+
114
+ if not isinstance(ra,float):
115
+ try:
116
+ ra=float(ra)
117
+ except:
118
+ raise Exception('object RA must be a float or an integer')
119
+ if not isinstance(dec,float):
120
+ try:
121
+ dec=float(dec)
122
+ except:
123
+ raise Exception('object DEC must be a float or an integer')
124
+
125
+ band=band.lower()
126
+
127
+ if not isinstance(size,int):
128
+ try:
129
+ size=int(size)
130
+ except:
131
+ raise Exception('size must take an integer value')
132
+
133
+ # Adjusts size to unit required by PanSTARRS (0.25"/pixel)
134
+ sizeAS=size
135
+ size=size*4
136
+
137
+ if size>6000:
138
+ raise Exception('maximum size is 25 arcmin')
139
+
140
+ if re.match('^[grizy]+$', band):
141
+ pass
142
+ else:
143
+ raise Exception('invalid bands, supported bands: [g,r,i,z,y]')
144
+
145
+ return ra,dec,size,sizeAS,band
146
+
147
+ def get_plot(ra,dec,size=30,band='g'):
148
+ # Verify and transform inputs
149
+ ra,dec,size,sizeAS,band=input_management(ra=ra,dec=dec,size=size,band=band)
150
+
151
+ # Create axes and plot image
152
+ plot=figure(width=400,height=400,title=f'PanSTARRS Image ({sizeAS}")')
153
+ # Fixes scaling issue
154
+ plot.min_border=75
155
+
156
+ plot.xgrid.grid_line_color=None
157
+ plot.ygrid.grid_line_color=None
158
+
159
+ image,image_data,_=get_image(ra=ra,dec=dec,size=size,band=band)
160
+
161
+ if not isinstance(image,np.ndarray) or not isinstance(image_data,astropy.io.fits.header.Header):
162
+ return None
163
+
164
+ # Get x and y limit (in pixels) from image header
165
+ xlim=image_data['NAXIS1']
166
+ ylim=image_data['NAXIS2']
167
+
168
+ # Get points on axes in world coordinates (deg)
169
+ wcs=WCS(image_data)
170
+
171
+ # Get array of pixels in x and y
172
+ x_points=np.arange(start=0,stop=xlim+1,step=1)
173
+ y_points=np.arange(start=0,stop=ylim+1,step=1)
174
+
175
+ # Apply transformation to coordinates
176
+ coords=wcs.all_pix2world(x_points,y_points,1)
177
+ x_points,y_points=coords[0],coords[1]
178
+
179
+ # Get image size in degrees
180
+ x_range=max(x_points)-min(x_points)
181
+ y_range=max(y_points)-min(y_points)
182
+
183
+ plot.x_range=Range1d(max(x_points),min(x_points))
184
+ plot.y_range=Range1d(min(y_points),max(y_points))
185
+
186
+ plot.image(image=[image],x=x_points[0],y=y_points[0],dw=x_range,dh=y_range,palette='Greys256',level="image",origin='bottom_right',anchor='bottom_right')
187
+ return plot
188
+
189
+ def PanSTARRSQueryCoords(ObjRa,ObjDec,radius=3):
190
+ radius=radius/3600
191
+
192
+ #Had to use JSON format to get this to work, the CSV format used is not easily formattable by pandas
193
+ url=f'https://gsss.stsci.edu/webservices/vo/CatalogSearch.aspx?CAT=PS1dr2OBJECTS&RA={ObjRa}&DEC={ObjDec}&SR={radius}&FORMAT=json'
194
+
195
+ try:
196
+ r=requests.get(url)
197
+ except:
198
+ print('[PanSTARRS: PanSTARRSQueryCoords] Error: experiencing issues with Pan-STARRS')
199
+ return None
200
+
201
+ if r.status_code!=200:
202
+ print('[PanSTARRS: PanSTARRSQueryCoords] Error: experiencing issues with Pan-STARRS')
203
+ return None
204
+
205
+ data=BytesIO(r.content)
206
+ try:
207
+ data=pd.read_json(data)
208
+ except:
209
+ print('[PanSTARRS: PanSTARRSQueryCoords] Note: No data found using given coordinates')
210
+
211
+ return data
212
+
213
+ def PanSTARRSGetPhotometryCoords(ObjRa,ObjDec,radius=3):
214
+ data=PanSTARRSQueryCoords(ObjRa,ObjDec,radius=radius)
215
+
216
+ if not isinstance(data,pd.DataFrame) or data.empty:
217
+ print('[PanSTARRS: PanSTARRSGetPhotometryCoords] Note: No PanSTARRS data at given coordinates.')
218
+ return None
219
+
220
+ photometry=data[['ra','dec','objID','gMeanPSFMag','gMeanPSFMagErr','rMeanPSFMag','rMeanPSFMagErr','iMeanPSFMag','iMeanPSFMagErr','zMeanPSFMag','zMeanPSFMagErr','yMeanPSFMag','yMeanPSFMagErr']].copy()
221
+ return photometry
@@ -0,0 +1,51 @@
1
+ import pandas as pd
2
+ import astropy.coordinates as coord
3
+ from astroquery.vizier import Vizier
4
+ import astropy.units as u
5
+ import math
6
+ import warnings
7
+ from astropy.utils.exceptions import AstropyWarning
8
+
9
+ catalogue_name='J/A+A/588/A103'
10
+
11
+ Vizier.ROW_LIMIT = -1
12
+
13
+ warnings.simplefilter('ignore', category=AstropyWarning)
14
+
15
+ def ROSATQueryCoords(ObjRa,ObjDec,SearchRadius=3):
16
+ data=[]
17
+
18
+ #Filter inputs
19
+ if not isinstance(SearchRadius,int) and not isinstance(SearchRadius,float):
20
+ raise Exception('search radius must be a float or an integer')
21
+
22
+ if not isinstance(ObjRa,float):
23
+ try:
24
+ ObjRa=float(ObjRa)
25
+ except:
26
+ raise Exception('object RA must be a float or an integer')
27
+ if not isinstance(ObjDec,float):
28
+ try:
29
+ ObjDec=float(ObjDec)
30
+ except:
31
+ raise Exception('object DEC must be a float or an integer')
32
+
33
+ v=Vizier(columns=['**'])
34
+
35
+ #Sends Vizier query, can return multiple objects in given search radius
36
+ data.append(v.query_region(coord.SkyCoord(ra=ObjRa,dec=ObjDec,unit=(u.deg,u.deg),frame='icrs'),width=SearchRadius*u.arcsec,catalog=catalogue_name))
37
+ if len(data[0])==0:
38
+ print('[ROSAT: ROSATQueryCoords] Error: no ROSAT data found at given coordinates')
39
+ return None
40
+ data=data[0][0].to_pandas()
41
+ data=data.reset_index(drop=True)
42
+ return data
43
+
44
+ def ROSATGetPhotometryCoords(ObjRa,ObjDec,SearchRadius=3):
45
+ data=ROSATQueryCoords(ObjRa,ObjDec,SearchRadius=SearchRadius)
46
+ if not isinstance(data,pd.DataFrame) or data.empty:
47
+ return None
48
+
49
+ photometry=data[['RAJ2000','DEJ2000','VmagVV10','VTmag','BTmag','VmagBSC','VmagHMXB','VmagLMXB','VmagWD','VsphotWD']].copy()
50
+
51
+ return photometry
@@ -0,0 +1,78 @@
1
+ from astroquery.sdss import SDSS
2
+ from astropy import coordinates as coords
3
+ from astropy import units as u
4
+ from astroquery.vizier import Vizier
5
+ import astropy.coordinates as coord
6
+ import pandas as pd
7
+ from bokeh.plotting import figure
8
+ import astropy
9
+
10
+ catalogue_name='V/154/sdss16'
11
+
12
+ Vizier.ROW_LIMIT = -1
13
+
14
+ def get_spectrum_data(ra,dec,radius):
15
+ pos=coords.SkyCoord(ra,dec,unit='deg')
16
+ radius=radius/3600*u.deg
17
+
18
+ data=SDSS.get_spectra(pos,radius)
19
+ if data!=None:
20
+ data=data[0][1]
21
+ else:
22
+ return None, None
23
+
24
+ spectrum_data=data.data
25
+
26
+ log_wavelength=spectrum_data['loglam']
27
+ wavelength=10**log_wavelength*u.AA
28
+ flux=spectrum_data['flux']*10**-17*u.Unit('erg cm-2 s-1 AA-1')
29
+
30
+ return wavelength,flux
31
+
32
+ def get_plot(ra,dec,radius=3):
33
+ x,y=get_spectrum_data(ra,dec,radius)
34
+
35
+ if not isinstance(x,astropy.units.quantity.Quantity) or not isinstance(y,astropy.units.quantity.Quantity):
36
+ return None
37
+
38
+ plot=figure(width=400,height=400,title="SDSS Spectrum",x_axis_label=r'\[\lambda\text{ }[\text{AA}]\]',y_axis_label=r"\[\text{flux [erg}\text{ cm }^{-2}\text{ s }^{-1}\text{AA}^{-1}]\]")
39
+ plot.line(x,y,color='black',line_width=1)
40
+
41
+ return plot
42
+
43
+ def get_data(ra,dec,radius=3):
44
+ data=[]
45
+
46
+ if not isinstance(radius,int) and not isinstance(radius,float):
47
+ raise Exception('search radius must be a float or an integer')
48
+
49
+ if not isinstance(ra,float):
50
+ try:
51
+ ra=float(ra)
52
+ except:
53
+ raise Exception('object RA must be a float or an integer')
54
+ if not isinstance(dec,float):
55
+ try:
56
+ dec=float(dec)
57
+ except:
58
+ raise Exception('object DEC must be a float or an integer')
59
+
60
+ v=Vizier(columns=['**'])
61
+
62
+ #Sends Vizier query, can return multiple objects in given search radius
63
+ data.append(v.query_region(coord.SkyCoord(ra=ra,dec=dec,unit=(u.deg,u.deg),frame='icrs'),width=radius*u.arcsec,catalog=catalogue_name))
64
+ if len(data[0])==0:
65
+ print('[SDSS: get_data] Error: no SDSS data found at given coordinates')
66
+ return None
67
+ data=data[0][0].to_pandas()
68
+ data=data.reset_index(drop=True)
69
+ return data
70
+
71
+ def get_photometry(ra,dec,radius=3):
72
+ SDSSdata=get_data(ra,dec,radius=radius)
73
+ if not isinstance(SDSSdata,pd.DataFrame) or SDSSdata.empty:
74
+ return None
75
+
76
+ photometry=SDSSdata[['RA_ICRS','DE_ICRS','objID','uPmag','e_uPmag','gPmag','e_gPmag','rPmag','e_rPmag','iPmag','e_iPmag','zPmag','e_zPmag']].copy()
77
+
78
+ return photometry