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

from builtins import zip 

from builtins import str 

from builtins import object 

import os 

import numpy as np 

import warnings 

from lsst.sims.photUtils import Sed 

from lsst.utils import getPackageDir 

 

__all__ = ["ApplyIGM"] 

 

class ApplyIGM(object): 

 

""" 

This class applies IGM to SED objects using lookup tables. If users want to enter their 

own lookup tables they can do that by specifying self.meanLookups and self.varLookups 

which are dictionaries containing redshift as the keys with (wavelength, transmission) 

arrays as the values. 

""" 

 

IGMisInitialized = False 

tablesPresent = False 

 

def initializeIGM(self, zMin = 1.5, zMax = 2.9, zDelta = 0.1, minWavelen = 300): 

 

""" 

Initialize an applyIGM object with the desired redshift grid. 

If lookup tables are not evenly spaced in redshift then input manually 

desired zRange array. 

 

@param [in] zMin is the minimum redshift. 

 

@param [in] zMax is the maximum redshift. 

 

@param [in] zDelta is the redshift spacing. 

 

@param [in] minWavelen is the minimum wavelength in the lookup tables 

""" 

self.zMin = zMin 

self.zMax = zMax 

self.zDelta = zDelta 

self.minWavelen = minWavelen 

#Don't have max wavelength since transmission goes to 1.0 at longest wavelengths 

self.zRange = np.arange(zMin, zMax + (zDelta/2.), zDelta) 

 

if self.tablesPresent == False: 

table_dir = getPackageDir('sims_catUtils') 

table_dir = os.path.join(table_dir, 

'python/lsst/sims/catUtils/IGM/igm_tables') 

self.loadTables(table_dir) 

 

self.IGMisInitialized = True 

 

 

def loadTables(self, filesDir, varianceTbl = True): 

 

""" 

Read in and store in dictionary the IGM Lookup Tables that contain IGM transmission 

for a given redshift and must be formatted in two columns: 

(wavelength (nm), IGM Transmission %) or for variance 

(wavelength (nm), IGM Transmission % Variance). Variance tables are not required and 

can be turned off as a requirement. Names in directory formatted as 

'MeanLookupTable_zSourceX.X.tbl' or 'VarLookupTable_zSourceX.X.tbl' where X.X is the redshift 

of the given lookup table. 

 

@param [in] filesDir is the location of the directory where lookup table are stored 

 

@param [in] varianceTbl is a boolean that is True if variance tables are present in dir 

for loading. 

""" 

 

self.meanLookups = {} 

self.varLookups = {} 

 

for zValue in self.zRange: 

self.meanLookups['%.1f' % zValue] = np.genfromtxt(str(filesDir + '/MeanLookupTable_zSource' + 

'%.1f' % zValue + '.tbl.gz')) 

if varianceTbl == True: 

try: 

self.varLookups['%.1f' % zValue] = np.genfromtxt(str(filesDir + '/VarLookupTable_zSource' + 

'%.1f' % zValue + '.tbl.gz')) 

except IOError: 

raise IOError("Cannot find variance tables.") 

 

self.tablesPresent = True 

 

def applyIGM(self, redshift, sedobj): 

 

""" 

Apply IGM extinction to already redshifted sed with redshift 

between zMin and zMax defined by range of lookup tables 

 

@param [in] redshift is the redshift of the incoming SED object 

 

@param [in] sedobj is the SED object to which IGM extinction will be applied. This object 

will be modified as a result of this. 

""" 

 

if self.IGMisInitialized == False: 

self.initializeIGM() 

 

#First make sure redshift is in range of lookup tables. 

if (redshift < self.zMin) or (redshift > self.zMax): 

warnings.warn(str("IGM Lookup tables only applicable for " + str(self.zMin) + " < z < " + str(self.zMax) + ". No action taken")) 

return 

 

#Now read in closest two lookup tables for given redshift 

lowerSed = Sed() 

upperSed = Sed() 

110 ↛ 120line 110 didn't jump to line 120, because the loop on line 110 didn't complete for lower, upper in zip(self.zRange[:-1], self.zRange[1:]): 

if lower <= redshift <= upper: 

lowerSed.setSED(self.meanLookups['%.1f' % lower][:,0], 

flambda = self.meanLookups['%.1f' % lower][:,1]) 

upperSed.setSED(self.meanLookups['%.1f' % upper][:,0], 

flambda = self.meanLookups['%.1f' % lower][:,1]) 

break 

 

#Redshift lookup tables to redshift of source, i.e. if source redshift is 1.78 shift lookup 

#table for 1.7 and lookup table for 1.8 to up and down to 1.78, respectively 

zLowerShift = ((1.0 + redshift)/(1.0 + lower)) - 1.0 

zUpperShift = ((1.0 + redshift)/(1.0 + upper)) - 1.0 

lowerSed.redshiftSED(zLowerShift) 

upperSed.redshiftSED(zUpperShift) 

 

#Resample lower and upper transmission data onto same wavelength grid. 

minWavelen = 300. #All lookup tables are usable above 300nm 

maxWavelen = np.amin([lowerSed.wavelen[-1], upperSed.wavelen[-1]]) - 0.01 

lowerSed.resampleSED(wavelen_min = minWavelen, wavelen_max = maxWavelen, wavelen_step = 0.01) 

upperSed.resampleSED(wavelen_match = lowerSed.wavelen) 

 

#Now insert this into a transmission array of 1.0 beyond the limits of current application 

#So that we can get an sed back that extends to the longest wavelengths of the incoming sed 

finalWavelen = np.arange(300., sedobj.wavelen[-1]+0.01, 0.01) 

finalFlambdaExtended = np.ones(len(finalWavelen)) 

 

#Weighted Average of Transmission from each lookup table to get final transmission 

#table at desired redshift 

dzGrid = self.zDelta #Step in redshift between transmission lookup table files 

finalSed = Sed() 

finalFlambda = (lowerSed.flambda*(1.0 - ((redshift - lower)/dzGrid)) + 

upperSed.flambda*(1.0 - ((upper - redshift)/dzGrid))) 

finalFlambdaExtended[0:len(finalFlambda)] = finalFlambda 

finalSed.setSED(wavelen = finalWavelen, flambda = finalFlambdaExtended) 

 

#Resample incoming sed to new grid so that we don't get warnings from multiplySED 

#about matching wavelength grids 

sedobj.resampleSED(wavelen_match=finalSed.wavelen) 

 

#Now multiply transmission curve by input SED to get final result and make it the new flambda 

#data in the original sed which also is now on a new grid starting at 300 nm 

test = sedobj.multiplySED(finalSed) 

sedobj.flambda = test.flambda