1 import xml.dom as dom
2 import xml.dom.minidom as minidom
3
4 import os, sys
5 import traceback
6 import numpy
7
8 from park.fitpark.fitModel import FitModel
9 from park.fitpark.fitTags import NAME_TAG, CLASSNAME_TAG, DATA_TAG
10 from park.fitpark.fitDataHelper import dataToXml, dataFromXml
11 from reflParameterSet import ReflParameterSet, ReflMagParameterSet, REFL_PS_TAG
12 from calcReflectivity import CalcReflectivity
13
14 """
15 A model implementing the reflectometry.
16 """
17
18 REFL_PM_TAG = 'RM'
19
20
22 """
23 Model class for Refl.
24 """
25
26 - def __init__(self,
27 name,
28 magnetic=False
29 ):
30 """
31 Constructor. A model must have a name.
32 """
33 FitModel.__init__(self, REFL_PM_TAG, name)
34 self.magnetic = magnetic
35
36
38 """
39 Return the full class name
40 """
41 return 'reflModel.ReflModel'
42
43
45 """
46 clear the contents of the model.
47 """
48 self._pmNames = []
49 self.setData([])
50
51
53 """
54 Return a list of strings representing the fitting parameter names.
55 The user class override this function.
56 """
57 pms = []
58 for name in self._pmNames:
59 pm = getattr(self, name)
60 pms.extend(pm.getParameters())
61 return pms
62
63
65 """
66 Return a list of parameters for the model.
67 """
68 return [getattr(self, name) for name in self._pmNames ]
69
70
72 """
73 Return a list of parameters for the model.
74 """
75 return getattr(self, pname)
76
77
79 """
80 Add a fitting parameter to the model.
81 pmName is the parameter's name that should not include the model name.
82 """
83 pm = ReflParameterSet(pmName)
84 setattr(self, pmName, pm)
85 self._pmNames.append(pmName)
86
87
88
89 - def layer(self,
90 name,
91 depth =100.0,
92 sigma =0.0,
93 rho =1.0,
94 mu =0.0,
95 rho_m =0.0,
96 theta_m=0.0
97 ):
110
111
112 - def incident(self,name, depth=100.0, sigma=0.0, rho=1.0, mu=0.0,
113 rho_m=0.0, theta_m=0.0):
115
116
117 - def substrate(self, name, depth=100.0, sigma=0.0, rho=1.0, mu=0.0,
118 rho_m=0.0, theta_m=0.0):
120
121
126
127
129 """
130 remove a parameter by its name.
131 """
132 self._pmNames.remove(pmName)
133 delattr(self, pmName)
134
135
144
145
147 """
148 Return a vector to calculate norm2. It is required by
149 leastsq() method to calculate the error bar of parameters.
150 """
151 if len(self.getData()) == 3:
152 dy = (self() - self.getData()[1])/self.getData()[2]
153
154 elif len(self.getData()) == 4:
155 dy = (self() - self.getData()[2])/self.getData()[3]
156
157 elif len(self.getData()) == 5:
158 dy = (self() - self.getData()[2])/self.getData()[3]
159 else:
160 dy = None
161
162 return dy
163
164
166 """
167 Return the chisq value for the optimization.
168 This provides the default implementation, which is
169 || residual ||^2.
170 """
171 dy = self.getResidual()
172 return numpy.dot(dy, dy)/len(self.getData()[0])
173
174
176 """
177 Rebuild the object from an python script file
178 """
179 fin = open( fname, 'r')
180 pyTxts = fin.read()
181 cmds = self._parsePyTexts(pyTxts)
182 for cmd in cmds:
183 exec cmd
184
185
187 """
188 Save the object in a file in python format.
189 fname: a file name or a file handler.
190 Return true when successes.
191 """
192 fout = None
193 try:
194 fout = open(fname, 'w')
195 fout.write(str0)
196 except:
197 pass
198
199 if fout is not None: fd.close()
200
201
202 - def _parsePyTexts(self, pyTxts):
203 """
204 restore information about Refl model.
205 """
206 s=pyTxts.strip().split('\n')
207 for i in xrange(len(s)):
208 line=s[i]
209 cmd=line.strip().split('(')[0].strip()
210 if cmd in ('incident','layer','interface', 'substrate'):
211 s[i] = 'self.'+ line
212 return s
213
214
216 """
217 restore information about Refl model.
218 """
219 for node in xmlNode.childNodes:
220 if node.nodeType == dom.Node.ELEMENT_NODE:
221 if node.nodeName == REFL_PS_TAG:
222 name = node.getAttribute(NAME_TAG)
223 pm = ReflParameterSet(name)
224 pm.parse(node)
225 self._pmNames.append(name)
226 setattr(self, name, pm)
227
228 elif node.nodeName == DATA_TAG:
229 self.setData(dataFromXml(node))
230 else:
231 pass
232
233
234
235
236
237
238
240 REFL_DATA = 'du53.dat'
241 model = ReflModel('M0')
242 model.layer('Air', rho=0.0, mu=0.0)
243 model.interface(8.0)
244 model.layer('dPS', depth=65,rho=1.87, mu=0.01)
245 model.interface(5.0)
246 model.layer('P2VP', depth=35,rho=1.7, mu=0.0)
247 model.interface(5.0)
248 model.layer('Si0x', depth=17,rho=3.8, mu=0.0)
249 model.interface(5.0)
250 model.layer('Si', rho=2.07, mu=0.0)
251
252 model.setData(REFL_DATA)
253 print 'Model:', model.getResidual()
254 print 'chisq:', model.getChisq()
255 print model.getLayers()
256
257
259 model = ReflModel('M0')
260
261 model.layer('Air', rho=0.0, mu=0.0)
262 model.interface(8.0)
263
264 model.layer('layer1', depth=60.0, rho=[1.6,2.4], mu=1.0)
265 model.interface(5.0)
266
267 model.layer('layer2', depth=40.0, rho=1.0, mu=4.0)
268 model.interface(5.0)
269
270 model.layer('Si', rho=2.07, mu=0.0)
271 model.interface(5.0)
272
273 model.setData('test.dat')
274
275 print 'chisq:', model.getChisq()
276
277
278 import pylab
279 pylab.semilogy(model.getData()[0], model(), 'r')
280 pylab.errorbar(model.getData()[0], model.getData()[2], model.getData()[3],
281 fmt='.',label="Experiment")
282 pylab.show()
283
284 if __name__ == '__main__':
285 demo()
286