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

1from builtins import zip 

2from builtins import str 

3from builtins import object 

4import os 

5import numpy as np 

6import warnings 

7from lsst.sims.photUtils import Sed 

8from lsst.utils import getPackageDir 

9 

10__all__ = ["ApplyIGM"] 

11 

12class ApplyIGM(object): 

13 

14 """ 

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

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

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

18 arrays as the values. 

19 """ 

20 

21 IGMisInitialized = False 

22 tablesPresent = False 

23 

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

25 

26 """ 

27 Initialize an applyIGM object with the desired redshift grid. 

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

29 desired zRange array. 

30 

31 @param [in] zMin is the minimum redshift. 

32 

33 @param [in] zMax is the maximum redshift. 

34 

35 @param [in] zDelta is the redshift spacing. 

36 

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

38 """ 

39 self.zMin = zMin 

40 self.zMax = zMax 

41 self.zDelta = zDelta 

42 self.minWavelen = minWavelen 

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

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

45 

46 if self.tablesPresent == False: 

47 table_dir = getPackageDir('sims_catUtils') 

48 table_dir = os.path.join(table_dir, 

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

50 self.loadTables(table_dir) 

51 

52 self.IGMisInitialized = True 

53 

54 

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

56 

57 """ 

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

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

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

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

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

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

64 of the given lookup table. 

65 

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

67 

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

69 for loading. 

70 """ 

71 

72 self.meanLookups = {} 

73 self.varLookups = {} 

74 

75 for zValue in self.zRange: 

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

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

78 if varianceTbl == True: 

79 try: 

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

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

82 except IOError: 

83 raise IOError("Cannot find variance tables.") 

84 

85 self.tablesPresent = True 

86 

87 def applyIGM(self, redshift, sedobj): 

88 

89 """ 

90 Apply IGM extinction to already redshifted sed with redshift 

91 between zMin and zMax defined by range of lookup tables 

92 

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

94 

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

96 will be modified as a result of this. 

97 """ 

98 

99 if self.IGMisInitialized == False: 

100 self.initializeIGM() 

101 

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

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

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

105 return 

106 

107 #Now read in closest two lookup tables for given redshift 

108 lowerSed = Sed() 

109 upperSed = Sed() 

110 for lower, upper in zip(self.zRange[:-1], self.zRange[1:]): 

111 if lower <= redshift <= upper: 

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

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

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

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

116 break 

117 

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

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

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

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

122 lowerSed.redshiftSED(zLowerShift) 

123 upperSed.redshiftSED(zUpperShift) 

124 

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

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

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

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

129 upperSed.resampleSED(wavelen_match = lowerSed.wavelen) 

130 

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

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

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

134 finalFlambdaExtended = np.ones(len(finalWavelen)) 

135 

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

137 #table at desired redshift 

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

139 finalSed = Sed() 

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

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

142 finalFlambdaExtended[0:len(finalFlambda)] = finalFlambda 

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

144 

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

146 #about matching wavelength grids 

147 sedobj.resampleSED(wavelen_match=finalSed.wavelen) 

148 

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

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

151 test = sedobj.multiplySED(finalSed) 

152 sedobj.flambda = test.flambda