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

from lsst.sims.maf.metrics import BaseMetric 

import numpy as np 

from lsst.sims.maf.utils import m52snr 

from scipy.interpolate import interp1d 

 

# Modifying from Knut Olson's fork at: 

# https://github.com/knutago/sims_maf_contrib/blob/master/tutorials/CrowdingMetric.ipynb 

 

__all__ = ['CrowdingMetric', 'CrowdingMagUncertMetric'] 

 

class CrowdingMetric(BaseMetric): 

""" 

Calculate whether the coadded depth in r has exceeded the confusion limit 

""" 

def __init__(self, crowding_error=0.1, seeingCol='finSeeing', 

fiveSigCol='fiveSigmaDepth', units='mag', maps=['StellarDensityMap'], 

metricName='Crowding To Precision', **kwargs): 

""" 

Parameters 

---------- 

crowding_error : float (0.1) 

The magnitude uncertainty from crowding. (mags) 

 

Returns 

------- 

float 

The magnitude of a star which has a photometric error of `crowding_error` 

""" 

cols=[seeingCol,fiveSigCol] 

self.crowding_error = crowding_error 

self.seeingCol = seeingCol 

self.fiveSigCol = fiveSigCol 

self.lumAreaArcsec = 3600.0**2 

 

super(CrowdingMetric, self).__init__(col=cols, maps=maps, units=units, metricName=metricName, **kwargs) 

 

 

def _compCrowdError(self, magVector, lumFunc, seeing, singleMag=None): 

""" 

Compute the crowding error for each observation 

 

Parameters 

---------- 

magVector : np.array 

Stellar magnitudes. 

lumFunc : np.array 

Stellar luminosity function. 

seeing : float 

The best seeing conditions. Assuming forced-photometry can use the best seeing conditions 

to help with confusion errors. 

singleMag : float (None) 

If singleMag is None, the crowding error is calculated for each mag in magVector. If 

singleMag is a float, the crowding error is interpolated to that single value. 

 

Returns 

------- 

np.array 

Magnitude uncertainties. 

 

 

Equation from Olsen, Blum, & Rigaut 2003, AJ, 126, 452 

""" 

lumVector = 10**(-0.4*magVector) 

coeff=np.sqrt(np.pi/self.lumAreaArcsec)*seeing/2. 

myIntergral = (np.add.accumulate((lumVector**2*lumFunc)[::-1]))[::-1] 

temp = np.sqrt(myIntergral)/lumVector 

if singleMag is not None: 

interp = interp1d(magVector, temp) 

temp = interp(singleMag) 

 

crowdError = coeff*temp 

 

return crowdError 

 

def run(self, dataSlice, slicePoint=None): 

 

magVector = slicePoint['starMapBins'][1:] 

lumFunc = slicePoint['starLumFunc'] 

 

crowdError =self._compCrowdError(magVector, lumFunc, seeing=min(dataSlice[self.seeingCol]) ) 

 

# Locate at which point crowding error is greater than user-defined limit 

aboveCrowd = np.where(crowdError >= self.crowding_error)[0] 

 

if np.size(aboveCrowd) == 0: 

return max(magVector) 

else: 

crowdMag = magVector[max(aboveCrowd[0]-1,0)] 

return crowdMag 

 

class CrowdingMagUncertMetric(CrowdingMetric): 

""" 

Given a stellar magnitude, calculate the mean uncertainty on the magnitude from crowding. 

""" 

def __init__(self, rmag=20., seeingCol='finSeeing', 

fiveSigCol='fiveSigmaDepth', maps=['StellarDensityMap'], units='mag', 

metricName='CrowdingMagUncert', **kwargs): 

""" 

Parameters 

---------- 

rmag : float 

The magnitude of the star to consider. 

 

Returns 

------- 

float 

The uncertainty in magnitudes caused by crowding for a star of rmag. 

""" 

self.rmag = rmag 

super(CrowdingMagUncertMetric, self).__init__(seeingCol=seeingCol,fiveSigCol=fiveSigCol, 

maps=maps, units=units, metricName=metricName, 

**kwargs) 

 

def run(self, dataSlice, slicePoint=None): 

 

magVector = slicePoint['starMapBins'][1:] 

lumFunc = slicePoint['starLumFunc'] 

# Magnitude uncertainty given crowding 

dmagCrowd = self._compCrowdError(magVector, lumFunc, 

dataSlice[self.seeingCol], singleMag=self.rmag) 

 

result = np.mean(dmagCrowd) 

return result