From 2fc48b141d768a404f2ddc7fdc7ca3b9dee2b3b2 Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Tue, 14 Jan 2025 12:18:32 +0100 Subject: [PATCH 01/33] initial conversion to the new parameter syntax Remaining issue with unit conversion (deg -> us) Remaining Descriptor conversion --- examples_old/PDF/Fitting_PDF_Profile_Ni.ipynb | 2 +- examples_old/PDF/Fitting_PDF_Profile_Si.ipynb | 80 +++++++++---------- examples_old/PDF2/Fitting_PDF_Profile.ipynb | 2 +- examples_old/PDF2/Ni_fitting.py | 2 +- .../calculators/cryspy/calculator.py | 8 +- .../calculators/cryspy/parser.py | 8 +- .../calculators/cryspy/wrapper.py | 12 +-- .../calculators/pdffit2/calculator.py | 16 ++-- .../calculators/pdffit2/wrapper.py | 4 +- .../calculators/pycrysfml/calculator.py | 4 +- .../calculators/pycrysfml/wrapper.py | 4 +- src/easydiffraction/io/cif.py | 36 ++++----- .../job/experiment/backgrounds/background.py | 4 +- .../job/experiment/backgrounds/factorial.py | 12 +-- .../job/experiment/backgrounds/point.py | 16 ++-- .../job/experiment/experiment.py | 62 +++++++------- src/easydiffraction/job/experiment/pd_1d.py | 30 +++---- .../job/experiment/polarization.py | 2 +- src/easydiffraction/job/job.py | 24 +++--- src/easydiffraction/job/model/site.py | 4 +- .../job/old_sample/old_sample.py | 6 +- tests_old/integration_tests/FittingData.ipynb | 3 +- 22 files changed, 170 insertions(+), 171 deletions(-) diff --git a/examples_old/PDF/Fitting_PDF_Profile_Ni.ipynb b/examples_old/PDF/Fitting_PDF_Profile_Ni.ipynb index d896745f..5b4e3f6f 100644 --- a/examples_old/PDF/Fitting_PDF_Profile_Ni.ipynb +++ b/examples_old/PDF/Fitting_PDF_Profile_Ni.ipynb @@ -301,7 +301,7 @@ "print(f\"The goodness of fit (chi2) is: {result.reduced_chi}\")\n", "print(\"The optimized parameters are:\")\n", "for param in job.get_fit_parameters():\n", - " print(f\"{param.name}: {param.raw_value} +\\- {param.error} {param.unit}\") " + " print(f\"{param.name}: {param.value} +\\- {param.variance} {param.unit}\") " ] }, { diff --git a/examples_old/PDF/Fitting_PDF_Profile_Si.ipynb b/examples_old/PDF/Fitting_PDF_Profile_Si.ipynb index d7a004c1..ef49ba00 100644 --- a/examples_old/PDF/Fitting_PDF_Profile_Si.ipynb +++ b/examples_old/PDF/Fitting_PDF_Profile_Si.ipynb @@ -481,12 +481,12 @@ "outputs": [], "source": [ "# Add initial data used in EasyDiffraction to pandas DataFrame\n", - "df_case1['ezd_ini'] = [phases_Si1[0].scale.raw_value, \n", - " parameters1.delta2.raw_value, \n", - " phase1_patterns1.cell.length_a.raw_value, \n", - " phase1_patterns1.atoms[0].adp.Uiso.raw_value, \n", - " parameters1.qdamp.raw_value, \n", - " parameters1.qbroad.raw_value]" + "df_case1['ezd_ini'] = [phases_Si1[0].scale.value, \n", + " parameters1.delta2.value, \n", + " phase1_patterns1.cell.length_a.value, \n", + " phase1_patterns1.atoms[0].adp.Uiso.value, \n", + " parameters1.qdamp.value, \n", + " parameters1.qbroad.value]" ] }, { @@ -584,7 +584,7 @@ "df_case1['ezd_fit'] = pd.Series(dtype='float64')\n", "\n", "for i in range(len(job_Si1.get_fit_parameters())):\n", - " df_case1['ezd_fit'][job_Si1.get_fit_parameters()[i].name] = job_Si1.get_fit_parameters()[i].raw_value\n", + " df_case1['ezd_fit'][job_Si1.get_fit_parameters()[i].name] = job_Si1.get_fit_parameters()[i].value\n", "df_case1" ] }, @@ -611,7 +611,7 @@ "print(\"The optimized parameters are:\")\n", "\n", "for param in job_Si1.get_fit_parameters():\n", - " print(f\"{param.name}: {param.raw_value} +\\- {param.error} {param.unit}\") " + " print(f\"{param.name}: {param.value} +\\- {param.variance} {param.unit}\") " ] }, { @@ -807,10 +807,10 @@ "outputs": [], "source": [ "# Add initial data used in EasyDiffraction to pandas DataFrame\n", - "df_case2['ezd_ini'] = [phases_Si2[0].scale.raw_value, \n", - " parameters2.delta2.raw_value, \n", - " phase1_patterns2.cell.length_a.raw_value, \n", - " phase1_patterns2.atoms[0].adp.Uiso.raw_value]" + "df_case2['ezd_ini'] = [phases_Si2[0].scale.value, \n", + " parameters2.delta2.value, \n", + " phase1_patterns2.cell.length_a.value, \n", + " phase1_patterns2.atoms[0].adp.Uiso.value]" ] }, { @@ -873,10 +873,10 @@ "metadata": {}, "outputs": [], "source": [ - "df_case2['ezd_ini'] = [phases_Si2[0].scale.raw_value, \n", - " parameters2.delta2.raw_value, \n", - " phase1_patterns2.cell.length_a.raw_value, \n", - " phase1_patterns2.atoms[0].adp.Uiso.raw_value\n", + "df_case2['ezd_ini'] = [phases_Si2[0].scale.value, \n", + " parameters2.delta2.value, \n", + " phase1_patterns2.cell.length_a.value, \n", + " phase1_patterns2.atoms[0].adp.Uiso.value\n", " ]\n", "df_case2" ] @@ -918,7 +918,7 @@ "df_case2['ezd_fit'] = pd.Series(dtype='float64')\n", "\n", "for i in range(len(job_Si2.get_fit_parameters())):\n", - " df_case2['ezd_fit'][job_Si2.get_fit_parameters()[i].name] = job_Si2.get_fit_parameters()[i].raw_value\n", + " df_case2['ezd_fit'][job_Si2.get_fit_parameters()[i].name] = job_Si2.get_fit_parameters()[i].value\n", "df_case2" ] }, @@ -944,7 +944,7 @@ "print(f\"The goodness of fit (chi2) is: {result_Si2.reduced_chi}\")\n", "print(\"The optimized parameters are:\")\n", "for param in job_Si2.get_fit_parameters():\n", - " print(f\"{param.name}: {param.raw_value} +\\- {param.error} {param.unit}\") " + " print(f\"{param.name}: {param.value} +\\- {param.variance} {param.unit}\") " ] }, { @@ -1139,12 +1139,12 @@ "outputs": [], "source": [ "# Add initial data used in EasyDiffraction to pandas DataFrame\n", - "df_case3['ezd_ini'] = [phases_Si3[0].scale.raw_value, \n", - " parameters3.delta2.raw_value, \n", - " phase1_patterns3.cell.length_a.raw_value, \n", - " phase1_patterns3.atoms[0].adp.Uiso.raw_value, \n", - " parameters3.qdamp.raw_value, \n", - " parameters3.qbroad.raw_value]" + "df_case3['ezd_ini'] = [phases_Si3[0].scale.value, \n", + " parameters3.delta2.value, \n", + " phase1_patterns3.cell.length_a.value, \n", + " phase1_patterns3.atoms[0].adp.Uiso.value, \n", + " parameters3.qdamp.value, \n", + " parameters3.qbroad.value]" ] }, { @@ -1236,7 +1236,7 @@ "df_case3['ezd_fit'] = pd.Series(dtype='float64')\n", "\n", "for i in range(len(job_Si3.get_fit_parameters())):\n", - " df_case3['ezd_fit'][job_Si3.get_fit_parameters()[i].name] = job_Si3.get_fit_parameters()[i].raw_value\n", + " df_case3['ezd_fit'][job_Si3.get_fit_parameters()[i].name] = job_Si3.get_fit_parameters()[i].value\n", "df_case3" ] }, @@ -1261,7 +1261,7 @@ "print(\"The optimized parameters are:\")\n", "\n", "for param in job_Si3.get_fit_parameters():\n", - " print(f\"{param.name}: {param.raw_value} +\\- {param.error} {param.unit}\") " + " print(f\"{param.name}: {param.value} +\\- {param.variance} {param.unit}\") " ] }, { @@ -1441,12 +1441,12 @@ "outputs": [], "source": [ "# Add initial data used in EasyDiffraction to pandas DataFrame\n", - "df_case4['ezd_ini'] = [phases_Si4[0].scale.raw_value, \n", - " parameters4.delta2.raw_value, \n", - " phase1_patterns4.cell.length_a.raw_value, \n", - " phase1_patterns4.atoms[0].adp.Uiso.raw_value, \n", - " parameters4.qdamp.raw_value, \n", - " parameters4.qbroad.raw_value]" + "df_case4['ezd_ini'] = [phases_Si4[0].scale.value, \n", + " parameters4.delta2.value, \n", + " phase1_patterns4.cell.length_a.value, \n", + " phase1_patterns4.atoms[0].adp.Uiso.value, \n", + " parameters4.qdamp.value, \n", + " parameters4.qbroad.value]" ] }, { @@ -1541,7 +1541,7 @@ "df_case4['ezd_fit'] = pd.Series(dtype='float64')\n", "\n", "for i in range(len(job_Si4.get_fit_parameters())):\n", - " df_case4['ezd_fit'][job_Si4.get_fit_parameters()[i].name] = job_Si4.get_fit_parameters()[i].raw_value\n", + " df_case4['ezd_fit'][job_Si4.get_fit_parameters()[i].name] = job_Si4.get_fit_parameters()[i].value\n", "df_case4" ] }, @@ -1566,7 +1566,7 @@ "print(\"The optimized parameters are:\")\n", "\n", "for param in job_Si4.get_fit_parameters():\n", - " print(f\"{param.name}: {param.raw_value} +\\- {param.error} {param.unit}\") " + " print(f\"{param.name}: {param.value} +\\- {param.variance} {param.unit}\") " ] }, { @@ -1735,10 +1735,10 @@ "outputs": [], "source": [ "# Add initial data used in EasyDiffraction to pandas DataFrame\n", - "df_case5['ezd_ini'] = [phases_Si5[0].scale.raw_value, \n", - " parameters5.delta2.raw_value, \n", - " phase1_patterns5.cell.length_a.raw_value, \n", - " phase1_patterns5.atoms[0].adp.Uiso.raw_value]" + "df_case5['ezd_ini'] = [phases_Si5[0].scale.value, \n", + " parameters5.delta2.value, \n", + " phase1_patterns5.cell.length_a.value, \n", + " phase1_patterns5.atoms[0].adp.Uiso.value]" ] }, { @@ -1828,7 +1828,7 @@ "df_case5['ezd_fit'] = pd.Series(dtype='float64')\n", "\n", "for i in range(len(job_Si5.get_fit_parameters())):\n", - " df_case5['ezd_fit'][job_Si5.get_fit_parameters()[i].name] = job_Si5.get_fit_parameters()[i].raw_value\n", + " df_case5['ezd_fit'][job_Si5.get_fit_parameters()[i].name] = job_Si5.get_fit_parameters()[i].value\n", "df_case5" ] }, @@ -1853,7 +1853,7 @@ "print(\"The optimized parameters are:\")\n", "\n", "for param in job_Si5.get_fit_parameters():\n", - " print(f\"{param.name}: {param.raw_value} +\\- {param.error} {param.unit}\") " + " print(f\"{param.name}: {param.value} +\\- {param.variance} {param.unit}\") " ] }, { diff --git a/examples_old/PDF2/Fitting_PDF_Profile.ipynb b/examples_old/PDF2/Fitting_PDF_Profile.ipynb index 1a308b29..d7f377d9 100644 --- a/examples_old/PDF2/Fitting_PDF_Profile.ipynb +++ b/examples_old/PDF2/Fitting_PDF_Profile.ipynb @@ -301,7 +301,7 @@ "print(f\"The goodness of fit (chi2) is: {result.reduced_chi}\")\n", "print(\"The optimized parameters are:\")\n", "for param in job.get_fit_parameters():\n", - " print(f\"{param.name}: {param.raw_value} +\\- {param.error} {param.unit}\") " + " print(f\"{param.name}: {param.value} +\\- {param.variance} {param.unit}\") " ] }, { diff --git a/examples_old/PDF2/Ni_fitting.py b/examples_old/PDF2/Ni_fitting.py index 8db66520..648a5dfe 100644 --- a/examples_old/PDF2/Ni_fitting.py +++ b/examples_old/PDF2/Ni_fitting.py @@ -66,7 +66,7 @@ print("The optimized parameters are:") for param in fit_parameters: - print("{}: {}".format(param.name, param.raw_value)) + print("{}: {}".format(param.name, param.value)) y_data = calculator.fit_func(x_data) diff --git a/src/easydiffraction/calculators/cryspy/calculator.py b/src/easydiffraction/calculators/cryspy/calculator.py index 5377c1ea..55fb46b2 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -446,8 +446,8 @@ def powder_1d_calculate(self, x_array: np.ndarray, full_return: bool = False, ** scale = 1.0 offset = 0 else: - scale = self.pattern.scale.raw_value / norm - offset = self.pattern.zero_shift.raw_value + scale = self.pattern.scale.value / norm + offset = self.pattern.zero_shift.value this_x_array = x_array - offset @@ -489,8 +489,8 @@ def powder_1d_tof_calculate(self, x_array: np.ndarray, pol_fn=None, full_return: scale = 1.0 offset = 0 else: - scale = self.pattern.scale.raw_value / normalization - offset = self.pattern.zero_shift.raw_value + scale = self.pattern.scale.value / normalization + offset = self.pattern.zero_shift.value self.model['tof_parameters'].zero = offset this_x_array = x_array - offset diff --git a/src/easydiffraction/calculators/cryspy/parser.py b/src/easydiffraction/calculators/cryspy/parser.py index 54ed7a2e..d24b3d53 100644 --- a/src/easydiffraction/calculators/cryspy/parser.py +++ b/src/easydiffraction/calculators/cryspy/parser.py @@ -21,7 +21,7 @@ def __init__( max=np.inf, absDelta=None, pctDelta=None, - units='', + unit='', category='', prettyCategory='', rowName='', @@ -62,7 +62,7 @@ def __init__( self['cifDict'] = cifDict self['parentIndex'] = 0 self['parentName'] = '' - self['units'] = units + self['unit'] = unit def calcObjAndDictToEdExperiments(calc_obj, calc_dict): @@ -180,7 +180,7 @@ def calcObjAndDictToEdExperiments(calc_obj, calc_dict): url='https://docs.easydiffraction.org/lib/dictionaries/_diffrn_radiation/', cifDict='core', absDelta=0.01, - units='Å', + unit='Å', fittable=True, fit=item.wavelength_refinement, ) @@ -200,7 +200,7 @@ def calcObjAndDictToEdExperiments(calc_obj, calc_dict): url='https://docs.easydiffraction.org/lib/dictionaries/_pd_calib/', cifDict='pd', absDelta=0.2, - units='°', + unit='°', fittable=True, fit=item.offset_ttheta_refinement, ) diff --git a/src/easydiffraction/calculators/cryspy/wrapper.py b/src/easydiffraction/calculators/cryspy/wrapper.py index 88e38677..d508ae41 100644 --- a/src/easydiffraction/calculators/cryspy/wrapper.py +++ b/src/easydiffraction/calculators/cryspy/wrapper.py @@ -126,7 +126,7 @@ def create(self, model: B) -> List[ItemContainer]: ) # Interface with Spacegroup elif issubclass(t_, SpaceGroup): - name = model.name_hm_alt.raw_value + name = model.name_hm_alt.value s_key = self.calculator.createSpaceGroup(key=model_key, name_hm_alt=name) keys = {'hermann_mauguin': 'name_hm_alt', 'coordinate-code': 'it_code'} r_list.append( @@ -152,7 +152,7 @@ def create(self, model: B) -> List[ItemContainer]: # Now do anisotropic ADP elif issubclass(t_, Anisotropic_base): pars = model.get_parameters() - adp_pars = {par.name: par.raw_value for par in pars} + adp_pars = {par.name: par.value for par in pars} ref_name = self.calculator.attachADP(model_key, adp_pars) r_list.append( ItemContainer( @@ -169,7 +169,7 @@ def create(self, model: B) -> List[ItemContainer]: _ = self.calculator.createEmptyCrystal(model.name, key=model_key) self.calculator.assignCell_toCrystal(self._identify(model.cell), model_key) self.calculator.assignSpaceGroup_toCrystal(self._identify(model._spacegroup), model_key) - self.calculator.setPhaseScale(str(model_key), scale=model.scale.raw_value) + self.calculator.setPhaseScale(str(model_key), scale=model.scale.value) r_list.append( ItemContainer( model_key, @@ -208,7 +208,7 @@ def add_phase(self, phases_obj: Phases, phase_obj: Phase) -> None: """ ident = self._identify(phase_obj, as_str=True) + '_phase' self.calculator.assignPhase(self._identify(phases_obj), ident) - self.calculator.setPhaseScale(self._identify(phase_obj), scale=phase_obj.scale.raw_value) + self.calculator.setPhaseScale(self._identify(phase_obj), scale=phase_obj.scale.value) def remove_phase(self, phases_obj: Phases, phase_obj: Phase) -> None: """ @@ -450,9 +450,9 @@ def create(self, model: B) -> List[ItemContainer]: elif issubclass(t_, Site) or issubclass(t_, Site_base): if not hasattr(model, 'msp'): return r_list - msp_type = model.msp.msp_type.raw_value + msp_type = model.msp.msp_type.value pars = model.msp.get_parameters() - msp_pars = {par.name: par.raw_value for par in pars} + msp_pars = {par.name: par.value for par in pars} ref_name = self.calculator.attachMSP(model_key, msp_type, msp_pars) r_list.append( ItemContainer( diff --git a/src/easydiffraction/calculators/pdffit2/calculator.py b/src/easydiffraction/calculators/pdffit2/calculator.py index 30fd8ba2..baa41c67 100644 --- a/src/easydiffraction/calculators/pdffit2/calculator.py +++ b/src/easydiffraction/calculators/pdffit2/calculator.py @@ -52,17 +52,17 @@ def calculate(self, x_array: np.ndarray) -> np.ndarray: P.add_structure(structure) # extract conditions from the model - qmax = self.model.qmax.raw_value - qdamp = self.model.qdamp.raw_value - delta1 = self.model.delta1.raw_value - delta2 = self.model.delta2.raw_value - qbroad = self.model.qbroad.raw_value - spdiameter = self.model.spdiameter.raw_value + qmax = self.model.qmax.value + qdamp = self.model.qdamp.value + delta1 = self.model.delta1.value + delta2 = self.model.delta2.value + qbroad = self.model.qbroad.value + spdiameter = self.model.spdiameter.value stype = self.type # scale - scale = self.phases[0].scale.raw_value + scale = self.phases[0].scale.value P.setvar('pscale', scale) P.setvar('delta1', delta1) P.setvar('delta2', delta2) @@ -72,7 +72,7 @@ def calculate(self, x_array: np.ndarray) -> np.ndarray: for i_atom, atom in enumerate(self.phases[0].atoms): if not hasattr(atom, 'adp'): continue - Uiso = atom.adp.Uiso.raw_value + Uiso = atom.adp.Uiso.value for i in range(1, 4): u_str = 'u{}{}({})'.format(i, i, i_atom + 1) P.setvar(u_str, Uiso) diff --git a/src/easydiffraction/calculators/pdffit2/wrapper.py b/src/easydiffraction/calculators/pdffit2/wrapper.py index c82a8662..e376f205 100644 --- a/src/easydiffraction/calculators/pdffit2/wrapper.py +++ b/src/easydiffraction/calculators/pdffit2/wrapper.py @@ -178,8 +178,8 @@ def remove_atom(self, crystal_obj, atom): def get_value(self, key, item_key): item = borg.map.get_item_by_key(key) if item_key in ['Uiso', 'Uani', 'Biso', 'Bani']: - return getattr(getattr(item, 'adp'), item_key).raw_value - return getattr(item, item_key).raw_value + return getattr(getattr(item, 'adp'), item_key).value + return getattr(item, item_key).value def updateCif(self, *args, **kwargs): if self._phase is not None: diff --git a/src/easydiffraction/calculators/pycrysfml/calculator.py b/src/easydiffraction/calculators/pycrysfml/calculator.py index 558c5aa0..66e719f4 100644 --- a/src/easydiffraction/calculators/pycrysfml/calculator.py +++ b/src/easydiffraction/calculators/pycrysfml/calculator.py @@ -54,8 +54,8 @@ def calculate(self, x_array: np.ndarray) -> np.ndarray: scale = 1.0 offset = 0 else: - scale = self.pattern.scale.raw_value - offset = self.pattern.zero_shift.raw_value + scale = self.pattern.scale.value + offset = self.pattern.zero_shift.value this_x_array = x_array + offset diff --git a/src/easydiffraction/calculators/pycrysfml/wrapper.py b/src/easydiffraction/calculators/pycrysfml/wrapper.py index f5ae7fd5..9413d21f 100644 --- a/src/easydiffraction/calculators/pycrysfml/wrapper.py +++ b/src/easydiffraction/calculators/pycrysfml/wrapper.py @@ -204,8 +204,8 @@ def __createModel(self, model): def get_value(self, key, item_key): item = borg.map.get_item_by_key(key) if item_key in ['Uiso', 'Uani', 'Biso', 'Bani']: - return getattr(getattr(item, 'adp'), item_key).raw_value - return getattr(item, item_key).raw_value + return getattr(getattr(item, 'adp'), item_key).value + return getattr(item, item_key).value def get_phase_components(self, phase_name): return None diff --git a/src/easydiffraction/io/cif.py b/src/easydiffraction/io/cif.py index 9c83cb2b..e8d2a780 100644 --- a/src/easydiffraction/io/cif.py +++ b/src/easydiffraction/io/cif.py @@ -242,9 +242,9 @@ def _sanitize_loop(self, data: StarLoop) -> StarLoop: # check for implicit hydrogens, warn if any present if 'atom_site_attached_hydrogens' in data.labels: attached_hydrogens = [ - x._kwargs['atom_site_attached_hydrogens'].raw_value + x._kwargs['atom_site_attached_hydrogens'].value for x in data.data - if x._kwargs['atom_site_attached_hydrogens'].raw_value != 0 + if x._kwargs['atom_site_attached_hydrogens'].value != 0 ] if len(attached_hydrogens) > 0: self.warnings.append( @@ -275,12 +275,12 @@ def _sanitize_loop(self, data: StarLoop) -> StarLoop: # Below, we split the strings on ' + ' to # check if the length (or number of elements) in the label and # symbol are equal. - if len(this_data._kwargs['atom_site_type_symbol'].raw_value.split(' + ')) > len( - this_data._kwargs['atom_site_label'].raw_value.split(' + ') + if len(this_data._kwargs['atom_site_type_symbol'].value.split(' + ')) > len( + this_data._kwargs['atom_site_label'].value.split(' + ') ): # parse symbol to get element names and occupancy and store # in "els_occu" - symbol_str = this_data._kwargs['atom_site_type_symbol'].raw_value + symbol_str = this_data._kwargs['atom_site_type_symbol'].value symbol_str_lst = symbol_str.split(' + ') for elocc_idx, sym in enumerate(symbol_str_lst): # Remove any bracketed items in the string @@ -290,14 +290,14 @@ def _sanitize_loop(self, data: StarLoop) -> StarLoop: # string, and store it as a # key-value pair in "els_occ". new_item: FakeCore = deepcopy(this_data) - new_item._kwargs['atom_site_type_symbol'].raw_value = str( + new_item._kwargs['atom_site_type_symbol'].value = str( re.findall(r'\D+', symbol_str_lst[elocc_idx].strip())[1] ).replace('', '') - new_item._kwargs['atom_site_label'].raw_value = ( - new_item._kwargs['atom_site_type_symbol'].raw_value + '_fix' + new_item._kwargs['atom_site_label'].value = ( + new_item._kwargs['atom_site_type_symbol'].value + '_fix' ) if 'atom_site_occupancy' in new_item._kwargs.keys(): - new_item._kwargs['atom_site_label'].raw_value = float( + new_item._kwargs['atom_site_label'].value = float( '0' + re.findall(r'\.?\d+', symbol_str_lst[elocc_idx].strip())[1] ) new_atoms.append(new_item) @@ -341,10 +341,10 @@ def _sanitize_loop(self, data: StarLoop) -> StarLoop: 'atom_site_fract_z', ): if label in this_data._kwargs.keys(): - frac = this_data._kwargs[label].raw_value + frac = this_data._kwargs[label].value for comparison_frac in important_fracs: if abs(1 - frac / comparison_frac) < 1e-4: - this_data._kwargs[label].raw_value = comparison_frac + this_data._kwargs[label].value = comparison_frac fracs_changed = True if fracs_changed: self.warnings.append( @@ -540,11 +540,11 @@ def get_atoms(self, cif_index: int = 0, atoms_class=None): if set(loop.labels).issuperset(set(needed_labels)): data_dict = {} for idx2, key in enumerate(needed_labels[1:]): - temp_value = section.data[0]._kwargs[key].raw_value + temp_value = section.data[0]._kwargs[key].value if not isinstance(temp_value, Number): temp_value = 0 self.append = self.warnings.append( - f'Atom {section.data[0]._kwargs[needed_labels[0]].raw_value} has non-numeric ' + f'Atom {section.data[0]._kwargs[needed_labels[0]].value} has non-numeric ' f'{key}. Setting to 0' ) data_dict[adp_types[adp_type][idx2]] = temp_value @@ -569,7 +569,7 @@ def get_atoms(self, cif_index: int = 0, atoms_class=None): ): obj.error = section.data[0]._kwargs[needed_labels[1 + idx2]].error - current_atom_label = section.data[0]._kwargs[needed_labels[0]].raw_value + current_atom_label = section.data[0]._kwargs[needed_labels[0]].value # Add to an atom if current_atom_label in atoms.atom_labels: idx2 = atoms.atom_labels.index(current_atom_label) @@ -601,7 +601,7 @@ def get_atoms(self, cif_index: int = 0, atoms_class=None): for idx, section in enumerate(these_sections): if set(loop.labels).issuperset(set(needed_labels)): data_dict = {} - msp_type_ext = section.data[0]._kwargs['atom_site_susceptibility_chi_type'].raw_value + msp_type_ext = section.data[0]._kwargs['atom_site_susceptibility_chi_type'].value msp_type = 'Ciso' if 'ani' in msp_type_ext.lower(): msp_type = 'Cani' @@ -615,11 +615,11 @@ def get_atoms(self, cif_index: int = 0, atoms_class=None): 'atom_site_susceptibility_chi_23', ] for idx2, key in enumerate(needed_labels[1:]): - temp_value = section.data[0]._kwargs[key].raw_value + temp_value = section.data[0]._kwargs[key].value if not isinstance(temp_value, Number): temp_value = 0 self.append = self.warnings.append( - f'Atom {section.data[0]._kwargs[needed_labels[0]].raw_value} has non-numeric ' + f'Atom {section.data[0]._kwargs[needed_labels[0]].value} has non-numeric ' f'{key}. Setting to 0' ) data_dict[msp_types[msp_type][idx2]] = temp_value @@ -644,7 +644,7 @@ def get_atoms(self, cif_index: int = 0, atoms_class=None): ): obj.error = section.data[0]._kwargs[needed_labels[1 + idx2]].error - current_atom_label = section.data[0]._kwargs[needed_labels[0]].raw_value + current_atom_label = section.data[0]._kwargs[needed_labels[0]].value # Add to an atom if current_atom_label in atoms.atom_labels: idx2 = atoms.atom_labels.index(current_atom_label) diff --git a/src/easydiffraction/job/experiment/backgrounds/background.py b/src/easydiffraction/job/experiment/backgrounds/background.py index 7175a209..4ea7163a 100644 --- a/src/easydiffraction/job/experiment/backgrounds/background.py +++ b/src/easydiffraction/job/experiment/backgrounds/background.py @@ -81,7 +81,7 @@ def calculate(self, x_array: np.ndarray) -> np.ndarray: def _modify_dict(self, skip: list = None) -> dict: d = {} - d['linked_experiment'] = self._linked_experiment.raw_value + d['linked_experiment'] = self._linked_experiment.value return d @@ -111,7 +111,7 @@ def linked_experiments(self) -> List[str]: :return: :rtype: """ - return [item.linked_experiment.raw_value for item in self] + return [item.linked_experiment.value for item in self] def __repr__(self) -> str: """ diff --git a/src/easydiffraction/job/experiment/backgrounds/factorial.py b/src/easydiffraction/job/experiment/backgrounds/factorial.py index 2cd7e0cf..1d605bb6 100644 --- a/src/easydiffraction/job/experiment/backgrounds/factorial.py +++ b/src/easydiffraction/job/experiment/backgrounds/factorial.py @@ -28,7 +28,7 @@ def __init__(self, power: Descriptor, amp: Parameter): :param amp: Amplitude for which x will be multiplied by :type amp: Parameter """ - name = f'Amplitude_{power.raw_value}' + name = f'Amplitude_{power.value}' super(BackgroundFactor, self).__init__(name, power=power, amp=amp) @classmethod @@ -181,8 +181,8 @@ def append(self, item: BackgroundFactor): """ if not isinstance(item, BackgroundFactor): raise TypeError('Item must be a BackgroundFactor') - if item.power.raw_value in self.sorted_powers: - raise AttributeError(f'A BackgroundFactor with power {item.power.raw_value} already exists.') + if item.power.value in self.sorted_powers: + raise AttributeError(f'A BackgroundFactor with power {item.power.value} already exists.') super(FactorialBackground, self).append(item) self.__index_contents() @@ -191,14 +191,14 @@ def get_parameters(self) -> List[Parameter]: Redefine get_parameters so that the returned values are in the correct order """ list_pars = np.array(super(FactorialBackground, self).get_parameters()) - idx = np.array([item.power.raw_value for item in self]).argsort() + idx = np.array([item.power.value for item in self]).argsort() return list_pars[idx].tolist() def __index_contents(self): """ Index the contents """ - x = np.array([item.power.raw_value for item in self]) + x = np.array([item.power.value for item in self]) idx = x.argsort() - y = np.array([item.amp.raw_value for item in self]) + y = np.array([item.amp.value for item in self]) self._sorted_self = {'idx': idx, 'power': x[idx], 'amp': y[idx]} diff --git a/src/easydiffraction/job/experiment/backgrounds/point.py b/src/easydiffraction/job/experiment/backgrounds/point.py index 7d6ec97e..0d0ff76b 100644 --- a/src/easydiffraction/job/experiment/backgrounds/point.py +++ b/src/easydiffraction/job/experiment/backgrounds/point.py @@ -9,7 +9,7 @@ from easyscience.Objects.Groups import BaseCollection from easyscience.Objects.ObjectClasses import BaseObj from easyscience.Objects.ObjectClasses import Descriptor -from easyscience.Objects.ObjectClasses import Parameter +from easyscience.Objects.new_variable import Parameter from .background import Background @@ -36,7 +36,7 @@ def __init__(self, x: Union[float, Descriptor] = 0.0, y: Union[float, Parameter] if not isinstance(y, Parameter): y = Parameter('intensity', y, fixed=True) if name is None: - name = '{:.1f}_deg'.format(x.raw_value).replace('.', ',') + name = '{:.1f}_deg'.format(x.value).replace('.', ',') x._callback = property(fget=None, fset=lambda x_value: self._modify_x_label(x_value), fdel=None) super(BackgroundPoint, self).__init__(name, x=x, y=y) @@ -157,7 +157,7 @@ def x_sorted_points(self) -> np.ndarray: :return: Sorted x-values :rtype: np.ndarray """ - x = np.array([item.x.raw_value for item in self]) + x = np.array([item.x.value for item in self]) x.sort() return x @@ -169,8 +169,8 @@ def y_sorted_points(self) -> np.ndarray: :return: Sorted y-values :rtype: np.ndarray """ - idx = np.array([item.x.raw_value for item in self]).argsort() - y = np.array([item.y.raw_value for item in self]) + idx = np.array([item.x.value for item in self]).argsort() + y = np.array([item.y.value for item in self]) return y[idx] @property @@ -192,8 +192,8 @@ def append(self, item: BackgroundPoint): """ if not isinstance(item, BackgroundPoint): raise TypeError('Item must be a BackgroundPoint') - if item.x.raw_value in self.x_sorted_points: - raise AttributeError(f'An BackgroundPoint at {item.x.raw_value} already exists.') + if item.x.value in self.x_sorted_points: + raise AttributeError(f'An BackgroundPoint at {item.x.value} already exists.') super(PointBackground, self).append(item) def get_parameters(self) -> List[Parameter]: @@ -201,5 +201,5 @@ def get_parameters(self) -> List[Parameter]: Redefine get_parameters so that the returned values are in the correct order """ list_pars = np.array(super(PointBackground, self).get_parameters()) - idx = np.array([item.x.raw_value for item in self]).argsort() + idx = np.array([item.x.value for item in self]).argsort() return list_pars[idx].tolist() diff --git a/src/easydiffraction/job/experiment/experiment.py b/src/easydiffraction/job/experiment/experiment.py index 8d131173..b7033aab 100644 --- a/src/easydiffraction/job/experiment/experiment.py +++ b/src/easydiffraction/job/experiment/experiment.py @@ -6,7 +6,7 @@ from easyscience.Datasets.xarray import xr from easyscience.Objects.job.experiment import ExperimentBase as coreExperiment from easyscience.Objects.ObjectClasses import Descriptor -from easyscience.Objects.ObjectClasses import Parameter +from easyscience.Objects.new_variable import Parameter from gemmi import cif from easydiffraction.io.cif_reader import background_from_cif_block as background_from_cif @@ -346,7 +346,7 @@ def background_from_cif_block(block, experiment_name: str = None) -> PointBackgr error = background_intensities[y]['error'] fixed = error is None error = 0.0 if error is None else error - bg_y = Parameter('intensity', intensity, error=error, fixed=fixed) + bg_y = Parameter('intensity', intensity, variance=error, fixed=fixed) bkg.append(BackgroundPoint(x=bg_x, y=bg_y)) return bkg @@ -566,19 +566,19 @@ def cw_param_as_cif(parameters=None, pattern=None): Returns a CIF representation of the CW instrument parameters """ cif_ipar_data = '' - cif_ipar_data += '\n_setup_wavelength ' + str(parameters.wavelength.raw_value) - cif_ipar_data += '\n_setup_offset_2theta ' + str(pattern.zero_shift.raw_value) + cif_ipar_data += '\n_setup_wavelength ' + str(parameters.wavelength.value) + cif_ipar_data += '\n_setup_offset_2theta ' + str(pattern.zero_shift.value) cif_ipar_data += '\n' - cif_ipar_data += '\n_pd_instr_resolution_u ' + str(parameters.resolution_u.raw_value) - cif_ipar_data += '\n_pd_instr_resolution_v ' + str(parameters.resolution_v.raw_value) - cif_ipar_data += '\n_pd_instr_resolution_w ' + str(parameters.resolution_w.raw_value) - cif_ipar_data += '\n_pd_instr_resolution_x ' + str(parameters.resolution_x.raw_value) - cif_ipar_data += '\n_pd_instr_resolution_y ' + str(parameters.resolution_y.raw_value) + cif_ipar_data += '\n_pd_instr_resolution_u ' + str(parameters.resolution_u.value) + cif_ipar_data += '\n_pd_instr_resolution_v ' + str(parameters.resolution_v.value) + cif_ipar_data += '\n_pd_instr_resolution_w ' + str(parameters.resolution_w.value) + cif_ipar_data += '\n_pd_instr_resolution_x ' + str(parameters.resolution_x.value) + cif_ipar_data += '\n_pd_instr_resolution_y ' + str(parameters.resolution_y.value) cif_ipar_data += '\n' - cif_ipar_data += '\n_pd_instr_reflex_asymmetry_p1 ' + str(parameters.reflex_asymmetry_p1.raw_value) - cif_ipar_data += '\n_pd_instr_reflex_asymmetry_p2 ' + str(parameters.reflex_asymmetry_p2.raw_value) - cif_ipar_data += '\n_pd_instr_reflex_asymmetry_p3 ' + str(parameters.reflex_asymmetry_p3.raw_value) - cif_ipar_data += '\n_pd_instr_reflex_asymmetry_p4 ' + str(parameters.reflex_asymmetry_p4.raw_value) + cif_ipar_data += '\n_pd_instr_reflex_asymmetry_p1 ' + str(parameters.reflex_asymmetry_p1.value) + cif_ipar_data += '\n_pd_instr_reflex_asymmetry_p2 ' + str(parameters.reflex_asymmetry_p2.value) + cif_ipar_data += '\n_pd_instr_reflex_asymmetry_p3 ' + str(parameters.reflex_asymmetry_p3.value) + cif_ipar_data += '\n_pd_instr_reflex_asymmetry_p4 ' + str(parameters.reflex_asymmetry_p4.value) return cif_ipar_data @staticmethod @@ -587,28 +587,28 @@ def tof_param_as_cif(pattern=None, parameters=None): Returns a CIF representation of the TOF instrument parameters """ cif_tof_data = '' - cif_tof_data += '\n_tof_parameters_zero ' + str(pattern.zero_shift.raw_value) - cif_tof_data += '\n_tof_parameters_dtt1 ' + str(parameters.dtt1.raw_value) - cif_tof_data += '\n_tof_parameters_dtt2 ' + str(parameters.dtt2.raw_value) - cif_tof_data += '\n_tof_parameters_2theta_bank ' + str(parameters.ttheta_bank.raw_value) - cif_tof_data += '\n_tof_profile_sigma0 ' + str(parameters.sigma0.raw_value) - cif_tof_data += '\n_tof_profile_sigma1 ' + str(parameters.sigma1.raw_value) - cif_tof_data += '\n_tof_profile_sigma2 ' + str(parameters.sigma2.raw_value) - cif_tof_data += '\n_tof_profile_gamma0 ' + str(parameters.gamma0.raw_value) - cif_tof_data += '\n_tof_profile_gamma1 ' + str(parameters.gamma1.raw_value) - cif_tof_data += '\n_tof_profile_gamma2 ' + str(parameters.gamma2.raw_value) - cif_tof_data += '\n_tof_profile_alpha0 ' + str(parameters.alpha0.raw_value) - cif_tof_data += '\n_tof_profile_alpha1 ' + str(parameters.alpha1.raw_value) - cif_tof_data += '\n_tof_profile_beta0 ' + str(parameters.beta0.raw_value) - cif_tof_data += '\n_tof_profile_beta1 ' + str(parameters.beta1.raw_value) + cif_tof_data += '\n_tof_parameters_zero ' + str(pattern.zero_shift.value) + cif_tof_data += '\n_tof_parameters_dtt1 ' + str(parameters.dtt1.value) + cif_tof_data += '\n_tof_parameters_dtt2 ' + str(parameters.dtt2.value) + cif_tof_data += '\n_tof_parameters_2theta_bank ' + str(parameters.ttheta_bank.value) + cif_tof_data += '\n_tof_profile_sigma0 ' + str(parameters.sigma0.value) + cif_tof_data += '\n_tof_profile_sigma1 ' + str(parameters.sigma1.value) + cif_tof_data += '\n_tof_profile_sigma2 ' + str(parameters.sigma2.value) + cif_tof_data += '\n_tof_profile_gamma0 ' + str(parameters.gamma0.value) + cif_tof_data += '\n_tof_profile_gamma1 ' + str(parameters.gamma1.value) + cif_tof_data += '\n_tof_profile_gamma2 ' + str(parameters.gamma2.value) + cif_tof_data += '\n_tof_profile_alpha0 ' + str(parameters.alpha0.value) + cif_tof_data += '\n_tof_profile_alpha1 ' + str(parameters.alpha1.value) + cif_tof_data += '\n_tof_profile_beta0 ' + str(parameters.beta0.value) + cif_tof_data += '\n_tof_profile_beta1 ' + str(parameters.beta1.value) return cif_tof_data @staticmethod def polar_param_as_cif(pattern=None): cif_pat_data = '' - cif_pat_data += '\n_diffrn_radiation_polarization ' + str(pattern.beam.polarization.raw_value) - cif_pat_data += '\n_diffrn_radiation_efficiency ' + str(pattern.efficiency.raw_value) - cif_pat_data += '\n_setup_field ' + str(pattern.field.raw_value) + cif_pat_data += '\n_diffrn_radiation_polarization ' + str(pattern.beam.polarization.value) + cif_pat_data += '\n_diffrn_radiation_efficiency ' + str(pattern.efficiency.value) + cif_pat_data += '\n_setup_field ' + str(pattern.field.value) # cif_pat_data += "\n_chi2_sum " + str(self._refine_sum) # cif_pat_data += "\n_chi2_diff " + str(self._refine_diff) # cif_pat_data += "\n_chi2_up " + str(self._refine_up) @@ -630,7 +630,7 @@ def background_as_cif(background=None, is_tof=False): cif_background += '\nloop_ \n_pd_background_2theta\n_pd_background_intensity' # background = self.parent.l_background._background_as_obj for i in range(len(background.data)): - cif_background += '\n' + str(background.data[i].x.raw_value) + ' ' + str(background.data[i].y.raw_value) + cif_background += '\n' + str(background.data[i].x.value) + ' ' + str(background.data[i].y.value) return cif_background # required dunder methods diff --git a/src/easydiffraction/job/experiment/pd_1d.py b/src/easydiffraction/job/experiment/pd_1d.py index 1f3e70b2..27690992 100644 --- a/src/easydiffraction/job/experiment/pd_1d.py +++ b/src/easydiffraction/job/experiment/pd_1d.py @@ -15,7 +15,7 @@ from easyscience.Datasets.xarray import xr from easyscience.Objects.ObjectClasses import BaseObj from easyscience.Objects.ObjectClasses import Descriptor -from easyscience.Objects.ObjectClasses import Parameter +from easyscience.Objects.new_variable import Parameter from easydiffraction.job.experiment.backgrounds.background import BackgroundContainer from easydiffraction.job.experiment.common import JobSetup @@ -76,7 +76,7 @@ class Powder1DParameters(BaseObj): 'zero_shift': { 'name': 'zero_shift', 'url': 'https://docs.easydiffraction.org/lib/dictionaries/_pd_instr/', - 'units': 'degree', + 'unit': 'degree', 'value': 0.0, 'fixed': True, }, @@ -130,7 +130,7 @@ class PolPowder1DParameters(Powder1DParameters): beam: ClassVar[PolarizedBeam] _defaults = { - 'field': {'name': 'magnetic_field', 'value': 1.0, 'units': 'T', 'fixed': True}, + 'field': {'name': 'magnetic_field', 'value': 1.0, 'unit': 'T', 'fixed': True}, } _defaults.update(Powder1DParameters._defaults) @@ -189,7 +189,7 @@ class Instrument1DCWParameters(BaseObj): 'wavelength': { 'name': 'wavelength', 'url': 'https://docs.easydiffraction.org/lib/dictionaries/_diffrn_radiation_wavelength/', - 'units': 'angstrom', + 'unit': 'angstrom', 'value': 1.54056, 'fixed': True, }, @@ -377,42 +377,42 @@ class Instrument1DTOFParameters(BaseObj): 'ttheta_bank': { 'name': 'ttheta_bank', 'url': 'https://docs.easydiffraction.org/lib/dictionaries/_pd_instr/', - 'units': 'deg', + 'unit': 'deg', 'value': 145.00, 'fixed': True, }, 'dtt1': { 'name': 'dtt1', 'url': 'https://docs.easydiffraction.org/lib/dictionaries/_pd_instr/', - 'units': 'microsec/angstrom', + 'unit': 'microsec/angstrom', 'value': 6167.24700, 'fixed': True, }, 'dtt2': { 'name': 'dtt2', 'url': 'https://docs.easydiffraction.org/lib/dictionaries/_pd_instr/', - 'units': 'microsec/angstrom**2', + 'unit': 'microsec/angstrom**2', 'value': -2.28000, 'fixed': True, }, 'sigma0': { 'name': 'sigma0', 'url': 'https://docs.easydiffraction.org/lib/dictionaries/_pd_instr/', - 'units': 'microsec**2', + 'unit': 'microsec**2', 'value': 0.409, 'fixed': True, }, 'sigma1': { 'name': 'sigma1', 'url': 'https://docs.easydiffraction.org/lib/dictionaries/_pd_instr/', - 'units': 'microsec**2/angstrom**2', + 'unit': 'microsec**2/angstrom**2', 'value': 8.118, 'fixed': True, }, 'sigma2': { 'name': 'sigma2', 'url': 'https://docs.easydiffraction.org/lib/dictionaries/_pd_instr/', - 'units': 'microsec**2/angstrom**4', + 'unit': 'microsec**2/angstrom**4', 'value': 0.0, 'fixed': True, }, @@ -550,13 +550,13 @@ class PDFParameters(Instrument1DCWParameters): _defaults = { 'qmax': { 'name': 'Q_max', - 'units': '1/angstrom', + 'unit': '1/angstrom', 'value': 30.0, 'fixed': True, }, 'qdamp': { 'name': 'Q_damp', - 'units': '1/angstrom', + 'unit': '1/angstrom', 'value': 0.01, 'fixed': True, }, @@ -567,19 +567,19 @@ class PDFParameters(Instrument1DCWParameters): }, 'delta1': { 'name': 'delta1', - 'units': 'angstrom', + 'unit': 'angstrom', 'value': 0.0, 'fixed': True, }, 'delta2': { 'name': 'delta2', - 'units': 'angstrom**2', + 'unit': 'angstrom**2', 'value': 0.0, 'fixed': True, }, 'spdiameter': { 'name': 'spdiameter', - 'units': 'angstrom', + 'unit': 'angstrom', 'min': 0.0, 'value': 0.0, 'fixed': True, diff --git a/src/easydiffraction/job/experiment/polarization.py b/src/easydiffraction/job/experiment/polarization.py index d2845f30..e83053c7 100644 --- a/src/easydiffraction/job/experiment/polarization.py +++ b/src/easydiffraction/job/experiment/polarization.py @@ -10,7 +10,7 @@ from typing import Union from easyscience.Objects.ObjectClasses import BaseObj -from easyscience.Objects.ObjectClasses import Parameter +from easyscience.Objects.new_variable import Parameter if TYPE_CHECKING: from easyscience.Objects.Inferface import iF diff --git a/src/easydiffraction/job/job.py b/src/easydiffraction/job/job.py index d05f8d89..35646ed9 100644 --- a/src/easydiffraction/job/job.py +++ b/src/easydiffraction/job/job.py @@ -336,11 +336,11 @@ def update_experiment_type(self) -> None: if self.type.is_tof: self._x_axis_name = 'time' if self.pattern is not None: - self.pattern.zero_shift.unit = 'μs' + self.pattern.zero_shift.convert_unit('μs') else: self._x_axis_name = 'tth' if self.pattern is not None: - self.pattern.zero_shift.unit = 'degree' + self.pattern.zero_shift.convert_unit('degree') def update_exp_type(self) -> None: """ @@ -436,13 +436,13 @@ def add_experiment_from_file(self, file_url: str) -> None: if ( hasattr(self.sample.parameters, 'dtt1') and hasattr(self.experiment.parameters, 'dtt1') - and self.sample.parameters.dtt1.raw_value != self.experiment.parameters.dtt1.raw_value + and self.sample.parameters.dtt1.value != self.experiment.parameters.dtt1.value ): self.sample.parameters.dtt1 = self.experiment.parameters.dtt1 if ( hasattr(self.sample.parameters, 'dtt2') and hasattr(self.experiment.parameters, 'dtt2') - and self.sample.parameters.dtt2.raw_value != self.experiment.parameters.dtt2.raw_value + and self.sample.parameters.dtt2.value != self.experiment.parameters.dtt2.value ): self.sample.parameters.dtt2 = self.experiment.parameters.dtt2 @@ -758,16 +758,16 @@ def show_simulation_chart(self, show_legend=True): if self.type.is_pd and self.type.is_cwl: x_axis_title = '2θ (degree)' x = np.arange( - self.instrument.twotheta_range_min.raw_value, - self.instrument.twotheta_range_max.raw_value + self.instrument.twotheta_range_inc.raw_value, - self.instrument.twotheta_range_inc.raw_value, + self.instrument.twotheta_range_min.value, + self.instrument.twotheta_range_max.value + self.instrument.twotheta_range_inc.value, + self.instrument.twotheta_range_inc.value, ) elif self.type.is_pd and self.type.is_tof: x_axis_title = 'TOF (µs)' x = np.arange( - self.instrument.tof_range_min.raw_value, - self.instrument.tof_range_max.raw_value + self.instrument.tof_range_inc.raw_value, - self.instrument.tof_range_inc.raw_value, + self.instrument.tof_range_min.value, + self.instrument.tof_range_max.value + self.instrument.tof_range_inc.value, + self.instrument.tof_range_inc.value, ) else: print(f"Warning: Simulation chart not available for this type of job '{self.type}'") @@ -1019,7 +1019,7 @@ def _parameters(self): if parameter.enabled: name = self.get_full_parameter_name(parameter.unique_name, parameter.display_name, parameter.url) parameters['name'].append(f'{name}') - parameters['value'].append(parameter.raw_value) + parameters['value'].append(parameter.value) parameters['unit'].append(f'{parameter.unit:~P}') parameters['error'].append(parameter.error) if parameter.error else parameters['error'].append('') parameters['min'].append(parameter.min) @@ -1032,7 +1032,7 @@ def _free_parameters(self): for parameter in self.get_fit_parameters(): name = self.get_full_parameter_name(parameter.unique_name, parameter.display_name, parameter.url) parameters['name'].append(f'{name}') - parameters['value'].append(parameter.raw_value) + parameters['value'].append(parameter.value) parameters['unit'].append(f'{parameter.unit:~P}') parameters['error'].append(parameter.error) return parameters diff --git a/src/easydiffraction/job/model/site.py b/src/easydiffraction/job/model/site.py index 577c7f12..6c4eed9a 100644 --- a/src/easydiffraction/job/model/site.py +++ b/src/easydiffraction/job/model/site.py @@ -16,7 +16,7 @@ from easycrystallography.Components.Susceptibility import MagneticSusceptibility from easycrystallography.io.star_base import StarLoop from easyscience.Objects.ObjectClasses import Descriptor -from easyscience.Objects.ObjectClasses import Parameter +from easyscience.Objects.new_variable import Parameter if TYPE_CHECKING: from easyscience.Objects.Inferface import iF @@ -100,7 +100,7 @@ def add_adp(self, main_loop, add_loops): if not has_adp: return [main_loop] add_loops = [] - adp_types = [item.adp.adp_type.raw_value for item in self] + adp_types = [item.adp.adp_type.value for item in self] if all(adp_types): if adp_types[0] in ['Uiso', 'Biso']: main_loop = main_loop.join( diff --git a/src/easydiffraction/job/old_sample/old_sample.py b/src/easydiffraction/job/old_sample/old_sample.py index 01736bdd..df34d56c 100644 --- a/src/easydiffraction/job/old_sample/old_sample.py +++ b/src/easydiffraction/job/old_sample/old_sample.py @@ -132,7 +132,7 @@ def phases_as_cif(self): cif_phase += '_phase_scale\n' cif_phase += '_phase_igsize\n' for phase in self.phases: - cif_phase += phase.name + ' ' + str(phase.scale.raw_value) + ' 0.0\n' + cif_phase += phase.name + ' ' + str(phase.scale.value) + ' 0.0\n' return cif_phase @property @@ -164,8 +164,8 @@ def set_background(self, background): self._pattern.backgrounds.append(background) def remove_background(self, background): - if background.linked_experiment.raw_value in self._pattern.backgrounds.linked_experiments: - del self._pattern.backgrounds[background.linked_experiment.raw_value] + if background.linked_experiment.value in self._pattern.backgrounds.linked_experiments: + del self._pattern.backgrounds[background.linked_experiment.value] else: raise ValueError diff --git a/tests_old/integration_tests/FittingData.ipynb b/tests_old/integration_tests/FittingData.ipynb index b4d92ec3..c9edb097 100644 --- a/tests_old/integration_tests/FittingData.ipynb +++ b/tests_old/integration_tests/FittingData.ipynb @@ -283,8 +283,7 @@ "outputs": [], "source": [ "print(f'Scale: {sample.pattern.scale}')\n", - "print(f'Scale: {sample.pattern.scale.value}')\n", - "print(f'Scale: {sample.pattern.scale.raw_value}')" + "print(f'Scale: {sample.pattern.scale.value}')" ] }, { From 697436fc2b119223660b9a252539d6f8c742aca2 Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Tue, 14 Jan 2025 13:00:21 +0100 Subject: [PATCH 02/33] added new Descriptors and fixed ruff --- src/easydiffraction/io/cif.py | 4 +--- src/easydiffraction/job/experiment/backgrounds/background.py | 2 +- src/easydiffraction/job/experiment/backgrounds/point.py | 4 ++-- src/easydiffraction/job/experiment/experiment.py | 2 +- src/easydiffraction/job/experiment/pd_1d.py | 4 ++-- src/easydiffraction/job/experiment/polarization.py | 2 +- src/easydiffraction/job/model/site.py | 2 +- 7 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/easydiffraction/io/cif.py b/src/easydiffraction/io/cif.py index e8d2a780..584225d7 100644 --- a/src/easydiffraction/io/cif.py +++ b/src/easydiffraction/io/cif.py @@ -293,9 +293,7 @@ def _sanitize_loop(self, data: StarLoop) -> StarLoop: new_item._kwargs['atom_site_type_symbol'].value = str( re.findall(r'\D+', symbol_str_lst[elocc_idx].strip())[1] ).replace('', '') - new_item._kwargs['atom_site_label'].value = ( - new_item._kwargs['atom_site_type_symbol'].value + '_fix' - ) + new_item._kwargs['atom_site_label'].value = new_item._kwargs['atom_site_type_symbol'].value + '_fix' if 'atom_site_occupancy' in new_item._kwargs.keys(): new_item._kwargs['atom_site_label'].value = float( '0' + re.findall(r'\.?\d+', symbol_str_lst[elocc_idx].strip())[1] diff --git a/src/easydiffraction/job/experiment/backgrounds/background.py b/src/easydiffraction/job/experiment/backgrounds/background.py index 4ea7163a..7ac40344 100644 --- a/src/easydiffraction/job/experiment/backgrounds/background.py +++ b/src/easydiffraction/job/experiment/backgrounds/background.py @@ -8,7 +8,7 @@ import numpy as np from easyscience.Objects.Groups import BaseCollection -from easyscience.Objects.Variable import Descriptor +from easyscience.Objects.new_variable import DescriptorStr as Descriptor class Background(BaseCollection): diff --git a/src/easydiffraction/job/experiment/backgrounds/point.py b/src/easydiffraction/job/experiment/backgrounds/point.py index 0d0ff76b..199f4ef9 100644 --- a/src/easydiffraction/job/experiment/backgrounds/point.py +++ b/src/easydiffraction/job/experiment/backgrounds/point.py @@ -7,9 +7,9 @@ import numpy as np from easyscience.Objects.Groups import BaseCollection -from easyscience.Objects.ObjectClasses import BaseObj -from easyscience.Objects.ObjectClasses import Descriptor +from easyscience.Objects.new_variable import DescriptorNumber as Descriptor from easyscience.Objects.new_variable import Parameter +from easyscience.Objects.ObjectClasses import BaseObj from .background import Background diff --git a/src/easydiffraction/job/experiment/experiment.py b/src/easydiffraction/job/experiment/experiment.py index b7033aab..5dcb244e 100644 --- a/src/easydiffraction/job/experiment/experiment.py +++ b/src/easydiffraction/job/experiment/experiment.py @@ -5,7 +5,7 @@ import numpy as np from easyscience.Datasets.xarray import xr from easyscience.Objects.job.experiment import ExperimentBase as coreExperiment -from easyscience.Objects.ObjectClasses import Descriptor +from easyscience.Objects.new_variable import DescriptorNumber as Descriptor from easyscience.Objects.new_variable import Parameter from gemmi import cif diff --git a/src/easydiffraction/job/experiment/pd_1d.py b/src/easydiffraction/job/experiment/pd_1d.py index 27690992..9daf79ad 100644 --- a/src/easydiffraction/job/experiment/pd_1d.py +++ b/src/easydiffraction/job/experiment/pd_1d.py @@ -13,9 +13,9 @@ from typing import Union from easyscience.Datasets.xarray import xr -from easyscience.Objects.ObjectClasses import BaseObj -from easyscience.Objects.ObjectClasses import Descriptor +from easyscience.Objects.new_variable import DescriptorStr as Descriptor from easyscience.Objects.new_variable import Parameter +from easyscience.Objects.ObjectClasses import BaseObj from easydiffraction.job.experiment.backgrounds.background import BackgroundContainer from easydiffraction.job.experiment.common import JobSetup diff --git a/src/easydiffraction/job/experiment/polarization.py b/src/easydiffraction/job/experiment/polarization.py index e83053c7..24bfcd2b 100644 --- a/src/easydiffraction/job/experiment/polarization.py +++ b/src/easydiffraction/job/experiment/polarization.py @@ -9,8 +9,8 @@ from typing import Optional from typing import Union -from easyscience.Objects.ObjectClasses import BaseObj from easyscience.Objects.new_variable import Parameter +from easyscience.Objects.ObjectClasses import BaseObj if TYPE_CHECKING: from easyscience.Objects.Inferface import iF diff --git a/src/easydiffraction/job/model/site.py b/src/easydiffraction/job/model/site.py index 6c4eed9a..7bc3627e 100644 --- a/src/easydiffraction/job/model/site.py +++ b/src/easydiffraction/job/model/site.py @@ -15,7 +15,7 @@ from easycrystallography.Components.Specie import Specie from easycrystallography.Components.Susceptibility import MagneticSusceptibility from easycrystallography.io.star_base import StarLoop -from easyscience.Objects.ObjectClasses import Descriptor +from easyscience.Objects.new_variable import DescriptorStr as Descriptor from easyscience.Objects.new_variable import Parameter if TYPE_CHECKING: From 4c787affa3112414d584af6e3c3f9214be703866 Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Tue, 14 Jan 2025 13:07:07 +0100 Subject: [PATCH 03/33] use ruff 0.9, since 0.8.x didn't give good enough info --- src/easydiffraction/io/cif.py | 6 ++---- .../job/experiment/backgrounds/background.py | 2 +- tests/unit_tests/job/experiment/test_experiment.py | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/easydiffraction/io/cif.py b/src/easydiffraction/io/cif.py index 584225d7..5027e12e 100644 --- a/src/easydiffraction/io/cif.py +++ b/src/easydiffraction/io/cif.py @@ -345,9 +345,7 @@ def _sanitize_loop(self, data: StarLoop) -> StarLoop: this_data._kwargs[label].value = comparison_frac fracs_changed = True if fracs_changed: - self.warnings.append( - 'Some fractional co-ordinates rounded to ideal values to ' 'avoid issues with finite precision.' - ) + self.warnings.append('Some fractional co-ordinates rounded to ideal values to avoid issues with finite precision.') return data def _sanitize_data(self, data: StarEntry) -> StarEntry: @@ -1056,7 +1054,7 @@ def str2float(text): def dataBlockToCif(block, includeBlockName=True): cif = '' if includeBlockName: - cif += f"data_{block['name']['value']}" + cif += f'data_{block["name"]["value"]}' cif += '\n\n' if 'params' in block: for category in block['params'].values(): diff --git a/src/easydiffraction/job/experiment/backgrounds/background.py b/src/easydiffraction/job/experiment/backgrounds/background.py index 7ac40344..9eda29db 100644 --- a/src/easydiffraction/job/experiment/backgrounds/background.py +++ b/src/easydiffraction/job/experiment/backgrounds/background.py @@ -31,7 +31,7 @@ def __init__(self, *args, linked_experiment=None, **kwargs): # Convert `linked_experiment` to a Descriptor if linked_experiment is None: raise AttributeError( - 'Backgrounds need to be associated with an experiment. ' 'Use the `linked_experiment` key word argument.' + 'Backgrounds need to be associated with an experiment. Use the `linked_experiment` key word argument.' ) elif isinstance(linked_experiment, str): linked_experiment = Descriptor('linked_experiment', linked_experiment) diff --git a/tests/unit_tests/job/experiment/test_experiment.py b/tests/unit_tests/job/experiment/test_experiment.py index 242ce316..926fbda8 100644 --- a/tests/unit_tests/job/experiment/test_experiment.py +++ b/tests/unit_tests/job/experiment/test_experiment.py @@ -59,7 +59,7 @@ def test_add_experiment(setup_experiment): npt.assert_array_equal(add_coordinate_call[0][1], data[:, 0]) for j in range(1, len(data), 2): - var_name = f'test_job_exp2_I{j//2}' + var_name = f'test_job_exp2_I{j // 2}' add_variable_call = mock_datastore.store.easyscience.add_variable.call_args_list[j // 2] assert add_variable_call[0][0] == var_name assert add_variable_call[0][1] == [coord_name] From 68df4b5811265b4056b5f3a7289d407ca53501b9 Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Tue, 14 Jan 2025 13:13:34 +0100 Subject: [PATCH 04/33] rely on `new_param` branch of EXC --- pyproject.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8e9139db..922b1ae2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,10 +25,10 @@ classifiers = [ ] requires-python = '>=3.9,<3.13' dependencies = [ - 'cryspy', # Calculations of diffraction patterns - 'easycrystallography', # Crystallography tools of the EasyScience framework - 'easyscience', # The base library of the EasyScience framework - 'pooch', # For data fetching + 'cryspy', # Calculations of diffraction patterns + 'easycrystallography @ git+https://github.com/EasyScience/EasyCrystallography.git@new_param', # Crystallography tools of the EasyScience framework + 'easyscience', # The base library of the EasyScience framework + 'pooch', # For data fetching ] [project.optional-dependencies] From 56b5ee28f346f1450b82eaaf218afdd8ef8b4314 Mon Sep 17 00:00:00 2001 From: rozyczko Date: Thu, 30 Jan 2025 14:23:11 +0100 Subject: [PATCH 05/33] assure exp names are correct --- .../calculators/cryspy/calculator.py | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/easydiffraction/calculators/cryspy/calculator.py b/src/easydiffraction/calculators/cryspy/calculator.py index 55fb46b2..1b450ed0 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -559,7 +559,7 @@ def do_calc_setup(self, scale: float, this_x_array: np.ndarray, pol_fn: Callable idx = [idx for idx, item in enumerate(self.phases.items) if item.label == crystal.data_name][0] phasesL.items.append(self.phases.items[idx]) phase_lists.append(phasesL) - profile, peak = self._do_run(self.model, self.polarized, this_x_array, crystal, phasesL, bg) + profile, peak = self._do_run(self.model, self.polarized, this_x_array, crystal, phasesL, bg, phase_scales) profiles.append(profile) peak_dat.append(peak) # pool = mp.ProcessPool(num_crys) @@ -768,12 +768,13 @@ def replaceExpCif(self, edCif, currentExperimentName): calcExperimentsDict = calcExperimentsObj.get_dictionary() calcDictBlockName = f'pd_{currentExperimentName}' + calcDictName = f'data_{currentExperimentName}' _, edExperimentsNoMeas = calcObjAndDictToEdExperiments(calcExperimentsObj, calcExperimentsDict) # self._cryspyData._cryspyObj.items[calcObjBlockIdx] = calcExperimentsObj.items[0] self._cryspyData._cryspyObj.items[0] = calcExperimentsObj.items[0] - self._cryspyData._cryspyDict[calcDictBlockName] = calcExperimentsDict[calcDictBlockName] + self._cryspyData._cryspyDict[calcDictBlockName] = calcExperimentsDict[calcDictName] sdataBlocksNoMeas = edExperimentsNoMeas[0] return sdataBlocksNoMeas @@ -885,12 +886,11 @@ def polarized_update(func, crystals, profiles, peak_dat, scales, x_str): return dependent, output - def _do_run(self, model, polarized, x_array, crystals, phase_list, bg): + def _do_run(self, model, polarized, x_array, crystals, phase_list, bg, phase_scales): idx = [idx for idx, item in enumerate(model.items) if isinstance(item, cryspy.PhaseL)][0] model.items[idx] = phase_list data_name = crystals.data_name - setattr(self.model, 'data_name', data_name) is_tof = False if self.model.PREFIX.lower() == 'tof': @@ -901,16 +901,31 @@ def _do_run(self, model, polarized, x_array, crystals, phase_list, bg): else: ttheta = np.radians(x_array) # needs recasting into radians for CW - # model -> dict - experiment_dict_model = self.model.get_dictionary() - exp_name_model = experiment_dict_model['type_name'] - if not self._cryspyData._cryspyDict: return None + crystal_entry = 'crystal_' + data_name + new_exp_key = '' + for key in self._cryspyData._cryspyDict.keys(): + if crystal_entry in key: + continue + new_exp_key = key + break + if new_exp_key: + exp_name_model_split = new_exp_key.split("_", 1)[1] + exp_name_model = new_exp_key + + # model -> dict + setattr(self.model, 'data_name', exp_name_model_split) + experiment_dict_model = self.model.get_dictionary() + + # update scale in experimental_dict_model + experiment_dict_model['phase_scale'] = np.array(phase_scales) self._cryspyDict = self._cryspyData._cryspyDict + self._cryspyDict[exp_name_model] = experiment_dict_model + self.excluded_points = np.full(len(ttheta), False) if hasattr(self.model, 'excluded_points'): self.excluded_points = self.model.excluded_points From 1af34a55963676257f36f135a153548c53a29e9e Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Thu, 30 Jan 2025 16:57:35 +0100 Subject: [PATCH 06/33] ruff --- src/easydiffraction/calculators/cryspy/calculator.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/easydiffraction/calculators/cryspy/calculator.py b/src/easydiffraction/calculators/cryspy/calculator.py index 1b450ed0..693177b4 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -912,7 +912,7 @@ def _do_run(self, model, polarized, x_array, crystals, phase_list, bg, phase_sca new_exp_key = key break if new_exp_key: - exp_name_model_split = new_exp_key.split("_", 1)[1] + exp_name_model_split = new_exp_key.split('_', 1)[1] exp_name_model = new_exp_key # model -> dict @@ -925,7 +925,6 @@ def _do_run(self, model, polarized, x_array, crystals, phase_list, bg, phase_sca self._cryspyDict[exp_name_model] = experiment_dict_model - self.excluded_points = np.full(len(ttheta), False) if hasattr(self.model, 'excluded_points'): self.excluded_points = self.model.excluded_points From d5cd71790c9c7f2a72c05380b27e93c850db262c Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Sun, 2 Feb 2025 22:47:17 +0100 Subject: [PATCH 07/33] minor fixes --- src/easydiffraction/job/job.py | 4 ++-- tests/integration_tests/scipp/test_scipp.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/easydiffraction/job/job.py b/src/easydiffraction/job/job.py index 35646ed9..39b03c03 100644 --- a/src/easydiffraction/job/job.py +++ b/src/easydiffraction/job/job.py @@ -335,8 +335,8 @@ def update_experiment_type(self) -> None: # axis if self.type.is_tof: self._x_axis_name = 'time' - if self.pattern is not None: - self.pattern.zero_shift.convert_unit('μs') + #if self.pattern is not None: + # self.pattern.zero_shift.convert_unit('μs') else: self._x_axis_name = 'tth' if self.pattern is not None: diff --git a/tests/integration_tests/scipp/test_scipp.py b/tests/integration_tests/scipp/test_scipp.py index 753d9376..ce852644 100644 --- a/tests/integration_tests/scipp/test_scipp.py +++ b/tests/integration_tests/scipp/test_scipp.py @@ -13,9 +13,9 @@ def test_read_tof_cif_from_scipp() -> None: job.add_experiment_from_file('tests/data/scipp.cif') assert job.experiment.name == 'test_data' - assert job.pattern.zero_shift.raw_value == 3.4 - assert job.parameters.dtt1.raw_value == 0.2 - assert job.parameters.dtt2.raw_value == -0.8 + assert job.pattern.zero_shift.value == 3.4 + assert job.parameters.dtt1.value == 0.2 + assert job.parameters.dtt2.value == -0.8 assert_array_equal(job.experiment.x.data, np.array([1.2, 1.4, 2.3])) assert_array_equal(job.experiment.y.data, np.array([13.6, 26.0, 9.7])) assert_array_equal( From 512bfcf318a7f132c3e11cf69a62eaab5ecc7190 Mon Sep 17 00:00:00 2001 From: rozyczko Date: Mon, 3 Feb 2025 08:37:28 +0100 Subject: [PATCH 08/33] ruff --- src/easydiffraction/job/job.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/easydiffraction/job/job.py b/src/easydiffraction/job/job.py index 39b03c03..589101f0 100644 --- a/src/easydiffraction/job/job.py +++ b/src/easydiffraction/job/job.py @@ -335,7 +335,7 @@ def update_experiment_type(self) -> None: # axis if self.type.is_tof: self._x_axis_name = 'time' - #if self.pattern is not None: + # if self.pattern is not None: # self.pattern.zero_shift.convert_unit('μs') else: self._x_axis_name = 'tth' From c4599832803b197376fe09b224a824462eef14e5 Mon Sep 17 00:00:00 2001 From: rozyczko Date: Tue, 4 Feb 2025 15:13:06 +0100 Subject: [PATCH 09/33] assign interface when necessary --- src/easydiffraction/job/experiment/experiment.py | 2 +- src/easydiffraction/job/job.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/easydiffraction/job/experiment/experiment.py b/src/easydiffraction/job/experiment/experiment.py index 5dcb244e..04e42947 100644 --- a/src/easydiffraction/job/experiment/experiment.py +++ b/src/easydiffraction/job/experiment/experiment.py @@ -87,7 +87,7 @@ class Experiment(coreExperiment): def __init__(self, job_name: str, datastore: xr.Dataset = None, *args, **kwargs): super(Experiment, self).__init__(job_name, *args, **kwargs) self.job_name = job_name - + self.interface = None self.is_tof = False self.is_polarized = False self.is_single_crystal = False diff --git a/src/easydiffraction/job/job.py b/src/easydiffraction/job/job.py index 589101f0..bbd10272 100644 --- a/src/easydiffraction/job/job.py +++ b/src/easydiffraction/job/job.py @@ -138,6 +138,7 @@ def __init__( # assign Job components self.sample = sample # container for phases self.interface = self.sample._interface + self.experiment.interface = self.interface self.analysis = analysis self.update_experiment_type() # necessary for the fitter From 59a7ddfee59229db12c9f7d14521e6764a6f7510 Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Fri, 7 Feb 2025 15:17:17 +0100 Subject: [PATCH 10/33] _pd_calib.2theta_offset in parameters for display proper handling of error format in experiment cif --- src/easydiffraction/io/cif_reader.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/easydiffraction/io/cif_reader.py b/src/easydiffraction/io/cif_reader.py index 195e5bb1..dfcd5928 100644 --- a/src/easydiffraction/io/cif_reader.py +++ b/src/easydiffraction/io/cif_reader.py @@ -121,8 +121,12 @@ def parameters_from_cif_block(block) -> dict: parameters['reflex_asymmetry_p3']['value'], parameters['reflex_asymmetry_p3']['error'] = parse_with_error(value) value = block.find_value('_pd_instr_reflex_asymmetry_p4') or block.find_value('_pd_instr.reflex_asymmetry_p4') if value is not None: - parameters['reflex_asymmetry_p3'] = {} - parameters['reflex_asymmetry_p3']['value'], parameters['reflex_asymmetry_p3']['error'] = parse_with_error(value) + parameters['reflex_asymmetry_p4'] = {} + parameters['reflex_asymmetry_p4']['value'], parameters['reflex_asymmetry_p4']['error'] = parse_with_error(value) + value = block.find_value('_pd_calib_2theta_offset') or block.find_value('_pd_calib.2theta_offset') + if value is not None: + parameters['zero_shift'] = {} + parameters['zero_shift']['value'], parameters['zero_shift']['error'] = parse_with_error(value) # ToF value = ( @@ -313,5 +317,6 @@ def parse_with_error(value: str) -> tuple: if not error: return float(value), 0.0 # 1.23() else: - return float(value), float(error) # 1.23(4) + err = (10 ** -(len(f'{value}'.split('.')[1]) - 1)) * int(error) + return float(value), err return float(value), None # 1.23 From 1fe8c4e2cb33289935fb469e41fee2ac9d44e192 Mon Sep 17 00:00:00 2001 From: rozyczko Date: Mon, 10 Feb 2025 11:20:08 +0100 Subject: [PATCH 11/33] minor changes for multiphase --- .../calculators/cryspy/calculator.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/easydiffraction/calculators/cryspy/calculator.py b/src/easydiffraction/calculators/cryspy/calculator.py index 693177b4..7a3bd737 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -556,7 +556,7 @@ def do_calc_setup(self, scale: float, this_x_array: np.ndarray, pol_fn: Callable delattr(crystal, 'atom_site_susceptibility') if hasattr(crystal, 'atom_site_scat'): delattr(crystal, 'atom_site_scat') - idx = [idx for idx, item in enumerate(self.phases.items) if item.label == crystal.data_name][0] + idx = [idx for idx, item in enumerate(self.phases.items) if crystal.data_name in item.label][0] phasesL.items.append(self.phases.items[idx]) phase_lists.append(phasesL) profile, peak = self._do_run(self.model, self.polarized, this_x_array, crystal, phasesL, bg, phase_scales) @@ -606,7 +606,6 @@ def do_calc_setup(self, scale: float, this_x_array: np.ndarray, pol_fn: Callable self.additional_data['components'] = scaled_dependents total_profile = np.sum([s['profile'] for s in self.additional_data['phases'].values()], axis=0) + new_bg - return total_profile, self.additional_data def calculate(self, x_array: np.ndarray, **kwargs) -> np.ndarray: @@ -904,10 +903,11 @@ def _do_run(self, model, polarized, x_array, crystals, phase_list, bg, phase_sca if not self._cryspyData._cryspyDict: return None - crystal_entry = 'crystal_' + data_name new_exp_key = '' + for key in self._cryspyData._cryspyDict.keys(): - if crystal_entry in key: + # skip phases + if 'crystal_' in key: continue new_exp_key = key break @@ -917,14 +917,18 @@ def _do_run(self, model, polarized, x_array, crystals, phase_list, bg, phase_sca # model -> dict setattr(self.model, 'data_name', exp_name_model_split) + + # get cryspy experiment dict from the model experiment_dict_model = self.model.get_dictionary() # update scale in experimental_dict_model experiment_dict_model['phase_scale'] = np.array(phase_scales) - self._cryspyDict = self._cryspyData._cryspyDict + self._cryspyDict = self._cryspyData._cryspyDict + # update _cryspyDict with the experiment self._cryspyDict[exp_name_model] = experiment_dict_model + # add extra fluff self.excluded_points = np.full(len(ttheta), False) if hasattr(self.model, 'excluded_points'): self.excluded_points = self.model.excluded_points @@ -951,6 +955,9 @@ def _do_run(self, model, polarized, x_array, crystals, phase_list, bg, phase_sca # interestingly, experimental signal is required, although not used for simple profile calc self._cryspyDict[exp_name_model]['signal_exp'] = np.array([np.zeros(len(ttheta)), np.zeros(len(ttheta))]) + # calculate profile + # + # _inOutDict contains the calculated profile res = rhochi_calc_chi_sq_by_dictionary( self._cryspyDict, dict_in_out=self._cryspyData._inOutDict, From 107675c046e343b4c522629da2b9f43256e6c300 Mon Sep 17 00:00:00 2001 From: rozyczko Date: Wed, 12 Feb 2025 14:28:43 +0100 Subject: [PATCH 12/33] added optional to some phase params to make possible editing CIF in place modified setup for the cryspy job object --- .../calculators/cryspy/calculator.py | 63 ++++++++++--------- src/easydiffraction/io/cif.py | 4 +- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/easydiffraction/calculators/cryspy/calculator.py b/src/easydiffraction/calculators/cryspy/calculator.py index 7a3bd737..25a14756 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -444,12 +444,13 @@ def powder_1d_calculate(self, x_array: np.ndarray, full_return: bool = False, ** if self.pattern is None: scale = 1.0 - offset = 0 + # offset = 0 else: scale = self.pattern.scale.value / norm - offset = self.pattern.zero_shift.value + # offset = self.pattern.zero_shift.value - this_x_array = x_array - offset + # this_x_array = x_array - offset + this_x_array = x_array if 'excluded_points' in kwargs: setattr(self.model, 'excluded_points', kwargs['excluded_points']) @@ -796,17 +797,19 @@ def updateCryspyDict(self, item, key, value): cryspy_key = CRYSPY_MODEL_PHASE_KEYS[key] loc = cryspy_dict[cryspy_key] # find the text in `item` after the last underscore + # will fail if new phase added atom_index = int(item[item.rfind('_') + 1 :]) - # is this a fractional coordinate? - if 'fract' in key: - coord_index = CRYSPY_MODEL_COORD_INDEX[key] - loc[coord_index][atom_index] = value - elif 'length' in key: - coord_index = CRYSPY_MODEL_COORD_INDEX[key] - loc[coord_index] = value - else: - loc[atom_index] = value - return + if atom_index < len(loc): + # is this a fractional coordinate? + if 'fract' in key: + coord_index = CRYSPY_MODEL_COORD_INDEX[key] + loc[coord_index][atom_index] = value + elif 'length' in key: + coord_index = CRYSPY_MODEL_COORD_INDEX[key] + loc[coord_index] = value + else: + loc[atom_index] = value + return elif key in CRYSPY_MODEL_INSTR_KEYS: # instrument param exp_name = list(self._cryspyData._cryspyDict.keys())[1] @@ -888,7 +891,6 @@ def polarized_update(func, crystals, profiles, peak_dat, scales, x_str): def _do_run(self, model, polarized, x_array, crystals, phase_list, bg, phase_scales): idx = [idx for idx, item in enumerate(model.items) if isinstance(item, cryspy.PhaseL)][0] model.items[idx] = phase_list - data_name = crystals.data_name is_tof = False @@ -903,32 +905,33 @@ def _do_run(self, model, polarized, x_array, crystals, phase_list, bg, phase_sca if not self._cryspyData._cryspyDict: return None - new_exp_key = '' - + phase_name = '' + exp_name_model = '' + # Find the name of the experiment in the model for key in self._cryspyData._cryspyDict.keys(): # skip phases if 'crystal_' in key: + # remove 'crytal_' from the key + phase_name = key.split('_', 1)[1] continue - new_exp_key = key + exp_name_model = key break - if new_exp_key: - exp_name_model_split = new_exp_key.split('_', 1)[1] - exp_name_model = new_exp_key - # model -> dict - setattr(self.model, 'data_name', exp_name_model_split) - - # get cryspy experiment dict from the model - experiment_dict_model = self.model.get_dictionary() - - # update scale in experimental_dict_model - experiment_dict_model['phase_scale'] = np.array(phase_scales) + if not exp_name_model: + # no exp defined, default + # exp_name_model_split = self.model.PREFIX + exp_name_model = self.model.PREFIX + '_' + phase_name + # get cryspy experiment dict from the model: expensive! + # model -> dict + setattr(self.model, 'data_name', phase_name) + experiment_dict_model = self.model.get_dictionary() + self._cryspyData._cryspyDict[exp_name_model] = experiment_dict_model self._cryspyDict = self._cryspyData._cryspyDict - # update _cryspyDict with the experiment - self._cryspyDict[exp_name_model] = experiment_dict_model # add extra fluff + self._cryspyDict[exp_name_model]['phase_scale'] = np.array(phase_scales) + self.excluded_points = np.full(len(ttheta), False) if hasattr(self.model, 'excluded_points'): self.excluded_points = self.model.excluded_points diff --git a/src/easydiffraction/io/cif.py b/src/easydiffraction/io/cif.py index 5027e12e..303e294c 100644 --- a/src/easydiffraction/io/cif.py +++ b/src/easydiffraction/io/cif.py @@ -1061,8 +1061,8 @@ def dataBlockToCif(block, includeBlockName=True): # for param in category.values(): for param in category.values(): # `param` is an easyCore Parameter object - # if param["optional"]: - # continue + if 'optional' in param and param['optional']: + continue value = param['value'] if value is None: continue From 48c2a9cfaacff280f84557a6b14bd759af2f3f93 Mon Sep 17 00:00:00 2001 From: rozyczko Date: Wed, 12 Feb 2025 14:57:18 +0100 Subject: [PATCH 13/33] fix offset setup --- src/easydiffraction/calculators/cryspy/calculator.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/easydiffraction/calculators/cryspy/calculator.py b/src/easydiffraction/calculators/cryspy/calculator.py index 25a14756..268d0b7e 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -444,13 +444,12 @@ def powder_1d_calculate(self, x_array: np.ndarray, full_return: bool = False, ** if self.pattern is None: scale = 1.0 - # offset = 0 + offset = 0 else: scale = self.pattern.scale.value / norm - # offset = self.pattern.zero_shift.value + offset = self.pattern.zero_shift.value + this_x_array = x_array - offset - # this_x_array = x_array - offset - this_x_array = x_array if 'excluded_points' in kwargs: setattr(self.model, 'excluded_points', kwargs['excluded_points']) From af4b833239f3b5522b1241c1c1080a188c8b6b72 Mon Sep 17 00:00:00 2001 From: rozyczko Date: Thu, 13 Feb 2025 15:21:10 +0100 Subject: [PATCH 14/33] added error parser for integers --- .../calculators/cryspy/calculator.py | 1 - src/easydiffraction/io/cif_reader.py | 18 ++++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/easydiffraction/calculators/cryspy/calculator.py b/src/easydiffraction/calculators/cryspy/calculator.py index 268d0b7e..a6955bc8 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -450,7 +450,6 @@ def powder_1d_calculate(self, x_array: np.ndarray, full_return: bool = False, ** offset = self.pattern.zero_shift.value this_x_array = x_array - offset - if 'excluded_points' in kwargs: setattr(self.model, 'excluded_points', kwargs['excluded_points']) diff --git a/src/easydiffraction/io/cif_reader.py b/src/easydiffraction/io/cif_reader.py index dfcd5928..90bb61ac 100644 --- a/src/easydiffraction/io/cif_reader.py +++ b/src/easydiffraction/io/cif_reader.py @@ -314,9 +314,19 @@ def parse_with_error(value: str) -> tuple: if '(' in value: value, error = value.split('(') error = error.strip(')') - if not error: - return float(value), 0.0 # 1.23() + if '.' in value: + # float + if not error: + return float(value), 0.0 # 1.23() + else: + err = (10 ** -(len(f'{value}'.split('.')[1]) - 1)) * int(error) + return float(value), err else: - err = (10 ** -(len(f'{value}'.split('.')[1]) - 1)) * int(error) - return float(value), err + # int + if not error: + return int(value), 0 + else: + err = 10 ** (len(str(error)) - 1) + return int(value), err + return float(value), None # 1.23 From ca28ab75ad5a2da453a79880e20787789aa94304 Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Fri, 14 Feb 2025 09:22:13 +0100 Subject: [PATCH 15/33] fixed reading of errors in phase cif --- src/easydiffraction/job/model/phase.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/easydiffraction/job/model/phase.py b/src/easydiffraction/job/model/phase.py index bf0a0e8e..018e8a6d 100644 --- a/src/easydiffraction/job/model/phase.py +++ b/src/easydiffraction/job/model/phase.py @@ -15,6 +15,10 @@ class Phase(ecPhase): def __init__(self, name, spacegroup=None, cell=None, atoms=None, scale=None, interface=None, enforce_sym=True, **kwargs): super(Phase, self).__init__(name, spacegroup, cell, atoms, scale, enforce_sym=enforce_sym) + # we need to overwrite cell and atoms, since ecPhase constructor doesn't append the error info + self.cell = cell + self.atoms = atoms + # spacegroup is not being overwritten, since no error info is being appended self.interface = interface def add_atom(self, *args, **kwargs): From c7a7b53078e84025e88daef403e35ed6fad8225b Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Fri, 14 Feb 2025 14:15:13 +0100 Subject: [PATCH 16/33] tof stuff from new_param_tof --- .../calculators/cryspy/calculator.py | 3 + .../calculators/cryspy/parser.py | 1380 ++++++++++++++++- src/easydiffraction/io/cif_reader.py | 6 + .../job/experiment/experiment.py | 5 + src/easydiffraction/job/experiment/pd_1d.py | 6 + src/easydiffraction/job/job.py | 5 +- 6 files changed, 1403 insertions(+), 2 deletions(-) diff --git a/src/easydiffraction/calculators/cryspy/calculator.py b/src/easydiffraction/calculators/cryspy/calculator.py index a6955bc8..4f3718dc 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -965,6 +965,9 @@ def _do_run(self, model, polarized, x_array, crystals, phase_list, bg, phase_sca flag_use_precalculated_data=False, flag_calc_analytical_derivatives=False, ) + if not res: + raise RuntimeError('No result from calculation') + chi2 = res[0] point_count = res[1] free_param_count = len(res[4]) diff --git a/src/easydiffraction/calculators/cryspy/parser.py b/src/easydiffraction/calculators/cryspy/parser.py index d24b3d53..4ddf7d55 100644 --- a/src/easydiffraction/calculators/cryspy/parser.py +++ b/src/easydiffraction/calculators/cryspy/parser.py @@ -65,7 +65,1385 @@ def __init__( self['unit'] = unit -def calcObjAndDictToEdExperiments(calc_obj, calc_dict): +def calcObjAndDictToEdExperiments(cryspy_obj, cryspy_dict): + # NEED to be modified similar to cryspyObjAndDictToEdModels -> cryspyObjToEdModels + + experiment_names = [] + # possible experiment prefixes + exp_substrings = [ + 'pd_', # 'pd-cwl + 'tof_', # 'pd-tof' + 'diffrn_', # 'sg-cwl' + 'data_', + ] + # get experiment names from cryspy_dict + for key in cryspy_dict.keys(): + for substring in exp_substrings: + if key.startswith(substring): + key = key.replace(substring, '').replace('_', '') + experiment_names.append(key) + + ed_experiments_meas_only = [] + ed_experiments_no_meas = [] + + for data_block in cryspy_obj.items: + data_block_name = data_block.data_name + + if data_block_name in experiment_names: + cryspy_experiment = data_block.items + ed_experiment_no_meas = {'name': '', 'params': {}, 'loops': {}} + ed_experiment_meas_only = {'name': '', 'loops': {}} + + # DATABLOCK ID + + ed_experiment_no_meas['name'] = dict( + Parameter( + data_block_name, + icon='microscope', + url='https://docs.easydiffraction.org/app/dictionaries/', + ) + ) + ed_experiment_meas_only['name'] = dict( + Parameter( + data_block_name, + icon='microscope', + url='https://docs.easydiffraction.org/app/dictionaries/', + ) + ) + + for item in cryspy_experiment: + # DATABLOCK SINGLES + + # Ranges category + if type(item) is cryspy.C_item_loop_classes.cl_1_range.Range: + ed_experiment_no_meas['params']['_pd_meas'] = {} + # pd-cwl ranges + if hasattr(item, 'ttheta_min') and hasattr(item, 'ttheta_max'): + ed_experiment_no_meas['params']['_pd_meas']['2theta_range_min'] = dict( + Parameter( + item.ttheta_min, + optional=True, + category='_pd_meas', + name='2theta_range_min', + prettyName='range min', + shortPrettyName='min', + url='https://docs.easydiffraction.org/app/dictionaries/', + cifDict='pd', + ) + ) + ed_experiment_no_meas['params']['_pd_meas']['2theta_range_max'] = dict( + Parameter( + item.ttheta_max, + optional=True, + category='_pd_meas', + name='2theta_range_max', + prettyName='range max', + shortPrettyName='max', + url='https://docs.easydiffraction.org/app/dictionaries/', + cifDict='pd', + ) + ) + ed_experiment_no_meas['params']['_pd_meas']['2theta_range_inc'] = dict( + Parameter( + 0.1, # initial value to be updated later + optional=True, + category='_pd_meas', + name='2theta_range_inc', + prettyName='range inc', + shortPrettyName='inc', + url='https://docs.easydiffraction.org/app/dictionaries/', + cifDict='pd', + ) + ) + # pd-tof ranges + elif hasattr(item, 'time_min') and hasattr(item, 'time_max'): + ed_experiment_no_meas['params']['_pd_meas']['tof_range_min'] = dict( + Parameter( + item.time_min, + optional=True, + category='_pd_meas', + name='tof_range_min', + prettyName='range min', + shortPrettyName='min', + url='https://docs.easydiffraction.org/app/dictionaries/', + ) + ) + ed_experiment_no_meas['params']['_pd_meas']['tof_range_max'] = dict( + Parameter( + item.time_max, + optional=True, + category='_pd_meas', + name='tof_range_max', + prettyName='range max', + shortPrettyName='max', + url='https://docs.easydiffraction.org/app/dictionaries/', + ) + ) + ed_experiment_no_meas['params']['_pd_meas']['tof_range_inc'] = dict( + Parameter( + 10.0, # initial value to be updated later + optional=True, + category='_pd_meas', + name='tof_range_inc', + prettyName='range inc', + shortPrettyName='inc', + url='https://docs.easydiffraction.org/app/dictionaries/', + ) + ) + + # Start from the beginning after reading ranges + for item in cryspy_experiment: + # DATABLOCK SINGLES + + # Phase(s) section + # pd-cwl and pd-tof phases + if type(item) is cryspy.C_item_loop_classes.cl_1_phase.PhaseL: + cryspy_phases = item.items + ed_phases = [] + for idx, cryspy_phase in enumerate(cryspy_phases): + ed_phase = {} + ed_phase['id'] = dict( + Parameter( + cryspy_phase.label, + idx=idx, + category='_pd_phase_block', + name='id', + shortPrettyName='label', + url='https://docs.easydiffraction.org/app/dictionaries/_phase/', + cifDict='pd', + ) + ) + ed_phase['scale'] = dict( + Parameter( + cryspy_phase.scale, + error=cryspy_phase.scale_sigma, + idx=idx, + category='_pd_phase_block', + prettyCategory='phase', + rowName=cryspy_phase.label, + name='scale', + prettyName='scale', + shortPrettyName='scale', + icon='weight', + categoryIcon='layer-group', + url='https://docs.easydiffraction.org/app/dictionaries/_phase/', + cifDict='pd', + pctDelta=25, + fittable=True, + fit=cryspy_phase.scale_refinement, + ) + ) + ed_phases.append(ed_phase) + ed_experiment_no_meas['loops']['_pd_phase_block'] = ed_phases + # sg-cwl phase + elif type(item) is cryspy.C_item_loop_classes.cl_1_phase.Phase: + cryspy_phases = [item] + ed_phases = [] + for idx, cryspy_phase in enumerate(cryspy_phases): + ed_phase = {} + ed_phase['id'] = dict( + Parameter( + cryspy_phase.label, + idx=idx, + category='_exptl_crystal', + name='id', + shortPrettyName='label', + url='https://docs.easydiffraction.org/app/dictionaries/_phase/', + cifDict='core', + ) + ) + ed_phase['scale'] = dict( + Parameter( + cryspy_phase.scale, + error=cryspy_phase.scale_sigma, + idx=idx, + category='_exptl_crystal', + prettyCategory='phase', + rowName=cryspy_phase.label, + name='scale', + prettyName='scale', + shortPrettyName='scale', + icon='weight', + categoryIcon='layer-group', + url='https://docs.easydiffraction.org/app/dictionaries/_phase/', + cifDict='core', + pctDelta=25, + fittable=True, + fit=cryspy_phase.scale_refinement, + ) + ) + ed_phases.append(ed_phase) + ed_experiment_no_meas['loops']['_exptl_crystal'] = ed_phases + + # Cryspy setup section (TOF/CWL) + elif type(item) is cryspy.C_item_loop_classes.cl_1_setup.Setup: + if hasattr(item, 'radiation'): + if '_diffrn_radiation' not in ed_experiment_no_meas['params']: + ed_experiment_no_meas['params']['_diffrn_radiation'] = {} + ed_experiment_no_meas['params']['_diffrn_radiation']['probe'] = dict( + Parameter( + item.radiation.replace('neutrons', 'neutron').replace('X-rays', 'x-ray'), # NEED FIX + permittedValues=['neutron', 'x-ray'], + category='_diffrn_radiation', + name='probe', + shortPrettyName='probe', + url='https://docs.easydiffraction.org/app/dictionaries/_diffrn_radiation/', + cifDict='core', + ) + ) + if hasattr(item, 'wavelength'): + if '_diffrn_radiation_wavelength' not in ed_experiment_no_meas['params']: + ed_experiment_no_meas['params']['_diffrn_radiation_wavelength'] = {} + ed_experiment_no_meas['params']['_diffrn_radiation_wavelength']['wavelength'] = dict( + Parameter( + item.wavelength, + error=item.wavelength_sigma, + category='_diffrn_radiation_wavelength', + prettyCategory='radiation', + name='wavelength', + prettyName='wavelength', + shortPrettyName='wavelength', + icon='radiation', + url='https://docs.easydiffraction.org/app/dictionaries/_diffrn_radiation/', + cifDict='core', + absDelta=0.01, + units='Å', + fittable=True, + fit=item.wavelength_refinement, + ) + ) + if hasattr(item, 'offset_ttheta'): + if '_pd_calib' not in ed_experiment_no_meas['params']: + ed_experiment_no_meas['params']['_pd_calib'] = {} + ed_experiment_no_meas['params']['_pd_calib']['2theta_offset'] = dict( + Parameter( + item.offset_ttheta, + error=item.offset_ttheta_sigma, + category='_pd_calib', + prettyCategory='calib', + name='2theta_offset', + prettyName='2θ offset', + shortPrettyName='offset', + icon='arrows-alt-h', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_calib/', + cifDict='pd', + absDelta=0.2, + units='°', + fittable=True, + fit=item.offset_ttheta_refinement, + ) + ) + + # Cryspy extinction parameters section + # sg-cwl + elif type(item) is cryspy.C_item_loop_classes.cl_1_extinction.Extinction: + if hasattr(item, 'model') and hasattr(item, 'mosaicity') and hasattr(item, 'radius'): + if '_extinction' not in ed_experiment_no_meas['params']: + ed_experiment_no_meas['params']['_extinction'] = {} + ed_experiment_no_meas['params']['_extinction']['model'] = dict( + Parameter( + item.model, + category='_extinction', + prettyCategory='ext', + name='model', + prettyName='model', + shortPrettyName='model', + icon='arrow-down', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + ) + ) + ed_experiment_no_meas['params']['_extinction']['mosaicity'] = dict( + Parameter( + item.mosaicity, + error=item.mosaicity_sigma, + category='_extinction', + prettyCategory='ext', + name='mosaicity', + prettyName='mosaicity', + shortPrettyName='mosaicity', # NEED FIX: rename to one letter... + icon='arrow-down', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + pctDelta=25, + fittable=True, + fit=item.mosaicity_refinement, + ) + ) + ed_experiment_no_meas['params']['_extinction']['radius'] = dict( + Parameter( + item.radius, + error=item.radius_sigma, + category='_extinction', + prettyCategory='ext', + name='radius', + prettyName='radius', + shortPrettyName='radius', # NEED FIX: rename to one letter... + icon='arrow-down', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + pctDelta=25, + fittable=True, + fit=item.radius_refinement, + ) + ) + + # Cryspy instrument resolution section (CWL) + elif type(item) is cryspy.C_item_loop_classes.cl_1_pd_instr_resolution.PdInstrResolution: + if ( + hasattr(item, 'u') + and hasattr(item, 'v') + and hasattr(item, 'w') + and hasattr(item, 'x') + and hasattr(item, 'y') + ): + if '_pd_instr' not in ed_experiment_no_meas['params']: + ed_experiment_no_meas['params']['_pd_instr'] = {} + ed_experiment_no_meas['params']['_pd_instr']['resolution_u'] = dict( + Parameter( + item.u, + error=item.u_sigma, + category='_pd_instr', + prettyCategory='inst', + name='resolution_u', + prettyName='resolution u', + shortPrettyName='u', + icon='shapes', # 'grip-lines-vertical' + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.1, + fittable=True, + fit=item.u_refinement, + ) + ) + ed_experiment_no_meas['params']['_pd_instr']['resolution_v'] = dict( + Parameter( + item.v, + error=item.v_sigma, + category='_pd_instr', + prettyCategory='inst', + name='resolution_v', + prettyName='resolution v', + shortPrettyName='v', + icon='shapes', # 'grip-lines-vertical' + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.1, + fittable=True, + fit=item.v_refinement, + ) + ) + ed_experiment_no_meas['params']['_pd_instr']['resolution_w'] = dict( + Parameter( + item.w, + error=item.w_sigma, + category='_pd_instr', + prettyCategory='inst', + name='resolution_w', + prettyName='resolution w', + shortPrettyName='w', + icon='shapes', # 'grip-lines-vertical' + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.1, + fittable=True, + fit=item.w_refinement, + ) + ) + ed_experiment_no_meas['params']['_pd_instr']['resolution_x'] = dict( + Parameter( + item.x, + error=item.x_sigma, + category='_pd_instr', + prettyCategory='inst', + name='resolution_x', + prettyName='resolution x', + shortPrettyName='x', + icon='shapes', # 'grip-lines-vertical' + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.1, + fittable=True, + fit=item.x_refinement, + ) + ) + ed_experiment_no_meas['params']['_pd_instr']['resolution_y'] = dict( + Parameter( + item.y, + error=item.y_sigma, + category='_pd_instr', + prettyCategory='inst', + name='resolution_y', + prettyName='resolution y', + shortPrettyName='y', + icon='shapes', # 'grip-lines-vertical' + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.1, + fittable=True, + fit=item.y_refinement, + ) + ) + + # Cryspy peak asymmetries section (CWL) + elif type(item) is cryspy.C_item_loop_classes.cl_1_pd_instr_reflex_asymmetry.PdInstrReflexAsymmetry: + if hasattr(item, 'p1') and hasattr(item, 'p2') and hasattr(item, 'p3') and hasattr(item, 'p4'): + if '_pd_instr' not in ed_experiment_no_meas['params']: + ed_experiment_no_meas['params']['_pd_instr'] = {} + ed_experiment_no_meas['params']['_pd_instr']['reflex_asymmetry_p1'] = dict( + Parameter( + item.p1, + error=item.p1_sigma, + category='_pd_instr', + prettyCategory='inst', + name='reflex_asymmetry_p1', + prettyName='asymmetry p1', + shortPrettyName='p1', + icon='balance-scale-left', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.5, + fittable=True, + fit=item.p1_refinement, + ) + ) + ed_experiment_no_meas['params']['_pd_instr']['reflex_asymmetry_p2'] = dict( + Parameter( + item.p2, + error=item.p2_sigma, + category='_pd_instr', + prettyCategory='inst', + name='reflex_asymmetry_p2', + prettyName='asymmetry p2', + shortPrettyName='p2', + icon='balance-scale-left', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.5, + fittable=True, + fit=item.p2_refinement, + ) + ) + ed_experiment_no_meas['params']['_pd_instr']['reflex_asymmetry_p3'] = dict( + Parameter( + item.p3, + error=item.p3_sigma, + category='_pd_instr', + prettyCategory='inst', + name='reflex_asymmetry_p3', + prettyName='asymmetry p3', + shortPrettyName='p3', + icon='balance-scale-left', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.5, + fittable=True, + fit=item.p3_refinement, + ) + ) + ed_experiment_no_meas['params']['_pd_instr']['reflex_asymmetry_p4'] = dict( + Parameter( + item.p4, + error=item.p4_sigma, + category='_pd_instr', + prettyCategory='inst', + name='reflex_asymmetry_p4', + prettyName='asymmetry p4', + shortPrettyName='p4', + icon='balance-scale-left', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.5, + fittable=True, + fit=item.p4_refinement, + ) + ) + + # Cryspy parameters section (TOF) + elif type(item) is cryspy.C_item_loop_classes.cl_1_tof_parameters.TOFParameters: + if ( + hasattr(item, 'zero') + and hasattr(item, 'dtt1') + and hasattr(item, 'dtt2') + and hasattr(item, 'ttheta_bank') + ): + if '_pd_instr' not in ed_experiment_no_meas['params']: + ed_experiment_no_meas['params']['_pd_instr'] = {} + ed_experiment_no_meas['params']['_pd_instr']['2theta_bank'] = dict( + Parameter( + item.ttheta_bank, + category='_pd_instr', + prettyCategory='inst', + name='2theta_bank', + prettyName='2theta bank', + shortPrettyName='2θ bank', + icon='hashtag', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + fittable=False, + ) + ) + ed_experiment_no_meas['params']['_pd_instr']['dtt1'] = dict( + Parameter( + item.dtt1, + error=item.dtt1_sigma, + category='_pd_instr', + prettyCategory='inst', + name='dtt1', # DIFC in GSAS + prettyName='dtt1', + shortPrettyName='dtt1', + icon='radiation', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=100.0, + fittable=True, + fit=item.dtt1_refinement, + ) + ) + ed_experiment_no_meas['params']['_pd_instr']['dtt2'] = dict( + Parameter( + item.dtt2, + error=item.dtt2_sigma, + category='_pd_instr', + prettyCategory='inst', + name='dtt2', # DIFA in GSAS + prettyName='dtt2', + shortPrettyName='dtt2', + icon='radiation', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.1, + fittable=True, + fit=item.dtt2_refinement, + ) + ) + ed_experiment_no_meas['params']['_pd_instr']['zero'] = dict( + Parameter( + item.zero, + error=item.zero_sigma, + category='_pd_instr', + prettyCategory='inst', + name='zero', # TZERO in GSAS + prettyName='zero', + shortPrettyName='zero', + icon='arrows-alt-h', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.5, + fittable=True, + fit=item.zero_refinement, + ) + ) + + # Cryspy peak profile section (TOF) + elif type(item) is cryspy.C_item_loop_classes.cl_1_tof_profile.TOFProfile: + if hasattr(item, 'alpha0') and hasattr(item, 'beta0') and hasattr(item, 'sigma0'): + if '_pd_instr' not in ed_experiment_no_meas['params']: + ed_experiment_no_meas['params']['_pd_instr'] = {} + ed_experiment_no_meas['params']['_pd_instr']['alpha0'] = dict( + Parameter( + item.alpha0, + error=item.alpha0_sigma, + category='_pd_instr', + prettyCategory='inst', + name='alpha0', + prettyName='alpha0', + shortPrettyName='α0', + icon='shapes', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.5, + fittable=True, + fit=item.alpha0_refinement, + ) + ) + ed_experiment_no_meas['params']['_pd_instr']['alpha1'] = dict( + Parameter( + item.alpha1, + error=item.alpha1_sigma, + category='_pd_instr', + prettyCategory='inst', + name='alpha1', + prettyName='alpha1', + shortPrettyName='α1', + icon='shapes', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.5, + fittable=True, + fit=item.alpha1_refinement, + ) + ) + ed_experiment_no_meas['params']['_pd_instr']['beta0'] = dict( + Parameter( + item.beta0, + error=item.beta0_sigma, + category='_pd_instr', + prettyCategory='inst', + name='beta0', + prettyName='beta0', + shortPrettyName='β0', + icon='shapes', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.5, + fittable=True, + fit=item.beta0_refinement, + ) + ) + ed_experiment_no_meas['params']['_pd_instr']['beta1'] = dict( + Parameter( + item.beta1, + error=item.beta1_sigma, + category='_pd_instr', + prettyCategory='inst', + name='beta1', + prettyName='beta1', + shortPrettyName='β1', + icon='shapes', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.5, + fittable=True, + fit=item.beta1_refinement, + ) + ) + ed_experiment_no_meas['params']['_pd_instr']['sigma0'] = dict( + Parameter( + item.sigma0, + error=item.sigma0_sigma, + category='_pd_instr', + prettyCategory='inst', + name='sigma0', + prettyName='sigma0', + shortPrettyName='σ0', + icon='shapes', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.5, + fittable=True, + fit=item.sigma0_refinement, + ) + ) + ed_experiment_no_meas['params']['_pd_instr']['sigma1'] = dict( + Parameter( + item.sigma1, + error=item.sigma1_sigma, + category='_pd_instr', + prettyCategory='inst', + name='sigma1', + prettyName='sigma1', + shortPrettyName='σ1', + icon='shapes', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.5, + fittable=True, + fit=item.sigma1_refinement, + ) + ) + if hasattr(item, 'sigma2'): + if '_pd_instr' not in ed_experiment_no_meas['params']: + ed_experiment_no_meas['params']['_pd_instr'] = {} + ed_experiment_no_meas['params']['_pd_instr']['sigma2'] = dict( + Parameter( + item.sigma2, + error=item.sigma2_sigma, + category='_pd_instr', + prettyCategory='inst', + name='sigma2', + prettyName='sigma2', + shortPrettyName='σ2', + icon='shapes', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.5, + fittable=True, + fit=item.sigma2_refinement, + ) + ) + if hasattr(item, 'gamma0') and hasattr(item, 'gamma1') and hasattr(item, 'gamma2'): + if '_pd_instr' not in ed_experiment_no_meas['params']: + ed_experiment_no_meas['params']['_pd_instr'] = {} + ed_experiment_no_meas['params']['_pd_instr']['gamma0'] = dict( + Parameter( + item.gamma0, + error=item.gamma0_sigma, + category='_pd_instr', + prettyCategory='inst', + name='gamma0', + prettyName='gamma0', + shortPrettyName='γ0', + icon='shapes', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.5, + fittable=True, + fit=item.gamma0_refinement, + ) + ) + ed_experiment_no_meas['params']['_pd_instr']['gamma1'] = dict( + Parameter( + item.gamma1, + error=item.gamma1_sigma, + category='_pd_instr', + prettyCategory='inst', + name='gamma1', + prettyName='gamma1', + shortPrettyName='γ1', + icon='shapes', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.5, + fittable=True, + fit=item.gamma1_refinement, + ) + ) + ed_experiment_no_meas['params']['_pd_instr']['gamma2'] = dict( + Parameter( + item.gamma2, + error=item.gamma2_sigma, + category='_pd_instr', + prettyCategory='inst', + name='gamma2', + prettyName='gamma2', + shortPrettyName='γ2', + icon='shapes', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + absDelta=0.5, + fittable=True, + fit=item.gamma2_refinement, + ) + ) + + # Cryspy background section (TOF, points) + elif type(item) is cryspy.C_item_loop_classes.cl_1_tof_background_by_points.TOFBackgroundPointL: + cryspy_bkg_points = item.items + ed_bkg_points = [] + for idx, cryspy_bkg_point in enumerate(cryspy_bkg_points): + ed_bkg_point = {} + ed_bkg_point['line_segment_X'] = dict( + Parameter( + cryspy_bkg_point.time, + idx=idx, + category='_pd_background', + name='line_segment_X', + prettyName='TOF', + shortPrettyName='TOF', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + cifDict='pd', + ) + ) + ed_bkg_point['line_segment_intensity'] = dict( + Parameter( + cryspy_bkg_point.intensity, + error=cryspy_bkg_point.intensity_sigma, + idx=idx, + category='_pd_background', + prettyCategory='bkg', + rowName=f'{cryspy_bkg_point.time:g}µs', # formatting float to str without trailing zeros + name='line_segment_intensity', + prettyName='intensity', + shortPrettyName='Ibkg', + icon='mountain', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + cifDict='pd', + pctDelta=25, + fittable=True, + fit=cryspy_bkg_point.intensity_refinement, + ) + ) + ed_bkg_point['X_coordinate'] = dict( + Parameter( + 'time-of-flight', + idx=idx, + category='_pd_background', + name='X_coordinate', + prettyName='X coord', + shortPrettyName='X coord', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + cifDict='pd', + ) + ) + ed_bkg_points.append(ed_bkg_point) + ed_experiment_no_meas['loops']['_pd_background'] = ed_bkg_points + + # Cryspy background section (TOF, polinom coeffs) + elif type(item) is cryspy.C_item_loop_classes.cl_1_tof_background.TOFBackground: + if hasattr(item, 'time_max'): + if '_tof_background' not in ed_experiment_no_meas['params']: + ed_experiment_no_meas['params']['_tof_background'] = {} + ed_experiment_no_meas['params']['_tof_background']['time_max'] = dict( + Parameter( + item.time_max, + optional=True, + category='_tof_background', + prettyCategory='bkg', + name='time_max', # Is this the name used on save cif? + prettyName='TOF max', + shortPrettyName='max', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_instr/', + ) + ) + ed_experiment_no_meas['params']['_tof_background']['coeff1'] = dict( + Parameter( + item.coeff1 if hasattr(item, 'coeff1') else 0.0, + error=item.coeff1_sigma, + category='_tof_background', + prettyCategory='bkg', + name='coeff1', + prettyName='coeff1', + shortPrettyName='c1', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + pctDelta=25, + fittable=True, + fit=item.coeff1_refinement, + ) + ) + ed_experiment_no_meas['params']['_tof_background']['coeff2'] = dict( + Parameter( + item.coeff2 if hasattr(item, 'coeff2') else 0.0, + error=item.coeff2_sigma, + category='_tof_background', + prettyCategory='bkg', + name='coeff2', + prettyName='coeff2', + shortPrettyName='c2', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + pctDelta=25, + fittable=True, + fit=item.coeff2_refinement, + ) + ) + ed_experiment_no_meas['params']['_tof_background']['coeff3'] = dict( + Parameter( + item.coeff3 if hasattr(item, 'coeff3') else 0.0, + error=item.coeff3_sigma, + category='_tof_background', + prettyCategory='bkg', + name='coeff3', + prettyName='coeff3', + shortPrettyName='c3', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + pctDelta=25, + fittable=True, + fit=item.coeff3_refinement, + ) + ) + ed_experiment_no_meas['params']['_tof_background']['coeff4'] = dict( + Parameter( + item.coeff4 if hasattr(item, 'coeff4') else 0.0, + error=item.coeff4_sigma, + category='_tof_background', + prettyCategory='bkg', + name='coeff4', + prettyName='coeff4', + shortPrettyName='c4', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + pctDelta=25, + fittable=True, + fit=item.coeff4_refinement, + ) + ) + ed_experiment_no_meas['params']['_tof_background']['coeff5'] = dict( + Parameter( + item.coeff5 if hasattr(item, 'coeff5') else 0.0, + error=item.coeff5_sigma, + category='_tof_background', + prettyCategory='bkg', + name='coeff5', + prettyName='coeff5', + shortPrettyName='c5', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + pctDelta=25, + fittable=True, + fit=item.coeff5_refinement, + ) + ) + ed_experiment_no_meas['params']['_tof_background']['coeff6'] = dict( + Parameter( + item.coeff6 if hasattr(item, 'coeff6') else 0.0, + error=item.coeff6_sigma, + category='_tof_background', + prettyCategory='bkg', + name='coeff6', + prettyName='coeff6', + shortPrettyName='c6', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + pctDelta=25, + fittable=True, + fit=item.coeff6_refinement, + ) + ) + ed_experiment_no_meas['params']['_tof_background']['coeff7'] = dict( + Parameter( + item.coeff7 if hasattr(item, 'coeff7') else 0.0, + error=item.coeff7_sigma, + category='_tof_background', + prettyCategory='bkg', + name='coeff7', + prettyName='coeff7', + shortPrettyName='c7', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + pctDelta=25, + fittable=True, + fit=item.coeff7_refinement, + ) + ) + ed_experiment_no_meas['params']['_tof_background']['coeff8'] = dict( + Parameter( + item.coeff8 if hasattr(item, 'coeff8') else 0.0, + error=item.coeff8_sigma, + category='_tof_background', + prettyCategory='bkg', + name='coeff8', + prettyName='coeff8', + shortPrettyName='c8', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + pctDelta=25, + fittable=True, + fit=item.coeff8_refinement, + ) + ) + ed_experiment_no_meas['params']['_tof_background']['coeff9'] = dict( + Parameter( + item.coeff9 if hasattr(item, 'coeff9') else 0.0, + error=item.coeff9_sigma, + category='_tof_background', + prettyCategory='bkg', + name='coeff9', + prettyName='coeff9', + shortPrettyName='c9', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + pctDelta=25, + fittable=True, + fit=item.coeff9_refinement, + ) + ) + ed_experiment_no_meas['params']['_tof_background']['coeff10'] = dict( + Parameter( + item.coeff10 if hasattr(item, 'coeff10') else 0.0, + error=item.coeff10_sigma, + category='_tof_background', + prettyCategory='bkg', + name='coeff10', + prettyName='coeff10', + shortPrettyName='c10', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + pctDelta=25, + fittable=True, + fit=item.coeff10_refinement, + ) + ) + ed_experiment_no_meas['params']['_tof_background']['coeff11'] = dict( + Parameter( + item.coeff11 if hasattr(item, 'coeff11') else 0.0, + error=item.coeff11_sigma, + category='_tof_background', + prettyCategory='bkg', + name='coeff11', + prettyName='coeff11', + shortPrettyName='c11', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + pctDelta=25, + fittable=True, + fit=item.coeff11_refinement, + ) + ) + ed_experiment_no_meas['params']['_tof_background']['coeff12'] = dict( + Parameter( + item.coeff12 if hasattr(item, 'coeff12') else 0.0, + error=item.coeff12_sigma, + category='_tof_background', + prettyCategory='bkg', + name='coeff12', + prettyName='coeff12', + shortPrettyName='c12', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + pctDelta=25, + fittable=True, + fit=item.coeff12_refinement, + ) + ) + ed_experiment_no_meas['params']['_tof_background']['coeff13'] = dict( + Parameter( + item.coeff13 if hasattr(item, 'coeff13') else 0.0, + error=item.coeff13_sigma, + category='_tof_background', + prettyCategory='bkg', + name='coeff13', + prettyName='coeff13', + shortPrettyName='c13', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + pctDelta=25, + fittable=True, + fit=item.coeff13_refinement, + ) + ) + ed_experiment_no_meas['params']['_tof_background']['coeff14'] = dict( + Parameter( + item.coeff14 if hasattr(item, 'coeff14') else 0.0, + error=item.coeff14_sigma, + category='_tof_background', + prettyCategory='bkg', + name='coeff14', + prettyName='coeff14', + shortPrettyName='c14', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + pctDelta=25, + fittable=True, + fit=item.coeff14_refinement, + ) + ) + ed_experiment_no_meas['params']['_tof_background']['coeff15'] = dict( + Parameter( + item.coeff15 if hasattr(item, 'coeff15') else 0.0, + error=item.coeff15_sigma, + category='_tof_background', + prettyCategory='bkg', + name='coeff15', + prettyName='coeff15', + shortPrettyName='c15', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + pctDelta=25, + fittable=True, + fit=item.coeff15_refinement, + ) + ) + ed_experiment_no_meas['params']['_tof_background']['coeff16'] = dict( + Parameter( + item.coeff16 if hasattr(item, 'coeff16') else 0.0, + error=item.coeff16_sigma, + category='_tof_background', + prettyCategory='bkg', + name='coeff16', + prettyName='coeff16', + shortPrettyName='c16', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + pctDelta=25, + fittable=True, + fit=item.coeff16_refinement, + ) + ) + ed_experiment_no_meas['params']['_tof_background']['coeff17'] = dict( + Parameter( + item.coeff17 if hasattr(item, 'coeff17') else 0.0, + error=item.coeff17_sigma, + category='_tof_background', + prettyCategory='bkg', + name='coeff17', + prettyName='coeff17', + shortPrettyName='c17', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + pctDelta=25, + fittable=True, + fit=item.coeff17_refinement, + ) + ) + ed_experiment_no_meas['params']['_tof_background']['coeff18'] = dict( + Parameter( + item.coeff18 if hasattr(item, 'coeff18') else 0.0, + error=item.coeff18_sigma, + category='_tof_background', + prettyCategory='bkg', + name='coeff18', + prettyName='coeff18', + shortPrettyName='c18', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + pctDelta=25, + fittable=True, + fit=item.coeff18_refinement, + ) + ) + + # Cryspy background section (CWL, points) + elif type(item) is cryspy.C_item_loop_classes.cl_1_pd_background.PdBackgroundL: + cryspy_bkg_points = item.items + ed_bkg_points = [] + for idx, cryspy_bkg_point in enumerate(cryspy_bkg_points): + ed_bkg_point = {} + ed_bkg_point['line_segment_X'] = dict( + Parameter( + cryspy_bkg_point.ttheta, + idx=idx, + category='_pd_background', + name='line_segment_X', + prettyName='2θ', + shortPrettyName='2θ', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + cifDict='pd', + ) + ) + ed_bkg_point['line_segment_intensity'] = dict( + Parameter( + cryspy_bkg_point.intensity, + error=cryspy_bkg_point.intensity_sigma, + idx=idx, + category='_pd_background', + prettyCategory='bkg', + rowName=f'{cryspy_bkg_point.ttheta:g}°', # formatting float to str without trailing zeros + name='line_segment_intensity', + prettyName='intensity', + shortPrettyName='Ibkg', + icon='mountain', + categoryIcon='wave-square', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + cifDict='pd', + pctDelta=25, + fittable=True, + fit=cryspy_bkg_point.intensity_refinement, + ) + ) + ed_bkg_point['X_coordinate'] = dict( + Parameter( + '2theta', + idx=idx, + category='_pd_background', + name='X_coordinate', + prettyName='X coord', + shortPrettyName='X coord', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_background/', + cifDict='pd', + ) + ) + ed_bkg_points.append(ed_bkg_point) + ed_experiment_no_meas['loops']['_pd_background'] = ed_bkg_points + + # Cryspy measured data section: pd-tof + elif type(item) is cryspy.C_item_loop_classes.cl_1_tof_meas.TOFMeasL: + if '_diffrn_radiation' not in ed_experiment_no_meas['params']: + ed_experiment_no_meas['params']['_diffrn_radiation'] = {} + ed_experiment_no_meas['params']['_diffrn_radiation']['type'] = dict( + Parameter( + 'tof', + optional=True, + category='_diffrn_radiation', + name='type', + shortPrettyName='type', + url='https://docs.easydiffraction.org/app/dictionaries/_diffrn_radiation/', + ) + ) + if '_sample' not in ed_experiment_no_meas['params']: + ed_experiment_no_meas['params']['_sample'] = {} + ed_experiment_no_meas['params']['_sample']['type'] = dict( + Parameter( + 'pd', + optional=True, + category='_sample', + name='type', # NEED FIX. If needed, should be different form _diffrn_radiation.type + shortPrettyName='type', # NEED FIX. If needed, should be different form _diffrn_radiation.type + url='https://docs.easydiffraction.org/app/dictionaries/_diffrn_radiation/', # NEED FIX + ) + ) + cryspy_meas_points = item.items + ed_meas_points = [] + for idx, cryspy_meas_point in enumerate(cryspy_meas_points): + ed_meas_point = {} + ed_meas_point['time_of_flight'] = dict( + Parameter( + cryspy_meas_point.time, + idx=idx, + category='_pd_meas', + name='time_of_flight', + shortPrettyName='tof', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_meas/', + cifDict='pd', + ) + ) + ed_meas_point['intensity_total'] = dict( + Parameter( + cryspy_meas_point.intensity, + idx=idx, + category='_pd_meas', + name='intensity_total', + shortPrettyName='I', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_meas/', + cifDict='pd', + ) + ) + ed_meas_point['intensity_total_su'] = dict( + Parameter( + cryspy_meas_point.intensity_sigma, + idx=idx, + category='_pd_meas', + name='intensity_total_su', + shortPrettyName='sI', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_meas/', + cifDict='pd', + ) + ) + ed_meas_points.append(ed_meas_point) + ed_experiment_meas_only['loops']['_pd_meas'] = ed_meas_points + + # Modify range_inc based on the measured data points in _pd_meas loop + pd_meas_range_min = ed_meas_points[0]['time_of_flight']['value'] + pd_meas_range_max = ed_meas_points[-1]['time_of_flight']['value'] + pd_meas_range_inc = (pd_meas_range_max - pd_meas_range_min) / (len(ed_meas_points) - 1) + ed_experiment_no_meas['params']['_pd_meas']['tof_range_inc']['value'] = pd_meas_range_inc + + # Cryspy measured data section: pd-cwl + elif type(item) is cryspy.C_item_loop_classes.cl_1_pd_meas.PdMeasL: + if '_diffrn_radiation' not in ed_experiment_no_meas['params']: + ed_experiment_no_meas['params']['_diffrn_radiation'] = {} + ed_experiment_no_meas['params']['_diffrn_radiation']['type'] = dict( + Parameter( + 'cwl', + optional=True, + category='_diffrn_radiation', + name='type', + shortPrettyName='type', + url='https://docs.easydiffraction.org/app/dictionaries/_diffrn_radiation/', + ) + ) + if '_sample' not in ed_experiment_no_meas['params']: + ed_experiment_no_meas['params']['_sample'] = {} + ed_experiment_no_meas['params']['_sample']['type'] = dict( + Parameter( + 'pd', + optional=True, + category='_sample', + name='type', # NEED FIX. If needed, should be different form _diffrn_radiation.type + shortPrettyName='type', # NEED FIX. If needed, should be different form _diffrn_radiation.type + url='https://docs.easydiffraction.org/app/dictionaries/_diffrn_radiation/', # NEED FIX + ) + ) + cryspy_meas_points = item.items + ed_meas_points = [] + for idx, cryspy_meas_point in enumerate(cryspy_meas_points): + ed_meas_point = {} + ed_meas_point['2theta_scan'] = dict( + Parameter( + cryspy_meas_point.ttheta, + idx=idx, + category='_pd_meas', + name='2theta_scan', + shortPrettyName='2θ', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_meas/', + cifDict='pd', + ) + ) + ed_meas_point['intensity_total'] = dict( + Parameter( + cryspy_meas_point.intensity, + idx=idx, + category='_pd_meas', + name='intensity_total', + shortPrettyName='I', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_meas/', + cifDict='pd', + ) + ) + ed_meas_point['intensity_total_su'] = dict( + Parameter( + cryspy_meas_point.intensity_sigma, + idx=idx, + category='_pd_meas', + name='intensity_total_su', + shortPrettyName='sI', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_meas/', + cifDict='pd', + ) + ) + ed_meas_points.append(ed_meas_point) + ed_experiment_meas_only['loops']['_pd_meas'] = ed_meas_points + + # Modify range_inc based on the measured data points in _pd_meas loop + pd_meas_range_min = ed_meas_points[0]['2theta_scan']['value'] + pd_meas_range_max = ed_meas_points[-1]['2theta_scan']['value'] + pd_meas_range_inc = (pd_meas_range_max - pd_meas_range_min) / (len(ed_meas_points) - 1) + ed_experiment_no_meas['params']['_pd_meas']['2theta_range_inc']['value'] = pd_meas_range_inc + + # Cryspy measured data section: sg-cwl + elif type(item) is cryspy.C_item_loop_classes.cl_1_diffrn_refln.DiffrnReflnL: + if '_diffrn_radiation' not in ed_experiment_no_meas['params']: + ed_experiment_no_meas['params']['_diffrn_radiation'] = {} + ed_experiment_no_meas['params']['_diffrn_radiation']['type'] = dict( + Parameter( + 'cwl', + optional=True, + category='_diffrn_radiation', + name='type', + shortPrettyName='type', + url='https://docs.easydiffraction.org/app/dictionaries/_diffrn_radiation/', + ) + ) + if '_sample' not in ed_experiment_no_meas['params']: + ed_experiment_no_meas['params']['_sample'] = {} + ed_experiment_no_meas['params']['_sample']['type'] = dict( + Parameter( + 'sg', + optional=True, + category='_sample', + name='type', # NEED FIX. If needed, should be different form _diffrn_radiation.type + shortPrettyName='type', # NEED FIX. If needed, should be different form _diffrn_radiation.type + url='https://docs.easydiffraction.org/app/dictionaries/_diffrn_radiation/', # NEED FIX + ) + ) + cryspy_meas_points = item.items + ed_meas_points = [] + for idx, cryspy_meas_point in enumerate(cryspy_meas_points): + ed_meas_point = {} + ed_meas_point['index_h'] = dict( + Parameter( + cryspy_meas_point.index_h, + idx=idx, + category='_refln', + name='index_h', + shortPrettyName='h', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_meas/', + cifDict='core', + ) + ) + ed_meas_point['index_k'] = dict( + Parameter( + cryspy_meas_point.index_k, + idx=idx, + category='_refln', + name='index_k', + shortPrettyName='k', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_meas/', + cifDict='core', + ) + ) + ed_meas_point['index_l'] = dict( + Parameter( + cryspy_meas_point.index_l, + idx=idx, + category='_refln', + name='index_l', + shortPrettyName='l', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_meas/', + cifDict='core', + ) + ) + ed_meas_point['intensity_total'] = dict( + Parameter( + cryspy_meas_point.intensity, + idx=idx, + category='_refln', + name='intensity_meas', + shortPrettyName='I', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_meas/', + cifDict='core', + ) + ) + ed_meas_point['intensity_total_su'] = dict( + Parameter( + cryspy_meas_point.intensity_sigma, + idx=idx, + category='_refln', + name='intensity_meas_su', + shortPrettyName='sI', + url='https://docs.easydiffraction.org/app/dictionaries/_pd_meas/', + cifDict='core', + ) + ) + ed_meas_points.append(ed_meas_point) + ed_experiment_meas_only['loops']['_refln'] = ed_meas_points + + if ed_experiment_meas_only is not None: + ed_experiments_meas_only.append(ed_experiment_meas_only) + if ed_experiment_no_meas is not None: + ed_experiments_no_meas.append(ed_experiment_no_meas) + + return ed_experiments_meas_only, ed_experiments_no_meas + + +def calcObjAndDictToEdExperiments_old(calc_obj, calc_dict): experiment_names = [] exp_substrings = ['pd_', 'data_'] # possible experiment prefixes # get experiment names from cryspy_dict diff --git a/src/easydiffraction/io/cif_reader.py b/src/easydiffraction/io/cif_reader.py index 90bb61ac..3822872d 100644 --- a/src/easydiffraction/io/cif_reader.py +++ b/src/easydiffraction/io/cif_reader.py @@ -153,6 +153,12 @@ def parameters_from_cif_block(block) -> dict: if value is not None: parameters['2theta_bank'] = {} parameters['2theta_bank']['value'], parameters['2theta_bank']['error'] = parse_with_error(value) + + value = block.find_value('_pd_instr.zero') or block.find_value('_pd_instr_zero') + if value is not None: + parameters['zero'] = {} + parameters['zero']['value'], parameters['zero']['error'] = parse_with_error(value) + value = block.find_value('_pd_instr_peak_shape') or block.find_value('_pd_instr.peak_shape') if value is not None: parameters['peak_shape'] = value diff --git a/src/easydiffraction/job/experiment/experiment.py b/src/easydiffraction/job/experiment/experiment.py index 04e42947..cec7787b 100644 --- a/src/easydiffraction/job/experiment/experiment.py +++ b/src/easydiffraction/job/experiment/experiment.py @@ -249,6 +249,11 @@ def tof_parameters_from_dict(self, p: dict): if p['2theta_bank'].get('error') is not None: parameters.ttheta_bank.error = p['2theta_bank'].get('error') parameters.ttheta_bank.fixed = False + if 'zero' in p: + parameters.zero = p['zero'].get('value', 0.0) + if p['zero'].get('error') is not None: + parameters.zero.error = p['zero'].get('error') + parameters.zero.fixed = False if 'alpha0' in p: parameters.alpha0 = p['alpha0'].get('value', 0.0) if p['alpha0'].get('error') is not None: diff --git a/src/easydiffraction/job/experiment/pd_1d.py b/src/easydiffraction/job/experiment/pd_1d.py index 9daf79ad..5bc5c4ca 100644 --- a/src/easydiffraction/job/experiment/pd_1d.py +++ b/src/easydiffraction/job/experiment/pd_1d.py @@ -461,6 +461,12 @@ class Instrument1DTOFParameters(BaseObj): 'value': 0.00224, 'fixed': True, }, + 'zero': { + 'name': 'zero', + 'url': 'https://docs.easydiffraction.org/lib/dictionaries/_pd_instr/', + 'value': 0.0, + 'fixed': True, + }, } ttheta_bank: ClassVar[Parameter] diff --git a/src/easydiffraction/job/job.py b/src/easydiffraction/job/job.py index bbd10272..16d1c0ed 100644 --- a/src/easydiffraction/job/job.py +++ b/src/easydiffraction/job/job.py @@ -420,7 +420,10 @@ def add_experiment_from_file(self, file_url: str) -> None: self.experiment.from_xye_file(file_url) else: self.experiment.from_cif_file(file_url) + self.update_after_new_experiment() + def update_after_new_experiment(self) -> None: + """ """ self.update_experiment_type() # re-do the sample in case of type change. # Different type read in (likely TOF), so re-create the sample @@ -453,7 +456,7 @@ def add_experiment_from_string(self, cif_string: str) -> None: Just a wrapper around the Experiment class method. """ self.experiment.from_cif_string(cif_string) - self.update_experiment_type() + self.update_after_new_experiment() def add_sample_from_file(self, file_url: str) -> None: """ From 7a9b9fdbb369ed0360fd43301eb350162aad6a61 Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Fri, 14 Feb 2025 15:40:00 +0100 Subject: [PATCH 17/33] changes after merging DescriptorAny in EasyCrystallography --- pyproject.toml | 2 +- src/easydiffraction/job/experiment/backgrounds/background.py | 2 +- src/easydiffraction/job/experiment/backgrounds/point.py | 4 ++-- src/easydiffraction/job/experiment/experiment.py | 4 ++-- src/easydiffraction/job/experiment/pd_1d.py | 4 ++-- src/easydiffraction/job/experiment/polarization.py | 2 +- src/easydiffraction/job/model/site.py | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 922b1ae2..4643eb19 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ requires-python = '>=3.9,<3.13' dependencies = [ 'cryspy', # Calculations of diffraction patterns 'easycrystallography @ git+https://github.com/EasyScience/EasyCrystallography.git@new_param', # Crystallography tools of the EasyScience framework - 'easyscience', # The base library of the EasyScience framework + 'easyscience @ git+https://github.com/EasyScience/EasyScience.git@new_param_fix', # The base library of the EasyScience framework 'pooch', # For data fetching ] diff --git a/src/easydiffraction/job/experiment/backgrounds/background.py b/src/easydiffraction/job/experiment/backgrounds/background.py index 9eda29db..935c390f 100644 --- a/src/easydiffraction/job/experiment/backgrounds/background.py +++ b/src/easydiffraction/job/experiment/backgrounds/background.py @@ -8,7 +8,7 @@ import numpy as np from easyscience.Objects.Groups import BaseCollection -from easyscience.Objects.new_variable import DescriptorStr as Descriptor +from easyscience.Objects.variable import DescriptorStr as Descriptor class Background(BaseCollection): diff --git a/src/easydiffraction/job/experiment/backgrounds/point.py b/src/easydiffraction/job/experiment/backgrounds/point.py index 199f4ef9..f00c51a3 100644 --- a/src/easydiffraction/job/experiment/backgrounds/point.py +++ b/src/easydiffraction/job/experiment/backgrounds/point.py @@ -7,9 +7,9 @@ import numpy as np from easyscience.Objects.Groups import BaseCollection -from easyscience.Objects.new_variable import DescriptorNumber as Descriptor -from easyscience.Objects.new_variable import Parameter from easyscience.Objects.ObjectClasses import BaseObj +from easyscience.Objects.variable import DescriptorNumber as Descriptor +from easyscience.Objects.variable import Parameter from .background import Background diff --git a/src/easydiffraction/job/experiment/experiment.py b/src/easydiffraction/job/experiment/experiment.py index cec7787b..a6b47c62 100644 --- a/src/easydiffraction/job/experiment/experiment.py +++ b/src/easydiffraction/job/experiment/experiment.py @@ -5,8 +5,8 @@ import numpy as np from easyscience.Datasets.xarray import xr from easyscience.Objects.job.experiment import ExperimentBase as coreExperiment -from easyscience.Objects.new_variable import DescriptorNumber as Descriptor -from easyscience.Objects.new_variable import Parameter +from easyscience.Objects.variable import DescriptorNumber as Descriptor +from easyscience.Objects.variable import Parameter from gemmi import cif from easydiffraction.io.cif_reader import background_from_cif_block as background_from_cif diff --git a/src/easydiffraction/job/experiment/pd_1d.py b/src/easydiffraction/job/experiment/pd_1d.py index 5bc5c4ca..ab2608ca 100644 --- a/src/easydiffraction/job/experiment/pd_1d.py +++ b/src/easydiffraction/job/experiment/pd_1d.py @@ -13,9 +13,9 @@ from typing import Union from easyscience.Datasets.xarray import xr -from easyscience.Objects.new_variable import DescriptorStr as Descriptor -from easyscience.Objects.new_variable import Parameter from easyscience.Objects.ObjectClasses import BaseObj +from easyscience.Objects.variable import DescriptorStr as Descriptor +from easyscience.Objects.variable import Parameter from easydiffraction.job.experiment.backgrounds.background import BackgroundContainer from easydiffraction.job.experiment.common import JobSetup diff --git a/src/easydiffraction/job/experiment/polarization.py b/src/easydiffraction/job/experiment/polarization.py index 24bfcd2b..ce9b5360 100644 --- a/src/easydiffraction/job/experiment/polarization.py +++ b/src/easydiffraction/job/experiment/polarization.py @@ -9,8 +9,8 @@ from typing import Optional from typing import Union -from easyscience.Objects.new_variable import Parameter from easyscience.Objects.ObjectClasses import BaseObj +from easyscience.Objects.variable import Parameter if TYPE_CHECKING: from easyscience.Objects.Inferface import iF diff --git a/src/easydiffraction/job/model/site.py b/src/easydiffraction/job/model/site.py index 7bc3627e..ac167101 100644 --- a/src/easydiffraction/job/model/site.py +++ b/src/easydiffraction/job/model/site.py @@ -15,8 +15,8 @@ from easycrystallography.Components.Specie import Specie from easycrystallography.Components.Susceptibility import MagneticSusceptibility from easycrystallography.io.star_base import StarLoop -from easyscience.Objects.new_variable import DescriptorStr as Descriptor -from easyscience.Objects.new_variable import Parameter +from easyscience.Objects.variable import DescriptorStr as Descriptor +from easyscience.Objects.variable import Parameter if TYPE_CHECKING: from easyscience.Objects.Inferface import iF From fd6679e1077ffb273017a290fe807f29b8ce86c7 Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Sat, 15 Feb 2025 19:33:42 +0100 Subject: [PATCH 18/33] fixed typo --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 4643eb19..681c0c39 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ requires-python = '>=3.9,<3.13' dependencies = [ 'cryspy', # Calculations of diffraction patterns 'easycrystallography @ git+https://github.com/EasyScience/EasyCrystallography.git@new_param', # Crystallography tools of the EasyScience framework - 'easyscience @ git+https://github.com/EasyScience/EasyScience.git@new_param_fix', # The base library of the EasyScience framework + 'easyscience @ git+https://github.com/EasyScience/EasyScience.git@new_params_fix', # The base library of the EasyScience framework 'pooch', # For data fetching ] From 1cb2aa8c9599beba618ecf5a530e96ac32caa6fb Mon Sep 17 00:00:00 2001 From: rozyczko Date: Mon, 17 Feb 2025 12:36:09 +0100 Subject: [PATCH 19/33] added updated version of dataBlockToCif --- src/easydiffraction/io/cif.py | 113 +++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 1 deletion(-) diff --git a/src/easydiffraction/io/cif.py b/src/easydiffraction/io/cif.py index 303e294c..737d514d 100644 --- a/src/easydiffraction/io/cif.py +++ b/src/easydiffraction/io/cif.py @@ -9,6 +9,7 @@ from inspect import signature from io import StringIO from io import TextIOWrapper +import numpy as np from numbers import Number from pathlib import Path from typing import List @@ -1050,8 +1051,118 @@ def str2float(text): return 0 raise ex - def dataBlockToCif(block, includeBlockName=True): + cif = '' + if includeBlockName: + cif += f'data_{block["name"]["value"]}' + cif += '\n\n' + if 'params' in block: + for category in block['params'].values(): + # for param in category.values(): + for param in category.values(): + # `param` is an easyCore Parameter object + if 'optional' in param and param['optional']: + continue + value = param['value'] + if value is None: + continue + + if isinstance(value, (float, int)): # If parameter is of float type + value = np.float32(value) # Simplifies output + if param["fit"]: + error = param["error"] + #error = np.float32(error) # Simplifies output + if error == 0: + paramStr = f'{value}()' # Adds empty brackets for standard uncertainty for free params + else: + _, _, paramStr = toStdDevSmalestPrecision(value, error) # Adds brackets with standard uncertainty for free params + else: + paramStr = str(value) # Keeps 32bit presicion format in contrast to f'{...}' + elif isinstance(value, str): # If parameter is of string type + if ' ' in value: # Adds quotes to text with spaces, e.g. P n m a -> "P n m a" + paramStr = f'"{value}"' + else: + paramStr = f'{value}' + else: + console.error(f'Unsupported parameter type {type(value)} for {value}') + continue + + cif += f'{param["category"]}.{param["name"]} {paramStr}' + cif += '\n' + cif += '\n' + + if 'loops' in block: + for categoryName, category in block['loops'].items(): + cif += '\nloop_\n' + + # loop header + if not category: + continue + row0 = category[0] + for param in row0.values(): + if 'optional' in param and param['optional']: + continue + cif += f'{categoryName}.{param["name"]}\n' + + # loop data + for row in category: + line = '' + for param in row.values(): + if 'optional' in param and param['optional']: + continue + value = param['value'] + if value is None: + continue + + if isinstance(value, (float, int)): # If parameter is number + if isinstance(value, float): + value = np.float32(value) # Simplifies output + if param["fit"]: + error = param["error"] + #error = np.float32(error) # Simplifies output + if error == 0: + paramStr = f'{value}()' # Adds empty brackets for standard uncertainty for free params + else: + _, _, paramStr = toStdDevSmalestPrecision(value, error) # Adds brackets with standard uncertainty for free params + else: + paramStr = str(value) # Keeps 32bit precision format in contrast to f'{...}' + elif isinstance(value, str): # If parameter is of string type + if ' ' in value: # Adds quotes to text with spaces, e.g. P n m a -> "P n m a" + paramStr = f'"{value}"' + else: + paramStr = f'{value}' + else: + print(f'Unsupported parameter type {type(value)} for {value}') + continue + + line += paramStr + ' ' + line = line.rstrip() + cif += f'{line}\n' + cif = cif.strip() + cif = cif.replace('\n\n\n', '\n\n') + cif = cif.replace('\n\n\n', '\n\n') + return cif + +def toStdDevSmalestPrecision(value, std_dev): + if std_dev > 1: + value_str = f'{round(value)}' + std_dev_str = f'{round(std_dev)}' + value_with_std_dev_str = f'{value_str}({std_dev_str})' + else: + precision = 1 + std_dev_decimals = precision - int(np.floor(np.log10(std_dev) + 1)) + std_dev = round(std_dev, std_dev_decimals) + std_dev_str = f'{std_dev:.{std_dev_decimals}f}' + value = round(value, std_dev_decimals) + value_str = f'{value:.{std_dev_decimals}f}' + clipped_std_dev = int(round(std_dev * 10**std_dev_decimals)) + value_with_std_dev_str = f'{value_str}({clipped_std_dev})' + return value_str, std_dev_str, value_with_std_dev_str + +def dataBlockToCif_old(block, includeBlockName=True): + """ + Kept for reference + """ cif = '' if includeBlockName: cif += f'data_{block["name"]["value"]}' From e7e82fb7c00020b233084597623b96ac1bd9219a Mon Sep 17 00:00:00 2001 From: rozyczko Date: Mon, 17 Feb 2025 12:39:19 +0100 Subject: [PATCH 20/33] ruff fixes. --- src/easydiffraction/io/cif.py | 40 ++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/easydiffraction/io/cif.py b/src/easydiffraction/io/cif.py index 737d514d..50291eca 100644 --- a/src/easydiffraction/io/cif.py +++ b/src/easydiffraction/io/cif.py @@ -9,13 +9,13 @@ from inspect import signature from io import StringIO from io import TextIOWrapper -import numpy as np from numbers import Number from pathlib import Path from typing import List from typing import Tuple from typing import Union +import numpy as np from easycrystallography.Components.AtomicDisplacement import AtomicDisplacement from easycrystallography.Components.Lattice import Lattice from easycrystallography.Components.SpaceGroup import SpaceGroup @@ -1051,6 +1051,7 @@ def str2float(text): return 0 raise ex + def dataBlockToCif(block, includeBlockName=True): cif = '' if includeBlockName: @@ -1069,13 +1070,15 @@ def dataBlockToCif(block, includeBlockName=True): if isinstance(value, (float, int)): # If parameter is of float type value = np.float32(value) # Simplifies output - if param["fit"]: - error = param["error"] - #error = np.float32(error) # Simplifies output + if param['fit']: + error = param['error'] + # error = np.float32(error) # Simplifies output if error == 0: - paramStr = f'{value}()' # Adds empty brackets for standard uncertainty for free params + # Adds empty brackets for standard uncertainty for free params + paramStr = f'{value}()' else: - _, _, paramStr = toStdDevSmalestPrecision(value, error) # Adds brackets with standard uncertainty for free params + # Adds brackets with standard uncertainty for free params + _, _, paramStr = toStdDevSmalestPrecision(value, error) else: paramStr = str(value) # Keeps 32bit presicion format in contrast to f'{...}' elif isinstance(value, str): # If parameter is of string type @@ -1084,7 +1087,7 @@ def dataBlockToCif(block, includeBlockName=True): else: paramStr = f'{value}' else: - console.error(f'Unsupported parameter type {type(value)} for {value}') + print(f'Unsupported parameter type {type(value)} for {value}') continue cif += f'{param["category"]}.{param["name"]} {paramStr}' @@ -1116,21 +1119,22 @@ def dataBlockToCif(block, includeBlockName=True): if isinstance(value, (float, int)): # If parameter is number if isinstance(value, float): - value = np.float32(value) # Simplifies output - if param["fit"]: - error = param["error"] - #error = np.float32(error) # Simplifies output + value = np.float32(value) # Simplifies output + if param['fit']: + error = param['error'] + # error = np.float32(error) # Simplifies output if error == 0: - paramStr = f'{value}()' # Adds empty brackets for standard uncertainty for free params + paramStr = f'{value}()' # Adds empty brackets for standard uncertainty for free params else: - _, _, paramStr = toStdDevSmalestPrecision(value, error) # Adds brackets with standard uncertainty for free params + # Adds brackets with standard uncertainty for free params + _, _, paramStr = toStdDevSmalestPrecision(value, error) else: paramStr = str(value) # Keeps 32bit precision format in contrast to f'{...}' elif isinstance(value, str): # If parameter is of string type - if ' ' in value: # Adds quotes to text with spaces, e.g. P n m a -> "P n m a" - paramStr = f'"{value}"' - else: - paramStr = f'{value}' + if ' ' in value: # Adds quotes to text with spaces, e.g. P n m a -> "P n m a" + paramStr = f'"{value}"' + else: + paramStr = f'{value}' else: print(f'Unsupported parameter type {type(value)} for {value}') continue @@ -1143,6 +1147,7 @@ def dataBlockToCif(block, includeBlockName=True): cif = cif.replace('\n\n\n', '\n\n') return cif + def toStdDevSmalestPrecision(value, std_dev): if std_dev > 1: value_str = f'{round(value)}' @@ -1159,6 +1164,7 @@ def toStdDevSmalestPrecision(value, std_dev): value_with_std_dev_str = f'{value_str}({clipped_std_dev})' return value_str, std_dev_str, value_with_std_dev_str + def dataBlockToCif_old(block, includeBlockName=True): """ Kept for reference From 68d430064d60482ac880f561694877e33c229062 Mon Sep 17 00:00:00 2001 From: rozyczko Date: Tue, 18 Feb 2025 10:00:25 +0100 Subject: [PATCH 21/33] Fixed TOF profile calcs. Fixed typos --- .../calculators/cryspy/calculator.py | 24 +++++++++++++++++-- src/easydiffraction/io/cif.py | 10 ++++---- src/easydiffraction/job/job.py | 6 +++-- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/easydiffraction/calculators/cryspy/calculator.py b/src/easydiffraction/calculators/cryspy/calculator.py index 4f3718dc..e2ff750f 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -846,7 +846,8 @@ def nonPolarized_update(crystals, profiles, peak_dat, scales, x_str): 'k': peak_dat[idx]['index_hkl'][1], 'l': peak_dat[idx]['index_hkl'][2], }, - 'profile': scales[idx] * dependent[idx, :] / normalization, + # 'profile': scales[idx] * dependent[idx, :] / normalization, + 'profile': dependent[idx, :] / normalization, 'components': {'total': dependent[idx, :]}, 'profile_scale': scales[idx], } @@ -891,6 +892,9 @@ def _do_run(self, model, polarized, x_array, crystals, phase_list, bg, phase_sca model.items[idx] = phase_list data_name = crystals.data_name + # print("===========================================") + # print(" RUNNING PROFILE CALCULATION") + # print("===========================================") is_tof = False if self.model.PREFIX.lower() == 'tof': is_tof = True @@ -917,7 +921,6 @@ def _do_run(self, model, polarized, x_array, crystals, phase_list, bg, phase_sca if not exp_name_model: # no exp defined, default - # exp_name_model_split = self.model.PREFIX exp_name_model = self.model.PREFIX + '_' + phase_name # get cryspy experiment dict from the model: expensive! # model -> dict @@ -925,6 +928,22 @@ def _do_run(self, model, polarized, x_array, crystals, phase_list, bg, phase_sca experiment_dict_model = self.model.get_dictionary() self._cryspyData._cryspyDict[exp_name_model] = experiment_dict_model + if is_tof and not exp_name_model.lower().startswith('tof'): + exp_name_model_orig = exp_name_model + # recast name from data_ to tof_ + exp_name_model_suffix = exp_name_model.split('_')[1] + exp_name_model = 'tof_' + exp_name_model_suffix + # get the dictionary from the model + experiment_dict_model = self.model.get_dictionary() + # remove old key + self._cryspyData._cryspyDict.pop(exp_name_model_orig) + # add new key + self._cryspyData._cryspyDict[exp_name_model] = experiment_dict_model + # modify type_name + self._cryspyData._cryspyDict[exp_name_model]['type_name'] = exp_name_model + # modify name + self._cryspyData._cryspyDict[exp_name_model]['name'] = exp_name_model_suffix + self._cryspyDict = self._cryspyData._cryspyDict # add extra fluff @@ -936,6 +955,7 @@ def _do_run(self, model, polarized, x_array, crystals, phase_list, bg, phase_sca self._cryspyDict[exp_name_model]['excluded_points'] = self.excluded_points self._cryspyDict[exp_name_model]['radiation'] = [RAD_MAP[self.pattern.radiation]] if is_tof: + self._cryspyDict[exp_name_model]['profile_peak_shape'] = 'Gauss' self._cryspyDict[exp_name_model]['time'] = np.array(ttheta) # required for TOF self._cryspyDict[exp_name_model]['time_max'] = ttheta[-1] self._cryspyDict[exp_name_model]['time_min'] = ttheta[0] diff --git a/src/easydiffraction/io/cif.py b/src/easydiffraction/io/cif.py index 50291eca..82956757 100644 --- a/src/easydiffraction/io/cif.py +++ b/src/easydiffraction/io/cif.py @@ -1078,7 +1078,7 @@ def dataBlockToCif(block, includeBlockName=True): paramStr = f'{value}()' else: # Adds brackets with standard uncertainty for free params - _, _, paramStr = toStdDevSmalestPrecision(value, error) + _, _, paramStr = toStdDevSmallestPrecision(value, error) else: paramStr = str(value) # Keeps 32bit presicion format in contrast to f'{...}' elif isinstance(value, str): # If parameter is of string type @@ -1087,7 +1087,7 @@ def dataBlockToCif(block, includeBlockName=True): else: paramStr = f'{value}' else: - print(f'Unsupported parameter type {type(value)} for {value}') + # print(f'Unsupported parameter type {type(value)} for {value}') continue cif += f'{param["category"]}.{param["name"]} {paramStr}' @@ -1127,7 +1127,7 @@ def dataBlockToCif(block, includeBlockName=True): paramStr = f'{value}()' # Adds empty brackets for standard uncertainty for free params else: # Adds brackets with standard uncertainty for free params - _, _, paramStr = toStdDevSmalestPrecision(value, error) + _, _, paramStr = toStdDevSmallestPrecision(value, error) else: paramStr = str(value) # Keeps 32bit precision format in contrast to f'{...}' elif isinstance(value, str): # If parameter is of string type @@ -1136,7 +1136,7 @@ def dataBlockToCif(block, includeBlockName=True): else: paramStr = f'{value}' else: - print(f'Unsupported parameter type {type(value)} for {value}') + # print(f'Unsupported parameter type {type(value)} for {value}') continue line += paramStr + ' ' @@ -1148,7 +1148,7 @@ def dataBlockToCif(block, includeBlockName=True): return cif -def toStdDevSmalestPrecision(value, std_dev): +def toStdDevSmallestPrecision(value, std_dev): if std_dev > 1: value_str = f'{round(value)}' std_dev_str = f'{round(std_dev)}' diff --git a/src/easydiffraction/job/job.py b/src/easydiffraction/job/job.py index 16d1c0ed..5d931b2a 100644 --- a/src/easydiffraction/job/job.py +++ b/src/easydiffraction/job/job.py @@ -1024,7 +1024,8 @@ def _parameters(self): name = self.get_full_parameter_name(parameter.unique_name, parameter.display_name, parameter.url) parameters['name'].append(f'{name}') parameters['value'].append(parameter.value) - parameters['unit'].append(f'{parameter.unit:~P}') + # parameters['unit'].append(f'{parameter.unit:~P}') + parameters['unit'].append(f'{parameter.unit}') parameters['error'].append(parameter.error) if parameter.error else parameters['error'].append('') parameters['min'].append(parameter.min) parameters['max'].append(parameter.max) @@ -1037,7 +1038,8 @@ def _free_parameters(self): name = self.get_full_parameter_name(parameter.unique_name, parameter.display_name, parameter.url) parameters['name'].append(f'{name}') parameters['value'].append(parameter.value) - parameters['unit'].append(f'{parameter.unit:~P}') + # parameters['unit'].append(f'{parameter.unit:~P}') + parameters['unit'].append(f'{parameter.unit}') parameters['error'].append(parameter.error) return parameters From bff8037b5813d3b56eaef57126797d343b6ef3d5 Mon Sep 17 00:00:00 2001 From: rozyczko Date: Wed, 19 Feb 2025 14:41:54 +0100 Subject: [PATCH 22/33] minor fixes and performance impromevents --- .../calculators/cryspy/calculator.py | 1 - src/easydiffraction/io/cif.py | 3 +-- src/easydiffraction/job/job.py | 15 +++++++++++---- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/easydiffraction/calculators/cryspy/calculator.py b/src/easydiffraction/calculators/cryspy/calculator.py index e2ff750f..a3f7d3de 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -846,7 +846,6 @@ def nonPolarized_update(crystals, profiles, peak_dat, scales, x_str): 'k': peak_dat[idx]['index_hkl'][1], 'l': peak_dat[idx]['index_hkl'][2], }, - # 'profile': scales[idx] * dependent[idx, :] / normalization, 'profile': dependent[idx, :] / normalization, 'components': {'total': dependent[idx, :]}, 'profile_scale': scales[idx], diff --git a/src/easydiffraction/io/cif.py b/src/easydiffraction/io/cif.py index 82956757..133b7fa9 100644 --- a/src/easydiffraction/io/cif.py +++ b/src/easydiffraction/io/cif.py @@ -1136,8 +1136,7 @@ def dataBlockToCif(block, includeBlockName=True): else: paramStr = f'{value}' else: - # print(f'Unsupported parameter type {type(value)} for {value}') - continue + paramStr = str(value) line += paramStr + ' ' line = line.rstrip() diff --git a/src/easydiffraction/job/job.py b/src/easydiffraction/job/job.py index 5d931b2a..d3ecc88f 100644 --- a/src/easydiffraction/job/job.py +++ b/src/easydiffraction/job/job.py @@ -156,6 +156,7 @@ def sample(self) -> Sample: def sample(self, value: Union[Sample, None]) -> None: # We need to deepcopy the sample to ensure that it is not shared between jobs if value is not None: + del self._sample self._sample = value # self._sample = deepcopy(value) # TODO fix deepcopy on EXC sample else: @@ -432,8 +433,14 @@ def update_after_new_experiment(self) -> None: pattern = self.experiment.pattern phases = self.sample.phases name = self.sample.name - self.sample = Sample(name, parameters=parameters, pattern=pattern, phases=phases) - self.sample.parameters = self.experiment.parameters + + self.sample = Sample(name=name, + parameters=parameters, + pattern=pattern, + phases=phases, + interface=self.interface, + dataset=self.datastore) # 1980 ms + self.sample.parameters = self.experiment.parameters # 360 ms self.update_experiment_type() self.update_interface() # Temporary fix for dtt1 and dtt2 parameters read from CIF in Scipp format @@ -636,8 +643,8 @@ def update_interface(self): self.interface._InterfaceFactoryTemplate__interface_obj.set_experiment_type( tof=self.type.is_tof, pol=self.type.is_pol ) - self.interface.generate_bindings(self) - self.generate_bindings() + # self.interface.generate_bindings(self) + # self.generate_bindings() # Charts From f543b62b3ad28f8e8ddc763255f63c52a3800b2b Mon Sep 17 00:00:00 2001 From: rozyczko Date: Wed, 19 Feb 2025 14:42:25 +0100 Subject: [PATCH 23/33] ruff --- src/easydiffraction/job/job.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/easydiffraction/job/job.py b/src/easydiffraction/job/job.py index d3ecc88f..622ea6f7 100644 --- a/src/easydiffraction/job/job.py +++ b/src/easydiffraction/job/job.py @@ -434,12 +434,14 @@ def update_after_new_experiment(self) -> None: phases = self.sample.phases name = self.sample.name - self.sample = Sample(name=name, - parameters=parameters, - pattern=pattern, - phases=phases, - interface=self.interface, - dataset=self.datastore) # 1980 ms + self.sample = Sample( + name=name, + parameters=parameters, + pattern=pattern, + phases=phases, + interface=self.interface, + dataset=self.datastore, + ) # 1980 ms self.sample.parameters = self.experiment.parameters # 360 ms self.update_experiment_type() self.update_interface() From 37de5e70f08fe7369ddaf59fbeaaed0e3705b019 Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Fri, 21 Feb 2025 14:34:08 +0100 Subject: [PATCH 24/33] fix for multiphase scale issue not being properly set up after fitting --- src/easydiffraction/calculators/cryspy/calculator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/easydiffraction/calculators/cryspy/calculator.py b/src/easydiffraction/calculators/cryspy/calculator.py index caf2f74e..1daa6715 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -849,7 +849,7 @@ def nonPolarized_update(crystals, profiles, peak_dat, scales, x_str): 'k': peak_dat[idx]['index_hkl'][1], 'l': peak_dat[idx]['index_hkl'][2], }, - 'profile': dependent[idx, :] / normalization, + 'profile': dependent[idx, :] / (normalization*len(scales)), 'components': {'total': dependent[idx, :]}, 'profile_scale': scales[idx], } From a4bcfe7267551db6ca640a9cc0b418470481b051 Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Fri, 21 Feb 2025 15:19:39 +0100 Subject: [PATCH 25/33] ruff. what else? --- src/easydiffraction/calculators/cryspy/calculator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/easydiffraction/calculators/cryspy/calculator.py b/src/easydiffraction/calculators/cryspy/calculator.py index 1daa6715..d611a821 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -849,7 +849,7 @@ def nonPolarized_update(crystals, profiles, peak_dat, scales, x_str): 'k': peak_dat[idx]['index_hkl'][1], 'l': peak_dat[idx]['index_hkl'][2], }, - 'profile': dependent[idx, :] / (normalization*len(scales)), + 'profile': dependent[idx, :] / (normalization * len(scales)), 'components': {'total': dependent[idx, :]}, 'profile_scale': scales[idx], } From 1eafc1e0a02f220198807332456159eaf1a170fb Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Sat, 22 Feb 2025 17:45:02 +0100 Subject: [PATCH 26/33] add fix for exp names, not just tof. fix phase generation for cases when arguments don't contain atoms/cell adjusted fitting results --- src/easydiffraction/calculators/cryspy/calculator.py | 7 +++++-- src/easydiffraction/job/model/phase.py | 6 ++++-- tests/functional_tests/fitting/test_fitting_pd-neut.py | 8 ++++---- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/easydiffraction/calculators/cryspy/calculator.py b/src/easydiffraction/calculators/cryspy/calculator.py index d611a821..0a493554 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -930,11 +930,14 @@ def _do_run(self, model, polarized, x_array, crystals, phase_list, bg, phase_sca experiment_dict_model = self.model.get_dictionary() self._cryspyData._cryspyDict[exp_name_model] = experiment_dict_model - if is_tof and not exp_name_model.lower().startswith('tof'): + # assure correct exp_name_model prefix. + # for cwl it is 'pd_', for tof it is 'tof_' + # if is_tof and not exp_name_model.lower().startswith('tof'): + if not exp_name_model.lower().startswith(self.model.PREFIX): exp_name_model_orig = exp_name_model # recast name from data_ to tof_ exp_name_model_suffix = exp_name_model.split('_')[1] - exp_name_model = 'tof_' + exp_name_model_suffix + exp_name_model = self.model.PREFIX + '_' + exp_name_model_suffix # get the dictionary from the model experiment_dict_model = self.model.get_dictionary() # remove old key diff --git a/src/easydiffraction/job/model/phase.py b/src/easydiffraction/job/model/phase.py index 018e8a6d..45687e1d 100644 --- a/src/easydiffraction/job/model/phase.py +++ b/src/easydiffraction/job/model/phase.py @@ -16,8 +16,10 @@ class Phase(ecPhase): def __init__(self, name, spacegroup=None, cell=None, atoms=None, scale=None, interface=None, enforce_sym=True, **kwargs): super(Phase, self).__init__(name, spacegroup, cell, atoms, scale, enforce_sym=enforce_sym) # we need to overwrite cell and atoms, since ecPhase constructor doesn't append the error info - self.cell = cell - self.atoms = atoms + if cell is not None: + self.cell = cell + if atoms is not None: + self.atoms = atoms # spacegroup is not being overwritten, since no error info is being appended self.interface = interface diff --git a/tests/functional_tests/fitting/test_fitting_pd-neut.py b/tests/functional_tests/fitting/test_fitting_pd-neut.py index 6685136e..2f52ed90 100644 --- a/tests/functional_tests/fitting/test_fitting_pd-neut.py +++ b/tests/functional_tests/fitting/test_fitting_pd-neut.py @@ -45,7 +45,7 @@ def test_fitting_pd_neut_cwl_LBCO_HRPT() -> None: assert job.fitting_results.x.size == 3098 assert job.fitting_results.n_pars == 13 assert job.fitting_results.success - assert_almost_equal(job.fitting_results.reduced_chi, 1.25, decimal=2) + assert_almost_equal(job.fitting_results.reduced_chi, 5.86, decimal=2) def test_fitting_pd_neut_tof_Si_SEPD() -> None: @@ -95,13 +95,13 @@ def test_fitting_pd_neut_tof_Si_SEPD() -> None: job.fit() - assert phase.space_group.name_hm_alt.raw_value == 'F d -3 m' - assert phase.space_group.it_coordinate_system_code.raw_value == '2' + assert phase.space_group.name_hm_alt.value == 'F d -3 m' + assert phase.space_group.it_coordinate_system_code.value == '2' assert job.fitting_results.minimizer_engine.package == 'lmfit' assert job.fitting_results.x.size == 5600 assert job.fitting_results.n_pars == 12 assert job.fitting_results.success - assert_almost_equal(job.fitting_results.reduced_chi, 5.42, decimal=2) + assert_almost_equal(job.fitting_results.reduced_chi, 16.18, decimal=2) if __name__ == '__main__': From 810fc889feac5c34be7e37537c6a75238d8926fd Mon Sep 17 00:00:00 2001 From: rozyczko Date: Wed, 26 Feb 2025 15:44:57 +0100 Subject: [PATCH 27/33] Added bridge link for intermediate updates Updated dependency for easyScience --- pyproject.toml | 2 +- src/easydiffraction/calculators/cryspy/calculator.py | 2 ++ src/easydiffraction/calculators/cryspy/wrapper.py | 8 ++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 8c9d9e33..4faf8ce6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ requires-python = '>=3.9,<3.13' dependencies = [ 'cryspy', # Calculations of diffraction patterns 'easycrystallography @ git+https://github.com/EasyScience/EasyCrystallography.git@new_param', # Crystallography tools of the EasyScience framework - 'easyscience @ git+https://github.com/EasyScience/EasyScience.git@new_params_fix', # The base library of the EasyScience framework + 'easyscience @ git+https://github.com/EasyScience/EasyScience.git@develop', # The base library of the EasyScience framework 'pooch', # For data fetching ] diff --git a/src/easydiffraction/calculators/cryspy/calculator.py b/src/easydiffraction/calculators/cryspy/calculator.py index 0a493554..70cce843 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -635,6 +635,8 @@ def full_calculate(self, x_array: np.ndarray, **kwargs) -> Tuple[np.ndarray, dic :return: points calculated at `x` :rtype: np.ndarray """ + # save the bridge link + self.bridge = kwargs.pop('bridge', None) res = np.zeros_like(x_array) self.additional_data['ivar'] = res args = x_array diff --git a/src/easydiffraction/calculators/cryspy/wrapper.py b/src/easydiffraction/calculators/cryspy/wrapper.py index 00a271d8..c1452d49 100644 --- a/src/easydiffraction/calculators/cryspy/wrapper.py +++ b/src/easydiffraction/calculators/cryspy/wrapper.py @@ -670,6 +670,8 @@ def __init__(self): self.calculator = Cryspy_calc() self._internal = None self._last_callback = {} + self.saved_kwargs = {} + self._iteration = 0 @staticmethod def feature_checker( @@ -719,7 +721,13 @@ def remove_phase(self, phases_obj, phase_obj: Phase) -> None: def fit_func(self, x_array: np.ndarray, *args, **kwargs) -> Union[np.ndarray, None]: if self._internal is not None: + self._iteration += 1 + kwargs.update(self.saved_kwargs) calculation, self._last_callback = self._internal.full_callback(x_array, *args, **kwargs) + # This is where we notify the observer (QML) that the calculation has been performed. + if 'bridge' in kwargs: + bridge = kwargs['bridge'] + bridge.intermediate_data_ready.emit(self._iteration, calculation) return calculation def set_exp_cif(self, cif: str) -> None: From 760db4e3221d5b5839b7c4aeb25fa6fec321ea41 Mon Sep 17 00:00:00 2001 From: rozyczko Date: Tue, 4 Mar 2025 08:59:18 +0100 Subject: [PATCH 28/33] fixed phase update for multiphase cases --- src/easydiffraction/calculators/cryspy/calculator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/easydiffraction/calculators/cryspy/calculator.py b/src/easydiffraction/calculators/cryspy/calculator.py index 70cce843..ea73041f 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -815,7 +815,7 @@ def updateCryspyDict(self, item, key, value): return elif key in CRYSPY_MODEL_INSTR_KEYS: # instrument param - exp_name = list(self._cryspyData._cryspyDict.keys())[1] + exp_name = list(self._cryspyData._cryspyDict.keys())[-1] cryspy_dict = self._cryspyData._cryspyDict[exp_name] cryspy_key = CRYSPY_MODEL_INSTR_KEYS[key] loc = cryspy_dict[cryspy_key] From d3e258d2edc7c620ddffa8ade66141201dddad29 Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Thu, 13 Mar 2025 19:16:24 +0100 Subject: [PATCH 29/33] minor fix for ToF --- src/easydiffraction/calculators/cryspy/calculator.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/easydiffraction/calculators/cryspy/calculator.py b/src/easydiffraction/calculators/cryspy/calculator.py index ea73041f..47ca1ad9 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -934,7 +934,6 @@ def _do_run(self, model, polarized, x_array, crystals, phase_list, bg, phase_sca # assure correct exp_name_model prefix. # for cwl it is 'pd_', for tof it is 'tof_' - # if is_tof and not exp_name_model.lower().startswith('tof'): if not exp_name_model.lower().startswith(self.model.PREFIX): exp_name_model_orig = exp_name_model # recast name from data_ to tof_ @@ -964,8 +963,8 @@ def _do_run(self, model, polarized, x_array, crystals, phase_list, bg, phase_sca if is_tof: self._cryspyDict[exp_name_model]['profile_peak_shape'] = 'Gauss' self._cryspyDict[exp_name_model]['time'] = np.array(ttheta) # required for TOF - self._cryspyDict[exp_name_model]['time_max'] = ttheta[-1] - self._cryspyDict[exp_name_model]['time_min'] = ttheta[0] + self._cryspyDict[exp_name_model]['time_max'] = float(ttheta[-1]) + self._cryspyDict[exp_name_model]['time_min'] = float(ttheta[0]) self._cryspyDict[exp_name_model]['background_time'] = self.pattern.backgrounds[0].x_sorted_points self._cryspyDict[exp_name_model]['background_intensity'] = self.pattern.backgrounds[0].y_sorted_points self._cryspyDict[exp_name_model]['flags_background_intensity'] = np.full( @@ -973,6 +972,8 @@ def _do_run(self, model, polarized, x_array, crystals, phase_list, bg, phase_sca ) for i, point in enumerate(self.pattern.backgrounds[0]): self._cryspyDict[exp_name_model]['flags_background_intensity'][i] = not point.y.fixed + self._cryspyDict[exp_name_model]['k'] = [0] + self._cryspyDict[exp_name_model]['cthm'] = [0.91] else: self._cryspyDict[exp_name_model]['ttheta'] = ttheta From c22b4bf9ba543cd028faed98aef8c5efbc473947 Mon Sep 17 00:00:00 2001 From: rozyczko Date: Wed, 19 Mar 2025 12:12:34 +0100 Subject: [PATCH 30/33] fixes for experiment update --- src/easydiffraction/calculators/cryspy/calculator.py | 4 ++-- src/easydiffraction/calculators/cryspy/parser.py | 4 ++-- src/easydiffraction/calculators/cryspy/wrapper.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/easydiffraction/calculators/cryspy/calculator.py b/src/easydiffraction/calculators/cryspy/calculator.py index 47ca1ad9..96280f9e 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -771,13 +771,13 @@ def replaceExpCif(self, edCif, currentExperimentName): calcExperimentsDict = calcExperimentsObj.get_dictionary() calcDictBlockName = f'pd_{currentExperimentName}' - calcDictName = f'data_{currentExperimentName}' + # calcDictName = f'data_{currentExperimentName}' _, edExperimentsNoMeas = calcObjAndDictToEdExperiments(calcExperimentsObj, calcExperimentsDict) # self._cryspyData._cryspyObj.items[calcObjBlockIdx] = calcExperimentsObj.items[0] self._cryspyData._cryspyObj.items[0] = calcExperimentsObj.items[0] - self._cryspyData._cryspyDict[calcDictBlockName] = calcExperimentsDict[calcDictName] + self._cryspyData._cryspyDict[calcDictBlockName] = calcExperimentsDict[calcDictBlockName] sdataBlocksNoMeas = edExperimentsNoMeas[0] return sdataBlocksNoMeas diff --git a/src/easydiffraction/calculators/cryspy/parser.py b/src/easydiffraction/calculators/cryspy/parser.py index 4ddf7d55..2288cb20 100644 --- a/src/easydiffraction/calculators/cryspy/parser.py +++ b/src/easydiffraction/calculators/cryspy/parser.py @@ -307,7 +307,7 @@ def calcObjAndDictToEdExperiments(cryspy_obj, cryspy_dict): url='https://docs.easydiffraction.org/app/dictionaries/_diffrn_radiation/', cifDict='core', absDelta=0.01, - units='Å', + unit='Å', fittable=True, fit=item.wavelength_refinement, ) @@ -328,7 +328,7 @@ def calcObjAndDictToEdExperiments(cryspy_obj, cryspy_dict): url='https://docs.easydiffraction.org/app/dictionaries/_pd_calib/', cifDict='pd', absDelta=0.2, - units='°', + unit='°', fittable=True, fit=item.offset_ttheta_refinement, ) diff --git a/src/easydiffraction/calculators/cryspy/wrapper.py b/src/easydiffraction/calculators/cryspy/wrapper.py index c1452d49..1001c8de 100644 --- a/src/easydiffraction/calculators/cryspy/wrapper.py +++ b/src/easydiffraction/calculators/cryspy/wrapper.py @@ -801,7 +801,7 @@ def updateExpCif(self, cif_string: str, model_names: list) -> None: self.calculator.updateExpCif(cif_string, model_names) def replaceExpCif(self, cif_string: str, exp_name: str) -> None: - self.calculator.replaceExpCif(cif_string, exp_name) + return self.calculator.replaceExpCif(cif_string, exp_name) def full_callback( self, From 67406dc05dd057d088a514ed42daf56f2e33e326 Mon Sep 17 00:00:00 2001 From: rozyczko Date: Thu, 20 Mar 2025 15:21:51 +0100 Subject: [PATCH 31/33] be careful with the offset --- src/easydiffraction/calculators/cryspy/calculator.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/easydiffraction/calculators/cryspy/calculator.py b/src/easydiffraction/calculators/cryspy/calculator.py index 96280f9e..e3a5f77a 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -447,11 +447,11 @@ def powder_1d_calculate(self, x_array: np.ndarray, full_return: bool = False, ** if self.pattern is None: scale = 1.0 - offset = 0 + # offset = 0 else: scale = self.pattern.scale.value / norm - offset = self.pattern.zero_shift.value - this_x_array = x_array - offset + # offset = self.pattern.zero_shift.value + # this_x_array = x_array - offset if 'excluded_points' in kwargs: setattr(self.model, 'excluded_points', kwargs['excluded_points']) @@ -459,7 +459,8 @@ def powder_1d_calculate(self, x_array: np.ndarray, full_return: bool = False, ** if borg.debug: print('CALLING FROM Cryspy\n----------------------') - results, additional = self.do_calc_setup(scale, this_x_array, pol_fn) + # results, additional = self.do_calc_setup(scale, this_x_array, pol_fn) + results, additional = self.do_calc_setup(scale, x_array, pol_fn) if full_return: return results, additional return results @@ -771,11 +772,8 @@ def replaceExpCif(self, edCif, currentExperimentName): calcExperimentsDict = calcExperimentsObj.get_dictionary() calcDictBlockName = f'pd_{currentExperimentName}' - # calcDictName = f'data_{currentExperimentName}' - _, edExperimentsNoMeas = calcObjAndDictToEdExperiments(calcExperimentsObj, calcExperimentsDict) - # self._cryspyData._cryspyObj.items[calcObjBlockIdx] = calcExperimentsObj.items[0] self._cryspyData._cryspyObj.items[0] = calcExperimentsObj.items[0] self._cryspyData._cryspyDict[calcDictBlockName] = calcExperimentsDict[calcDictBlockName] sdataBlocksNoMeas = edExperimentsNoMeas[0] From d5bd9bcb9a9d3269937a9a82d9cf3e5705670ebb Mon Sep 17 00:00:00 2001 From: rozyczko Date: Mon, 24 Mar 2025 14:19:40 +0100 Subject: [PATCH 32/33] all deps are now released. --- pyproject.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4faf8ce6..48b36b3f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,10 +25,10 @@ classifiers = [ ] requires-python = '>=3.9,<3.13' dependencies = [ - 'cryspy', # Calculations of diffraction patterns - 'easycrystallography @ git+https://github.com/EasyScience/EasyCrystallography.git@new_param', # Crystallography tools of the EasyScience framework - 'easyscience @ git+https://github.com/EasyScience/EasyScience.git@develop', # The base library of the EasyScience framework - 'pooch', # For data fetching + 'cryspy', # Calculations of diffraction patterns + 'easycrystallography', # Crystallography tools of the EasyScience framework + 'easyscience', # The base library of the EasyScience framework + 'pooch', # For data fetching ] [project.optional-dependencies] From 0b5dd3f7a29f3ddc32ba2cb6affff2c0621fb1b3 Mon Sep 17 00:00:00 2001 From: rozyczko Date: Wed, 26 Mar 2025 13:20:01 +0100 Subject: [PATCH 33/33] offset correction is necessary --- src/easydiffraction/calculators/cryspy/calculator.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/easydiffraction/calculators/cryspy/calculator.py b/src/easydiffraction/calculators/cryspy/calculator.py index e3a5f77a..ea081740 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -447,11 +447,11 @@ def powder_1d_calculate(self, x_array: np.ndarray, full_return: bool = False, ** if self.pattern is None: scale = 1.0 - # offset = 0 + offset = 0 else: scale = self.pattern.scale.value / norm - # offset = self.pattern.zero_shift.value - # this_x_array = x_array - offset + offset = self.pattern.zero_shift.value + this_x_array = x_array - offset if 'excluded_points' in kwargs: setattr(self.model, 'excluded_points', kwargs['excluded_points']) @@ -459,8 +459,7 @@ def powder_1d_calculate(self, x_array: np.ndarray, full_return: bool = False, ** if borg.debug: print('CALLING FROM Cryspy\n----------------------') - # results, additional = self.do_calc_setup(scale, this_x_array, pol_fn) - results, additional = self.do_calc_setup(scale, x_array, pol_fn) + results, additional = self.do_calc_setup(scale, this_x_array, pol_fn) if full_return: return results, additional return results