Hide keyboard shortcuts

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

from __future__ import print_function 

from builtins import range 

import os 

import numpy as np 

 

import lsst.utils 

from lsst.sims.photUtils import Sed 

from lsst.sims.catUtils.matchSED.matchUtils import matchGalaxy 

from lsst.sims.photUtils import BandpassDict 

from lsst.sims.catUtils.dust import EBVbase as ebv 

 

__all__ = ["selectGalaxySED"] 

 

class selectGalaxySED(matchGalaxy): 

 

""" 

This class provides methods to match galaxy catalog magnitudes to an SED. 

""" 

 

def matchToRestFrame(self, sedList, catMags, mag_error = None, bandpassDict = None, makeCopy = False): 

 

""" 

This will find the closest match to the magnitudes of a galaxy catalog if those magnitudes are in 

the rest frame. Objects without magnitudes in at least two adjacent bandpasses will return as none 

and print out a message. 

 

@param [in] sedList is the set of spectral objects from the models SEDs provided by loadBC03 

or other custom loader routine. 

 

@param [in] catMags is an array of the magnitudes of catalog objects to be matched with a model SED. 

It should be organized so that there is one object's magnitudes along each row. 

 

@param [in] mag_error are provided error values for magnitudes in objectMags. If none provided 

then this defaults to 1.0. This should be an array of the same size as catMags. 

 

@param [in] bandpassDict is an OrderedDict of bandpass objects with which to calculate magnitudes.  

If left equal to None it will by default load the SDSS [u,g,r,i,z] bandpasses. 

 

@param [in] makeCopy indicates whether or not to operate on copies of the SED objects in sedList 

since this method will change the wavelength grid. 

 

@param [out] sedMatches is a list with the name of a model SED that matches most closely to each 

object in the catalog. 

 

@param [out] magNormMatches are the magnitude normalizations for the given magnitudes and 

matched SED. 

 

@param [out] matchErrors contains the Mean Squared Error between the colors of each object and  

the colors of the matched SED. 

""" 

 

#Set up photometry to calculate model Mags 

53 ↛ 54line 53 didn't jump to line 54, because the condition on line 53 was never true if bandpassDict is None: 

galPhot = BandpassDict.loadTotalBandpassesFromFiles(['u','g','r','i','z'], 

bandpassDir = os.path.join(lsst.utils.getPackageDir('throughputs'),'sdss'), 

bandpassRoot = 'sdss_') 

else: 

galPhot = bandpassDict 

 

modelColors = [] 

sedMatches = [] 

magNormMatches = [] 

 

#Find the colors for all model SEDs 

modelColors = self.calcBasicColors(sedList, galPhot, makeCopy = makeCopy) 

modelColors = np.transpose(modelColors) 

 

#Match the catalog colors to models 

numCatMags = len(catMags) 

numOn = 0 

notMatched = 0 

matchColors = [] 

matchErrors = [] 

 

for filtNum in range(0, len(galPhot)-1): 

matchColors.append(np.transpose(catMags)[filtNum] - np.transpose(catMags)[filtNum+1]) 

 

matchColors = np.transpose(matchColors) 

 

for catObject in matchColors: 

#This is done to handle objects with incomplete magnitude data 

colorRange = np.arange(0, len(galPhot)-1) 

filtNums = np.arange(0, len(galPhot)) 

if np.isnan(np.amin(catObject))==True: 

colorRange = np.where(np.isnan(catObject)==False)[0] 

filtNums = np.unique([colorRange, colorRange+1]) #To pick out right filters in calcMagNorm 

if len(colorRange) == 0: 

print('Could not match object #%i. No magnitudes for two adjacent bandpasses.' % (numOn)) 

notMatched += 1 

sedMatches.append(None) 

magNormMatches.append(None) 

matchErrors.append(None) 

else: 

distanceArray = np.zeros(len(sedList)) 

for colorNum in colorRange: 

distanceArray += np.power((modelColors[colorNum] - catObject[colorNum]),2) 

matchedSEDNum = np.nanargmin(distanceArray) 

sedMatches.append(sedList[matchedSEDNum].name) 

