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
38 properties = []
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
51 """
52 Name of the correction, and enough detail to record in the
53 reduced data log.
54 """
55 raise NotImplementedError
56
57
63
65
66 if isinstance(other,Correction):
67 return Pipeline([self,other])
68 raise NotImplementedError
69
71
72
73 if not isinstance(other, Pipeline):
74 return self(other)
75 raise NotImplementedError
76
80
82
83 if isinstance(other, Correction):
84 return Pipeline(self.stages + [other])
85
86 if isinstance(other, Pipeline):
87 return Pipeline(self.stages + other.stages)
88 raise NotImplementedError
89
91
92 if isinstance(other, Correction):
93 return Pipeline([other] + self.stages)
94
95 data = copy(other)
96 for stage in self.stages:
97 data.log(str(stage))
98 stage.apply(data)
99 return data
100
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
120 a |= pipeline
121 assert a.x == 12
122
123 if __name__ == "__main__": test()
124