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# oneDSlicer - slices based on values in one data column in simData. 

2 

3import numpy as np 

4from functools import wraps 

5import warnings 

6from lsst.sims.maf.utils import optimalBins 

7from lsst.sims.maf.stackers import ColInfo 

8from lsst.sims.maf.plots.onedPlotters import OneDBinnedData 

9 

10from .baseSlicer import BaseSlicer 

11 

12__all__ = ['OneDSlicer'] 

13 

14class OneDSlicer(BaseSlicer): 

15 """oneD Slicer.""" 

16 def __init__(self, sliceColName=None, sliceColUnits=None, 

17 bins=None, binMin=None, binMax=None, binsize=None, 

18 verbose=True, badval=0): 

19 """ 

20 'sliceColName' is the name of the data column to use for slicing. 

21 'sliceColUnits' lets the user set the units (for plotting purposes) of the slice column. 

22 'bins' can be a numpy array with the binpoints for sliceCol or a single integer value 

23 (if a single value, this will be used as the number of bins, together with data min/max or binMin/Max), 

24 as in numpy's histogram function. 

25 If 'binsize' is used, this will override the bins value and will be used together with the data min/max 

26 or binMin/Max to set the binpoint values. 

27 

28 Bins work like numpy histogram bins: the last 'bin' value is end value of last bin; 

29 all bins except for last bin are half-open ([a, b>), the last one is ([a, b]). 

30 """ 

31 super(OneDSlicer, self).__init__(verbose=verbose, badval=badval) 

32 self.sliceColName = sliceColName 

33 self.columnsNeeded = [sliceColName] 

34 self.bins = bins 

35 self.binMin = binMin 

36 self.binMax = binMax 

37 self.binsize = binsize 

38 if sliceColUnits is None: 

39 co = ColInfo() 

40 self.sliceColUnits = co.getUnits(self.sliceColName) 

41 else: 

42 self.sliceColUnits = sliceColUnits 

43 self.slicer_init = {'sliceColName':self.sliceColName, 'sliceColUnits':sliceColUnits, 

44 'badval':badval} 

45 self.plotFuncs = [OneDBinnedData,] 

46 

47 def setupSlicer(self, simData, maps=None): 

48 """ 

49 Set up bins in slicer. 

50 """ 

51 if self.sliceColName is None: 

52 raise Exception('sliceColName was not defined when slicer instantiated.') 

53 sliceCol = simData[self.sliceColName] 

54 # Set bin min/max values. 

55 if self.binMin is None: 

56 self.binMin = np.nanmin(sliceCol) 

57 if self.binMax is None: 

58 self.binMax = np.nanmax(sliceCol) 

59 # Give warning if binMin = binMax, and do something at least slightly reasonable. 

60 if self.binMin == self.binMax: 

61 warnings.warn('binMin = binMax (maybe your data is single-valued?). ' 

62 'Increasing binMax by 1 (or 2*binsize, if binsize set).') 

63 if self.binsize is not None: 

64 self.binMax = self.binMax + 2 * self.binsize 

65 else: 

66 self.binMax = self.binMax + 1 

67 # Set bins. 

68 # Using binsize. 

69 if self.binsize is not None: 

70 # Add an extra 'bin' to the edge values of the bins (makes plots much prettier). 

71 self.binMin -= self.binsize 

72 self.binMax += self.binsize 

73 if self.bins is not None: 

74 warnings.warn('Both binsize and bins have been set; Using binsize %f only.' %(self.binsize)) 

75 self.bins = np.arange(self.binMin, self.binMax+self.binsize/2.0, self.binsize, 'float') 

76 # Using bins value. 

77 else: 

78 # Bins was a sequence (np array or list) 

79 if hasattr(self.bins, '__iter__'): 

80 self.bins = np.sort(self.bins) 

81 self.binMin = self.bins[0] 

82 self.binMax = self.bins[-1] 

83 # Or bins was a single value. 

84 else: 

85 if self.bins is None: 

86 self.bins = optimalBins(sliceCol, self.binMin, self.binMax) 

87 nbins = np.round(self.bins) 

88 self.binsize = (self.binMax - self.binMin) / float(nbins) 

89 self.bins = np.arange(self.binMin, self.binMax+self.binsize/2.0, self.binsize, 'float') 

90 # Set nbins to be one less than # of bins because last binvalue is RH edge only 

91 self.nslice = len(self.bins) - 1 

92 self.shape = self.nslice 

93 # Set slicePoint metadata. 

94 self.slicePoints['sid'] = np.arange(self.nslice) 

95 self.slicePoints['bins'] = self.bins 

96 # Add metadata from map if needed. 

97 self._runMaps(maps) 

98 # Set up data slicing. 

99 self.simIdxs = np.argsort(simData[self.sliceColName]) 

100 simFieldsSorted = np.sort(simData[self.sliceColName]) 

101 # "left" values are location where simdata == bin value 

102 self.left = np.searchsorted(simFieldsSorted, self.bins[:-1], 'left') 

103 self.left = np.concatenate((self.left, np.array([len(self.simIdxs),]))) 

104 # Set up _sliceSimData method for this class. 

105 @wraps(self._sliceSimData) 

106 def _sliceSimData(islice): 

107 """Slice simData on oneD sliceCol, to return relevant indexes for slicepoint.""" 

108 idxs = self.simIdxs[self.left[islice]:self.left[islice+1]] 

109 return {'idxs':idxs, 

110 'slicePoint':{'sid':islice, 'binLeft':self.bins[islice]}} 

111 setattr(self, '_sliceSimData', _sliceSimData) 

112 

113 def __eq__(self, otherSlicer): 

114 """Evaluate if slicers are equivalent.""" 

115 result = False 

116 if isinstance(otherSlicer, OneDSlicer): 

117 if self.sliceColName == otherSlicer.sliceColName: 

118 # If slicer restored from disk or setup, then 'bins' in slicePoints dict. 

119 # This is preferred method to see if slicers are equal. 

120 if ('bins' in self.slicePoints) & ('bins' in otherSlicer.slicePoints): 

121 result = np.all(otherSlicer.slicePoints['bins'] == self.slicePoints['bins']) 

122 # However, even before we 'setup' the slicer with data, the slicers could be equivalent. 

123 else: 

124 if (self.bins is not None) and (otherSlicer.bins is not None): 

125 result = np.all(self.bins == otherSlicer.bins) 

126 elif ((self.binsize is not None) and (self.binMin is not None) & (self.binMax is not None) and 

127 (otherSlicer.binsize is not None) and (otherSlicer.binMin is not None) and (otherSlicer.binMax is not None)): 

128 if ((self.binsize == otherSlicer.binsize) and 

129 (self.binMin == otherSlicer.binMin) and 

130 (self.binMax == otherSlicer.binMax)): 

131 result = True 

132 return result