1818 'tooltip' : 'Degree offset in two theta' ,
1919 'url' : '' ,
2020 'default' : (0 , 'deg' )
21+ },
22+ 'magnetic_field' : {
23+ 'header' : 'Field' ,
24+ 'tooltip' : 'Applied magnetic field' ,
25+ 'url' : '' ,
26+ 'default' : (0 , 'T' )
2127 }
2228}
2329
4854 }
4955}
5056
57+ POLARIZATION_DETAILS = {
58+ 'polarization' : {
59+ 'header' : '' ,
60+ 'tooltip' : '' ,
61+ 'url' : '' ,
62+ 'default' : (1 , '' )
63+ },
64+ 'efficiency' : {
65+ 'header' : '' ,
66+ 'tooltip' : '' ,
67+ 'url' : '' ,
68+ 'default' : (1 , '' )
69+ }
70+ }
71+
5172
5273class Resolution (LoggedPathDict ):
5374 """
5475 Data store for the resolution parameters
5576 """
77+
5678 def __init__ (self , u : Base , v : Base , w : Base , x : Base , y : Base ):
5779 """
5880 Dictionary store for resolution parameters
@@ -128,6 +150,7 @@ class Background(LoggedPathDict):
128150 """
129151 Data store for the background data parameters
130152 """
153+
131154 def __init__ (self , ttheta : float , intensity : Base ):
132155 """
133156 Background dictionary
@@ -173,6 +196,7 @@ class Backgrounds(ContainerObj):
173196 """
174197 Store for a collection of background points
175198 """
199+
176200 def __init__ (self , backgrounds : Union [Background , dict , list ]):
177201 """
178202 Constructor for Background data points
@@ -185,14 +209,24 @@ def __init__(self, backgrounds: Union[Background, dict, list]):
185209 def __repr__ (self ):
186210 return '{} Backgrounds' .format (len (self ))
187211
212+ def sort (self , reverse = False ):
213+ keys = list (self .keys ())
214+ keys .sort (key = float , reverse = reverse )
215+ new_bg = []
216+ for key in keys :
217+ new_bg .append (self [key ])
218+ super ().__init__ (new_bg , Background )
219+
188220
189221class MeasuredPattern (LoggedPathDict ):
190222 """
191223 Storage container for measured patterns
192224 """
193- def __init__ (self , x : list , y_obs : list , sy_obs : list , y_obs_up : Union [list , None ] = None ,
194- sy_obs_up : Union [list , None ] = None , y_obs_down : Union [list , None ] = None ,
195- sy_obs_down : Union [list , None ] = None ):
225+
226+ def __init__ (self , x : list , y_obs : list , sy_obs : list ,
227+ y_obs_diff : Union [list , None ] = None , sy_obs_diff : Union [list , None ] = None ,
228+ y_obs_up : Union [list , None ] = None , sy_obs_up : Union [list , None ] = None ,
229+ y_obs_down : Union [list , None ] = None , sy_obs_down : Union [list , None ] = None ):
196230 """
197231 Constructor for a measured pattern
198232
@@ -206,7 +240,8 @@ def __init__(self, x: list, y_obs: list, sy_obs: list, y_obs_up: Union[list, Non
206240 """
207241 # 1d polarised powder diffraction data
208242 # if y_obs_up is not None and sy_obs_up is not None and y_obs_down is not None and sy_obs_down is not None:
209- super ().__init__ (x = x , y_obs = y_obs , sy_obs = sy_obs , y_obs_up = y_obs_up , sy_obs_up = sy_obs_up ,
243+ super ().__init__ (x = x , y_obs = y_obs , sy_obs = sy_obs , y_obs_diff = y_obs_diff , sy_obs_diff = sy_obs_diff ,
244+ y_obs_up = y_obs_up , sy_obs_up = sy_obs_up ,
210245 y_obs_down = y_obs_down , sy_obs_down = sy_obs_down )
211246 self ._log = logging .getLogger (__class__ .__module__ )
212247 # # 1d unpolarised powder diffraction data
@@ -254,22 +289,27 @@ def default(cls, polarised: bool = False):
254289 x = []
255290 y_obs = []
256291 sy_obs = []
292+ y_obs_diff = None
293+ sy_obs_diff = None
257294 y_obs_up = None
258295 sy_obs_up = None
259296 y_obs_down = None
260297 sy_obs_down = None
261298 if polarised :
299+ y_obs_diff = []
300+ sy_obs_diff = []
262301 y_obs_up = []
263302 sy_obs_up = []
264303 y_obs_down = []
265304 sy_obs_down = []
266- return cls (x , y_obs , sy_obs , y_obs_up , sy_obs_up , y_obs_down , sy_obs_down )
305+ return cls (x , y_obs , sy_obs , y_obs_diff , sy_obs_diff , y_obs_up , sy_obs_up , y_obs_down , sy_obs_down )
267306
268307
269308class ExperimentPhase (LoggedPathDict ):
270309 """
271310 Storage container for the Experimental Phase details
272311 """
312+
273313 def __init__ (self , name : str , scale : Base ):
274314 """
275315 Constructor for the Experimental phase container
@@ -278,9 +318,11 @@ def __init__(self, name: str, scale: Base):
278318 """
279319 super ().__init__ (name = name , scale = scale )
280320 self ._log = logging .getLogger (__class__ .__module__ )
321+
281322 self .setItemByPath (['scale' , 'header' ], SCALE_DETAILS ['scale' ]['header' ])
282323 self .setItemByPath (['scale' , 'tooltip' ], SCALE_DETAILS ['scale' ]['tooltip' ])
283324 self .setItemByPath (['scale' , 'url' ], SCALE_DETAILS ['scale' ]['url' ])
325+
284326 self ._log .debug ('Created phase: {}' .format (self ))
285327
286328 @classmethod
@@ -311,6 +353,7 @@ class ExperimentPhases(ContainerObj):
311353 """
312354 Storage of multiple phase markers associated with experiments
313355 """
356+
314357 def __init__ (self , experiment_phases : Union [list , ExperimentPhase , dict ]):
315358 """
316359 Constructor for holding multiple experiments
@@ -324,11 +367,69 @@ def __repr__(self) -> str:
324367 return '{} Experimental phases' .format (len (self ))
325368
326369
370+ class RefinementType (LoggedPathDict ):
371+ _default = {'_sum' : False , '_diff' : False }
372+
373+ def __init__ (self ):
374+ super ().__init__ (** self ._default )
375+ self .object = None
376+
377+ def set_object (self , obj ):
378+ self .object = obj
379+
380+ @property
381+ def sum (self ):
382+ return self ['_sum' ]
383+
384+ @sum .setter
385+ def sum (self , value ):
386+ if self .object is not None :
387+ self .object .sum = value
388+ self ['_sum' ] = value
389+
390+ @property
391+ def diff (self ):
392+ return self ['_diff' ]
393+
394+ @diff .setter
395+ def diff (self , value ):
396+ if self .object is not None :
397+ self .object .diff = value
398+ self ['_diff' ] = value
399+
400+
401+ class Polarization (LoggedPathDict ):
402+ def __init__ (self , polarization : Base , efficiency : Base ):
403+ super ().__init__ (polarization = polarization , efficiency = efficiency )
404+
405+ self .setItemByPath (['polarization' , 'header' ], POLARIZATION_DETAILS ['polarization' ]['header' ])
406+ self .setItemByPath (['polarization' , 'tooltip' ], POLARIZATION_DETAILS ['polarization' ]['tooltip' ])
407+ self .setItemByPath (['polarization' , 'url' ], POLARIZATION_DETAILS ['polarization' ]['url' ])
408+
409+ self .setItemByPath (['efficiency' , 'header' ], POLARIZATION_DETAILS ['efficiency' ]['header' ])
410+ self .setItemByPath (['efficiency' , 'tooltip' ], POLARIZATION_DETAILS ['efficiency' ]['tooltip' ])
411+ self .setItemByPath (['efficiency' , 'url' ], POLARIZATION_DETAILS ['efficiency' ]['url' ])
412+
413+ @classmethod
414+ def default (cls ):
415+ polarization = Base (* POLARIZATION_DETAILS ['polarization' ]['default' ])
416+ efficiency = Base (* POLARIZATION_DETAILS ['efficiency' ]['default' ])
417+ return cls (polarization , efficiency )
418+
419+ @classmethod
420+ def fromPars (cls , polarization , efficiency ):
421+ polarization = Base (polarization , POLARIZATION_DETAILS ['polarization' ]['default' ][1 ])
422+ efficiency = Base (efficiency , POLARIZATION_DETAILS ['efficiency' ]['default' ][1 ])
423+ return cls (polarization , efficiency )
424+
425+
327426class Experiment (LoggedPathDict ):
328427 """
329428 Experimental details data container
330429 """
331- def __init__ (self , name : str , wavelength : Base , offset : Base , phase : ExperimentPhases , background : Backgrounds ,
430+
431+ def __init__ (self , name : str , wavelength : Base , offset : Base , magnetic_field : Base , phase : ExperimentPhases ,
432+ background : Backgrounds ,
332433 resolution : Resolution , measured_pattern : MeasuredPattern ):
333434 """
334435 Constructor for experimental data container
@@ -341,8 +442,14 @@ def __init__(self, name: str, wavelength: Base, offset: Base, phase: ExperimentP
341442 :param resolution: Description of the resolution
342443 :param measured_pattern: What was actually measured
343444 """
344- super ().__init__ (name = name , wavelength = wavelength , offset = offset , phase = phase , background = background ,
345- resolution = resolution , measured_pattern = measured_pattern )
445+
446+ refinement_type = RefinementType ()
447+ refinement_type .sum = True
448+
449+ super ().__init__ (name = name , wavelength = wavelength , offset = offset , magnetic_field = magnetic_field , phase = phase ,
450+ background = background ,
451+ resolution = resolution , measured_pattern = measured_pattern , refinement_type = refinement_type ,
452+ polarization = Polarization .default ())
346453 self ._log = logging .getLogger (__class__ .__module__ )
347454
348455 self .setItemByPath (['wavelength' , 'header' ], EXPERIMENT_DETAILS ['wavelength' ]['header' ])
@@ -353,6 +460,10 @@ def __init__(self, name: str, wavelength: Base, offset: Base, phase: ExperimentP
353460 self .setItemByPath (['offset' , 'tooltip' ], EXPERIMENT_DETAILS ['offset' ]['tooltip' ])
354461 self .setItemByPath (['offset' , 'url' ], EXPERIMENT_DETAILS ['offset' ]['url' ])
355462
463+ self .setItemByPath (['magnetic_field' , 'header' ], EXPERIMENT_DETAILS ['magnetic_field' ]['header' ])
464+ self .setItemByPath (['magnetic_field' , 'tooltip' ], EXPERIMENT_DETAILS ['magnetic_field' ]['tooltip' ])
465+ self .setItemByPath (['magnetic_field' , 'url' ], EXPERIMENT_DETAILS ['magnetic_field' ]['url' ])
466+
356467 @classmethod
357468 def default (cls , name : str ) -> 'Experiment' :
358469 """
@@ -363,15 +474,16 @@ def default(cls, name: str) -> 'Experiment':
363474 """
364475 wavelength = Base (* EXPERIMENT_DETAILS ['wavelength' ]['default' ])
365476 offset = Base (* EXPERIMENT_DETAILS ['offset' ]['default' ])
477+ field = Base (* EXPERIMENT_DETAILS ['magnetic_field' ]['default' ])
366478 phase = ExperimentPhases ({})
367479 backgrounds = Backgrounds (Background .default ())
368480 resolution = Resolution .default ()
369481 measured_pattern = MeasuredPattern .default ()
370- return cls (name , wavelength , offset , phase , backgrounds , resolution , measured_pattern )
482+ return cls (name , wavelength , offset , field , phase , backgrounds , resolution , measured_pattern )
371483
372484 @classmethod
373485 def fromPars (cls , name : str , wavelength : float , offset : float , scale : float , background : Backgrounds ,
374- resolution : Resolution , measured_pattern : MeasuredPattern ) -> 'Experiment' :
486+ resolution : Resolution , measured_pattern : MeasuredPattern , magnetic_field : float = None ) -> 'Experiment' :
375487 """
376488 Constructor of experiment from parameters
377489
@@ -386,8 +498,12 @@ def fromPars(cls, name: str, wavelength: float, offset: float, scale: float, bac
386498 """
387499 wavelength = Base (wavelength , EXPERIMENT_DETAILS ['wavelength' ]['default' ][1 ])
388500 offset = Base (offset , EXPERIMENT_DETAILS ['offset' ]['default' ][1 ])
501+ if magnetic_field is None :
502+ magnetic_field = Base (* EXPERIMENT_DETAILS ['magnetic_field' ]['default' ])
503+ else :
504+ magnetic_field = Base (magnetic_field , EXPERIMENT_DETAILS ['magnetic_field' ]['default' ][1 ])
389505 phase = ExperimentPhases (ExperimentPhase .fromPars (name , scale ))
390- return cls (name , wavelength , offset , phase , background , resolution , measured_pattern )
506+ return cls (name , wavelength , offset , magnetic_field , phase , background , resolution , measured_pattern )
391507
392508 def __repr__ (self ):
393509 return 'Experiment: {}' .format (self ['name' ])
@@ -397,6 +513,7 @@ class Experiments(ContainerObj):
397513 """
398514 Container for multiple experiments
399515 """
516+
400517 def __init__ (self , experiments : Union [Experiment , dict , list ]):
401518 """
402519 Constructor for holding multiple experiments
0 commit comments