magNorm = self.calcMagNorm(np.array(catMags[numOn]), sedList[matchedSEDNum], 

galPhot, mag_error = mag_error, filtRange = filtNums) 

magNormMatches.append(magNorm) 

matchErrors.append(distanceArray[matchedSEDNum]/len(colorRange)) 

numOn += 1 

104 ↛ 105line 104 didn't jump to line 105, because the condition on line 104 was never true if numOn % 10000 == 0: 

print('Matched %i of %i catalog objects to SEDs' % (numOn-notMatched, numCatMags)) 

 

print('Done Matching. Matched %i of %i catalog objects to SEDs' % (numCatMags-notMatched, numCatMags)) 

108 ↛ 111line 108 didn't jump to line 111, because the condition on line 108 was never false if notMatched > 0: 

print('%i objects did not get matched' % (notMatched)) 

 

return sedMatches, magNormMatches, matchErrors 

 

def matchToObserved(self, sedList, catMags, catRedshifts, catRA = None, catDec = None, 

mag_error = None, bandpassDict = None, dzAcc = 2, reddening = True, 

extCoeffs = (4.239, 3.303, 2.285, 1.698, 1.263)): 

 

""" 

This will find the closest match to the magnitudes of a galaxy catalog if those magnitudes are in 

the observed frame and can correct for reddening from within the milky way as well if needed. 

In order to make things faster it first calculates colors for all model SEDs at redshifts between 

the minimum and maximum redshifts of the catalog objects provided with a grid spacing in redshift 

defined by the parameter dzAcc. Objects without magnitudes in at least two adjacent bandpasses will 

return as none and print out a message. 

 

@param [in] sedList is the set of spectral objects from the models SEDs provided by loadBC03 

or other custom loader routine. 

 

@param [in] catMags is an array of the magnitudes of catalog objects to be matched with a model SED. 

It should be organized so that there is one object's magnitudes along each row. 

 

@param [in] catRedshifts is an array of the redshifts of each catalog object. 

 

@param [in] catRA is an array of the RA positions for each catalog object. 

 

@param [in] catDec is an array of the Dec position for each catalog object. 

 

@param [in] mag_error are provided error values for magnitudes in objectMags. If none provided 

then this defaults to 1.0. This should be an array of the same size as catMags. 

 

@param [in] bandpassDict is a BandpassDict with which to calculate magnitudes. 

If left equal to None it will by default load the SDSS [u,g,r,i,z] bandpasses and therefore agree with 

default extCoeffs. 

 

@param [in] dzAcc is the number of decimal places you want to use when building the redshift grid. 

For example, dzAcc = 2 will create a grid between the minimum and maximum redshifts with colors 

calculated at every 0.01 change in redshift. 

 

@param [in] reddening is a boolean that determines whether to correct catalog magnitudes for 

dust in the milky way. By default, it is True. 

If true, this uses calculateEBV from EBV.py to find an EBV value for the object's 

ra and dec coordinates and then uses the coefficients provided by extCoeffs which should come 

from Schlafly and Finkbeiner (2011) for the correct filters and in the same order as provided 

in bandpassDict. 

If false, this means it will not run the dereddening procedure. 

 

@param [in] extCoeffs are the Schlafly and Finkbeiner (2011) (ApJ, 737, 103) coefficients for the 

given filters from bandpassDict and need to be in the same order as bandpassDict. The default given 

are the SDSS [u,g,r,i,z] values. 

 

@param [out] sedMatches is a list with the name of a model SED that matches most closely to each 

object in the catalog. 

 

@param [out] magNormMatches are the magnitude normalizations for the given magnitudes and 

matched SED. 

 

@param [out] matchErrors contains the Mean Squared Error between the colors of each object and  

the colors of the matched SED. 

""" 

 

#Set up photometry to calculate model Mags 

if bandpassDict is None: 

galPhot = BandpassDict.loadTotalBandpassesFromFiles(['u','g','r','i','z'], 

bandpassDir = os.path.join(lsst.utils.getPackageDir('throughputs'),'sdss'), 

bandpassRoot = 'sdss_') 

else: 

galPhot = bandpassDict 

 

