1 """
2 Reflectometry profile interactor.
3 """
4
5 from matplotlib import transforms
6
7 from reflutils import twinx, interface_color, disable_color, active_color, \
8 rho_color, mu_color, phi_color, theta_color, title_color
9
10 from binder import BindArtist
11 from layerInteractor import Interactor
12 from interfaceInteractor import InterfaceInteractor
13 from roughnessInteractor import RoughnessInteractor
14 from listener import Listener
15 from fit import Fit
16
17
19 """
20 Reflectometry profile editor
21 """
22 - def __init__(self,
23 ax,
24 model,
25 listener,
26 parent
27 ):
28 self.listener= listener
29 self.ax = ax
30 self.parent = parent
31 self.customTitle = parent.get_title()
32 if self.customTitle == None:
33 self.customTitle = r"customerTitle"
34
35
36 if model.magnetic:
37 self.ax2 = twinx( self.ax )
38 else:
39 self.ax2 = None
40
41
42 self.title_text = None
43 self.set_title( self.customTitle )
44
45 self.ax.set_xlabel( r'$\rm{z}\ (\AA)$' )
46 if model.magnetic:
47 self.ax.set_ylabel( r'$\rm{Density}\ \times 10^{-6}\ \ \rho,\ \mu,\ \rho_M$')
48 else:
49 self.ax.set_ylabel(r'$\rm{Density}\ \times 10^{-6}\ \ \rho,\ \mu$')
50
51 if model.magnetic:
52 self.ax2.set_ylabel(r'$\rm{Magnetic\ Angle\ (\ ^\circ)}$')
53
54
55
56
57
58
59 self.connect = BindArtist( ax.figure )
60
61
62 self.connect.clearall()
63
64
65 self.connect('motion', ax, self.onMotion )
66 self.connect('click', ax.figure, self.onContext)
67
68
69
70
71 self.model = model
72
73
74 self.interface = InterfaceInteractor(self,ax)
75
76
77 self.roughness = RoughnessInteractor(self,ax)
78
79 self.profiles = []
80 self.layernum = None
81 self.axes_frozen = False
82
83 self._showRho = True
84 self._showMu = True
85 self._showPhi = True
86 self._showTheta = True
87 self._showDepth = True
88
89
90 [self.hrho] = ax.plot([],[],'-',color=rho_color,label=r'$\rho$')
91 [self.hmu ] = ax.plot([],[],'-',color=mu_color, label=r'$\mu$' )
92
93
94 if self.model.magnetic:
95 [self.hP ] = self.ax.plot( [], [], '-', color=phi_color,
96 label = r'$\rho_M$')
97 [self.htheta] = self.ax2.plot( [], [], '-', color=theta_color,
98 label = r'$\theta_M$')
99
100
101 if self.parent.modelPanel.IsShowLegend():
102 self.ShowLegend(show=True)
103
104
105 self.update()
106
107
108
109 - def ShowRho(self, show=True, update=False):
113
114 - def ShowMu(self, show=True, update=False):
118
119 - def ShowPhi(self, show=True, update=False):
123
124 - def ShowTheta(self, show=True, update=False):
128
129 - def ShowDepth(self, show=True, update=False):
133
134
136 if show:
137 if self.model.magnetic:
138 self.hlegend = self.ax.legend(
139 (self.hrho, self.hmu, self.hP, self.htheta),
140
141 (r'$\rho$', r'$\mu$', r'$\rho_M$', r'$\theta_M$'),
142 loc = (0.85,0.5)
143
144 )
145 else:
146 self.hlegend = self.ax.legend( (self.hrho, self.hmu),
147 (r'$\rho$', r'$\mu$'),
148 loc = (0.85,0.5)
149
150 )
151
152 self.hlegend.get_frame().set( alpha=0.2, facecolor='yellow' )
153 else:
154 del self.hlegend
155 self.ax.legend_=None
156
157 if update:
158 self.update()
159
160
162 """Respond to motion events by changing the active layer."""
163
164 Layer_num = self.model.find(event.xdata)
165
166 self.parent.modelPanel.update(Layer_num)
167
168 self.set_layer( Layer_num )
169
170 return False
171
172
173 - def onContext(self, ev):
174 """Context menu (eventually ...)."""
175 return False
176
177
179 return self.customTitle
180
181
183 self.customTitle = title
184 if title != None:
185 if self.title_text != None:
186 self.title_text.remove()
187 self.title_text=self.ax.text(-0.1, 1.05,
188 str(title),
189 transform=self.ax.transAxes,
190 ha='left',
191 va='bottom',
192 fontsize=12,
193 color=title_color
194 )
195
196 self.parent.set_title( title )
197
198
199
201 """Make layer n the active layer."""
202
203 if n == self.layernum:
204 return
205 self.layernum = n
206
207
208
209
210 for interactor in self.profiles:
211 interactor.clear_markers()
212
213
214 if self.model.magnetic:
215 axes = [self.ax]*3 + [self.ax2]
216 else:
217 axes = [self.ax]*2
218
219 profile_colors = [rho_color, mu_color, phi_color, theta_color]
220 profile_pars = ["rho", "mu", "phi", "theta" ]
221 self.profiles = [ Interactor(self,ax,L,p, color=c)
222 for ax,c,p, L in zip(axes,
223 profile_colors,
224 profile_pars,
225 self.model[n])
226 ]
227
228 if self._showRho:
229 self.profiles[0].set_layer(n)
230 else:
231 self.profiles[0].set_layer(n, False)
232
233
234 if self._showMu:
235 self.profiles[1].set_layer(n)
236 else:
237 self.profiles[1].set_layer(n, False)
238
239 if self.model.magnetic:
240
241 if self._showPhi:
242 self.profiles[2].set_layer(n)
243 else:
244 self.profiles[2].set_layer(n, False)
245
246
247 if self._showTheta:
248 self.profiles[3].set_layer(n)
249 else:
250 self.profiles[3].set_layer(n, False)
251
252
253
254 self.roughness.set_layer(n)
255
256
257
258 self.draw()
259
260
262 """
263 Respond to changes in the model by recalculating the profiles and
264 resetting the widgets.
265 """
266
267
268 self.listener.signal('update',self)
269
270
271 self.model.calc_offsets()
272
273
274
275 if len(self.profiles)>0:
276
277 if self._showRho:
278 self.profiles[0].update()
279 else:
280 self.profiles[0].update(False)
281
282
283 if self._showMu:
284 self.profiles[1].update()
285 else:
286 self.profiles[1].update(False)
287
288
289 if self.model.magnetic:
290
291 if self._showPhi:
292 self.profiles[2].update()
293 else:
294 self.profiles[2].update(False)
295
296
297 if self._showTheta:
298 self.profiles[3].update()
299 else:
300 self.profiles[3].update(False)
301
302 if self._showDepth:
303 self.interface.update()
304 else:
305 self.interface.update(False)
306
307 self.roughness.update()
308
309
310 z,p = self.model.calc(n=200)
311
312 self.hrho.set_data(z,p[0])
313 if self._showRho:
314 self.hrho.set_visible(True)
315 else:
316 self.hrho.set_visible(False)
317
318
319 self.hmu.set_data(z,p[1])
320 if self._showMu:
321 self.hmu.set_visible(True)
322 else:
323 self.hmu.set_visible(False)
324
325 if self.model.magnetic:
326
327 self.hP.set_data(z,p[2])
328 if self._showPhi:
329 self.hP.set_visible(True)
330 else:
331 self.hP.set_visible(False)
332
333
334 self.htheta.set_data(z,p[3])
335 if self._showTheta:
336 self.htheta.set_visible(True)
337 else:
338 self.htheta.set_visible(False)
339
340
341
342
343
344
345 m = self.model.calcMarker()
346
347 if self.model.magnetic:
348 lo = min( p[0].min(), p[1].min(), p[2].min(), m[0] )
349 hi = max( p[0].max(), p[1].max(), p[2].max(), m[1] )
350 fluff = 0.1*(hi-lo)
351 self.ylim = lo-fluff, hi+fluff
352 else:
353 lo = min( p[0].min(), p[1].min(), m[0] )
354 hi = max( p[0].max(), p[1].max(), m[1] )
355 fluff = 0.05*(hi-lo)
356 self.ylim = lo-fluff, hi+fluff
357
358 self.ax.set_ylim(lo-fluff, hi+fluff)
359
360
361 self.draw()
362
363
365 self.axes_frozen = True
366
367
369 self.axes_frozen = False
370
371
373 """Set the limits and tell the canvas to render itself."""
374
375
376
377 if not self.axes_frozen:
378 self.ax.set_xlim(self.model.offset[0 ],
379 self.model.offset[-1]
380 )
381 self.ax.set_ylim(*self.ylim)
382 if self.model.magnetic:
383 self.ax2.set_ylim(0,360)
384
385 self.ax.figure.canvas.draw_idle()
386
387
388
389
390
392 from reflectometry.model1d import Profile
393 import pylab
394
395 names = [ r"Si", r"Fe_2O_3", r"Fe", r"Thiol", r"D_2O" ]
396
397
398 d = [100, 120, 180]
399
400
401 rho = [2.07, 3, 8, -1, 5.76]
402 mu = [0, 0, 2, 0, 1]
403 P = [0, 0, 5, 0, 0]
404 theta = [0, 0, 270, 0, 0]
405 rough = [30,10,20,30]
406
407 model = Profile(depth=d,
408 rho=rho,
409 mu=mu,
410 phi=P,
411 theta=theta,
412 rough=rough,
413 names=names
414 )
415
416
417 listener = Listener()
418 profile = ReflectometryInteractor(pylab.subplot(111), model, listener)
419 fit = Fit([profile])
420 listener.connect("update",profile,fit.update)
421 pylab.show()
422 print "d2 = ",model.depth[2]
423
424 if __name__ == "__main__": demo()
425