Skip to content

Commit 79fd35e

Browse files
Pre release (#15)
* Prepare for v0.0.9 release (#14) * Add polarised experiment * Add chi2 options * Calculate profile up/down * RE-implement chi2 * Add Polarization efficiency/level * Fix fitable values * Fix hidden refinement * Remove auto-refine * Temporary fix of min/max for polarization and efficiency * Fix calculated pattern values * Add calculated background * Fix background for polarised neutrons * Fixup creation of phaess and exps * Typo fixes [ci skip] * Fix polarisation (until cryspy is fixed) * Fix refine polarisation * Fix error on scale * Don't print to the console * Create empty cryspy obj if rcif path is None * Fix experiments as cif * 1st implementation of editable CIF at the back end * Undo/redo is broken for manual editing * Sample editing is still not fully implemented * Fix issue with complex numbers for the scattering length * Change space group name source * Add exp from cif compatibility * Add phase from cif compatibility * Allow to run bulk update without macro * Add datablock label to calculations cif * Part of back-end implementation of Main.cif Edit * Remove global_ from CIFs on saving * Simplify writing CIF files * Save calculations.cif to project * Switch to master branch for cryspy * Add calculations.cif * Intermediate fixes * Re-write of DictComparison * Fix unit tests and dictTools * fix fit tests on windows/linux * More windows test fixes * Fix undo/redo for list types * More undo/redo work * Sort Backgrounds * Ugly hack to save name/keyword changes * Change keyword list to string * Sort background list of string keys numerically * Move filenames to master obj * Internal main_rcif to project_rcif * Move from phases to samples * Variable name changes * Rename phases to sample Co-authored-by: Andrew Sazonov <[email protected]> * Update Release.json Co-authored-by: Andrew Sazonov <[email protected]>
1 parent d824b2f commit 79fd35e

File tree

19 files changed

+897
-431
lines changed

19 files changed

+897
-431
lines changed

Scripts/InstallPyPackages.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ def install(*packages):
5555

5656
upgradePip()
5757

58-
installFromGit(owner='ikibalin', repo='cryspy', branch='transition-to-version-0.2', egg='cryspy_0.2.0_beta')
58+
#installFromGit(owner='ikibalin', repo='cryspy', branch='transition-to-version-0.2', egg='cryspy_0.2.0_beta')
5959
install(
60+
'cryspy',
6061
'dictdiffer',
6162
'asteval',
6263
'pytest',

easyInterface/Diffraction/Calculators/CryspyCalculator.py

+472-246
Large diffs are not rendered by default.

easyInterface/Diffraction/DataClasses/DataObj/Calculation.py

+14-7
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,15 @@ class CalculatedPattern(LoggedPathDict):
7373
"""
7474
Storage container for a calculated pattern
7575
"""
76-
def __init__(self, x: list, y_calc: list, y_diff_lower: list, y_diff_upper: list):
77-
super().__init__(x=x, y_calc=y_calc, y_diff_lower=y_diff_lower, y_diff_upper=y_diff_upper)
76+
def __init__(self, x: list, y_diff_lower: list, y_diff_upper: list, y_calc_up: list, y_calc_down: list = [], y_calc_bkg: list = []):
77+
y_calc_down_temp = y_calc_down
78+
if len(y_calc_down) == 0:
79+
y_calc_down_temp = [0]*len(y_calc_up)
80+
81+
super().__init__(x=x, y_calc_sum=np.array(y_calc_up) + np.array(y_calc_down_temp), y_calc_diff=np.array(y_calc_up) - np.array(y_calc_down_temp),
82+
y_calc_up=y_calc_up, y_calc_down=y_calc_down,
83+
y_diff_lower=y_diff_lower, y_diff_upper=y_diff_upper,
84+
y_calc_bkg=y_calc_bkg)
7885
self._log = logging.getLogger(__class__.__module__)
7986

8087
def __repr__(self):
@@ -92,17 +99,17 @@ def __init__(self, name: str, bragg_peaks: BraggPeaks, calculated_pattern: Calcu
9299
@classmethod
93100
def default(cls, name: str):
94101
bragg_peaks = BraggPeaks({})
95-
calculated_pattern = CalculatedPattern([0], [0], [0], [0])
102+
calculated_pattern = CalculatedPattern([0], [0], [0], [0],[0])
96103
limits = Limits()
97104
return cls(name, bragg_peaks, calculated_pattern, limits)
98105

99106
@classmethod
100107
def fromPars(cls, name: str, bragg_crystals: CrystalBraggPeaks,
101-
y_obs_lower: list, y_obs_upper: list,
102-
tth: list, y_calc: list, y_diff_lower: list, y_diff_upper: list):
108+
y_calc_lower: list, y_calc_upper: list,
109+
tth: list, y_calc: list, y_diff_lower: list, y_diff_upper: list, y_calc_bkg: list):
103110
bragg_peaks = BraggPeaks(bragg_crystals)
104-
calculated_pattern = CalculatedPattern(tth, y_calc, y_diff_lower, y_diff_upper)
105-
limits = Limits(y_obs_lower, y_obs_upper, y_diff_upper, y_diff_lower, x_calc=tth, y_calc=y_calc)
111+
calculated_pattern = CalculatedPattern(tth, y_calc, y_diff_lower, y_diff_upper, y_calc_bkg)
112+
limits = Limits(y_calc_lower, y_calc_upper, y_diff_upper, y_diff_lower, x_calc=tth, y_calc=y_calc)
106113
return cls(name, bragg_peaks, calculated_pattern, limits)
107114

108115
def __repr__(self):

easyInterface/Diffraction/DataClasses/DataObj/Experiment.py

+128-11
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
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

@@ -48,11 +54,27 @@
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

5273
class 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

189221
class 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

269308
class 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+
327426
class 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

easyInterface/Diffraction/DataClasses/PhaseObj/Atom.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ def fromXYZ(cls, atom_site_label: str, type_symbol: str, x: float, y: float, z:
169169
return obj
170170

171171
@classmethod
172-
def fromPars(cls, atom_site_label: str, type_symbol: str, scat_length_neutron: float,
172+
def fromPars(cls, atom_site_label: str, type_symbol: str, scat_length_neutron: complex,
173173
fract_x: float, fract_y: float, fract_z: float, occupancy: float, adp_type: str,
174174
U_iso_or_equiv: float, ADp: list = None, MSp: list = None) -> 'Atom':
175175
"""

0 commit comments

Comments
 (0)