#Calculate ebv from ra, dec coordinates if needed 

if reddening == True: 

#Check that catRA and catDec are included 

if catRA is None or catDec is None: 

raise RuntimeError("Reddening is True, but catRA and catDec are not included.") 

calcEBV = ebv() 

raDec = np.array((catRA,catDec)) 

#If only matching one object need to reshape for calculateEbv 

186 ↛ 187line 186 didn't jump to line 187, because the condition on line 186 was never true if len(raDec.shape) == 1: 

raDec = raDec.reshape((2,1)) 

ebvVals = calcEBV.calculateEbv(equatorialCoordinates = raDec) 

objMags = self.deReddenMags(ebvVals, catMags, extCoeffs) 

else: 

objMags = catMags 

 

minRedshift = np.round(np.min(catRedshifts), dzAcc) 

maxRedshift = np.round(np.max(catRedshifts), dzAcc) 

dz = np.power(10., (-1*dzAcc)) 

 

redshiftRange = np.round(np.arange(minRedshift - dz, maxRedshift + (2*dz), dz), dzAcc) 

numRedshifted = 0 

sedMatches = [None] * len(catRedshifts) 

magNormMatches = [None] * len(catRedshifts) 

matchErrors = [None] * len(catRedshifts) 

redshiftIndex = np.argsort(catRedshifts) 

 

numOn = 0 

notMatched = 0 

lastRedshift = -100 

print('Starting Matching. Arranged by redshift value.') 

for redshift in redshiftRange: 

 

if numRedshifted % 10 == 0: 

print('%i out of %i redshifts gone through' % (numRedshifted, len(redshiftRange))) 

numRedshifted += 1 

 

colorSet = [] 

for galSpec in sedList: 

sedColors = [] 

fileSED = Sed() 

fileSED.setSED(wavelen = galSpec.wavelen, flambda = galSpec.flambda) 

fileSED.redshiftSED(redshift) 

sedColors = self.calcBasicColors([fileSED], galPhot, makeCopy = True) 

colorSet.append(sedColors) 

colorSet = np.transpose(colorSet) 

for currentIndex in redshiftIndex[numOn:]: 

matchMags = objMags[currentIndex] 

if lastRedshift < np.round(catRedshifts[currentIndex],dzAcc) <= redshift: 

colorRange = np.arange(0, len(galPhot)-1) 

matchColors = [] 

for colorNum in colorRange: 

matchColors.append(matchMags[colorNum] - matchMags[colorNum+1]) 

#This is done to handle objects with incomplete magnitude data 

filtNums = np.arange(0, len(galPhot)) 

if np.isnan(np.amin(matchColors))==True: 

colorRange = np.where(np.isnan(matchColors)==False)[0] 

filtNums = np.unique([colorRange, colorRange+1]) #Pick right filters in calcMagNorm 

if len(colorRange) == 0: 

print('Could not match object #%i. No magnitudes for two adjacent bandpasses.' \ 

% (currentIndex)) 

notMatched += 1 

#Don't need to assign 'None' here in result array, b/c 'None' is default value 

else: 

distanceArray = [np.zeros(len(sedList))] 

for colorNum in colorRange: 

distanceArray += np.power((colorSet[colorNum] - matchColors[colorNum]),2) 

matchedSEDNum = np.nanargmin(distanceArray) 

sedMatches[currentIndex] = sedList[matchedSEDNum].name 

magNormVal = self.calcMagNorm(np.array(matchMags), sedList[matchedSEDNum], 

galPhot, mag_error = mag_error, 

redshift = catRedshifts[currentIndex], 

filtRange = filtNums) 

magNormMatches[currentIndex] = magNormVal 

matchErrors[currentIndex] = (distanceArray[0,matchedSEDNum]/len(colorRange)) 

numOn += 1 

else: 

break 

lastRedshift = redshift 

 

print('Done Matching. Matched %i of %i catalog objects to SEDs' % (len(catMags)-notMatched, 

len(catMags))) 

if notMatched > 0: 

print('%i objects did not get matched.' % (notMatched)) 

 

return sedMatches, magNormMatches, matchErrors