From e2bf19c6f6266da5062a5e954c43ce9a92367643 Mon Sep 17 00:00:00 2001 From: Robyn Sanderson Date: Tue, 1 Nov 2022 10:02:27 -0700 Subject: [PATCH 1/7] added start of datamodel for CATS, including a sketch for storing selections in multiple spaces --- datamodel/pawprint/pawprint.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 datamodel/pawprint/pawprint.py diff --git a/datamodel/pawprint/pawprint.py b/datamodel/pawprint/pawprint.py new file mode 100644 index 0000000..418c7f0 --- /dev/null +++ b/datamodel/pawprint/pawprint.py @@ -0,0 +1,21 @@ +from matplotlib.path import Path as mpl_path + +class pawprintClass(dict): + '''Dictionary class to store a "pawprint": polygons in multiple observational spaces that define an initial selection used for stream track modeling, membership calculation / density modeling, or background modeling.''' + + def __init__(self): + self.skyprint = {} #polygon(s) in stream coordinates phi1, phi2 + self.streamspec = {} #rotation matrix to transform from ??? to phi1/phi2 + self.cmdprint = {} #polygon(s) in cmd space + self.cmdspec = {} #some kind of specification for which colors and mags? + self.pmprint = {} #polygon(s) in proper-motion space + self.pmspec = {} #some way to specify which PM coordinates the polygons are functions of + + def _inside_poly(data, vertices): + '''This function takes a list of points (data) and returns a boolean mask that is True for all points inside the polygon defined by vertices''' + return mpl_path(vertices).contains_points(data) + + def in_pawprint(self, data): + '''will take in some data and return masks for stuff in the pawprint (basically by successively applying _inside_poly''' + + From 1b7d9c29dcbb2c289f30732aed97844a53ab94a2 Mon Sep 17 00:00:00 2001 From: Robyn Sanderson Date: Tue, 1 Nov 2022 10:40:23 -0700 Subject: [PATCH 2/7] expanding on datamodel sketch for pawprint --- datamodel/pawprint/pawprint.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/datamodel/pawprint/pawprint.py b/datamodel/pawprint/pawprint.py index 418c7f0..32acd7b 100644 --- a/datamodel/pawprint/pawprint.py +++ b/datamodel/pawprint/pawprint.py @@ -1,21 +1,32 @@ from matplotlib.path import Path as mpl_path +class trackClass(): #borrow from galstreams? + class pawprintClass(dict): '''Dictionary class to store a "pawprint": polygons in multiple observational spaces that define an initial selection used for stream track modeling, membership calculation / density modeling, or background modeling.''' def __init__(self): - self.skyprint = {} #polygon(s) in stream coordinates phi1, phi2 + self.skyprint = {} #polygon(s) in stream coordinates phi1, phi2? or angular width along track as fn of phi1? self.streamspec = {} #rotation matrix to transform from ??? to phi1/phi2 self.cmdprint = {} #polygon(s) in cmd space self.cmdspec = {} #some kind of specification for which colors and mags? self.pmprint = {} #polygon(s) in proper-motion space self.pmspec = {} #some way to specify which PM coordinates the polygons are functions of + + #do we want to put tracks in here too? or have separate model for those? + self.skytrack = {} #polynomial function returns phi2(phi1) + self.cmdtrack = {} #polynomial function returns ?? + self.pmtrack = {} #polynomial functions return [pm1, pm2](phi1) + self.distancetrack = {} #polynomial function returns distance(phi1) + self.rvtrack = {} #polynomial function returns rv(phi1) def _inside_poly(data, vertices): '''This function takes a list of points (data) and returns a boolean mask that is True for all points inside the polygon defined by vertices''' return mpl_path(vertices).contains_points(data) def in_pawprint(self, data): - '''will take in some data and return masks for stuff in the pawprint (basically by successively applying _inside_poly''' + '''take in some data and return masks for stuff in the pawprint (basically by successively applying _inside_poly)''' + + def save_pawprint(self): + '''save as YAML (Eduardo)''' - From 0854082342b232ede878e0dda7e6f01102517ebe Mon Sep 17 00:00:00 2001 From: Robyn Sanderson Date: Tue, 1 Nov 2022 11:56:51 -0700 Subject: [PATCH 3/7] added sketch of star datamodel --- datamodel/star/star.py | 93 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 datamodel/star/star.py diff --git a/datamodel/star/star.py b/datamodel/star/star.py new file mode 100644 index 0000000..cdf73b1 --- /dev/null +++ b/datamodel/star/star.py @@ -0,0 +1,93 @@ +import numpy as np +from astropy.coordinates import SkyCoord + +#notes on data types +dtypes_dict = { + #identifiers + 'sourceID': 'u8', #Gaia DR3 source id, unsigned integer + 'sourceID_spec': 's3', #which version of gaia catalog the source ID refers to + 'streamID': 's10', #10-char string? check galstreams + 'crossmatches':dict(), #dictionary to store IDs in other surveys + + #phase space + 'w': SkyCoord(), #phase space coordinates + 'w_uncert': SkyCoord(), #uncertainties? + 'variability': 'u2', #0 if not variable, 1 if variable + + #photometry from Gaia used for selections in pawprint + 'phot_g_mean_mag': 'f4', + 'phot_rp_mean_mag': 'f4', + 'phot_g_mean_mag_error': 'f4', + 'phot_rp_mean_mag_error': 'f4', + + #consensus chemistry + 'feh_logeps': 'f4', #sun-independent value + 'feh': 'f4', #iron abundance as [Fe/H] + 'feh_solar': 'f4', #solar value of [Fe/H] for this star + + 'alpha_logeps': 'f4', #sun-independent value + 'alpha_fe': 'f4', #alpha abundance as [alpha/Fe] + 'alpha_solar': 'f4', #solar value of [alpha/H] for this star + + + #references: assumes that sky position, photometry, and PM are from Gaia + 'refs': { + 'distance': ['s19'] #ADS bibcode (or pointer to docs) for distance measurement; can be a list + 'rv': ['s19'] + 'feh': ['s19'] + 'alpha': ['s19'] + 'variability': ['s19'] + '' + } + +} + +def get_phase_space(): + '''queries gaia to initialize SkyCoords for phase-space position and uncertainty''' + +def get_gaia_photometry(): + '''queries gaia to get photometry and uncertainties, returned as 32 bit floats''' + +def get_abundances(): + '''queries ancillary data tables for spectroscopy, probably given some options that perhaps user can set''' + +class starMeasurementClass(dict): + '''dictionary class to store __measured__ attributes for one star in the catalog''' + def __init__(self, options): #how to specify options for initialization? + self.sourceID = np.uint(0) + self.sourceID_spec = np.str_('DR3') #default for now + self.streamID = np.str_('') + self.crossmatches = {} + + self.w, self.w_uncert = get_phase_space() #need function to return sky coordinates and uncertainties in two skycoord objects by querying Gaia + + self.phot_g_mean_mag = np.float32(0) + self.phot_rp_mean_mag = np.float32(0) + self.phot_g_mean_mag_error = np.float32(0) + self.phot_rp_mean_mag_error = np.float32(0) + + self.variability = np.bool_(0) + + self.feh = np.float32(0) + self.feh_logeps = np.float32(0) + self.feh_solar = np.float32(0) + self.alpha_logeps = np.float32(0) + self.alpha_fe = np.float32(0) + self.alpha_solar = np.float32(0) + + self.refs = { + 'distance': [''] #ADS bibcode (or pointer to docs) for distance measurement; can be a list + 'rv': [''] + 'feh': [''] + 'alpha': [''] + 'variability': [''] + } + + get_gaia_photometry(self) #load gaia photometry in from catalog + get_abundances(self) #load abundances from detailed spectroscopoc tables + + + +class starPredictionClass(dict): + '''dictionary class to store __predicted/modeled__ attributes for one star in the catalog''' + From e7248ed104c0fc53125044f4f628b363da2b782f Mon Sep 17 00:00:00 2001 From: Robyn Sanderson Date: Tue, 1 Nov 2022 14:47:27 -0700 Subject: [PATCH 4/7] moved masking to star class --- datamodel/pawprint/pawprint.py | 2 ++ datamodel/star/star.py | 31 +++++++++++++++++++++++++------ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/datamodel/pawprint/pawprint.py b/datamodel/pawprint/pawprint.py index 32acd7b..d6b87eb 100644 --- a/datamodel/pawprint/pawprint.py +++ b/datamodel/pawprint/pawprint.py @@ -1,4 +1,6 @@ from matplotlib.path import Path as mpl_path +from galstreams import Track6D + class trackClass(): #borrow from galstreams? diff --git a/datamodel/star/star.py b/datamodel/star/star.py index cdf73b1..f3b06da 100644 --- a/datamodel/star/star.py +++ b/datamodel/star/star.py @@ -1,17 +1,24 @@ import numpy as np -from astropy.coordinates import SkyCoord +from astropy.coordinates import SkyCoord, CoordFrame #notes on data types dtypes_dict = { #identifiers 'sourceID': 'u8', #Gaia DR3 source id, unsigned integer - 'sourceID_spec': 's3', #which version of gaia catalog the source ID refers to + 'sourceID_version': 'u2', #integer representing version of gaia catalog that the source ID refers to 'streamID': 's10', #10-char string? check galstreams 'crossmatches':dict(), #dictionary to store IDs in other surveys #phase space 'w': SkyCoord(), #phase space coordinates 'w_uncert': SkyCoord(), #uncertainties? + + #precompute and store phi1 and phi2 for a desired coordinate frame + 'phi1': 'f8' + 'phi2': 'f8' + 'rotation': CoordFrame() #placeholder + + #flag for variable stars 'variability': 'u2', #0 if not variable, 1 if variable #photometry from Gaia used for selections in pawprint @@ -40,6 +47,8 @@ '' } + #TODO: membership likelihoods + } def get_phase_space(): @@ -53,9 +62,9 @@ def get_abundances(): class starMeasurementClass(dict): '''dictionary class to store __measured__ attributes for one star in the catalog''' - def __init__(self, options): #how to specify options for initialization? + def __init__(self, **options): #how to specify options for initialization? self.sourceID = np.uint(0) - self.sourceID_spec = np.str_('DR3') #default for now + self.sourceID_version = np.uint(3) #default for now is DR3 self.streamID = np.str_('') self.crossmatches = {} @@ -83,11 +92,21 @@ def __init__(self, options): #how to specify options for initialization? 'variability': [''] } + #some stuff could be read directly and stored get_gaia_photometry(self) #load gaia photometry in from catalog get_abundances(self) #load abundances from detailed spectroscopoc tables - - class starPredictionClass(dict): '''dictionary class to store __predicted/modeled__ attributes for one star in the catalog''' + + +def _inside_poly(data, vertices): + '''This function takes a list of points (data) and returns a boolean mask that is True for all points inside the polygon defined by vertices''' + return mpl_path(vertices).contains_points(data) + +def in_pawprint(self, pawprint): + '''take in some data and return masks for stuff in the pawprint (basically by successively applying _inside_poly)''' + + + From fd437428536490ce0832081414d2d6c9d7cecdc6 Mon Sep 17 00:00:00 2001 From: Robyn Sanderson Date: Tue, 1 Nov 2022 17:25:00 -0700 Subject: [PATCH 5/7] added demo example code and made a bunch of revisions based on discussions --- datamodel/pawprint/pawprint.py | 114 ++++++++++++++++++++++++++------- datamodel/star/star.py | 79 ++++++++++++++--------- 2 files changed, 140 insertions(+), 53 deletions(-) diff --git a/datamodel/pawprint/pawprint.py b/datamodel/pawprint/pawprint.py index d6b87eb..9c3fd77 100644 --- a/datamodel/pawprint/pawprint.py +++ b/datamodel/pawprint/pawprint.py @@ -1,34 +1,100 @@ +import galstreams as gst from matplotlib.path import Path as mpl_path -from galstreams import Track6D +from astropy.coordinates import CoordFrame #shorthand + +#use ecsv for polygon specification? +#asdf packages these together + + +class densityClass: #TODO: how to represent densities? + +class Footprint2D(dict): + def __init__(self, vertex_coordinates, footprint_type): + if footprint_type='sky': + #steal Cecilia's implementation from galstreams and return mpl_path and vertices in skycoords + self.vertices = SkyCoord(vertex_coordinates) + + if footprint_type='cartesian': + #should return a mpl_path and vertices in regular old cartesian coords + self.vertices = vertex_coordinates + + self.poly = mpl_path(vertices) + + @classmethod + def from_vertices(cls, vertex_coordinates, footprint_type): + return cls(vertices,footprint_type) + + @classmethod + def from_box(cls, min1, max1, min2, max2, footprint_type): + vertices = get_vertices_from_box(min1, max1, min2, max2) + return cls(vertices,footprint_type) + + @classmethod + def from_file(cls,fname): + with ecsv.load(fname) as f: + vertices = f['vertices'] + footprint_type = f['footprint_type'] + return cls(vertices,footprint_type) + + def get_vertices_from_box(min1, max1, min2, max2): + return [[min1,min2],[min1,max2],[max1,min2],[max1,max2]] + + def save(fname): + #TODO - save as .ecsv + -class trackClass(): #borrow from galstreams? class pawprintClass(dict): - '''Dictionary class to store a "pawprint": polygons in multiple observational spaces that define an initial selection used for stream track modeling, membership calculation / density modeling, or background modeling.''' - - def __init__(self): - self.skyprint = {} #polygon(s) in stream coordinates phi1, phi2? or angular width along track as fn of phi1? - self.streamspec = {} #rotation matrix to transform from ??? to phi1/phi2 - self.cmdprint = {} #polygon(s) in cmd space - self.cmdspec = {} #some kind of specification for which colors and mags? - self.pmprint = {} #polygon(s) in proper-motion space - self.pmspec = {} #some way to specify which PM coordinates the polygons are functions of - - #do we want to put tracks in here too? or have separate model for those? - self.skytrack = {} #polynomial function returns phi2(phi1) - self.cmdtrack = {} #polynomial function returns ?? - self.pmtrack = {} #polynomial functions return [pm1, pm2](phi1) - self.distancetrack = {} #polynomial function returns distance(phi1) - self.rvtrack = {} #polynomial function returns rv(phi1) + '''Dictionary class to store a "pawprint": + polygons in multiple observational spaces that define the initial selection + used for stream track modeling, + membership calculation / density modeling, and background modeling. + + New convention: everything is in phi1 phi2 (don't cross the streams) + + ''' + + def __init__(self, stream_name, pawprint_ID, from_galstreams=True): + + #we need a way to specify and load the vertices for the footprints. + #How do we want to do it? + #I sketched here passing the name of the stream + #but we could also pass a list of vertices provided by WG2/3 + + self.stream_name = stream_name + self.pawprint_ID = pawprint_ID + self.stream_frame = CoordFrame(self,input_data_specifier?) + + #right now loading tracks via galstreams, later include updates to track + if from_galstreams: + track_file = _make_track_file_name(stream_name,pawprint_ID) #todo + summary_file = _make_summary_file_name(stream_name,pawprint_ID) #todo + self.track = gst.Track6D(stream_name, track_file, summary_file) + + self.width = 0.0#(lambda phi1: return width(phi1)) + + + + stream_vertices,background_vertices = load_sky_vertices(self) + + self.skyprint = {'stream':Footprint2D(stream_vertices,type='sky'), + 'background':Footprint2D(background_vertices,type='sky')} + #write new thing to rept footprint a la galstreams, but for any 2 + - def _inside_poly(data, vertices): - '''This function takes a list of points (data) and returns a boolean mask that is True for all points inside the polygon defined by vertices''' - return mpl_path(vertices).contains_points(data) - def in_pawprint(self, data): - '''take in some data and return masks for stuff in the pawprint (basically by successively applying _inside_poly)''' + #WG3: how to implement distance dependence in isochrone selections? + self.cmd_filters = {'poly1':['g', 'bprp'], 'poly2':['h','jk']} # list of which filters are in which footprint in the list. need to match keys in starlist + self.cmdprint = {'poly1':Footprint2D(load_cmd_vertices(self,'poly1'),type='cartesian'),...} #polygon(s) in cmd space + + + self.pmprint = {} = Footprint2D(load_pm_vertices(self),type='sky') #polygon(s) in proper-motion space mu_phi1, mu_phi2 + + + + def save_pawprint(self): - '''save as YAML (Eduardo)''' + '''TODO: save as YAML (Eduardo)''' diff --git a/datamodel/star/star.py b/datamodel/star/star.py index f3b06da..2f7322e 100644 --- a/datamodel/star/star.py +++ b/datamodel/star/star.py @@ -10,8 +10,10 @@ 'crossmatches':dict(), #dictionary to store IDs in other surveys #phase space - 'w': SkyCoord(), #phase space coordinates - 'w_uncert': SkyCoord(), #uncertainties? + 'w': {}#dict of phase space coordinates + 'w_uncert': {}#dictionary of uncertainties per coordinate + #todo: add function to convert w to SkyCoord + #todo: bring in pyia to account for transformations to uncertainties #precompute and store phi1 and phi2 for a desired coordinate frame 'phi1': 'f8' @@ -27,6 +29,8 @@ 'phot_g_mean_mag_error': 'f4', 'phot_rp_mean_mag_error': 'f4', + #TODO WG3: how to store extinction? + #consensus chemistry 'feh_logeps': 'f4', #sun-independent value 'feh': 'f4', #iron abundance as [Fe/H] @@ -44,7 +48,7 @@ 'feh': ['s19'] 'alpha': ['s19'] 'variability': ['s19'] - '' + 'extinction': ['s19'] } #TODO: membership likelihoods @@ -60,44 +64,60 @@ def get_gaia_photometry(): def get_abundances(): '''queries ancillary data tables for spectroscopy, probably given some options that perhaps user can set''' -class starMeasurementClass(dict): + +class starClass(dict): + def __init__(self, streamID): + #starclass + self.data = starDataClass(streamID) + + +class starDataClass(dict): '''dictionary class to store __measured__ attributes for one star in the catalog''' - def __init__(self, **options): #how to specify options for initialization? - self.sourceID = np.uint(0) + def __init__(self, streamID): + self.sourceID_version = np.uint(3) #default for now is DR3 - self.streamID = np.str_('') + self.streamID = np.str_(streamID) + + self.sourceID = load_stream(self.streamID) #read from adrian's initial files + + self.nstars = len(self.sourceID) + self.crossmatches = {} - self.w, self.w_uncert = get_phase_space() #need function to return sky coordinates and uncertainties in two skycoord objects by querying Gaia + self.w, self.w_uncert = phasespace_to_skycoords() #TODO:function to return sky coordinates and uncertainties in two skycoord objects by querying Gaia - self.phot_g_mean_mag = np.float32(0) - self.phot_rp_mean_mag = np.float32(0) - self.phot_g_mean_mag_error = np.float32(0) - self.phot_rp_mean_mag_error = np.float32(0) + #flexible magnitudes - pin down standardised naming convention + #my proposal: [survey]_[filter] + #uncertainties and extinctions are specified by the same tags + self.mags = {'gaia_g':np.array(nstars,dtype='f4'),'gaia_rp':np.array(nstars,dtype='f4'), } + self.mag_uncert = {'gaia_g':np.array(nstars,dtype='f4'),'gaia_rp':np.array(nstars,dtype='f4'), } + self.ext = {'gaia_g':np.array(nstars,dtype='f4'),'gaia_rp':np.array(nstars,dtype='f4'), } + - self.variability = np.bool_(0) + self.variability = np.array(nstars,dtype='u2') - self.feh = np.float32(0) - self.feh_logeps = np.float32(0) - self.feh_solar = np.float32(0) - self.alpha_logeps = np.float32(0) - self.alpha_fe = np.float32(0) - self.alpha_solar = np.float32(0) + self.feh = np.masked_array(nstars,dtype='f4') + self.feh_logeps = np.masked_array(nstars,dtype='f4') + self.feh_solar = np.masked_array(nstars,dtype='f4') + self.alpha_logeps = np.masked_array(nstars,dtype='f4') + self.alpha_fe = np.masked_array(nstars,dtype='f4') + self.alpha_solar = np.masked_array(nstars,dtype='f4') self.refs = { - 'distance': [''] #ADS bibcode (or pointer to docs) for distance measurement; can be a list - 'rv': [''] - 'feh': [''] - 'alpha': [''] - 'variability': [''] + 'distance': np.array(nstars,dtype='s19') #ADS bibcode (or pointer to doi) for distance measurement; can be a list + 'rv': np.array(nstars,dtype='s19') + 'feh': np.array(nstars,dtype='s19') + 'alpha': np.array(nstars,dtype='s19') + 'variability': np.array(nstars,dtype='s19') } #some stuff could be read directly and stored - get_gaia_photometry(self) #load gaia photometry in from catalog - get_abundances(self) #load abundances from detailed spectroscopoc tables + if get_gaia: + get_gaia_photometry(self) #load gaia photometry in from catalog + get_abundances(self) #load abundances from detailed spectroscopoc tables -class starPredictionClass(dict): - '''dictionary class to store __predicted/modeled__ attributes for one star in the catalog''' +class starDerivedClass(dict): + stuff @@ -105,8 +125,9 @@ def _inside_poly(data, vertices): '''This function takes a list of points (data) and returns a boolean mask that is True for all points inside the polygon defined by vertices''' return mpl_path(vertices).contains_points(data) -def in_pawprint(self, pawprint): +def makeMask(self, pawprint, what): '''take in some data and return masks for stuff in the pawprint (basically by successively applying _inside_poly)''' + #returns mask with same dimension as data From 5e7fb501d32d02dd238fe5197a289a0deb96b843 Mon Sep 17 00:00:00 2001 From: Robyn Sanderson Date: Tue, 1 Nov 2022 17:25:30 -0700 Subject: [PATCH 6/7] added demo example code --- datamodel/pawprint/mwe.py | 43 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 datamodel/pawprint/mwe.py diff --git a/datamodel/pawprint/mwe.py b/datamodel/pawprint/mwe.py new file mode 100644 index 0000000..bb74f4b --- /dev/null +++ b/datamodel/pawprint/mwe.py @@ -0,0 +1,43 @@ + +pawprint = pawprintClass('Pal5','PW19') + +#Generate random points on the sphere in an area around the track +rao,raf = np.min(pawprint.track.ra.deg), np.max(pawprint.track.ra.deg) +deco,decf = np.min(pawprint.track.dec.deg),np.max(pawprint.track.dec.deg) +field_ra, field_dec = galstreams.get_random_spherical_angles(5000,az=[rao,raf], + lat=[deco,decf],degree=True) +field = coord.SkyCoord(ra=field_ra*u.deg, dec=field_dec*u.deg, frame='icrs') + +stars = starClass(field) + + +plt.figure(1,figsize=(10,8)) +ax = plt.subplot(111) + + + + +#Plot the track +ax.plot(pawprint.track.ra, pawprint.track.dec, '.', ms=2., color='C0') +#plot the default polygon track stored in the library +ax.plot(pawprint.skyprint['stream'].icrs.ra, pawprint.skyprint['stream'].icrs.dec, ls='--', color='C0') +#Random background "field" points +ax.plot(stars.ra, stars.dec, 'k.', ms=0.5) + +#Select the field points inside the polygon footprint +on = stars.makeMask(pawprint, what = 'sky.stream') #is a function of starlist +ax.plot(stars.ra[on], stars.dec[on], '.', ms=2.5, color='C0') + +#Create a new polygon footprint off-stream, with a given offset and width, and select field points inside it +# +#off_poly = mwsts[st].create_sky_polygon_footprint_from_track(width=1.*u.deg, phi2_offset=3.5*u.deg) +off = stars.makeMask(pawprint, what = 'sky.background') +#Plot the off-stream polygon footprint and points selected inside it +ax.plot(pawprint.skyprint['background'].icrs.ra, pawprint.skyprint['background'].icrs.dec, ls=':', color='C1') +ax.plot(stars.ra[off], stars.dec[off], '.', ms=2.5, color='C1') + +ax.set_xlim(rao,raf) +ax.set_ylim(deco,decf) +ax.set_xlabel('RA (deg)') +ax.set_ylabel('DEC (deg)') +ax.invert_xaxis() \ No newline at end of file From 3c4f0f18fbcb7fca54677d4ca39233999ef13a18 Mon Sep 17 00:00:00 2001 From: Robyn Sanderson Date: Wed, 2 Nov 2022 09:30:43 -0700 Subject: [PATCH 7/7] goodbye --- datamodel/pawprint/mwe.py | 43 ----------- datamodel/pawprint/pawprint.py | 100 ------------------------- datamodel/star/star.py | 133 --------------------------------- 3 files changed, 276 deletions(-) delete mode 100644 datamodel/pawprint/mwe.py delete mode 100644 datamodel/pawprint/pawprint.py delete mode 100644 datamodel/star/star.py diff --git a/datamodel/pawprint/mwe.py b/datamodel/pawprint/mwe.py deleted file mode 100644 index bb74f4b..0000000 --- a/datamodel/pawprint/mwe.py +++ /dev/null @@ -1,43 +0,0 @@ - -pawprint = pawprintClass('Pal5','PW19') - -#Generate random points on the sphere in an area around the track -rao,raf = np.min(pawprint.track.ra.deg), np.max(pawprint.track.ra.deg) -deco,decf = np.min(pawprint.track.dec.deg),np.max(pawprint.track.dec.deg) -field_ra, field_dec = galstreams.get_random_spherical_angles(5000,az=[rao,raf], - lat=[deco,decf],degree=True) -field = coord.SkyCoord(ra=field_ra*u.deg, dec=field_dec*u.deg, frame='icrs') - -stars = starClass(field) - - -plt.figure(1,figsize=(10,8)) -ax = plt.subplot(111) - - - - -#Plot the track -ax.plot(pawprint.track.ra, pawprint.track.dec, '.', ms=2., color='C0') -#plot the default polygon track stored in the library -ax.plot(pawprint.skyprint['stream'].icrs.ra, pawprint.skyprint['stream'].icrs.dec, ls='--', color='C0') -#Random background "field" points -ax.plot(stars.ra, stars.dec, 'k.', ms=0.5) - -#Select the field points inside the polygon footprint -on = stars.makeMask(pawprint, what = 'sky.stream') #is a function of starlist -ax.plot(stars.ra[on], stars.dec[on], '.', ms=2.5, color='C0') - -#Create a new polygon footprint off-stream, with a given offset and width, and select field points inside it -# -#off_poly = mwsts[st].create_sky_polygon_footprint_from_track(width=1.*u.deg, phi2_offset=3.5*u.deg) -off = stars.makeMask(pawprint, what = 'sky.background') -#Plot the off-stream polygon footprint and points selected inside it -ax.plot(pawprint.skyprint['background'].icrs.ra, pawprint.skyprint['background'].icrs.dec, ls=':', color='C1') -ax.plot(stars.ra[off], stars.dec[off], '.', ms=2.5, color='C1') - -ax.set_xlim(rao,raf) -ax.set_ylim(deco,decf) -ax.set_xlabel('RA (deg)') -ax.set_ylabel('DEC (deg)') -ax.invert_xaxis() \ No newline at end of file diff --git a/datamodel/pawprint/pawprint.py b/datamodel/pawprint/pawprint.py deleted file mode 100644 index 9c3fd77..0000000 --- a/datamodel/pawprint/pawprint.py +++ /dev/null @@ -1,100 +0,0 @@ -import galstreams as gst -from matplotlib.path import Path as mpl_path -from astropy.coordinates import CoordFrame #shorthand - -#use ecsv for polygon specification? -#asdf packages these together - - -class densityClass: #TODO: how to represent densities? - -class Footprint2D(dict): - def __init__(self, vertex_coordinates, footprint_type): - if footprint_type='sky': - #steal Cecilia's implementation from galstreams and return mpl_path and vertices in skycoords - self.vertices = SkyCoord(vertex_coordinates) - - if footprint_type='cartesian': - #should return a mpl_path and vertices in regular old cartesian coords - self.vertices = vertex_coordinates - - self.poly = mpl_path(vertices) - - @classmethod - def from_vertices(cls, vertex_coordinates, footprint_type): - return cls(vertices,footprint_type) - - @classmethod - def from_box(cls, min1, max1, min2, max2, footprint_type): - vertices = get_vertices_from_box(min1, max1, min2, max2) - return cls(vertices,footprint_type) - - @classmethod - def from_file(cls,fname): - with ecsv.load(fname) as f: - vertices = f['vertices'] - footprint_type = f['footprint_type'] - return cls(vertices,footprint_type) - - def get_vertices_from_box(min1, max1, min2, max2): - return [[min1,min2],[min1,max2],[max1,min2],[max1,max2]] - - def save(fname): - #TODO - save as .ecsv - - - - -class pawprintClass(dict): - '''Dictionary class to store a "pawprint": - polygons in multiple observational spaces that define the initial selection - used for stream track modeling, - membership calculation / density modeling, and background modeling. - - New convention: everything is in phi1 phi2 (don't cross the streams) - - ''' - - def __init__(self, stream_name, pawprint_ID, from_galstreams=True): - - #we need a way to specify and load the vertices for the footprints. - #How do we want to do it? - #I sketched here passing the name of the stream - #but we could also pass a list of vertices provided by WG2/3 - - self.stream_name = stream_name - self.pawprint_ID = pawprint_ID - self.stream_frame = CoordFrame(self,input_data_specifier?) - - #right now loading tracks via galstreams, later include updates to track - if from_galstreams: - track_file = _make_track_file_name(stream_name,pawprint_ID) #todo - summary_file = _make_summary_file_name(stream_name,pawprint_ID) #todo - self.track = gst.Track6D(stream_name, track_file, summary_file) - - self.width = 0.0#(lambda phi1: return width(phi1)) - - - - stream_vertices,background_vertices = load_sky_vertices(self) - - self.skyprint = {'stream':Footprint2D(stream_vertices,type='sky'), - 'background':Footprint2D(background_vertices,type='sky')} - #write new thing to rept footprint a la galstreams, but for any 2 - - - - #WG3: how to implement distance dependence in isochrone selections? - self.cmd_filters = {'poly1':['g', 'bprp'], 'poly2':['h','jk']} # list of which filters are in which footprint in the list. need to match keys in starlist - self.cmdprint = {'poly1':Footprint2D(load_cmd_vertices(self,'poly1'),type='cartesian'),...} #polygon(s) in cmd space - - - self.pmprint = {} = Footprint2D(load_pm_vertices(self),type='sky') #polygon(s) in proper-motion space mu_phi1, mu_phi2 - - - - - - def save_pawprint(self): - '''TODO: save as YAML (Eduardo)''' - diff --git a/datamodel/star/star.py b/datamodel/star/star.py deleted file mode 100644 index 2f7322e..0000000 --- a/datamodel/star/star.py +++ /dev/null @@ -1,133 +0,0 @@ -import numpy as np -from astropy.coordinates import SkyCoord, CoordFrame - -#notes on data types -dtypes_dict = { - #identifiers - 'sourceID': 'u8', #Gaia DR3 source id, unsigned integer - 'sourceID_version': 'u2', #integer representing version of gaia catalog that the source ID refers to - 'streamID': 's10', #10-char string? check galstreams - 'crossmatches':dict(), #dictionary to store IDs in other surveys - - #phase space - 'w': {}#dict of phase space coordinates - 'w_uncert': {}#dictionary of uncertainties per coordinate - #todo: add function to convert w to SkyCoord - #todo: bring in pyia to account for transformations to uncertainties - - #precompute and store phi1 and phi2 for a desired coordinate frame - 'phi1': 'f8' - 'phi2': 'f8' - 'rotation': CoordFrame() #placeholder - - #flag for variable stars - 'variability': 'u2', #0 if not variable, 1 if variable - - #photometry from Gaia used for selections in pawprint - 'phot_g_mean_mag': 'f4', - 'phot_rp_mean_mag': 'f4', - 'phot_g_mean_mag_error': 'f4', - 'phot_rp_mean_mag_error': 'f4', - - #TODO WG3: how to store extinction? - - #consensus chemistry - 'feh_logeps': 'f4', #sun-independent value - 'feh': 'f4', #iron abundance as [Fe/H] - 'feh_solar': 'f4', #solar value of [Fe/H] for this star - - 'alpha_logeps': 'f4', #sun-independent value - 'alpha_fe': 'f4', #alpha abundance as [alpha/Fe] - 'alpha_solar': 'f4', #solar value of [alpha/H] for this star - - - #references: assumes that sky position, photometry, and PM are from Gaia - 'refs': { - 'distance': ['s19'] #ADS bibcode (or pointer to docs) for distance measurement; can be a list - 'rv': ['s19'] - 'feh': ['s19'] - 'alpha': ['s19'] - 'variability': ['s19'] - 'extinction': ['s19'] - } - - #TODO: membership likelihoods - -} - -def get_phase_space(): - '''queries gaia to initialize SkyCoords for phase-space position and uncertainty''' - -def get_gaia_photometry(): - '''queries gaia to get photometry and uncertainties, returned as 32 bit floats''' - -def get_abundances(): - '''queries ancillary data tables for spectroscopy, probably given some options that perhaps user can set''' - - -class starClass(dict): - def __init__(self, streamID): - #starclass - self.data = starDataClass(streamID) - - -class starDataClass(dict): - '''dictionary class to store __measured__ attributes for one star in the catalog''' - def __init__(self, streamID): - - self.sourceID_version = np.uint(3) #default for now is DR3 - self.streamID = np.str_(streamID) - - self.sourceID = load_stream(self.streamID) #read from adrian's initial files - - self.nstars = len(self.sourceID) - - self.crossmatches = {} - - self.w, self.w_uncert = phasespace_to_skycoords() #TODO:function to return sky coordinates and uncertainties in two skycoord objects by querying Gaia - - #flexible magnitudes - pin down standardised naming convention - #my proposal: [survey]_[filter] - #uncertainties and extinctions are specified by the same tags - self.mags = {'gaia_g':np.array(nstars,dtype='f4'),'gaia_rp':np.array(nstars,dtype='f4'), } - self.mag_uncert = {'gaia_g':np.array(nstars,dtype='f4'),'gaia_rp':np.array(nstars,dtype='f4'), } - self.ext = {'gaia_g':np.array(nstars,dtype='f4'),'gaia_rp':np.array(nstars,dtype='f4'), } - - - self.variability = np.array(nstars,dtype='u2') - - self.feh = np.masked_array(nstars,dtype='f4') - self.feh_logeps = np.masked_array(nstars,dtype='f4') - self.feh_solar = np.masked_array(nstars,dtype='f4') - self.alpha_logeps = np.masked_array(nstars,dtype='f4') - self.alpha_fe = np.masked_array(nstars,dtype='f4') - self.alpha_solar = np.masked_array(nstars,dtype='f4') - - self.refs = { - 'distance': np.array(nstars,dtype='s19') #ADS bibcode (or pointer to doi) for distance measurement; can be a list - 'rv': np.array(nstars,dtype='s19') - 'feh': np.array(nstars,dtype='s19') - 'alpha': np.array(nstars,dtype='s19') - 'variability': np.array(nstars,dtype='s19') - } - - #some stuff could be read directly and stored - if get_gaia: - get_gaia_photometry(self) #load gaia photometry in from catalog - get_abundances(self) #load abundances from detailed spectroscopoc tables - -class starDerivedClass(dict): - stuff - - - -def _inside_poly(data, vertices): - '''This function takes a list of points (data) and returns a boolean mask that is True for all points inside the polygon defined by vertices''' - return mpl_path(vertices).contains_points(data) - -def makeMask(self, pawprint, what): - '''take in some data and return masks for stuff in the pawprint (basically by successively applying _inside_poly)''' - #returns mask with same dimension as data - - -