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

1import numpy as np 

2from .baseStacker import BaseStacker 

3from .generalStackers import FiveSigmaStacker 

4 

5__all__ = ['NEODistStacker'] 

6 

7 

8class NEODistStacker(BaseStacker): 

9 """ 

10 For each observation, find the max distance to a ~144 km NEO, 

11 also stack on the x,y position of the object. 

12 """ 

13 colsAdded = ['MaxGeoDist', 'NEOHelioX', 'NEOHelioY'] 

14 

15 def __init__(self, 

16 stepsize=.001, maxDist=3., minDist=.3, H=22, elongCol='solarElong', 

17 filterCol='filter', sunAzCol='sunAz', azCol='azimuth', m5Col='fiveSigmaDepth'): 

18 """ 

19 stepsize: The stepsize to use when solving (in AU) 

20 maxDist: How far out to try and measure (in AU) 

21 H: Asteroid magnitude 

22 

23 Adds columns: 

24 MaxGeoDist: Geocentric distance to the NEO 

25 NEOHelioX: Heliocentric X (with Earth at x,y,z (0,1,0)) 

26 NEOHelioY: Heliocentric Y (with Earth at (0,1,0)) 

27 

28 Note that both opsim v3 and v4 report solarElongation in degrees. 

29 """ 

30 self.units = ['AU', 'AU', 'AU'] 

31 # Also grab things needed for the HA stacker 

32 self.colsReq = [elongCol, filterCol, sunAzCol, azCol, m5Col] 

33 

34 self.sunAzCol = sunAzCol 

35 self.elongCol = elongCol 

36 self.filterCol = filterCol 

37 self.azCol = azCol 

38 self.m5Col = m5Col 

39 

40 self.H = H 

41 # Magic numbers (Ivezic '15, private comm.)that convert an asteroid 

42 # V-band magnitude to LSST filters: 

43 # V_5 = m_5 + (adjust value) 

44 self.limitingAdjust = {'u': -2.1, 'g': -0.5, 'r': 0.2, 'i': 0.4, 'z': 0.6, 'y': 0.6} 

45 self.deltas = np.arange(minDist, maxDist+stepsize, stepsize) 

46 self.G = 0.15 

47 

48 # Magic numbers from http://adsabs.harvard.edu/abs/2002AJ....124.1776J 

49 self.a1 = 3.33 

50 self.b1 = 0.63 

51 self.a2 = 1.87 

52 self.b2 = 1.22 

53 

54 def _run(self, simData, cols_present=False): 

55 if cols_present: 

56 # This is a pretty rare stacker. Assume we need to rerun 

57 pass 

58 elongRad = np.radians(simData[self.elongCol]) 

59 v5 = np.zeros(simData.size, dtype=float) + simData[self.m5Col] 

60 for filterName in self.limitingAdjust: 

61 fmatch = np.where(simData[self.filterCol] == filterName) 

62 v5[fmatch] += self.limitingAdjust[filterName] 

63 for i, elong in enumerate(elongRad): 

64 # Law of cosines: 

65 # Heliocentric Radius of the object 

66 R = np.sqrt(1.+self.deltas**2-2.*self.deltas*np.cos(elong)) 

67 # Angle between sun and earth as seen by NEO 

68 alphas = np.arccos((1.-R**2-self.deltas**2)/(-2.*self.deltas*R)) 

69 ta2 = np.tan(alphas/2.) 

70 phi1 = np.exp(-self.a1*ta2**self.b1) 

71 phi2 = np.exp(-self.a2*ta2**self.b2) 

72 

73 alpha_term = 2.5*np.log10((1. - self.G)*phi1+self.G*phi2) 

74 appmag = self.H+5.*np.log10(R*self.deltas)-alpha_term 

75 # There can be some local minima/maxima when solving, so 

76 # need to find the *1st* spot where it is too faint, not the 

77 # last spot it is bright enough. 

78 tooFaint = np.where(appmag > v5[i]) 

79 

80 # Check that there is a minimum 

81 if np.size(tooFaint[0]) == 0: 

82 simData['MaxGeoDist'][i] = 0 

83 else: 

84 simData['MaxGeoDist'][i] = np.min(self.deltas[tooFaint]) 

85 

86 # Make coords in heliocentric 

87 interior = np.where(elongRad <= np.pi/2.) 

88 outer = np.where(elongRad > np.pi/2.) 

89 simData['NEOHelioX'][interior] = simData['MaxGeoDist'][interior]*np.sin(elongRad[interior]) 

90 simData['NEOHelioY'][interior] = -simData['MaxGeoDist'][interior]*np.cos(elongRad[interior]) + 1. 

91 

92 simData['NEOHelioX'][outer] = simData['MaxGeoDist'][outer]*np.sin(np.pi-elongRad[outer]) 

93 simData['NEOHelioY'][outer] = simData['MaxGeoDist'][outer]*np.cos(np.pi-elongRad[outer]) + 1. 

94 

95 # Flip the X coord if sun az is negative? 

96 if simData[self.azCol].min() < - np.pi/2.0: 

97 halfval = 180. 

98 else: 

99 halfval = np.pi 

100 flip = np.where(((simData[self.sunAzCol] > halfval) & (simData[self.azCol] > halfval)) | 

101 ((simData[self.sunAzCol] < halfval) & (simData[self.azCol] > halfval))) 

102 

103 simData['NEOHelioX'][flip] *= -1. 

104 

105 return simData