Package reflectometry :: Package reduction :: Module correction

Source Code for Module reflectometry.reduction.correction

  1  """ 
  2  Correction is an abstract interface for data corrections. 
  3   
  4  A correction applies to a dataset.  Different kinds of 
  5  datasets support different kinds of corrections.  For 
  6  example, polarized data supports a polarized data correction 
  7  as well as the usual data corrections on the polarization 
  8  cross sections. 
  9   
 10  A correction has a string name that can be stored in a log file. 
 11   
 12  See properties.py for a discussion of correction parameters. 
 13   
 14  We may want to support an undo/redo stack, either by providing 
 15  an undo method for reversing the effect of the correction, or 
 16  by taking a snapshot of the data before the operation if the 
 17  operation is not reversable, or by rerunning all corrections 
 18  up to the current point.  We need to be careful how this 
 19  mechanism is implemented since the correction parameters 
 20  stored in the object may change over time, and since reversing 
 21  the effects of the correction may require some information about 
 22  the contents of the data. 
 23   
 24  Consider having C1(data) return a copy of the data with the 
 25  correction applied and data.apply(C1) modify the data set. 
 26   
 27  Individual corrections must inherit from Correction to support 
 28  the pipeline syntax:: 
 29   
 30      data |= normalize() | smooth() | attenuate() | ... | plot() 
 31  """ 
 32   
 33  __all__ = ['Correction'] 
 34   
 35  from copy import copy 
 36   
37 -class Correction(object):
38 properties = [] # Property sheet for interacting with correction
39 - def apply(self, data):
40 """ 41 Apply the correction to the dataset, modifying the dataset 42 in the process. The data is returned, allowing users to 43 apply multiple corrections in one step: 44 C2(C1(data)) 45 Each correction will automatically be logged in the data using 46 data.log(str(Correction)) 47 """ 48 raise NotImplementedError
49
50 - def __str__(self):
51 """ 52 Name of the correction, and enough detail to record in the 53 reduced data log. 54 """ 55 raise NotImplementedError
56 57 # ==== Inherited behaviours ====
58 - def __call__(self, data):
59 data = copy(data) 60 data.log(str(self)) 61 self.apply(data) 62 return data
63
64 - def __or__(self, other):
65 # "Correction | Correction" forms a pipeline 66 if isinstance(other,Correction): 67 return Pipeline([self,other]) 68 raise NotImplementedError
69
70 - def __ror__(self, other):
71 # "Pipeline | Correction" is handled by pipeline 72 # "data | Correction" applies the correction to the data 73 if not isinstance(other, Pipeline): 74 return self(other) 75 raise NotImplementedError
76
77 -class Pipeline(Correction):
78 - def __init__(self, stages):
79 self.stages = stages
80
81 - def __or__(self, other):
82 # "Pipeline | Correction" 83 if isinstance(other, Correction): 84 return Pipeline(self.stages + [other]) 85 # "Pipeline | Pipeline" 86 if isinstance(other, Pipeline): 87 return Pipeline(self.stages + other.stages) 88 raise NotImplementedError
89
90 - def __ror__(self, other):
91 # "Correction | Pipeline" 92 if isinstance(other, Correction): 93 return Pipeline([other] + self.stages) 94 # "data | Pipeline" 95 data = copy(other) 96 for stage in self.stages: 97 data.log(str(stage)) 98 stage.apply(data) 99 return data
100
101 -def test():
102 class Add(Correction): 103 def __init__(self, v): self.v = v 104 def __str__(self): return "Add(%g)"%self.v 105 def apply(self, data): data.x += self.v
106 class Mul(Correction): 107 def __init__(self, v): self.v = v 108 def __str__(self): return "Mul(%g)"%self.v 109 def apply(self, data): data.x *= self.v 110 class Data(object): 111 x = 0 112 messages = [] 113 def log(self, msg): self.messages = self.messages + [msg] 114 a = Data() 115 pipeline = Add(3)|Mul(2)|Add(4) 116 assert a.x==0 117 a |= Add(1) 118 assert a.x == 1 119 assert (a|pipeline).x == 12 # Is a copy 120 a |= pipeline 121 assert a.x == 12 # Has been modified 122 123 if __name__ == "__main__": test() 124