Coverage for python/lsst/sims/catUtils/matchSED/selectGalaxySED.py : 8%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from __future__ import print_function
2from builtins import range
3import os
4import numpy as np
6import lsst.utils
7from lsst.sims.photUtils import Sed
8from lsst.sims.catUtils.matchSED.matchUtils import matchGalaxy
9from lsst.sims.photUtils import BandpassDict
10from lsst.sims.catUtils.dust import EBVbase as ebv
12__all__ = ["selectGalaxySED"]
14class selectGalaxySED(matchGalaxy):
16 """
17 This class provides methods to match galaxy catalog magnitudes to an SED.
18 """
20 def matchToRestFrame(self, sedList, catMags, mag_error = None, bandpassDict = None, makeCopy = False):
22 """
23 This will find the closest match to the magnitudes of a galaxy catalog if those magnitudes are in
24 the rest frame. Objects without magnitudes in at least two adjacent bandpasses will return as none
25 and print out a message.
27 @param [in] sedList is the set of spectral objects from the models SEDs provided by loadBC03
28 or other custom loader routine.
30 @param [in] catMags is an array of the magnitudes of catalog objects to be matched with a model SED.
31 It should be organized so that there is one object's magnitudes along each row.
33 @param [in] mag_error are provided error values for magnitudes in objectMags. If none provided
34 then this defaults to 1.0. This should be an array of the same size as catMags.
36 @param [in] bandpassDict is an OrderedDict of bandpass objects with which to calculate magnitudes.
37 If left equal to None it will by default load the SDSS [u,g,r,i,z] bandpasses.
39 @param [in] makeCopy indicates whether or not to operate on copies of the SED objects in sedList
40 since this method will change the wavelength grid.
42 @param [out] sedMatches is a list with the name of a model SED that matches most closely to each
43 object in the catalog.
45 @param [out] magNormMatches are the magnitude normalizations for the given magnitudes and
46 matched SED.
48 @param [out] matchErrors contains the Mean Squared Error between the colors of each object and
49 the colors of the matched SED.
50 """
52 #Set up photometry to calculate model Mags
53 if bandpassDict is None:
54 galPhot = BandpassDict.loadTotalBandpassesFromFiles(['u','g','r','i','z'],
55 bandpassDir = os.path.join(lsst.utils.getPackageDir('throughputs'),'sdss'),
56 bandpassRoot = 'sdss_')
57 else:
58 galPhot = bandpassDict
60 modelColors = []
61 sedMatches = []
62 magNormMatches = []
64 #Find the colors for all model SEDs
65 modelColors = self.calcBasicColors(sedList, galPhot, makeCopy = makeCopy)
66 modelColors = np.transpose(modelColors)
68 #Match the catalog colors to models
69 numCatMags = len(catMags)
70 numOn = 0
71 notMatched = 0
72 matchColors = []
73 matchErrors = []
75 for filtNum in range(0, len(galPhot)-1):
76 matchColors.append(np.transpose(catMags)[filtNum] - np.transpose(catMags)[filtNum+1])
78 matchColors = np.transpose(matchColors)
80 for catObject in matchColors:
81 #This is done to handle objects with incomplete magnitude data
82 colorRange = np.arange(0, len(galPhot)-1)
83 filtNums = np.arange(0, len(galPhot))
84 if np.isnan(np.amin(catObject))==True:
85 colorRange = np.where(np.isnan(catObject)==False)[0]
86 filtNums = np.unique([colorRange, colorRange+1]) #To pick out right filters in calcMagNorm
87 if len(colorRange) == 0:
88 print('Could not match object #%i. No magnitudes for two adjacent bandpasses.' % (numOn))
89 notMatched += 1
90 sedMatches.append(None)
91 magNormMatches.append(None)
92 matchErrors.append(None)
93 else:
94 distanceArray = np.zeros(len(sedList))
95 for colorNum in colorRange:
96 distanceArray += np.power((modelColors[colorNum] - catObject[colorNum]),2)
97 matchedSEDNum = np.nanargmin(distanceArray)
98 sedMatches.append(sedList[matchedSEDNum].name)
99 magNorm = self.calcMagNorm(np.array(catMags[numOn]), sedList[matchedSEDNum],
100 galPhot, mag_error = mag_error, filtRange = filtNums)
101 magNormMatches.append(magNorm)
102 matchErrors.append(distanceArray[matchedSEDNum]/len(colorRange))
103 numOn += 1
104 if numOn % 10000 == 0:
105 print('Matched %i of %i catalog objects to SEDs' % (numOn-notMatched, numCatMags))
107 print('Done Matching. Matched %i of %i catalog objects to SEDs' % (numCatMags-notMatched, numCatMags))
108 if notMatched > 0:
109 print('%i objects did not get matched' % (notMatched))
111 return sedMatches, magNormMatches, matchErrors
113 def matchToObserved(self, sedList, catMags, catRedshifts, catRA = None, catDec = None,
114 mag_error = None, bandpassDict = None, dzAcc = 2, reddening = True,
115 extCoeffs = (4.239, 3.303, 2.285, 1.698, 1.263)):
117 """
118 This will find the closest match to the magnitudes of a galaxy catalog if those magnitudes are in
119 the observed frame and can correct for reddening from within the milky way as well if needed.
120 In order to make things faster it first calculates colors for all model SEDs at redshifts between
121 the minimum and maximum redshifts of the catalog objects provided with a grid spacing in redshift
122 defined by the parameter dzAcc. Objects without magnitudes in at least two adjacent bandpasses will
123 return as none and print out a message.
125 @param [in] sedList is the set of spectral objects from the models SEDs provided by loadBC03
126 or other custom loader routine.
128 @param [in] catMags is an array of the magnitudes of catalog objects to be matched with a model SED.
129 It should be organized so that there is one object's magnitudes along each row.
131 @param [in] catRedshifts is an array of the redshifts of each catalog object.
133 @param [in] catRA is an array of the RA positions for each catalog object.
135 @param [in] catDec is an array of the Dec position for each catalog object.
137 @param [in] mag_error are provided error values for magnitudes in objectMags. If none provided
138 then this defaults to 1.0. This should be an array of the same size as catMags.
140 @param [in] bandpassDict is a BandpassDict with which to calculate magnitudes.
141 If left equal to None it will by default load the SDSS [u,g,r,i,z] bandpasses and therefore agree with
142 default extCoeffs.
144 @param [in] dzAcc is the number of decimal places you want to use when building the redshift grid.
145 For example, dzAcc = 2 will create a grid between the minimum and maximum redshifts with colors
146 calculated at every 0.01 change in redshift.
148 @param [in] reddening is a boolean that determines whether to correct catalog magnitudes for
149 dust in the milky way. By default, it is True.
150 If true, this uses calculateEBV from EBV.py to find an EBV value for the object's
151 ra and dec coordinates and then uses the coefficients provided by extCoeffs which should come
152 from Schlafly and Finkbeiner (2011) for the correct filters and in the same order as provided
153 in bandpassDict.
154 If false, this means it will not run the dereddening procedure.
156 @param [in] extCoeffs are the Schlafly and Finkbeiner (2011) (ApJ, 737, 103) coefficients for the
157 given filters from bandpassDict and need to be in the same order as bandpassDict. The default given
158 are the SDSS [u,g,r,i,z] values.
160 @param [out] sedMatches is a list with the name of a model SED that matches most closely to each
161 object in the catalog.
163 @param [out] magNormMatches are the magnitude normalizations for the given magnitudes and
164 matched SED.
166 @param [out] matchErrors contains the Mean Squared Error between the colors of each object and
167 the colors of the matched SED.
168 """
170 #Set up photometry to calculate model Mags
171 if bandpassDict is None:
172 galPhot = BandpassDict.loadTotalBandpassesFromFiles(['u','g','r','i','z'],
173 bandpassDir = os.path.join(lsst.utils.getPackageDir('throughputs'),'sdss'),
174 bandpassRoot = 'sdss_')
175 else:
176 galPhot = bandpassDict
178 #Calculate ebv from ra, dec coordinates if needed
179 if reddening == True:
180 #Check that catRA and catDec are included
181 if catRA is None or catDec is None:
182 raise RuntimeError("Reddening is True, but catRA and catDec are not included.")
183 calcEBV = ebv()
184 raDec = np.array((catRA,catDec))
185 #If only matching one object need to reshape for calculateEbv
186 if len(raDec.shape) == 1:
187 raDec = raDec.reshape((2,1))
188 ebvVals = calcEBV.calculateEbv(equatorialCoordinates = raDec)
189 objMags = self.deReddenMags(ebvVals, catMags, extCoeffs)
190 else:
191 objMags = catMags
193 minRedshift = np.round(np.min(catRedshifts), dzAcc)
194 maxRedshift = np.round(np.max(catRedshifts), dzAcc)
195 dz = np.power(10., (-1*dzAcc))
197 redshiftRange = np.round(np.arange(minRedshift - dz, maxRedshift + (2*dz), dz), dzAcc)
198 numRedshifted = 0
199 sedMatches = [None] * len(catRedshifts)
200 magNormMatches = [None] * len(catRedshifts)
201 matchErrors = [None] * len(catRedshifts)
202 redshiftIndex = np.argsort(catRedshifts)
204 numOn = 0
205 notMatched = 0
206 lastRedshift = -100
207 print('Starting Matching. Arranged by redshift value.')
208 for redshift in redshiftRange:
210 if numRedshifted % 10 == 0:
211 print('%i out of %i redshifts gone through' % (numRedshifted, len(redshiftRange)))
212 numRedshifted += 1
214 colorSet = []
215 for galSpec in sedList:
216 sedColors = []
217 fileSED = Sed()
218 fileSED.setSED(wavelen = galSpec.wavelen, flambda = galSpec.flambda)
219 fileSED.redshiftSED(redshift)
220 sedColors = self.calcBasicColors([fileSED], galPhot, makeCopy = True)
221 colorSet.append(sedColors)
222 colorSet = np.transpose(colorSet)
223 for currentIndex in redshiftIndex[numOn:]:
224 matchMags = objMags[currentIndex]
225 if lastRedshift < np.round(catRedshifts[currentIndex],dzAcc) <= redshift:
226 colorRange = np.arange(0, len(galPhot)-1)
227 matchColors = []
228 for colorNum in colorRange:
229 matchColors.append(matchMags[colorNum] - matchMags[colorNum+1])
230 #This is done to handle objects with incomplete magnitude data
231 filtNums = np.arange(0, len(galPhot))
232 if np.isnan(np.amin(matchColors))==True:
233 colorRange = np.where(np.isnan(matchColors)==False)[0]
234 filtNums = np.unique([colorRange, colorRange+1]) #Pick right filters in calcMagNorm
235 if len(colorRange) == 0:
236 print('Could not match object #%i. No magnitudes for two adjacent bandpasses.' \
237 % (currentIndex))
238 notMatched += 1
239 #Don't need to assign 'None' here in result array, b/c 'None' is default value
240 else:
241 distanceArray = [np.zeros(len(sedList))]
242 for colorNum in colorRange:
243 distanceArray += np.power((colorSet[colorNum] - matchColors[colorNum]),2)
244 matchedSEDNum = np.nanargmin(distanceArray)
245 sedMatches[currentIndex] = sedList[matchedSEDNum].name
246 magNormVal = self.calcMagNorm(np.array(matchMags), sedList[matchedSEDNum],
247 galPhot, mag_error = mag_error,
248 redshift = catRedshifts[currentIndex],
249 filtRange = filtNums)
250 magNormMatches[currentIndex] = magNormVal
251 matchErrors[currentIndex] = (distanceArray[0,matchedSEDNum]/len(colorRange))
252 numOn += 1
253 else:
254 break
255 lastRedshift = redshift
257 print('Done Matching. Matched %i of %i catalog objects to SEDs' % (len(catMags)-notMatched,
258 len(catMags)))
259 if notMatched > 0:
260 print('%i objects did not get matched.' % (notMatched))
262 return sedMatches, magNormMatches, matchErrors