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.
- AstroToolkit/Figures/HRD.py +82 -0
- AstroToolkit/Figures/SED.py +364 -0
- AstroToolkit/Figures/__init__.py +0 -0
- AstroToolkit/Miscellaneous/ProperMotionCorrection.py +50 -0
- AstroToolkit/Miscellaneous/ReadFits.py +35 -0
- AstroToolkit/Miscellaneous/TestFile.py +138 -0
- AstroToolkit/Miscellaneous/__init__.py +0 -0
- AstroToolkit/Overlays/Overlay_GALEX.py +148 -0
- AstroToolkit/Overlays/Overlay_Gaia.py +63 -0
- AstroToolkit/Overlays/Overlay_ROSAT.py +20 -0
- AstroToolkit/Overlays/Overlay_Selection.py +42 -0
- AstroToolkit/Overlays/Overlay_ZTF.py +46 -0
- AstroToolkit/Overlays/__init__.py +0 -0
- AstroToolkit/Surveys/DSS.py +153 -0
- AstroToolkit/Surveys/GALEX.py +45 -0
- AstroToolkit/Surveys/Gaia.py +168 -0
- AstroToolkit/Surveys/PanSTARRS.py +221 -0
- AstroToolkit/Surveys/ROSAT.py +51 -0
- AstroToolkit/Surveys/SDSS.py +78 -0
- AstroToolkit/Surveys/SkyMapper.py +215 -0
- AstroToolkit/Surveys/TWOMASS.py +45 -0
- AstroToolkit/Surveys/WISE.py +45 -0
- AstroToolkit/Surveys/ZTF.py +206 -0
- AstroToolkit/Surveys/__init__.py +0 -0
- AstroToolkit/Timeseries/__init__.py +0 -0
- AstroToolkit/Timeseries/pyaov.py +781 -0
- AstroToolkit/Timeseries/ztfanalysis.py +847 -0
- AstroToolkit/Tools.py +1222 -0
- AstroToolkit/__init__.py +0 -0
- AstroToolkit-1.0.0.dist-info/LICENSE +0 -0
- AstroToolkit-1.0.0.dist-info/METADATA +934 -0
- AstroToolkit-1.0.0.dist-info/RECORD +34 -0
- AstroToolkit-1.0.0.dist-info/WHEEL +5 -0
- AstroToolkit-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -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
|