From 2fc48b141d768a404f2ddc7fdc7ca3b9dee2b3b2 Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Tue, 14 Jan 2025 12:18:32 +0100 Subject: [PATCH 01/43] 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/43] 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/43] 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/43] 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/43] 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/43] 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 68e71b12ba1eebe22ea07eb9bfbc6ad714a53bc0 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 31 Jan 2025 12:40:09 +0100 Subject: [PATCH 07/43] Update README for logo links and project info --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 19d69f6c..891eab1b 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -

+

- + - + - EasyDiffraction + EasyDiffraction

@@ -34,8 +34,7 @@ We welcome contributions! Our vision is for **EasyDiffraction** to be a community-driven, open-source project supported by a diverse group of contributors. -The project is currently maintained by the [European Spallation Source (ESS)] in -Sweden. +The project is currently maintained by the [European Spallation Source (ESS)]. If you'd like to contribute, please refer to our [Contributing Guidelines] for information about our code of conduct and instructions on submitting pull From f2c2a64eedfe9904bc60c5dbd0b5a6b112348931 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Fri, 31 Jan 2025 12:45:25 +0100 Subject: [PATCH 08/43] Add CI workflow for documentation build and deploy --- .github/workflows/build-docs.yml | 222 +++++++++++++++ DEVELOPMENT.md | 6 +- LICENSE | 3 +- docs/analysis.md | 45 +++ docs/dictionaries.md | 110 ++++++++ docs/dictionaries/_atom_site.md | 49 ++++ docs/dictionaries/_cell.md | 25 ++ docs/dictionaries/_diffrn_radiation.md | 15 + .../_diffrn_radiation_wavelength.md | 13 + docs/dictionaries/_exptl_crystal.md | 5 + docs/dictionaries/_extinction.md | 5 + docs/dictionaries/_pd_background.md | 23 ++ docs/dictionaries/_pd_calib.md | 13 + docs/dictionaries/_pd_instr.md | 73 +++++ docs/dictionaries/_pd_meas.md | 25 ++ docs/dictionaries/_pd_phase.md | 17 ++ docs/dictionaries/_space_group.md | 17 ++ docs/easyscience.md | 95 +++++++ docs/experiment.md | 261 ++++++++++++++++++ docs/getting-started.md | 125 +++++++++ docs/glossary.md | 25 ++ docs/how-to-use/index.md | 8 + docs/index.md | 19 ++ docs/mkdocs.yml | 39 +++ docs/model.md | 5 + docs/project-structure.md | 134 +++++++++ pyproject.toml | 17 +- 27 files changed, 1387 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/build-docs.yml create mode 100644 docs/analysis.md create mode 100644 docs/dictionaries.md create mode 100644 docs/dictionaries/_atom_site.md create mode 100644 docs/dictionaries/_cell.md create mode 100644 docs/dictionaries/_diffrn_radiation.md create mode 100644 docs/dictionaries/_diffrn_radiation_wavelength.md create mode 100644 docs/dictionaries/_exptl_crystal.md create mode 100644 docs/dictionaries/_extinction.md create mode 100644 docs/dictionaries/_pd_background.md create mode 100644 docs/dictionaries/_pd_calib.md create mode 100644 docs/dictionaries/_pd_instr.md create mode 100644 docs/dictionaries/_pd_meas.md create mode 100644 docs/dictionaries/_pd_phase.md create mode 100644 docs/dictionaries/_space_group.md create mode 100644 docs/easyscience.md create mode 100644 docs/experiment.md create mode 100644 docs/getting-started.md create mode 100644 docs/glossary.md create mode 100644 docs/how-to-use/index.md create mode 100644 docs/index.md create mode 100644 docs/mkdocs.yml create mode 100644 docs/model.md create mode 100644 docs/project-structure.md diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml new file mode 100644 index 00000000..55b5ecfd --- /dev/null +++ b/.github/workflows/build-docs.yml @@ -0,0 +1,222 @@ +name: Build and deploy docs + +on: + # Trigger the workflow on push + push: + # Every branch + branches: + - '**' + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +env: + # Set the environment variables to be used in all jobs defined in this workflow + # Set the CI_BRANCH environment variable to be the branch name + # NOTE: Use the same branch name as the one of easyscience/diffraction-lib. This is + # required to download the Jupyter notebooks from the easyscience/diffraction-lib repository + # Set the NOTEBOOKS_DIR environment variable to be the directory containing the Jupyter notebooks + CI_BRANCH: ${{ github.head_ref || github.ref_name }} + NOTEBOOKS_DIR: examples + +jobs: + # Job 1: Build the static files for the documentation site + build-docs: + runs-on: macos-14 # Use macOS to switch to dark mode for Plotly charts + + steps: + - name: Cancel previous workflow runs + uses: n1hility/cancel-previous-runs@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + # Without this step, GITHUB_REPOSITORY is not accessible from mkdocs.yml + - name: Get GitHub repository + run: echo "GITHUB_REPOSITORY=$GITHUB_REPOSITORY" >> $GITHUB_ENV + + # Save the latest release version of easyscience/diffraction-lib to RELEASE_VERSION + # RELEASE_VERSION is used in the mkdocs.yml file to set release_version. + # The release_version is then needed to display the latest release version in the index.md file + - name: Get the latest release version of EasyDiffraction Library + # This method is not working in CI with the following error: "API rate limit exceeded..." + #run: echo "RELEASE_VERSION=$(curl https://api.github.com/repos/easyscience/diffraction-lib/releases/latest | grep -i 'tag_name' | awk -F '"' '{print $4}')" >> $GITHUB_ENV + # This method is not optimal and takes some more time to run, but it works and it is reliable + run: | + git clone --depth 1 https://github.com/easyscience/EasyDiffractionLib . + git fetch --tags + echo "RELEASE_VERSION=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV + + # Activate dark mode to create documentation with Plotly charts in dark mode + # Need a better solution to automatically switch the chart colour theme based on the mkdocs material switcher + # Something similar to mkdocs_plotly_plugin https://haoda-li.github.io/mkdocs-plotly-plugin/, + # but for generating documentation from notepads + - name: Activate dark mode + run: | + brew install dark-mode + dark-mode status + dark-mode on + dark-mode status + + - name: Check-out repository + uses: actions/checkout@v4 + + - name: Set up Python environment + uses: actions/setup-python@v4 + with: + python-version: '3.12' + + - name: Upgrade package installer for Python + run: python -m pip install --upgrade pip + + # Install MkDocs -- static site generator + # https://www.mkdocs.org + - name: Install MkDocs and its dependencies + run: > + pip install mkdocs mkdocs-material 'mkdocs-autorefs<1.3.0' + mkdocs-jupyter mkdocs-plugin-inline-svg + mkdocs-markdownextradata-plugin mkdocstrings-python + + # Install EasyDiffraction Library to run Jupyter notebooks + # Install with the 'charts' and 'docs' extras + - name: Install EasyDiffraction Library and its dependencies + run: pip install 'easydiffraction[charts]' + + # Download and add the extra files from the easyscience/assets-docs repository + - name: Get easyscience/assets-docs files + run: | + git clone https://github.com/easyscience/assets-docs.git + cp -R assets-docs/docs/assets/ docs/assets/ + cp -R assets-docs/includes/ includes/ + cp -R assets-docs/overrides/ overrides/ + + # Download and add the extra files from the easyscience/assets-branding repository + - name: Get easyscience/assets-branding files + run: | + git clone https://github.com/easyscience/assets-branding.git + mkdir -p docs/assets/images/ + cp assets-branding/EasyDiffraction/logos/edl-logo_dark.svg docs/assets/images/logo_dark.svg + cp assets-branding/EasyDiffraction/logos/edl-logo_light.svg docs/assets/images/logo_light.svg + cp assets-branding/EasyDiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png + mkdir -p overrides/.icons/ + cp assets-branding/EasyDiffraction/icons/ed-icon_bw.svg overrides/.icons/easydiffraction.svg + cp assets-branding/EasyScience/icons/es-icon_bw.svg overrides/.icons/easyscience.svg + + # Copy Jupyter notebooks from the project to the docs folder + # The notebooks are used to generate the documentation + - name: + Copy Jupyter notebooks from ${{ env.NOTEBOOKS_DIR }}/ to docs/${{ + env.NOTEBOOKS_DIR }}/ + run: cp -R ${{ env.NOTEBOOKS_DIR }}/ docs/${{ env.NOTEBOOKS_DIR }}/ + + # The following step is needed to avoid the following message during the build: + # "Matplotlib is building the font cache; this may take a moment" + - name: Pre-build site step + run: python -c "import easydiffraction" + + # Create the mkdocs.yml file + # The file is created by merging two files: + # - assets-docs/mkdocs.yml - the common configuration (theme, plugins, etc.) + # - docs/mkdocs.yml - the project-specific configuration (project name, TOC, etc.) + - name: Create mkdocs.yml file + run: | + cp assets-docs/mkdocs.yml mkdocs.yml + echo "" >> mkdocs.yml + cat docs/mkdocs.yml >> mkdocs.yml + + # Build the static files + # Input: docs/ directory containing the Markdown files + # Output: site/ directory containing the generated HTML files + - name: Build site with MkDocs + run: | + export JUPYTER_PLATFORM_DIRS=1 + mkdocs build + + # Set up the Pages action to configure the static files to be deployed + # NOTE: The repository must have GitHub Pages enabled and configured to build using GitHub Actions + # This can be done via https://github.com/easyscience/diffraction-lib/settings/pages + # Select: Build and deploy - Source - GitHub Actions + - name: Setup GitHub Pages + uses: actions/configure-pages@v5 + + # Upload the static files from the site/ directory to be used in the next job + # This artifact is named github-pages and is a single gzip archive containing a single tar file + # The artifact is then used in the next job by actions/deploy-pages to deploy the static files to GitHub Pages + # Unfortunately, the artifact is not available for download, so extra steps below are needed to do similar things + - name: + Upload built site as artifact for + easyscience.github.io/diffraction-lib (all branches) + uses: actions/upload-pages-artifact@v3 + with: + path: site/ + + # Upload the static files from the site/ directory to be used in the next job + # This extra step is needed to allow the download of the artifact in the next job + # for pushing its content to the branch named 'easydiffraction.org' + - name: + Upload built site as artifact for gh_pages and easydiffraction.org + (master branch) + if: ${{ env.CI_BRANCH == 'master' }} + uses: actions/upload-artifact@v4 + with: + name: artifact # name of the artifact (without the extension zip) + path: site/ + if-no-files-found: 'error' + compression-level: 0 + + # Job 2: Deploy the static files + deploy-docs: + needs: build-docs # previous job 'build-docs' need to be finished first + + # Grant GITHUB_TOKEN the permissions required to make a Pages deployment + permissions: + contents: read + pages: write # to deploy to Pages + id-token: write # to verify the deployment, originates from an appropriate source + + # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. + # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. + concurrency: + group: 'pages' + cancel-in-progress: false + + # Deploy to the github-pages environment + environment: + name: github-pages # Artifact name + url: ${{ steps.deployment.outputs.page_url }} + + runs-on: ubuntu-latest + + steps: + # Deploy the static files created in the previous job to GitHub Pages + # To allow the deployment of the static files to GitHub Pages, no + # restrictions on the branch name need to be set for desired branches on + # https://github.com/easyscience/diffraction-lib/settings/environments + # Currently, only develop and master branches are allowed to deploy to GitHub Pages + # Deployed pages are available at https://easyscience.github.io/diffraction-lib + - name: Deploy to easyscience.github.io/diffraction-lib (all branches) + uses: actions/deploy-pages@v4 + + # Download built site as artifact from a previous job for gh_pages and easydiffraction.org (master branch) + - name: Download built site from previous job (master branch) + if: ${{ env.CI_BRANCH == 'master' }} + uses: actions/download-artifact@v4 + with: # name or path are taken from the upload step of the previous job + name: artifact + path: site/ # directory to extract downloaded zipped artifacts + + # Push the site files created in the previous job to the gh_pages branch + # To be able to push to the gh_pages branch, the personal GitHub API access + # token GH_API_PERSONAL_ACCSESS_TOKEN must be set for this repository via + # https://github.com/easyscience/diffraction-lib/settings/secrets/actions + # This branch is used to deploy the site to the custom domain https://easydiffraction.org + # Deploying is done with a webhook: https://github.com/easyscience/diffraction-lib/settings/hooks + # This is done for the gh_pages branch when the site is tested with a step above + - name: + Deploy to gh_pages branch to trigger deployment to easydiffraction.org + (master branch) + if: ${{ env.CI_BRANCH == 'master' }} + uses: s0/git-publish-subdir-action@develop + env: + GITHUB_TOKEN: ${{ secrets.GH_API_PERSONAL_ACCSESS_TOKEN }} + REPO: self + BRANCH: gh_pages + FOLDER: site diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index f4523dfc..fc32ef79 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -27,9 +27,11 @@ This is an example of a workflow that describes the development process. ```console python -m pip install --upgrade pip ``` -- Install easydiffraction from root with `dev` extras for development +- Install easydiffraction from root with `dev` extras for development, + `charts` extras for Jupyter notebooks and `docs` extras for building + documentation ```console - pip install '.[dev]' + pip install '.[dev,charts,docs]' ``` - Make changes in the code - Run Ruff - Python linter and code formatter (configuration is in diff --git a/LICENSE b/LICENSE index f893b208..450a5ac0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,7 @@ BSD 3-Clause License -Copyright (c) 2024, EasyDiffractionLib contributors (https://github.com/EasyScience/EasyDiffractionLib) +Copyright (c) 2025, EasyDiffraction contributors +(https://github.com/EasyScience/EasyDiffractionLib) All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/docs/analysis.md b/docs/analysis.md new file mode 100644 index 00000000..a1e7c2e1 --- /dev/null +++ b/docs/analysis.md @@ -0,0 +1,45 @@ +# Analysis + +This section contains information about the analysis of diffraction data in EasyDiffraction. + +### Model-dependent analysis + +There are two general approaches to the analysis of data: **model-dependent** and **model-independent**. In the following examples, we are going to focus on the former. However, the latter is worth briefly highlighting. + +A model-independent approach to analysis is where no assumptions are made about the system that is being studied and conclusions are drawn only from the data that has been observed. However, in many applications, it is desirable to include what we think we know about the system, and so model-dependent analysis is used. + +Model-dependent analysis involves the development of a mathematical model that describes the model dataset that would be found for our system. This mathematical model usually has parameters that are linked to the physics and chemistry of our system. These parameters are varied to optimise the model, using an optimisation algorithm, with respect to the experimental data, i.e., to get the best agreement between the model data and the experimental data. + +Below is a diagram illustrating this process: + +```mermaid +flowchart LR + a(Propose
model) + b(Set/change
model
parameter
values) + c(Calculate
model
data) + d(Compare
model data to
experimental
data) + e(Stop
iteration) + a --> b + b --> c + c --> d + d-- Threshold
not
reached -->b + d-- Threshold
reached -->e +``` + +Model-dependent analysis is popular in the analysis of neutron scattering data, and we will use it in the following examples. + +## Calculation engines + +EasyDiffraction is designed to be a flexible and extensible tool for calculating diffraction patterns. It can use different calculation engines to perform the calculations. + +We currently rely on [CrysPy](https://www.cryspy.fr) as a calculation engine. CrysPy is a Python library originally developed for analysing polarised neutron diffraction data. It is now evolving into a more general purpose library and covers powders and single crystals, nuclear and (commensurate) magnetic structures, unpolarised neutron and X-ray diffraction. + +Another calculation engine is [CrysFML](https://code.ill.fr/scientific-software/CrysFML2008). This library is a collection of Fortran modules for crystallographic computations. It is used in the software package [FullProf](https://www.ill.eu/sites/fullprof/), and we are currently working on its integration into EasyDiffraction. + +## Minimisation engines + +EasyDiffraction uses different third-party libraries to perform the model-dependent analysis. + +Most of the examples in this section will use the [lmfit](https://lmfit.github.io/lmfit-py/) package, which provides a high-level interface to non-linear optimisation and curve fitting problems for Python. It is one of the tools that can be used to fit models to the experimental data. + +Another package that can be used for the same purpose is [bumps](https://bumps.readthedocs.io/en/latest/). In addition to traditional optimizers which search for the best minimum they can find in the search space, bumps provides Bayesian uncertainty analysis which explores all viable minima and finds confidence intervals on the parameters based on uncertainty in the measured values. diff --git a/docs/dictionaries.md b/docs/dictionaries.md new file mode 100644 index 00000000..4399dfb4 --- /dev/null +++ b/docs/dictionaries.md @@ -0,0 +1,110 @@ +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd +[3]: glossary.md + +# Dictionaries + +All parameter names used in EasyDiffraction are divided into several dictionaries given below. Each keyword in the dictionaries has one badge showing the corresponding type of dictionary, and can have one or more badges showing the type of experiment to which the keyword belongs. + +## Crystallographic information file + +EasyDiffraction input and output files use the simple, human-readable STAR/CIF data format, following the specifications of [International Union of Crystallography](https://www.iucr.org) (IUCr), wherever possible. + +## Model dictionary + +This dictionary provides data names for describing model parameters. + +[pd-neut-cwl][3]{:.label-experiment} [pd-neut-tof][3]{:.label-experiment} [sc-neut-cwl][3]{:.label-experiment} [pd-xray][3]{:.label-experiment} + +* [\_space_group](dictionaries/_space_group.md) [coreCIF][1]{:.label-cif} + * [\_space_group.name_H-M_alt](dictionaries/_space_group.md) [coreCIF][1]{:.label-cif} + * [\_space_group.IT_coordinate_system_code](dictionaries/_space_group.md) [coreCIF][1]{:.label-cif} +* [\_cell](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} + * [\_cell.angle_alpha](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} + * [\_cell.angle_beta](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} + * [\_cell.angle_gamma](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} + * [\_cell.length_a](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} + * [\_cell.length_b](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} + * [\_cell.length_c](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} +* [\_atom_site](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} + * [\_atom_site.label](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} + * [\_atom_site.type_symbol](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} + * [\_atom_site.fract_x](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} + * [\_atom_site.fract_y](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} + * [\_atom_site.fract_z](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} + * [\_atom_site.occupancy](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} + * [\_atom_site.ADP_type](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} + * [\_atom_site.B_iso_or_equiv](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} + * [\_atom_site.site_symmetry_multiplicity](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} + * [\_atom_site.Wyckoff_symbol](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} + +## Experiment and instrument dictionary + +This dictionary provides data names for describing experimental and instrumental parameters. + +[pd-neut-cwl][3]{:.label-experiment} [pd-neut-tof][3]{:.label-experiment} [sc-neut-cwl][3]{:.label-experiment} [pd-xray][3]{:.label-experiment} + +* [\_diffrn_radiation](dictionaries/_diffrn_radiation.md) [coreCIF][1]{:.label-cif} + * [\_diffrn_radiation.probe](dictionaries/_diffrn_radiation.md) [coreCIF][1]{:.label-cif} + +[pd-neut-cwl][3]{:.label-experiment} [sc-neut-cwl][3]{:.label-experiment} [pd-xray][3]{:.label-experiment} + +* [\_diffrn_radiation_wavelength](dictionaries/_diffrn_radiation_wavelength.md) [coreCIF][1]{:.label-cif} + * [\_diffrn_radiation_wavelength.wavelength](dictionaries/_diffrn_radiation_wavelength.md) [coreCIF][1]{:.label-cif} +* [\_pd_background](dictionaries/_pd_background.md) [pdCIF][2]{:.label-cif} + * [\_pd_background.line_segment_X](dictionaries/_pd_background.md) [pdCIF][2]{:.label-cif} + * [\_pd_background.line_segment_intensity](dictionaries/_pd_background.md) [pdCIF][2]{:.label-cif} + * [\_pd_background.X_coordinate](dictionaries/_pd_background.md) [pdCIF][2]{:.label-cif} +* [\_pd_phase_block](dictionaries/_pd_phase.md) [pdCIF][2]{:.label-cif} + * [\_pd_phase_block.id](dictionaries/_pd_phase.md) [pdCIF][2]{:.label-cif} + * [\_pd_phase_block.scale](dictionaries/_pd_phase.md) [customCIF][0]{:.label-cif} + +[pd-neut-cwl][3]{:.label-experiment} + +* [\_pd_calib](dictionaries/_pd_calib.md) [pdCIF][2]{:.label-cif} + * [\_pd_calib.2theta_offset](dictionaries/_pd_calib.md) [pdCIF][2]{:.label-cif} +* [\_pd_instr](dictionaries/_pd_instr.md) [pdCIF][2]{:.label-cif} + * [\_pd_instr.resolution_u](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + * [\_pd_instr.resolution_v](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + * [\_pd_instr.resolution_w](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + * [\_pd_instr.resolution_x](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + * [\_pd_instr.resolution_y](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + * [\_pd_instr.reflex_asymmetry_p1](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + * [\_pd_instr.reflex_asymmetry_p2](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + * [\_pd_instr.reflex_asymmetry_p3](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + * [\_pd_instr.reflex_asymmetry_p4](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} +* [\_pd_meas](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} + * [\_pd_meas.2theta_scan](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} + * [\_pd_meas.intensity_total](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} + * [\_pd_meas.intensity_total_su](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} + +[pd-neut-tof][3]{:.label-experiment} + +* [\_pd_instr](dictionaries/_pd_instr.md) [pdCIF][2]{:.label-cif} + * [\_pd_instr.zero](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + * [\_pd_instr.dtt1](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + * [\_pd_instr.dtt2](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + * [\_pd_instr.2theta_bank](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + * [\_pd_instr.alpha0](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + * [\_pd_instr.alpha1](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + * [\_pd_instr.beta0](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + * [\_pd_instr.beta1](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + * [\_pd_instr.sigma0](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + * [\_pd_instr.sigma1](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + * [\_pd_instr.sigma2](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} +* [\_pd_meas](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} + * [\_pd_meas.time_of_flight](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} + * [\_pd_meas.intensity_total](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} + * [\_pd_meas.intensity_total_su](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} + +[sc-neut-cwl][3]{:.label-experiment} + +* [\_extinction](dictionaries/_extinction.md) [customCIF][0]{:.label-cif} + * [\_extinction.model](dictionaries/_extinction.md) [customCIF][0]{:.label-cif} + * [\_extinction.mosaicity](dictionaries/_extinction.md) [customCIF][0]{:.label-cif} + * [\_extinction.radius](dictionaries/_extinction.md) [customCIF][0]{:.label-cif} + +* [\_exptl_crystal](dictionaries/_exptl_crystal.md) [customCIF][0]{:.label-cif} + * [\_exptl_crystal.id](dictionaries/_exptl_crystal.md) [customCIF][0]{:.label-cif} + * [\_exptl_crystal.scale](dictionaries/_exptl_crystal.md) [customCIF][0]{:.label-cif} diff --git a/docs/dictionaries/_atom_site.md b/docs/dictionaries/_atom_site.md new file mode 100644 index 00000000..2dae780c --- /dev/null +++ b/docs/dictionaries/_atom_site.md @@ -0,0 +1,49 @@ +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + +[coreCIF][1]{:.label-cif} + +# \_atom_site + +Data items in this category record details about the atom sites in a crystal structure, such as the positional coordinates and atomic displacement parameters. Please see the [IUCr page](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/CATOM_SITE.html) for further details. + +## [\_atom_site.label](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.label.html) + +This is a unique identifier for a particular site in the asymmetric unit of the crystal unit cell. + +## [\_atom_site.type_symbol](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.type_symbol.html) + +A code to identify the atom specie(s) occupying this site. + +## \_atom_site.fract + +Atom-site coordinates as fractions of the [\_cell_length](_cell.md) values. + +* [\_atom_site.fract_x](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.fract_x.html) +* [\_atom_site.fract_y](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.fract_y.html) +* [\_atom_site.fract_z](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.fract_z.html) + +## [\_atom_site.occupancy](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.occupancy.html) + +The fraction of the atom type present at this site. + +## [\_atom_site.ADP_type](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.adp_type.html) + +Code for type of atomic displacement parameters used for the site. Currently only `Biso` (isotropic B) is supported. + +## [\_atom_site.B_iso_or_equiv](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.B_iso_or_equiv.html) + +Isotropic atomic displacement parameter, or equivalent isotropic atomic displacement parameter, in angstroms squared. + +## [\_atom_site.site_symmetry_multiplicity](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.site_symmetry_multiplicity.html) + +`optional parameter` + +The number of different sites that are generated by the application of the space-group symmetry to the coordinates given for this site. It is equal to the multiplicity given for this Wyckoff site in International Tables for Crystallography Vol. A (2002). + +## [\_atom_site.Wyckoff_symbol](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.Wyckoff_symbol.html) + +`optional parameter` + +The Wyckoff symbol (letter) as listed in the space-group tables of International Tables for Crystallography Vol. A. diff --git a/docs/dictionaries/_cell.md b/docs/dictionaries/_cell.md new file mode 100644 index 00000000..61f0f583 --- /dev/null +++ b/docs/dictionaries/_cell.md @@ -0,0 +1,25 @@ +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + +[coreCIF][1]{:.label-cif} + +# \_cell + +Data items in this category record details about the crystallographic cell parameters and their measurement. Please see the [IUCr page](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/CCELL.html) for further details. + +## \_cell.angle + +The angles between the bounding cell axes in degrees. + +* [\_cell.angle_alpha](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Icell.angle_alpha.html) +* [\_cell.angle_beta](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Icell.angle_beta.html) +* [\_cell.angle_gamma](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Icell.angle_gamma.html) + +## \_cell.length + +The lengths of each cell axis in angstroms. + +* [\_cell.length_a](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Icell.length_a.html) +* [\_cell.length_b](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Icell.length_b.html) +* [\_cell.length_c](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Icell.length_c.html) diff --git a/docs/dictionaries/_diffrn_radiation.md b/docs/dictionaries/_diffrn_radiation.md new file mode 100644 index 00000000..9e3cd175 --- /dev/null +++ b/docs/dictionaries/_diffrn_radiation.md @@ -0,0 +1,15 @@ +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + +[coreCIF][1]{:.label-cif} + +# \_diffrn_radiation + +Data items in this category describe the radiation used in measuring the diffraction intensities. Please see the [IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) for further details. + +## [\_diffrn_radiation.probe](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) + +The nature of the radiation used (i.e. the name of the subatomic particle or the region of the electromagnetic spectrum). + +Supported values: `neutron` and `x-ray` diff --git a/docs/dictionaries/_diffrn_radiation_wavelength.md b/docs/dictionaries/_diffrn_radiation_wavelength.md new file mode 100644 index 00000000..4b31e012 --- /dev/null +++ b/docs/dictionaries/_diffrn_radiation_wavelength.md @@ -0,0 +1,13 @@ +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + +[coreCIF][1]{:.label-cif} + +# \_diffrn_radiation_wavelength + +Data items in this category describe the wavelength of radiation used in diffraction measurements. Please see the [IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) for further details. + +## [\_diffrn_radiation_wavelength.wavelength](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) + +Wavelength of the radiation used to measure the unit cell. diff --git a/docs/dictionaries/_exptl_crystal.md b/docs/dictionaries/_exptl_crystal.md new file mode 100644 index 00000000..9e79204d --- /dev/null +++ b/docs/dictionaries/_exptl_crystal.md @@ -0,0 +1,5 @@ +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + +[customCIF][0]{:.label-cif} diff --git a/docs/dictionaries/_extinction.md b/docs/dictionaries/_extinction.md new file mode 100644 index 00000000..9e79204d --- /dev/null +++ b/docs/dictionaries/_extinction.md @@ -0,0 +1,5 @@ +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + +[customCIF][0]{:.label-cif} diff --git a/docs/dictionaries/_pd_background.md b/docs/dictionaries/_pd_background.md new file mode 100644 index 00000000..a28a2963 --- /dev/null +++ b/docs/dictionaries/_pd_background.md @@ -0,0 +1,23 @@ +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + +[pdCIF][2]{:.label-cif} + +# \_pd_background + +This category defines various background functions that could be used when calculating diffractograms. Please see the [IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) for further details. + +## [\_pd_background.line_segment_X](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) + +List of X-coordinates used to create many straight-line segments representing the background in a calculated diffractogram. + +Supported values: `2theta` and `time-of-flight` + +## [\_pd_background.line_segment_intensity](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) + +List of intensities used to create many straight-line segments representing the background in a calculated diffractogram. + +## [\_pd_background.X_coordinate](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) + +The type of X-coordinate against which the pd_background values were calculated. diff --git a/docs/dictionaries/_pd_calib.md b/docs/dictionaries/_pd_calib.md new file mode 100644 index 00000000..46f34db5 --- /dev/null +++ b/docs/dictionaries/_pd_calib.md @@ -0,0 +1,13 @@ +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + +[customCIF][0]{:.label-cif} + +# \_pd_calib + +This section defines the parameters used for the calibration of the instrument, similar to this [IUCr section](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd). + +## [\_pd_calib.2theta_offset](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) + +An offset angle (in degrees) used to calibrate 2θ. diff --git a/docs/dictionaries/_pd_instr.md b/docs/dictionaries/_pd_instr.md new file mode 100644 index 00000000..ab341721 --- /dev/null +++ b/docs/dictionaries/_pd_instr.md @@ -0,0 +1,73 @@ +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + +[customCIF][0]{:.label-cif} + +# _pd_instr + +This section contains information relevant to the instrument used for the diffraction measurement, similar to this [IUCr section](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd). + +## [\_pd_instr.resolution](#) + +In general, the profile of a Bragg reflection centred at the peak position can be approximated by mathematical convolution of contributions from the instrument, called the instrumental resolution function, and from the microstructure of the sample. Because many contributions to powder diffraction peaks have a nearly Gaussian or Lorentzian shape, the pseudo-Voigt function, is widely used to describe peak profiles in powder diffraction. + +Half-width parameters (normally characterising the instrumental resolution function) as implemented in [CrysPy](https://cryspy.fr): + +* \_pd_instr.resolution_u +* \_pd_instr.resolution_v +* \_pd_instr.resolution_w + +Lorentzian isotropic microstrain parameter as implemented in [CrysPy](https://cryspy.fr): + +* \_pd_instr.resolution_x + +Lorentzian isotropic particle size parameteras implemented in [CrysPy](https://cryspy.fr): + +* \_pd_instr.resolution_y + +## [\_pd_instr.reflex_asymmetry](#) + +Peak profile asymmetry parameters as implemented in [CrysPy](https://cryspy.fr). + +* \_pd_instr.reflex_asymmetry_p1 +* \_pd_instr.reflex_asymmetry_p2 +* \_pd_instr.reflex_asymmetry_p3 +* \_pd_instr.reflex_asymmetry_p4 + +## [\_pd_instr.2theta_bank](#) + +Time-of-flight parameters as implemented in [CrysPy](https://cryspy.fr). + +## [\_pd_instr.dtt](#) + +Time-of-flight parameters as implemented in [CrysPy](https://cryspy.fr). + +* \_pd_instr.dtt1 +* \_pd_instr.dtt2 + +## [\_pd_instr.zero](#) + +Time-of-flight parameters as implemented in [CrysPy](https://cryspy.fr). + +## [\_pd_instr.alpha](#) + +Time-of-flight parameters as implemented in [CrysPy](https://cryspy.fr). + +* \_pd_instr.alpha0 +* \_pd_instr.alpha1 + +## [\_pd_instr.beta](#) + +Time-of-flight parameters as implemented in [CrysPy](https://cryspy.fr). + +* \_pd_instr.beta0 +* \_pd_instr.beta1 + +## [\_pd_instr.sigma](#) + +Time-of-flight parameters as implemented in [CrysPy](https://cryspy.fr). + +* \_pd_instr.sigma0 +* \_pd_instr.sigma1 +* \_pd_instr.sigma2 diff --git a/docs/dictionaries/_pd_meas.md b/docs/dictionaries/_pd_meas.md new file mode 100644 index 00000000..90a01244 --- /dev/null +++ b/docs/dictionaries/_pd_meas.md @@ -0,0 +1,25 @@ +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + +[pdCIF][2]{:.label-cif} + +# _pd_meas + +This section contains the measured diffractogram, similar to this [IUCr section](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd). + +## [\_pd_meas.2theta_scan](https://raw.githubusercontent.com/COMCIFS/Powder_Dictionary/master/cif_pow.dic) + +2θ diffraction angle (in degrees) for intensity points measured in a scanning method. + +## [\_pd_meas.time-of-flight](https://raw.githubusercontent.com/COMCIFS/Powder_Dictionary/master/cif_pow.dic) + +Measured time (in microseconds) for time-of-flight neutron measurements. + +## [\_pd_meas.intensity_total](https://raw.githubusercontent.com/COMCIFS/Powder_Dictionary/master/cif_pow.dic) + +Intensity recorded at each measurement point as a function of angle. + +## [\_pd_meas.intensity_total_su](https://raw.githubusercontent.com/COMCIFS/Powder_Dictionary/master/cif_pow.dic) + +Standard uncertainty of \_pd_meas.2theta_scan. diff --git a/docs/dictionaries/_pd_phase.md b/docs/dictionaries/_pd_phase.md new file mode 100644 index 00000000..8bfcc779 --- /dev/null +++ b/docs/dictionaries/_pd_phase.md @@ -0,0 +1,17 @@ +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + +[pdCIF][2]{:.label-cif} + +# \_pd_phase_block + +A table of phases relevant to the current data block. Each phase is identified by its data block identifier. Please see the [IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) for further details. + +## [\_pd_phase_block.id](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) + +A block ID code identifying a block containing phase information. + +## \_pd_phase_block.scale + +Phase scale. diff --git a/docs/dictionaries/_space_group.md b/docs/dictionaries/_space_group.md new file mode 100644 index 00000000..8b82f8b4 --- /dev/null +++ b/docs/dictionaries/_space_group.md @@ -0,0 +1,17 @@ +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + +[coreCIF][1]{:.label-cif} + +# \_space_group + +Contains all the data items that refer to the space group as a whole. Please see the [IUCr page](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/CSPACE_GROUP.html) for further details. + +## [\_space_group.name_H-M_alt](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Ispace_group.name_H-M_alt.html) + +The international Hermann-Mauguin space-group symbol as defined in International Tables for Crystallography Volume A. It allows any Hermann-Mauguin symbol to be given. + +## [\_space_group.IT_coordinate_system_code](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Ispace_group.IT_coordinate_system_code.html) + +A qualifier taken from the enumeration list identifying which setting in International Tables for Crystallography Volume A (2002) (IT) is used. diff --git a/docs/easyscience.md b/docs/easyscience.md new file mode 100644 index 00000000..451be2ba --- /dev/null +++ b/docs/easyscience.md @@ -0,0 +1,95 @@ +# The EasyScience framework + +EasyScience is a framework of software tools that can be used to build experimental data analysis packages. +For example, it has already been used in the development of [EasyDiffraction] and [EasyReflectometry]. Two more packages are about to be started: EasyImaging (Bragg edge imaging) and EasyDynamics (Quasielastic neutron scattering, QENS). + +The framework consists of both front- and back-end elements, known as [EasyApp] and [EasyScience], respectively. +The front-end provides a shared library of graphical interface elements that can be used to build a graphical user interface. +The back-end offers a toolset to perform model-dependent analysis, including the ability to plug-in existing calculation engines. + +Below is a diagram illustrating the relationship between the modules of the EasyScience framework: + + + + + EasyDiffractionBkg + Diffraction + + + + EasyDiffraction + + + EasyDiffractionLib + + + + EasyDiffractionApp + + + + + TechniqueIndependantBkg + Generic + + + + EasyBackend + + + EasyCore + + + + EasyCrystallography + + + + + + + + + + EasyFrontend + + + EasyApp + + + + + + + + EasyReflectometryBkg + Reflectometry + + + + EasyReflectometry + + + EasyReflectometryLib + + + + EasyReflectometryApp + + + + + + + + + + + + + + +[EasyDiffraction]: https://easydiffraction.org +[EasyReflectometry]: https://easyreflectometry.org +[EasyApp]: https://github.com/easyscience/easyapp +[EasyScience]: https://github.com/easyscience/easyscience \ No newline at end of file diff --git a/docs/experiment.md b/docs/experiment.md new file mode 100644 index 00000000..43163144 --- /dev/null +++ b/docs/experiment.md @@ -0,0 +1,261 @@ +[3]: glossary.md + +# Experiment + +This section describes different types of experimental data which EasyDiffraction can handle. + +## CIF-based description + +The following examples show the CIF data blocks for different types of diffraction experiments supported in EasyDiffraction. + +### [pd-neut-cwl][3]{:.label-experiment} + +
+
+data_hrpt
+
+_diffrn_radiation.probe                 neutron
+_diffrn_radiation_wavelength.wavelength 1.494
+
+_pd_calib.2theta_offset 0.6225(4)
+
+_pd_instr.resolution_u  0.0834
+_pd_instr.resolution_v -0.1168
+_pd_instr.resolution_w  0.123
+_pd_instr.resolution_x  0
+_pd_instr.resolution_y  0.0797
+
+_pd_instr.reflex_asymmetry_p1 0
+_pd_instr.reflex_asymmetry_p2 0
+_pd_instr.reflex_asymmetry_p3 0
+_pd_instr.reflex_asymmetry_p4 0
+
+loop_
+_pd_phase_block.id
+_pd_phase_block.scale
+lbco 9.0976(3)
+
+loop_
+_pd_background.line_segment_X
+_pd_background.line_segment_intensity
+_pd_background.X_coordinate
+ 10  174.3  2theta
+ 20  159.8  2theta
+ 30  167.9  2theta
+ 50  166.1  2theta
+ 70  172.3  2theta
+ 90  171.1  2theta
+110  172.4  2theta
+130  182.5  2theta
+150  173.0  2theta
+165  171.1  2theta
+
+loop_
+_pd_meas.2theta_scan
+_pd_meas.intensity_total
+_pd_meas.intensity_total_su
+ 10.00  167  12.6
+ 10.05  157  12.5
+ 10.10  187  13.3
+ 10.15  197  14.0
+ 10.20  164  12.5
+ 10.25  171  13.0
+...
+164.60  153  20.7
+164.65  173  30.1
+164.70  187  27.9
+164.75  175  38.2
+164.80  168  30.9
+164.85  109  41.2
+
+
+ +### [pd-neut-tof][3]{:.label-experiment} + +
+
+data_wish
+
+_diffrn_radiation.probe neutron
+
+_pd_instr.2theta_bank 152.827
+
+_pd_instr.dtt1 20773.1(3)
+_pd_instr.dtt2    -1.08308
+_pd_instr.zero   -13.7(5)
+
+_pd_instr.alpha0 -0.009(1)
+_pd_instr.alpha1  0.109(2)
+_pd_instr.beta0   0.00670(3)
+_pd_instr.beta1   0.0100(3)
+_pd_instr.sigma0  0
+_pd_instr.sigma1  0
+_pd_instr.sigma2 15.7(8)
+
+loop_
+_pd_phase_block.id
+_pd_phase_block.scale
+ncaf 1.093(5)
+
+loop_
+_pd_background.line_segment_X
+_pd_background.line_segment_intensity
+_pd_background.X_coordinate
+  9162.3  465(38) time-of-flight
+ 11136.8  593(30) time-of-flight
+ 14906.5  546(18) time-of-flight
+ 17352.2  496(14) time-of-flight
+ 20179.5  452(10) time-of-flight
+ 22176.0  468(12) time-of-flight
+ 24644.7  380(6)  time-of-flight
+ 28257.2  378(4)  time-of-flight
+ 34034.4  328(4)  time-of-flight
+ 41214.6  323(3)  time-of-flight
+ 49830.9  273(3)  time-of-flight
+ 58204.9  260(4)  time-of-flight
+ 70186.9  262(5)  time-of-flight
+ 82103.2  268(5)  time-of-flight
+102712.0  262(15) time-of-flight
+
+loop_
+_pd_meas.time_of_flight
+_pd_meas.intensity_total
+_pd_meas.intensity_total_su
+  9001.0  616.523  124.564
+  9006.8  578.769  123.141
+  9012.6  574.184  120.507
+  9018.5  507.739  111.300
+  9024.3  404.672  101.616
+  9030.1  469.244  107.991
+...
+103085.0  275.072   60.978
+103151.4  214.187   55.675
+103217.9  256.211   62.825
+103284.4  323.872   73.082
+103351.0  242.382   65.736
+103417.6  277.666   73.837
+
+
+ +### [sc-neut-cwl][3]{:.label-experiment} + +
+
+data_heidi
+
+_diffrn_radiation.probe                 neutron
+_diffrn_radiation_wavelength.wavelength 0.793
+
+_pd_calib.2theta_offset 0.6225(4)
+
+_pd_instr.resolution_u  0.0834
+_pd_instr.resolution_v -0.1168
+_pd_instr.resolution_w  0.123
+_pd_instr.resolution_x  0
+_pd_instr.resolution_y  0.0797
+
+_pd_instr.reflex_asymmetry_p1 0
+_pd_instr.reflex_asymmetry_p2 0
+_pd_instr.reflex_asymmetry_p3 0
+_pd_instr.reflex_asymmetry_p4 0
+
+loop_
+_exptl_crystal.id
+_exptl_crystal.scale
+tbti 2.92(6)
+
+loop_
+_refln.index_h
+_refln.index_k
+_refln.index_l
+_refln.intensity_meas
+_refln.intensity_meas_su
+ 1  1  1   194.5677    2.3253
+ 2  2  0    22.6319    1.1233
+ 3  1  1    99.2917    2.5620
+ 2  2  2   219.2877    3.2522
+...
+16  8  8    29.3063   12.6552
+17  7  7  1601.5154  628.8915
+13 13  7  1176.0896  414.6018
+19  5  1     0.8334   20.4207
+15  9  9    10.9864    8.0650
+12 12 10    14.4074   11.3800
+
+
+ +## Other supported data files + +If you do not have a CIF file with both the instrumental parameters and measured data, as in the example (hrpt.cif) from the previous section, you can import only measured data. In that case, the data are then automatically converted into CIF with default parameters. These can be later edited in the code. + +The following measured data formats are supported: + +* If standard deviations of measured intensities are present, the file should have either `*.xye` or `*.xys` extension and contain the following 3 columns: + * [\_pd_meas.2theta\_scan](dictionaries/_pd_meas.md), + * [\_pd_meas.intensity\_total](dictionaries/_pd_meas.md), + * [\_pd_meas.intensity\_total\_su](dictionaries/_pd_meas.md). +* If standard deviations of measured intensities are not given, the file should have `*.xy` extension and contain the following 2 columns: + * [\_pd_meas.2theta\_scan](dictionaries/_pd_meas.md), + * [\_pd_meas.intensity\_total](dictionaries/_pd_meas.md). + +In the second case, the standard deviations [\_pd_meas.intensity\_total\_su](dictionaries/_pd_meas.md) are calculated as the square root of the measured intensities [\_pd_meas.intensity\_total](dictionaries/_pd_meas.md). + +Optional comments with `#` are possible in data file headers. + +Here are some examples: + +### example1.xye + +
+
+# 2theta  intensity    su
+   10.00     167      12.6
+   10.05     157      12.5
+   10.10     187      13.3
+   10.15     197      14.0
+   10.20     164      12.5
+  ...
+  164.65     173      30.1
+  164.70     187      27.9
+  164.75     175      38.2
+  164.80     168      30.9
+  164.85     109      41.2
+
+
+ +### example2.xy + +
+
+# 2theta  intensity
+   10.00     167    
+   10.05     157    
+   10.10     187    
+   10.15     197    
+   10.20     164    
+  ...
+  164.65     173    
+  164.70     187    
+  164.75     175    
+  164.80     168    
+  164.85     109  
+
+
+ +### example3.xy + +
+
+10  167.3    
+10.05  157.4    
+10.1  187.1    
+10.15  197.8    
+10.2  164.9    
+...
+164.65  173.3    
+164.7  187.5    
+164.75  175.8    
+164.8  168.1    
+164.85  109     
+
+
diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 00000000..daff7352 --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,125 @@ +# Getting started + +## Requirements + +The EasyDiffraction library is developed in Python, so Python must be installed on your system. The library is compatible with Python versions 3.9 through 3.12. + +## Environment setup optional { #environment-setup data-toc-label="Environment setup" } + +We recommend using a virtual environment – an isolated Python runtime where any packages you install or update are contained within that environment. If you encounter issues, you can simply delete and recreate the environment. Setting it up is straightforward: + +* Create a new virtual environment with: +```console +python3 -m venv venv +``` + +* Activate the environment with: + + === ":material-apple: macOS" + ```console + . venv/bin/activate + ``` + === ":fontawesome-brands-windows: Windows" + ```console + . venv/Scripts/activate + ``` + === ":material-linux: Linux" + ```console + . venv/bin/activate + ``` + +Your terminal should now print `(venv)` before the prompt, which is how you know that you are inside the virtual environment that you just created. + +* Exit the environment with: + ``` + deactivate + ``` + +## Installation + +### From PyPI recommended { #from-pypi data-toc-label="From PyPI" } + +EasyDiffraction is published on the Python Package Index (PyPI) repository and can be installed with the package installer for Python (pip), ideally by using a [virtual environment](#environment-setup). + +We recommend installing the latest release of EasyDiffraction with the `charts` extras, which include optional dependencies used for simplified visualization of charts and tables. This can be especially useful for running the Jupyter Notebook examples. To do so, use the following command: +```console +pip install 'easydiffraction[charts]' +``` + +If only the core functionality is needed, the library can be installed simply with: +```console +pip install easydiffraction +``` + +To install a specific version of EasyDiffraction, e.g. 0.1.3, use: +```console +pip install 'easydiffraction==0.1.3' +``` + +Upgrading to the latest version can be done with: +```console +pip install --upgrade --force-reinstall easydiffraction +``` + +To show the currently installed version, use: +```console +pip show easydiffraction +``` + +### From GitHub + +Installing an unreleased version is not recommended and should only be done for testing purposes. + +Here is an example of how to install EasyDiffraction directly from our GitHub repository, e.g., from the `develop` branch: +```console +pip install git+https://github.com/EasyScience/EasyDiffractionLib@develop +``` + +To do the same with extra dependencies, use: +```console +pip install 'easydiffraction[charts] @ git+https://github.com/EasyScience/EasyDiffractionLib@develop' +``` + +## Examples + +We have a collection of Jupyter Notebook examples that demonstrate how to use EasyDiffraction for various tasks. These examples are presented in the [How to use](how-to-use/index.md#how-to-use) section of the documentation as static HTML pages. + +You can also run these Jupyter Notebook examples yourself either locally or in Google Colab. + +These Jupyter Notebook examples can be downloaded either one by one from the [How to use](how-to-use/index.md#how-to-use) section or all together as a zip archive from the [EasyDiffraction releases](https://github.com/EasyScience/EasyDiffractionLib/releases/latest). + +### Run locally + +To run the examples locally, you need to install Jupyter Notebook or JupyterLab. Here are the steps to take in the case of Jupyter Notebook: + +* Install Jupyter Notebook: + ```console + pip install notebook + ``` +* Download EasyDiffraction examples from GitHub for the latest release, e.g., using curl: + ```console + curl --location --remote-name https://github.com/EasyScience/EasyDiffractionLib/releases/latest/download/examples.zip + ``` +* Unzip the downloaded archive: + ```console + unzip examples.zip + ``` +* Run Jupyter Notebook server in the `examples/` directory: + ```console + jupyter notebook examples/ + ``` +* Open your web browser and go to: + ```console + http://localhost:8888/ + ``` +* Select one of the `*.ipynb` files. + +### Via Google Colab + +!!! note + + To run the examples in Google Colab, you need to have a Google account. + +Google Colab is a free cloud service that allows you to run Jupyter Notebooks online, enabling you to run the examples without installing anything on your local machine. + +In the top right corner of each example, under the [How to use](how-to-use/index.md#how-to-use) section, you will find a button to open that example in Google Colab :google-colab: diff --git a/docs/glossary.md b/docs/glossary.md new file mode 100644 index 00000000..b0db79cc --- /dev/null +++ b/docs/glossary.md @@ -0,0 +1,25 @@ +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + +# Glossary + +This page contains the most common abbreviations used in EasyDiffraction documentation. + +## Dictionary type labels + +* [coreCIF][1]{:.label-cif} Core CIF dictionary by the [IUCr](https://www.iucr.org). +* [pdCIF][2]{:.label-cif} Powder CIF dictionary by the [IUCr](https://www.iucr.org). +* [customCIF][0]{:.label-cif} Custom CIF dictionary by the EasyDiffraction developers. + +## Experiment type labels + +### Neutron diffraction + +* [pd-neut-cwl][0]{:.label-experiment} Powder neutron diffraction with constant wavelength. +* [pd-neut-tof][0]{:.label-experiment} Powder neutron diffraction with time-of-flight. +* [sc-neut-cwl][0]{:.label-experiment} Single crystal neutron diffraction with constant wavelength. + +### X-ray diffraction + +* [pd-xray][0]{:.label-experiment} Powder X-ray diffraction. diff --git a/docs/how-to-use/index.md b/docs/how-to-use/index.md new file mode 100644 index 00000000..513e6113 --- /dev/null +++ b/docs/how-to-use/index.md @@ -0,0 +1,8 @@ +# How to use + +This section provides a collection of Jupyter Notebook examples that demonstrate how to use EasyDiffraction for various tasks. These examples are presented as static HTML pages. + +In the top right corner of each example, you will find + +* a button to download the example as a Jupyter Notebook :material-download: +* a button to open that example in Google Colab :google-colab: diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..ee249904 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,19 @@ +# Making diffraction data analysis easy + +## About + +EasyDiffraction is scientific software for calculating neutron powder diffraction patterns based on a structural model and refining its parameters against experimental data. + +EasyDiffraction is distributed as both a cross-platform desktop application and a Python library. + +Here you can find instructions for using the EasyDiffraction Python library. Documentation for the EasyDiffraction graphical user interface can be found [elsewhere](https://docs.easydiffraction.org/app). + +EasyDiffraction is part of the [EasyScience framework](https://easyscience.software), briefly described in the next section. + +## License + +EasyDiffraction is licensed under the [BSD 3-Clause License](https://raw.githubusercontent.com/EasyScience/EasyDiffractionLib/master/LICENSE). + +## Latest release + +The latest release of EasyDiffraction Python library is [{{ vars.release_version }}](https://github.com/EasyScience/EasyDiffractionLib/releases/latest). diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml new file mode 100644 index 00000000..f97ca6fd --- /dev/null +++ b/docs/mkdocs.yml @@ -0,0 +1,39 @@ +# Project information +site_name: EasyDiffraction Library +site_url: https://easyscience.github.io/diffraction-lib + +# Repository +repo_url: https://github.com/easyscience/diffraction-lib +edit_uri: edit/develop/docs/ + +# Copyright +copyright: © 2025 EasyDiffraction + +# Format and layout of the global navigation for the site +not_in_nav: | + dictionaries +nav: + - Introduction: index.md + - EasyScience: easyscience.md + - Getting started: getting-started.md + - Glossary: glossary.md + - Dictionaries: dictionaries.md + - Project structure: project-structure.md + - Model: model.md + - Experiment: experiment.md + - Analysis: analysis.md + - How to use: + - how-to-use/index.md + - Basic: + - Define model: examples/Define-model.ipynb + - Define experiment: examples/Define-experiment.ipynb + - Simulation: + - pd-xray NaCl: examples/Simulation_pd-xray_NaCl.ipynb + - Fitting: + - pd-neut-cwl LBCO-HRPT: examples/Fitting_pd-neut-cwl_LBCO-HRPT.ipynb + - pd-neut-tof Si-SEPD: examples/Fitting_pd-neut-tof_Si-SEPD.ipynb + - pd-neut-tof NCAF-WISH: examples/Fitting_pd-neut-tof_NCAF-WISH.ipynb + - Advanced fitting: + - MCMC pd-neut-tof NCAF-WISH: examples/Fitting-emcee_pd-neut-cwl_LBCO-HRPT.ipynb + - Extra: + - Change minimizer: examples/Change-minimizer.ipynb diff --git a/docs/model.md b/docs/model.md new file mode 100644 index 00000000..fad000b5 --- /dev/null +++ b/docs/model.md @@ -0,0 +1,5 @@ +# Model + +EasyDiffraction allow you to load the crystallographic model in CIF format. The model is then used to calculate the diffraction pattern, which is compared to the experimental data. The model parameters can be refined to improve the agreement between the calculated and measured data. + +An example of the CIF-based model has been given in the [Project structure](project-structure.md) section. diff --git a/docs/project-structure.md b/docs/project-structure.md new file mode 100644 index 00000000..96282536 --- /dev/null +++ b/docs/project-structure.md @@ -0,0 +1,134 @@ +# Project structure + +## CIF-based project files + +Example project structure for the constant wavelength powder neutron diffraction measurement is given below: + +
+
+La0.5Ba0.5CoO3     - Project directory.
+├── project.cif    - Main project description file.
+├── models         - Folder with individual crystallographic phases.
+│   ├── lbco.cif   - File with La0.5Ba0.5CoO3 phase parameters.
+│   └── ...
+├── experiments    - Folder with instrumental parameters and measured data.
+│   ├── hrpt.cif   - Measured data from HRPT@PSI & instrumental parameters.
+│   └── ...
+└── summary
+    └── report.cif - Summary report after structure refinement.
+
+
+ +Here is the content of the project files: + +### project.cif + +
+
+data_La0.5Ba0.5CoO3
+
+_project.description "neutrons, powder, constant wavelength, HRPT@PSI"
+
+loop_
+_model.cif_file_name
+lbco.cif
+
+loop_
+_experiment.cif_file_name
+hrpt.cif
+
+
+ +### models / lbco.cif + +
+
+data_lbco
+
+_space_group.name_H-M_alt              "P m -3 m"
+_space_group.IT_coordinate_system_code 1
+
+_cell.length_a      3.8909(1)
+_cell.length_b      3.8909
+_cell.length_c      3.8909
+_cell.angle_alpha  90
+_cell.angle_beta   90
+_cell.angle_gamma  90
+
+loop_
+_atom_site.label
+_atom_site.type_symbol
+_atom_site.fract_x
+_atom_site.fract_y
+_atom_site.fract_z
+_atom_site.occupancy
+_atom_site.adp_type
+_atom_site.B_iso_or_equiv
+La La   0   0   0     0.5  Biso 0.4958
+Ba Ba   0   0   0     0.5  Biso 0.4943
+Co Co   0.5 0.5 0.5   1    Biso 0.2567
+O  O    0   0.5 0.5   1    Biso 1.4041
+
+
+ +### experiments / hrpt.cif + +
+
+data_hrpt
+
+_diffrn_radiation.probe                 neutron
+_diffrn_radiation_wavelength.wavelength 1.494
+
+_pd_calib.2theta_offset 0.6225(4)
+
+_pd_instr.resolution_u  0.0834
+_pd_instr.resolution_v -0.1168
+_pd_instr.resolution_w  0.123
+_pd_instr.resolution_x  0
+_pd_instr.resolution_y  0.0797
+
+_pd_instr.reflex_asymmetry_p1 0
+_pd_instr.reflex_asymmetry_p2 0
+_pd_instr.reflex_asymmetry_p3 0
+_pd_instr.reflex_asymmetry_p4 0
+
+loop_
+_pd_phase_block.id
+_pd_phase_block.scale
+lbco 9.0976(3)
+
+loop_
+_pd_background.line_segment_X
+_pd_background.line_segment_intensity
+_pd_background.X_coordinate
+ 10  174.3  2theta
+ 20  159.8  2theta
+ 30  167.9  2theta
+ 50  166.1  2theta
+ 70  172.3  2theta
+ 90  171.1  2theta
+110  172.4  2theta
+130  182.5  2theta
+150  173.0  2theta
+165  171.1  2theta
+
+loop_
+_pd_meas.2theta_scan
+_pd_meas.intensity_total
+_pd_meas.intensity_total_su
+ 10.00  167  12.6
+ 10.05  157  12.5
+ 10.10  187  13.3
+ 10.15  197  14.0
+ 10.20  164  12.5
+ 10.25  171  13.0
+...
+164.60  153  20.7
+164.65  173  30.1
+164.70  187  27.9
+164.75  175  38.2
+164.80  168  30.9
+164.85  109  41.2
+
+
diff --git a/pyproject.toml b/pyproject.toml index 8e9139db..b8b61de5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,10 +44,19 @@ dev = [ 'versioningit', # Versioning ] charts = [ - 'darkdetect', # Detecting dark mode - 'pandas', # Displaying tables in juptyer notebooks - 'plotly', # Interactive plots - 'py3Dmol', # Visualisation of crystal structures + 'darkdetect', # Detecting dark mode + 'pandas', # Displaying tables in juptyer notebooks + 'plotly<6.0.0', # Interactive plots. 0.6.0 => Empty charts in Jupyter notebooks ... + 'py3Dmol', # Visualisation of crystal structures +] +docs = [ + 'mkdocs', # Static site generator + 'mkdocs-material', # Documentation framework on top of MkDocs + 'mkdocs-autorefs<1.3.0', # 1.3.0 => DeprecationWarning: Setting a fallback anchor function is deprecated and ... + 'mkdocs-jupyter', + 'mkdocs-plugin-inline-svg', + 'mkdocs-markdownextradata-plugin', + 'mkdocstrings', ] pdf = [ 'diffpy.pdffit2', # Calculations of atomic pair distribution function From d5cd71790c9c7f2a72c05380b27e93c850db262c Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Sun, 2 Feb 2025 22:47:17 +0100 Subject: [PATCH 09/43] 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 10/43] 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 eb6f02deb98b37a25b3bcb3e7d1ae0114b2920d1 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 3 Feb 2025 10:36:14 +0100 Subject: [PATCH 11/43] Update development workflow --- .github/workflows/build-docs.yml | 2 +- DEVELOPMENT.md | 55 +++++++++++++++++-- pyproject.toml | 29 +++++----- tools/build_docs.sh | 3 + tools/cleanup_docs.sh | 10 ++++ ...ting_and_formatting.sh => code_quality.sh} | 3 + tools/install_deps.sh | 5 ++ tools/prepare_docs.sh | 21 +++++++ 8 files changed, 109 insertions(+), 19 deletions(-) create mode 100755 tools/build_docs.sh create mode 100755 tools/cleanup_docs.sh rename tools/{linting_and_formatting.sh => code_quality.sh} (77%) create mode 100755 tools/install_deps.sh create mode 100755 tools/prepare_docs.sh diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 55b5ecfd..c5323307 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -112,7 +112,7 @@ jobs: - name: Pre-build site step run: python -c "import easydiffraction" - # Create the mkdocs.yml file + # Create the mkdocs.yml configuration file # The file is created by merging two files: # - assets-docs/mkdocs.yml - the common configuration (theme, plugins, etc.) # - docs/mkdocs.yml - the project-specific configuration (project name, TOC, etc.) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index fc32ef79..3a1e102f 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -34,8 +34,12 @@ This is an example of a workflow that describes the development process. pip install '.[dev,charts,docs]' ``` - Make changes in the code + ```console + ... + ``` - Run Ruff - Python linter and code formatter (configuration is in - pyproject.toml) Linting (overwriting files) + pyproject.toml)
+ Linting (overwriting files) ```console ruff check . --fix ``` @@ -43,7 +47,8 @@ This is an example of a workflow that describes the development process. ```console ruff format . ``` -- Install and run Prettier - code formatter for markdown, YAML, TOML files +- Install and run Prettier - code formatter for Markdown, YAML, TOML, + etc. files (configuration in prettierrc.toml)
Formatting (overwriting files) ```console npm install prettier prettier-plugin-toml --save-dev --save-exact @@ -53,7 +58,9 @@ This is an example of a workflow that describes the development process. ```console pytest tests/ --color=yes -n auto ``` -- Clear all Jupyter notebooks output +- Clear all Jupyter notebooks output (Only those that were changed!). + Replace `examples/*.ipynb` with the path to the notebook(s) you want + to clear ```console jupyter nbconvert --clear-output --inplace examples/*.ipynb ``` @@ -63,7 +70,47 @@ This is an example of a workflow that describes the development process. ``` - Run Jupyter notebooks as tests ```console - pytest --nbmake examples/*ipynb --nbmake-timeout=300 --color=yes -n=auto + pytest --nbmake examples/ --ignore-glob='examples/*emcee*' --nbmake-timeout=300 --color=yes -n=auto + ``` +- Add extra files to build documentation (from `../assets-docs/` and + `../assets-branding/` directories) + ```console + cp -R ../assets-docs/docs/assets/ docs/assets/ + cp -R ../assets-docs/includes/ includes/ + cp -R ../assets-docs/overrides/ overrides/ + mkdir -p docs/assets/images/ + cp ../assets-branding/EasyDiffraction/logos/edl-logo_dark.svg docs/assets/images/logo_dark.svg + cp ../assets-branding/EasyDiffraction/logos/edl-logo_light.svg docs/assets/images/logo_light.svg + cp ../assets-branding/EasyDiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png + mkdir -p overrides/.icons/ + cp ../assets-branding/EasyDiffraction/icons/ed-icon_bw.svg overrides/.icons/easydiffraction.svg + cp ../assets-branding/EasyScience/icons/es-icon_bw.svg overrides/.icons/easyscience.svg + cp -R examples/ docs/examples/ + cp ../assets-docs/mkdocs.yml mkdocs.yml + echo "" >> mkdocs.yml + cat docs/mkdocs.yml >> mkdocs.yml + ``` +- Build documentation with MkDocs - static site generator + ```console + export JUPYTER_PLATFORM_DIRS=1 + mkdocs serve + ``` +- Test the documentation locally (built in the `site/` directory). E.g., + on macOS, open the site in the default browser via the terminal + ```console + open http://127.0.0.1:8000 + ``` +- Clean up after building documentation + ```console + rm -rf site/ + rm -rf docs/assets/ + rm -rf includes/ + rm -rf overrides/ + rm -rf docs/examples/ + rm -rf node_modules/ + rm mkdocs.yml + rm package-lock.json + rm package.json ``` - Commit changes ```console diff --git a/pyproject.toml b/pyproject.toml index b8b61de5..48b36b3f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,15 +33,16 @@ dependencies = [ [project.optional-dependencies] dev = [ - 'build', # Building the package - 'jinja2', # Templating for the documentation - 'nbmake', # Building notebooks - 'nbqa', # Linting and formatting notebooks - 'pytest', # Testing - 'pytest-cov', # Coverage - 'pytest-xdist', # Enable parallel testing - 'ruff', # Linting and formatting code - 'versioningit', # Versioning + 'build', # Building the package + 'jinja2', # Templating for the documentation + 'nbmake', # Building notebooks + 'nbqa', # Linting and formatting notebooks + 'pytest', # Testing + 'pytest-cov', # Coverage + 'pytest-xdist', # Enable parallel testing + 'ruff', # Linting and formatting code + 'validate-pyproject[all]', # Validate pyproject.toml + 'versioningit', # Versioning ] charts = [ 'darkdetect', # Detecting dark mode @@ -52,11 +53,11 @@ charts = [ docs = [ 'mkdocs', # Static site generator 'mkdocs-material', # Documentation framework on top of MkDocs - 'mkdocs-autorefs<1.3.0', # 1.3.0 => DeprecationWarning: Setting a fallback anchor function is deprecated and ... - 'mkdocs-jupyter', - 'mkdocs-plugin-inline-svg', - 'mkdocs-markdownextradata-plugin', - 'mkdocstrings', + 'mkdocs-autorefs<1.3.0', # MkDocs: Auto-references support. 1.3.0 => DeprecationWarning: Setting a fallback anchor function is deprecated and ... + 'mkdocs-jupyter', # MkDocs: Jupyter notebook support + 'mkdocs-plugin-inline-svg', # MkDocs: Inline SVG support + 'mkdocs-markdownextradata-plugin', # MkDocs: Markdown extra data support, such as global variables + 'mkdocstrings', # MkDocs: Python docstring support ] pdf = [ 'diffpy.pdffit2', # Calculations of atomic pair distribution function diff --git a/tools/build_docs.sh b/tools/build_docs.sh new file mode 100755 index 00000000..016182c8 --- /dev/null +++ b/tools/build_docs.sh @@ -0,0 +1,3 @@ +echo "\033[0;33m:::::: Build docs (http://127.0.0.1:8000)\033[0m" +export JUPYTER_PLATFORM_DIRS=1 +mkdocs serve diff --git a/tools/cleanup_docs.sh b/tools/cleanup_docs.sh new file mode 100755 index 00000000..b220a0fb --- /dev/null +++ b/tools/cleanup_docs.sh @@ -0,0 +1,10 @@ +echo "\033[0;33m:::::: Clean up after building documentation\033[0m" +rm -rf site/ +rm -rf docs/assets/ +rm -rf includes/ +rm -rf overrides/ +rm -rf docs/examples/ +rm -rf node_modules/ +rm mkdocs.yml +rm package-lock.json +rm package.json diff --git a/tools/linting_and_formatting.sh b/tools/code_quality.sh similarity index 77% rename from tools/linting_and_formatting.sh rename to tools/code_quality.sh index bcdc1149..718dd07d 100755 --- a/tools/linting_and_formatting.sh +++ b/tools/code_quality.sh @@ -1,3 +1,6 @@ +echo "\033[0;33m:::::: Check the validity of pyproject.toml\033[0m" +validate-pyproject pyproject.toml + echo "\033[0;33m:::::: Check and fix code linting\033[0m" ruff check . --fix diff --git a/tools/install_deps.sh b/tools/install_deps.sh new file mode 100755 index 00000000..948da6df --- /dev/null +++ b/tools/install_deps.sh @@ -0,0 +1,5 @@ +echo "\033[0;33m:::::: Install Python dependencies\033[0m" +pip install '.[dev,charts,docs]' + +echo "\033[0;33m:::::: Install npm dependencies\033[0m" +npm install prettier prettier-plugin-toml --save-dev --save-exact diff --git a/tools/prepare_docs.sh b/tools/prepare_docs.sh new file mode 100755 index 00000000..0170c6d0 --- /dev/null +++ b/tools/prepare_docs.sh @@ -0,0 +1,21 @@ +echo "\033[0;33m:::::: Add the extra files from the ../assets-docs\033[0m" +cp -R ../assets-docs/docs/assets/ docs/assets/ +cp -R ../assets-docs/includes/ includes/ +cp -R ../assets-docs/overrides/ overrides/ + +echo "\033[0;33m:::::: Add the extra files from the ../assets-branding\033[0m" +mkdir -p docs/assets/images/ +cp ../assets-branding/EasyDiffraction/logos/edl-logo_dark.svg docs/assets/images/logo_dark.svg +cp ../assets-branding/EasyDiffraction/logos/edl-logo_light.svg docs/assets/images/logo_light.svg +cp ../assets-branding/EasyDiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png +mkdir -p overrides/.icons/ +cp ../assets-branding/EasyDiffraction/icons/ed-icon_bw.svg overrides/.icons/easydiffraction.svg +cp ../assets-branding/EasyScience/icons/es-icon_bw.svg overrides/.icons/easyscience.svg + +echo "\033[0;33m:::::: Add Jupyter notebooks from the project to the docs/\033[0m" +cp -R examples/ docs/examples/ + +echo "\033[0;33m:::::: Create the mkdocs.yml configuration file\033[0m" +cp ../assets-docs/mkdocs.yml mkdocs.yml +echo "" >> mkdocs.yml +cat docs/mkdocs.yml >> mkdocs.yml From 159d1500f16a4b9c0ab6c659605c860bc6b2eedd Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 3 Feb 2025 12:01:40 +0100 Subject: [PATCH 12/43] Update docs and improve formatting --- .github/workflows/build-docs.yml | 2 + DEVELOPMENT.md | 34 +-- docs/analysis.md | 54 ++++- docs/dictionaries.md | 222 +++++++++++------- docs/dictionaries/_atom_site.md | 39 ++- docs/dictionaries/_cell.md | 27 ++- docs/dictionaries/_diffrn_radiation.md | 18 +- .../_diffrn_radiation_wavelength.md | 15 +- docs/dictionaries/_exptl_crystal.md | 6 +- docs/dictionaries/_extinction.md | 6 +- docs/dictionaries/_pd_background.md | 21 +- docs/dictionaries/_pd_calib.md | 14 +- docs/dictionaries/_pd_instr.md | 68 +++--- docs/dictionaries/_pd_meas.md | 18 +- docs/dictionaries/_pd_phase.md | 15 +- docs/dictionaries/_space_group.md | 22 +- docs/easyscience.md | 23 +- docs/experiment.md | 24 +- docs/getting-started.md | 89 +++++-- docs/glossary.md | 33 ++- docs/how-to-use/index.md | 10 +- docs/index.md | 23 +- docs/model.md | 8 +- docs/project-structure.md | 19 +- tools/prepare_docs.sh | 2 + 25 files changed, 537 insertions(+), 275 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index c5323307..991c00f4 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -93,6 +93,8 @@ jobs: run: | git clone https://github.com/easyscience/assets-branding.git mkdir -p docs/assets/images/ + cp assets-branding/EasyDiffraction/logos/ed-logo_dark.svg docs/assets/images/ + cp assets-branding/EasyDiffraction/logos/ed-logo_light.svg docs/assets/images/ cp assets-branding/EasyDiffraction/logos/edl-logo_dark.svg docs/assets/images/logo_dark.svg cp assets-branding/EasyDiffraction/logos/edl-logo_light.svg docs/assets/images/logo_light.svg cp assets-branding/EasyDiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 3a1e102f..cdb7ea78 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -27,9 +27,8 @@ This is an example of a workflow that describes the development process. ```console python -m pip install --upgrade pip ``` -- Install easydiffraction from root with `dev` extras for development, - `charts` extras for Jupyter notebooks and `docs` extras for building - documentation +- Install easydiffraction from root with `dev` extras for development, `charts` + extras for Jupyter notebooks and `docs` extras for building documentation ```console pip install '.[dev,charts,docs]' ``` @@ -37,9 +36,12 @@ This is an example of a workflow that describes the development process. ```console ... ``` +- Check the validity of pyproject.toml + ```console + validate-pyproject pyproject.toml + ``` - Run Ruff - Python linter and code formatter (configuration is in - pyproject.toml)
- Linting (overwriting files) + pyproject.toml)
Linting (overwriting files) ```console ruff check . --fix ``` @@ -47,9 +49,8 @@ This is an example of a workflow that describes the development process. ```console ruff format . ``` -- Install and run Prettier - code formatter for Markdown, YAML, TOML, - etc. files (configuration in prettierrc.toml)
- Formatting (overwriting files) +- Install and run Prettier - code formatter for Markdown, YAML, TOML, etc. files + (configuration in prettierrc.toml)
Formatting (overwriting files) ```console npm install prettier prettier-plugin-toml --save-dev --save-exact npx prettier . --write --config=prettierrc.toml @@ -58,9 +59,8 @@ This is an example of a workflow that describes the development process. ```console pytest tests/ --color=yes -n auto ``` -- Clear all Jupyter notebooks output (Only those that were changed!). - Replace `examples/*.ipynb` with the path to the notebook(s) you want - to clear +- Clear all Jupyter notebooks output (Only those that were changed!). Replace + `examples/*.ipynb` with the path to the notebook(s) you want to clear ```console jupyter nbconvert --clear-output --inplace examples/*.ipynb ``` @@ -72,13 +72,15 @@ This is an example of a workflow that describes the development process. ```console pytest --nbmake examples/ --ignore-glob='examples/*emcee*' --nbmake-timeout=300 --color=yes -n=auto ``` -- Add extra files to build documentation (from `../assets-docs/` and +- Add extra files to build documentation (from `../assets-docs/` and `../assets-branding/` directories) ```console cp -R ../assets-docs/docs/assets/ docs/assets/ cp -R ../assets-docs/includes/ includes/ - cp -R ../assets-docs/overrides/ overrides/ + cp -R ../assets-docs/overrides/ overrides/ mkdir -p docs/assets/images/ + cp ../assets-branding/EasyDiffraction/logos/ed-logo_dark.svg docs/assets/images/ + cp ../assets-branding/EasyDiffraction/logos/ed-logo_light.svg docs/assets/images/ cp ../assets-branding/EasyDiffraction/logos/edl-logo_dark.svg docs/assets/images/logo_dark.svg cp ../assets-branding/EasyDiffraction/logos/edl-logo_light.svg docs/assets/images/logo_light.svg cp ../assets-branding/EasyDiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png @@ -89,14 +91,14 @@ This is an example of a workflow that describes the development process. cp ../assets-docs/mkdocs.yml mkdocs.yml echo "" >> mkdocs.yml cat docs/mkdocs.yml >> mkdocs.yml - ``` + ``` - Build documentation with MkDocs - static site generator ```console export JUPYTER_PLATFORM_DIRS=1 mkdocs serve ``` -- Test the documentation locally (built in the `site/` directory). E.g., - on macOS, open the site in the default browser via the terminal +- Test the documentation locally (built in the `site/` directory). E.g., on + macOS, open the site in the default browser via the terminal ```console open http://127.0.0.1:8000 ``` diff --git a/docs/analysis.md b/docs/analysis.md index a1e7c2e1..1bca73a6 100644 --- a/docs/analysis.md +++ b/docs/analysis.md @@ -1,14 +1,26 @@ # Analysis -This section contains information about the analysis of diffraction data in EasyDiffraction. +This section contains information about the analysis of diffraction data in +EasyDiffraction. ### Model-dependent analysis -There are two general approaches to the analysis of data: **model-dependent** and **model-independent**. In the following examples, we are going to focus on the former. However, the latter is worth briefly highlighting. +There are two general approaches to the analysis of data: **model-dependent** +and **model-independent**. In the following examples, we are going to focus on +the former. However, the latter is worth briefly highlighting. -A model-independent approach to analysis is where no assumptions are made about the system that is being studied and conclusions are drawn only from the data that has been observed. However, in many applications, it is desirable to include what we think we know about the system, and so model-dependent analysis is used. +A model-independent approach to analysis is where no assumptions are made about +the system that is being studied and conclusions are drawn only from the data +that has been observed. However, in many applications, it is desirable to +include what we think we know about the system, and so model-dependent analysis +is used. -Model-dependent analysis involves the development of a mathematical model that describes the model dataset that would be found for our system. This mathematical model usually has parameters that are linked to the physics and chemistry of our system. These parameters are varied to optimise the model, using an optimisation algorithm, with respect to the experimental data, i.e., to get the best agreement between the model data and the experimental data. +Model-dependent analysis involves the development of a mathematical model that +describes the model dataset that would be found for our system. This +mathematical model usually has parameters that are linked to the physics and +chemistry of our system. These parameters are varied to optimise the model, +using an optimisation algorithm, with respect to the experimental data, i.e., to +get the best agreement between the model data and the experimental data. Below is a diagram illustrating this process: @@ -26,20 +38,40 @@ flowchart LR d-- Threshold
reached -->e ``` -Model-dependent analysis is popular in the analysis of neutron scattering data, and we will use it in the following examples. +Model-dependent analysis is popular in the analysis of neutron scattering data, +and we will use it in the following examples. ## Calculation engines -EasyDiffraction is designed to be a flexible and extensible tool for calculating diffraction patterns. It can use different calculation engines to perform the calculations. +EasyDiffraction is designed to be a flexible and extensible tool for calculating +diffraction patterns. It can use different calculation engines to perform the +calculations. -We currently rely on [CrysPy](https://www.cryspy.fr) as a calculation engine. CrysPy is a Python library originally developed for analysing polarised neutron diffraction data. It is now evolving into a more general purpose library and covers powders and single crystals, nuclear and (commensurate) magnetic structures, unpolarised neutron and X-ray diffraction. +We currently rely on [CrysPy](https://www.cryspy.fr) as a calculation engine. +CrysPy is a Python library originally developed for analysing polarised neutron +diffraction data. It is now evolving into a more general purpose library and +covers powders and single crystals, nuclear and (commensurate) magnetic +structures, unpolarised neutron and X-ray diffraction. -Another calculation engine is [CrysFML](https://code.ill.fr/scientific-software/CrysFML2008). This library is a collection of Fortran modules for crystallographic computations. It is used in the software package [FullProf](https://www.ill.eu/sites/fullprof/), and we are currently working on its integration into EasyDiffraction. +Another calculation engine is +[CrysFML](https://code.ill.fr/scientific-software/CrysFML2008). This library is +a collection of Fortran modules for crystallographic computations. It is used in +the software package [FullProf](https://www.ill.eu/sites/fullprof/), and we are +currently working on its integration into EasyDiffraction. ## Minimisation engines -EasyDiffraction uses different third-party libraries to perform the model-dependent analysis. +EasyDiffraction uses different third-party libraries to perform the +model-dependent analysis. -Most of the examples in this section will use the [lmfit](https://lmfit.github.io/lmfit-py/) package, which provides a high-level interface to non-linear optimisation and curve fitting problems for Python. It is one of the tools that can be used to fit models to the experimental data. +Most of the examples in this section will use the +[lmfit](https://lmfit.github.io/lmfit-py/) package, which provides a high-level +interface to non-linear optimisation and curve fitting problems for Python. It +is one of the tools that can be used to fit models to the experimental data. -Another package that can be used for the same purpose is [bumps](https://bumps.readthedocs.io/en/latest/). In addition to traditional optimizers which search for the best minimum they can find in the search space, bumps provides Bayesian uncertainty analysis which explores all viable minima and finds confidence intervals on the parameters based on uncertainty in the measured values. +Another package that can be used for the same purpose is +[bumps](https://bumps.readthedocs.io/en/latest/). In addition to traditional +optimizers which search for the best minimum they can find in the search space, +bumps provides Bayesian uncertainty analysis which explores all viable minima +and finds confidence intervals on the parameters based on uncertainty in the +measured values. diff --git a/docs/dictionaries.md b/docs/dictionaries.md index 4399dfb4..528c1c03 100644 --- a/docs/dictionaries.md +++ b/docs/dictionaries.md @@ -1,110 +1,158 @@ -[0]: # -[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core -[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd -[3]: glossary.md - # Dictionaries -All parameter names used in EasyDiffraction are divided into several dictionaries given below. Each keyword in the dictionaries has one badge showing the corresponding type of dictionary, and can have one or more badges showing the type of experiment to which the keyword belongs. +All parameter names used in EasyDiffraction are divided into several +dictionaries given below. Each keyword in the dictionaries has one badge showing +the corresponding type of dictionary, and can have one or more badges showing +the type of experiment to which the keyword belongs. ## Crystallographic information file -EasyDiffraction input and output files use the simple, human-readable STAR/CIF data format, following the specifications of [International Union of Crystallography](https://www.iucr.org) (IUCr), wherever possible. +EasyDiffraction input and output files use the simple, human-readable STAR/CIF +data format, following the specifications of +[International Union of Crystallography](https://www.iucr.org) (IUCr), wherever +possible. ## Model dictionary This dictionary provides data names for describing model parameters. -[pd-neut-cwl][3]{:.label-experiment} [pd-neut-tof][3]{:.label-experiment} [sc-neut-cwl][3]{:.label-experiment} [pd-xray][3]{:.label-experiment} - -* [\_space_group](dictionaries/_space_group.md) [coreCIF][1]{:.label-cif} - * [\_space_group.name_H-M_alt](dictionaries/_space_group.md) [coreCIF][1]{:.label-cif} - * [\_space_group.IT_coordinate_system_code](dictionaries/_space_group.md) [coreCIF][1]{:.label-cif} -* [\_cell](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} - * [\_cell.angle_alpha](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} - * [\_cell.angle_beta](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} - * [\_cell.angle_gamma](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} - * [\_cell.length_a](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} - * [\_cell.length_b](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} - * [\_cell.length_c](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} -* [\_atom_site](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} - * [\_atom_site.label](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} - * [\_atom_site.type_symbol](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} - * [\_atom_site.fract_x](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} - * [\_atom_site.fract_y](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} - * [\_atom_site.fract_z](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} - * [\_atom_site.occupancy](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} - * [\_atom_site.ADP_type](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} - * [\_atom_site.B_iso_or_equiv](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} - * [\_atom_site.site_symmetry_multiplicity](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} - * [\_atom_site.Wyckoff_symbol](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} +[pd-neut-cwl][3]{:.label-experiment} [pd-neut-tof][3]{:.label-experiment} +[sc-neut-cwl][3]{:.label-experiment} [pd-xray][3]{:.label-experiment} + +- [\_space_group](dictionaries/_space_group.md) [coreCIF][1]{:.label-cif} + - [\_space_group.name_H-M_alt](dictionaries/_space_group.md) + [coreCIF][1]{:.label-cif} + - [\_space_group.IT_coordinate_system_code](dictionaries/_space_group.md) + [coreCIF][1]{:.label-cif} +- [\_cell](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} + - [\_cell.angle_alpha](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} + - [\_cell.angle_beta](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} + - [\_cell.angle_gamma](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} + - [\_cell.length_a](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} + - [\_cell.length_b](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} + - [\_cell.length_c](dictionaries/_cell.md) [coreCIF][1]{:.label-cif} +- [\_atom_site](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} + - [\_atom_site.label](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} + - [\_atom_site.type_symbol](dictionaries/_atom_site.md) + [coreCIF][1]{:.label-cif} + - [\_atom_site.fract_x](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} + - [\_atom_site.fract_y](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} + - [\_atom_site.fract_z](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} + - [\_atom_site.occupancy](dictionaries/_atom_site.md) + [coreCIF][1]{:.label-cif} + - [\_atom_site.ADP_type](dictionaries/_atom_site.md) [coreCIF][1]{:.label-cif} + - [\_atom_site.B_iso_or_equiv](dictionaries/_atom_site.md) + [coreCIF][1]{:.label-cif} + - [\_atom_site.site_symmetry_multiplicity](dictionaries/_atom_site.md) + [coreCIF][1]{:.label-cif} + - [\_atom_site.Wyckoff_symbol](dictionaries/_atom_site.md) + [coreCIF][1]{:.label-cif} ## Experiment and instrument dictionary -This dictionary provides data names for describing experimental and instrumental parameters. - -[pd-neut-cwl][3]{:.label-experiment} [pd-neut-tof][3]{:.label-experiment} [sc-neut-cwl][3]{:.label-experiment} [pd-xray][3]{:.label-experiment} - -* [\_diffrn_radiation](dictionaries/_diffrn_radiation.md) [coreCIF][1]{:.label-cif} - * [\_diffrn_radiation.probe](dictionaries/_diffrn_radiation.md) [coreCIF][1]{:.label-cif} - -[pd-neut-cwl][3]{:.label-experiment} [sc-neut-cwl][3]{:.label-experiment} [pd-xray][3]{:.label-experiment} - -* [\_diffrn_radiation_wavelength](dictionaries/_diffrn_radiation_wavelength.md) [coreCIF][1]{:.label-cif} - * [\_diffrn_radiation_wavelength.wavelength](dictionaries/_diffrn_radiation_wavelength.md) [coreCIF][1]{:.label-cif} -* [\_pd_background](dictionaries/_pd_background.md) [pdCIF][2]{:.label-cif} - * [\_pd_background.line_segment_X](dictionaries/_pd_background.md) [pdCIF][2]{:.label-cif} - * [\_pd_background.line_segment_intensity](dictionaries/_pd_background.md) [pdCIF][2]{:.label-cif} - * [\_pd_background.X_coordinate](dictionaries/_pd_background.md) [pdCIF][2]{:.label-cif} -* [\_pd_phase_block](dictionaries/_pd_phase.md) [pdCIF][2]{:.label-cif} - * [\_pd_phase_block.id](dictionaries/_pd_phase.md) [pdCIF][2]{:.label-cif} - * [\_pd_phase_block.scale](dictionaries/_pd_phase.md) [customCIF][0]{:.label-cif} +This dictionary provides data names for describing experimental and instrumental +parameters. + +[pd-neut-cwl][3]{:.label-experiment} [pd-neut-tof][3]{:.label-experiment} +[sc-neut-cwl][3]{:.label-experiment} [pd-xray][3]{:.label-experiment} + +- [\_diffrn_radiation](dictionaries/_diffrn_radiation.md) + [coreCIF][1]{:.label-cif} + - [\_diffrn_radiation.probe](dictionaries/_diffrn_radiation.md) + [coreCIF][1]{:.label-cif} + +[pd-neut-cwl][3]{:.label-experiment} [sc-neut-cwl][3]{:.label-experiment} +[pd-xray][3]{:.label-experiment} + +- [\_diffrn_radiation_wavelength](dictionaries/_diffrn_radiation_wavelength.md) + [coreCIF][1]{:.label-cif} + - [\_diffrn_radiation_wavelength.wavelength](dictionaries/_diffrn_radiation_wavelength.md) + [coreCIF][1]{:.label-cif} +- [\_pd_background](dictionaries/_pd_background.md) [pdCIF][2]{:.label-cif} + - [\_pd_background.line_segment_X](dictionaries/_pd_background.md) + [pdCIF][2]{:.label-cif} + - [\_pd_background.line_segment_intensity](dictionaries/_pd_background.md) + [pdCIF][2]{:.label-cif} + - [\_pd_background.X_coordinate](dictionaries/_pd_background.md) + [pdCIF][2]{:.label-cif} +- [\_pd_phase_block](dictionaries/_pd_phase.md) [pdCIF][2]{:.label-cif} + - [\_pd_phase_block.id](dictionaries/_pd_phase.md) [pdCIF][2]{:.label-cif} + - [\_pd_phase_block.scale](dictionaries/_pd_phase.md) + [customCIF][0]{:.label-cif} [pd-neut-cwl][3]{:.label-experiment} -* [\_pd_calib](dictionaries/_pd_calib.md) [pdCIF][2]{:.label-cif} - * [\_pd_calib.2theta_offset](dictionaries/_pd_calib.md) [pdCIF][2]{:.label-cif} -* [\_pd_instr](dictionaries/_pd_instr.md) [pdCIF][2]{:.label-cif} - * [\_pd_instr.resolution_u](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} - * [\_pd_instr.resolution_v](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} - * [\_pd_instr.resolution_w](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} - * [\_pd_instr.resolution_x](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} - * [\_pd_instr.resolution_y](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} - * [\_pd_instr.reflex_asymmetry_p1](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} - * [\_pd_instr.reflex_asymmetry_p2](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} - * [\_pd_instr.reflex_asymmetry_p3](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} - * [\_pd_instr.reflex_asymmetry_p4](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} -* [\_pd_meas](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} - * [\_pd_meas.2theta_scan](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} - * [\_pd_meas.intensity_total](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} - * [\_pd_meas.intensity_total_su](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} +- [\_pd_calib](dictionaries/_pd_calib.md) [pdCIF][2]{:.label-cif} + - [\_pd_calib.2theta_offset](dictionaries/_pd_calib.md) + [pdCIF][2]{:.label-cif} +- [\_pd_instr](dictionaries/_pd_instr.md) [pdCIF][2]{:.label-cif} + - [\_pd_instr.resolution_u](dictionaries/_pd_instr.md) + [customCIF][0]{:.label-cif} + - [\_pd_instr.resolution_v](dictionaries/_pd_instr.md) + [customCIF][0]{:.label-cif} + - [\_pd_instr.resolution_w](dictionaries/_pd_instr.md) + [customCIF][0]{:.label-cif} + - [\_pd_instr.resolution_x](dictionaries/_pd_instr.md) + [customCIF][0]{:.label-cif} + - [\_pd_instr.resolution_y](dictionaries/_pd_instr.md) + [customCIF][0]{:.label-cif} + - [\_pd_instr.reflex_asymmetry_p1](dictionaries/_pd_instr.md) + [customCIF][0]{:.label-cif} + - [\_pd_instr.reflex_asymmetry_p2](dictionaries/_pd_instr.md) + [customCIF][0]{:.label-cif} + - [\_pd_instr.reflex_asymmetry_p3](dictionaries/_pd_instr.md) + [customCIF][0]{:.label-cif} + - [\_pd_instr.reflex_asymmetry_p4](dictionaries/_pd_instr.md) + [customCIF][0]{:.label-cif} +- [\_pd_meas](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} + - [\_pd_meas.2theta_scan](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} + - [\_pd_meas.intensity_total](dictionaries/_pd_meas.md) + [pdCIF][2]{:.label-cif} + - [\_pd_meas.intensity_total_su](dictionaries/_pd_meas.md) + [pdCIF][2]{:.label-cif} [pd-neut-tof][3]{:.label-experiment} -* [\_pd_instr](dictionaries/_pd_instr.md) [pdCIF][2]{:.label-cif} - * [\_pd_instr.zero](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} - * [\_pd_instr.dtt1](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} - * [\_pd_instr.dtt2](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} - * [\_pd_instr.2theta_bank](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} - * [\_pd_instr.alpha0](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} - * [\_pd_instr.alpha1](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} - * [\_pd_instr.beta0](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} - * [\_pd_instr.beta1](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} - * [\_pd_instr.sigma0](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} - * [\_pd_instr.sigma1](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} - * [\_pd_instr.sigma2](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} -* [\_pd_meas](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} - * [\_pd_meas.time_of_flight](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} - * [\_pd_meas.intensity_total](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} - * [\_pd_meas.intensity_total_su](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} +- [\_pd_instr](dictionaries/_pd_instr.md) [pdCIF][2]{:.label-cif} + - [\_pd_instr.zero](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + - [\_pd_instr.dtt1](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + - [\_pd_instr.dtt2](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + - [\_pd_instr.2theta_bank](dictionaries/_pd_instr.md) + [customCIF][0]{:.label-cif} + - [\_pd_instr.alpha0](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + - [\_pd_instr.alpha1](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + - [\_pd_instr.beta0](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + - [\_pd_instr.beta1](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + - [\_pd_instr.sigma0](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + - [\_pd_instr.sigma1](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} + - [\_pd_instr.sigma2](dictionaries/_pd_instr.md) [customCIF][0]{:.label-cif} +- [\_pd_meas](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} + - [\_pd_meas.time_of_flight](dictionaries/_pd_meas.md) [pdCIF][2]{:.label-cif} + - [\_pd_meas.intensity_total](dictionaries/_pd_meas.md) + [pdCIF][2]{:.label-cif} + - [\_pd_meas.intensity_total_su](dictionaries/_pd_meas.md) + [pdCIF][2]{:.label-cif} [sc-neut-cwl][3]{:.label-experiment} -* [\_extinction](dictionaries/_extinction.md) [customCIF][0]{:.label-cif} - * [\_extinction.model](dictionaries/_extinction.md) [customCIF][0]{:.label-cif} - * [\_extinction.mosaicity](dictionaries/_extinction.md) [customCIF][0]{:.label-cif} - * [\_extinction.radius](dictionaries/_extinction.md) [customCIF][0]{:.label-cif} +- [\_extinction](dictionaries/_extinction.md) [customCIF][0]{:.label-cif} + + - [\_extinction.model](dictionaries/_extinction.md) + [customCIF][0]{:.label-cif} + - [\_extinction.mosaicity](dictionaries/_extinction.md) + [customCIF][0]{:.label-cif} + - [\_extinction.radius](dictionaries/_extinction.md) + [customCIF][0]{:.label-cif} -* [\_exptl_crystal](dictionaries/_exptl_crystal.md) [customCIF][0]{:.label-cif} - * [\_exptl_crystal.id](dictionaries/_exptl_crystal.md) [customCIF][0]{:.label-cif} - * [\_exptl_crystal.scale](dictionaries/_exptl_crystal.md) [customCIF][0]{:.label-cif} +- [\_exptl_crystal](dictionaries/_exptl_crystal.md) [customCIF][0]{:.label-cif} + - [\_exptl_crystal.id](dictionaries/_exptl_crystal.md) + [customCIF][0]{:.label-cif} + - [\_exptl_crystal.scale](dictionaries/_exptl_crystal.md) + [customCIF][0]{:.label-cif} + + +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd +[3]: glossary.md + diff --git a/docs/dictionaries/_atom_site.md b/docs/dictionaries/_atom_site.md index 2dae780c..1a81a75c 100644 --- a/docs/dictionaries/_atom_site.md +++ b/docs/dictionaries/_atom_site.md @@ -1,16 +1,17 @@ -[0]: # -[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core -[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd - [coreCIF][1]{:.label-cif} # \_atom_site -Data items in this category record details about the atom sites in a crystal structure, such as the positional coordinates and atomic displacement parameters. Please see the [IUCr page](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/CATOM_SITE.html) for further details. +Data items in this category record details about the atom sites in a crystal +structure, such as the positional coordinates and atomic displacement +parameters. Please see the +[IUCr page](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/CATOM_SITE.html) +for further details. ## [\_atom_site.label](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.label.html) -This is a unique identifier for a particular site in the asymmetric unit of the crystal unit cell. +This is a unique identifier for a particular site in the asymmetric unit of the +crystal unit cell. ## [\_atom_site.type_symbol](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.type_symbol.html) @@ -20,9 +21,9 @@ A code to identify the atom specie(s) occupying this site. Atom-site coordinates as fractions of the [\_cell_length](_cell.md) values. -* [\_atom_site.fract_x](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.fract_x.html) -* [\_atom_site.fract_y](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.fract_y.html) -* [\_atom_site.fract_z](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.fract_z.html) +- [\_atom_site.fract_x](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.fract_x.html) +- [\_atom_site.fract_y](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.fract_y.html) +- [\_atom_site.fract_z](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.fract_z.html) ## [\_atom_site.occupancy](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.occupancy.html) @@ -30,20 +31,32 @@ The fraction of the atom type present at this site. ## [\_atom_site.ADP_type](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.adp_type.html) -Code for type of atomic displacement parameters used for the site. Currently only `Biso` (isotropic B) is supported. +Code for type of atomic displacement parameters used for the site. Currently +only `Biso` (isotropic B) is supported. ## [\_atom_site.B_iso_or_equiv](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.B_iso_or_equiv.html) -Isotropic atomic displacement parameter, or equivalent isotropic atomic displacement parameter, in angstroms squared. +Isotropic atomic displacement parameter, or equivalent isotropic atomic +displacement parameter, in angstroms squared. ## [\_atom_site.site_symmetry_multiplicity](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.site_symmetry_multiplicity.html) `optional parameter` -The number of different sites that are generated by the application of the space-group symmetry to the coordinates given for this site. It is equal to the multiplicity given for this Wyckoff site in International Tables for Crystallography Vol. A (2002). +The number of different sites that are generated by the application of the +space-group symmetry to the coordinates given for this site. It is equal to the +multiplicity given for this Wyckoff site in International Tables for +Crystallography Vol. A (2002). ## [\_atom_site.Wyckoff_symbol](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Iatom_site.Wyckoff_symbol.html) `optional parameter` -The Wyckoff symbol (letter) as listed in the space-group tables of International Tables for Crystallography Vol. A. +The Wyckoff symbol (letter) as listed in the space-group tables of International +Tables for Crystallography Vol. A. + + +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + diff --git a/docs/dictionaries/_cell.md b/docs/dictionaries/_cell.md index 61f0f583..5aeb12ae 100644 --- a/docs/dictionaries/_cell.md +++ b/docs/dictionaries/_cell.md @@ -1,25 +1,30 @@ -[0]: # -[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core -[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd - [coreCIF][1]{:.label-cif} # \_cell -Data items in this category record details about the crystallographic cell parameters and their measurement. Please see the [IUCr page](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/CCELL.html) for further details. +Data items in this category record details about the crystallographic cell +parameters and their measurement. Please see the +[IUCr page](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/CCELL.html) +for further details. ## \_cell.angle The angles between the bounding cell axes in degrees. -* [\_cell.angle_alpha](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Icell.angle_alpha.html) -* [\_cell.angle_beta](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Icell.angle_beta.html) -* [\_cell.angle_gamma](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Icell.angle_gamma.html) +- [\_cell.angle_alpha](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Icell.angle_alpha.html) +- [\_cell.angle_beta](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Icell.angle_beta.html) +- [\_cell.angle_gamma](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Icell.angle_gamma.html) ## \_cell.length The lengths of each cell axis in angstroms. -* [\_cell.length_a](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Icell.length_a.html) -* [\_cell.length_b](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Icell.length_b.html) -* [\_cell.length_c](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Icell.length_c.html) +- [\_cell.length_a](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Icell.length_a.html) +- [\_cell.length_b](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Icell.length_b.html) +- [\_cell.length_c](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Icell.length_c.html) + + +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + diff --git a/docs/dictionaries/_diffrn_radiation.md b/docs/dictionaries/_diffrn_radiation.md index 9e3cd175..e3c0a7e9 100644 --- a/docs/dictionaries/_diffrn_radiation.md +++ b/docs/dictionaries/_diffrn_radiation.md @@ -1,15 +1,21 @@ -[0]: # -[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core -[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd - [coreCIF][1]{:.label-cif} # \_diffrn_radiation -Data items in this category describe the radiation used in measuring the diffraction intensities. Please see the [IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) for further details. +Data items in this category describe the radiation used in measuring the +diffraction intensities. Please see the +[IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) for +further details. ## [\_diffrn_radiation.probe](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) -The nature of the radiation used (i.e. the name of the subatomic particle or the region of the electromagnetic spectrum). +The nature of the radiation used (i.e. the name of the subatomic particle or the +region of the electromagnetic spectrum). Supported values: `neutron` and `x-ray` + + +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + diff --git a/docs/dictionaries/_diffrn_radiation_wavelength.md b/docs/dictionaries/_diffrn_radiation_wavelength.md index 4b31e012..4d205788 100644 --- a/docs/dictionaries/_diffrn_radiation_wavelength.md +++ b/docs/dictionaries/_diffrn_radiation_wavelength.md @@ -1,13 +1,18 @@ -[0]: # -[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core -[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd - [coreCIF][1]{:.label-cif} # \_diffrn_radiation_wavelength -Data items in this category describe the wavelength of radiation used in diffraction measurements. Please see the [IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) for further details. +Data items in this category describe the wavelength of radiation used in +diffraction measurements. Please see the +[IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) for +further details. ## [\_diffrn_radiation_wavelength.wavelength](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) Wavelength of the radiation used to measure the unit cell. + + +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + diff --git a/docs/dictionaries/_exptl_crystal.md b/docs/dictionaries/_exptl_crystal.md index 9e79204d..8d568b2b 100644 --- a/docs/dictionaries/_exptl_crystal.md +++ b/docs/dictionaries/_exptl_crystal.md @@ -1,5 +1,7 @@ +[customCIF][0]{:.label-cif} + + [0]: # [1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core [2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd - -[customCIF][0]{:.label-cif} + diff --git a/docs/dictionaries/_extinction.md b/docs/dictionaries/_extinction.md index 9e79204d..8d568b2b 100644 --- a/docs/dictionaries/_extinction.md +++ b/docs/dictionaries/_extinction.md @@ -1,5 +1,7 @@ +[customCIF][0]{:.label-cif} + + [0]: # [1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core [2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd - -[customCIF][0]{:.label-cif} + diff --git a/docs/dictionaries/_pd_background.md b/docs/dictionaries/_pd_background.md index a28a2963..89985470 100644 --- a/docs/dictionaries/_pd_background.md +++ b/docs/dictionaries/_pd_background.md @@ -1,23 +1,30 @@ -[0]: # -[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core -[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd - [pdCIF][2]{:.label-cif} # \_pd_background -This category defines various background functions that could be used when calculating diffractograms. Please see the [IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) for further details. +This category defines various background functions that could be used when +calculating diffractograms. Please see the +[IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) for +further details. ## [\_pd_background.line_segment_X](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) -List of X-coordinates used to create many straight-line segments representing the background in a calculated diffractogram. +List of X-coordinates used to create many straight-line segments representing +the background in a calculated diffractogram. Supported values: `2theta` and `time-of-flight` ## [\_pd_background.line_segment_intensity](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) -List of intensities used to create many straight-line segments representing the background in a calculated diffractogram. +List of intensities used to create many straight-line segments representing the +background in a calculated diffractogram. ## [\_pd_background.X_coordinate](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) The type of X-coordinate against which the pd_background values were calculated. + + +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + diff --git a/docs/dictionaries/_pd_calib.md b/docs/dictionaries/_pd_calib.md index 46f34db5..2b96a4c8 100644 --- a/docs/dictionaries/_pd_calib.md +++ b/docs/dictionaries/_pd_calib.md @@ -1,13 +1,17 @@ -[0]: # -[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core -[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd - [customCIF][0]{:.label-cif} # \_pd_calib -This section defines the parameters used for the calibration of the instrument, similar to this [IUCr section](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd). +This section defines the parameters used for the calibration of the instrument, +similar to this +[IUCr section](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd). ## [\_pd_calib.2theta_offset](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) An offset angle (in degrees) used to calibrate 2θ. + + +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + diff --git a/docs/dictionaries/_pd_instr.md b/docs/dictionaries/_pd_instr.md index ab341721..3975161c 100644 --- a/docs/dictionaries/_pd_instr.md +++ b/docs/dictionaries/_pd_instr.md @@ -1,39 +1,45 @@ -[0]: # -[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core -[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd - [customCIF][0]{:.label-cif} -# _pd_instr +# \_pd_instr -This section contains information relevant to the instrument used for the diffraction measurement, similar to this [IUCr section](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd). +This section contains information relevant to the instrument used for the +diffraction measurement, similar to this +[IUCr section](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd). ## [\_pd_instr.resolution](#) -In general, the profile of a Bragg reflection centred at the peak position can be approximated by mathematical convolution of contributions from the instrument, called the instrumental resolution function, and from the microstructure of the sample. Because many contributions to powder diffraction peaks have a nearly Gaussian or Lorentzian shape, the pseudo-Voigt function, is widely used to describe peak profiles in powder diffraction. +In general, the profile of a Bragg reflection centred at the peak position can +be approximated by mathematical convolution of contributions from the +instrument, called the instrumental resolution function, and from the +microstructure of the sample. Because many contributions to powder diffraction +peaks have a nearly Gaussian or Lorentzian shape, the pseudo-Voigt function, is +widely used to describe peak profiles in powder diffraction. -Half-width parameters (normally characterising the instrumental resolution function) as implemented in [CrysPy](https://cryspy.fr): +Half-width parameters (normally characterising the instrumental resolution +function) as implemented in [CrysPy](https://cryspy.fr): -* \_pd_instr.resolution_u -* \_pd_instr.resolution_v -* \_pd_instr.resolution_w +- \_pd_instr.resolution_u +- \_pd_instr.resolution_v +- \_pd_instr.resolution_w -Lorentzian isotropic microstrain parameter as implemented in [CrysPy](https://cryspy.fr): +Lorentzian isotropic microstrain parameter as implemented in +[CrysPy](https://cryspy.fr): -* \_pd_instr.resolution_x +- \_pd_instr.resolution_x -Lorentzian isotropic particle size parameteras implemented in [CrysPy](https://cryspy.fr): +Lorentzian isotropic particle size parameteras implemented in +[CrysPy](https://cryspy.fr): -* \_pd_instr.resolution_y +- \_pd_instr.resolution_y ## [\_pd_instr.reflex_asymmetry](#) Peak profile asymmetry parameters as implemented in [CrysPy](https://cryspy.fr). -* \_pd_instr.reflex_asymmetry_p1 -* \_pd_instr.reflex_asymmetry_p2 -* \_pd_instr.reflex_asymmetry_p3 -* \_pd_instr.reflex_asymmetry_p4 +- \_pd_instr.reflex_asymmetry_p1 +- \_pd_instr.reflex_asymmetry_p2 +- \_pd_instr.reflex_asymmetry_p3 +- \_pd_instr.reflex_asymmetry_p4 ## [\_pd_instr.2theta_bank](#) @@ -43,8 +49,8 @@ Time-of-flight parameters as implemented in [CrysPy](https://cryspy.fr). Time-of-flight parameters as implemented in [CrysPy](https://cryspy.fr). -* \_pd_instr.dtt1 -* \_pd_instr.dtt2 +- \_pd_instr.dtt1 +- \_pd_instr.dtt2 ## [\_pd_instr.zero](#) @@ -54,20 +60,26 @@ Time-of-flight parameters as implemented in [CrysPy](https://cryspy.fr). Time-of-flight parameters as implemented in [CrysPy](https://cryspy.fr). -* \_pd_instr.alpha0 -* \_pd_instr.alpha1 +- \_pd_instr.alpha0 +- \_pd_instr.alpha1 ## [\_pd_instr.beta](#) Time-of-flight parameters as implemented in [CrysPy](https://cryspy.fr). -* \_pd_instr.beta0 -* \_pd_instr.beta1 +- \_pd_instr.beta0 +- \_pd_instr.beta1 ## [\_pd_instr.sigma](#) Time-of-flight parameters as implemented in [CrysPy](https://cryspy.fr). -* \_pd_instr.sigma0 -* \_pd_instr.sigma1 -* \_pd_instr.sigma2 +- \_pd_instr.sigma0 +- \_pd_instr.sigma1 +- \_pd_instr.sigma2 + + +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + diff --git a/docs/dictionaries/_pd_meas.md b/docs/dictionaries/_pd_meas.md index 90a01244..b294a96a 100644 --- a/docs/dictionaries/_pd_meas.md +++ b/docs/dictionaries/_pd_meas.md @@ -1,16 +1,14 @@ -[0]: # -[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core -[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd - [pdCIF][2]{:.label-cif} -# _pd_meas +# \_pd_meas -This section contains the measured diffractogram, similar to this [IUCr section](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd). +This section contains the measured diffractogram, similar to this +[IUCr section](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd). ## [\_pd_meas.2theta_scan](https://raw.githubusercontent.com/COMCIFS/Powder_Dictionary/master/cif_pow.dic) -2θ diffraction angle (in degrees) for intensity points measured in a scanning method. +2θ diffraction angle (in degrees) for intensity points measured in a scanning +method. ## [\_pd_meas.time-of-flight](https://raw.githubusercontent.com/COMCIFS/Powder_Dictionary/master/cif_pow.dic) @@ -23,3 +21,9 @@ Intensity recorded at each measurement point as a function of angle. ## [\_pd_meas.intensity_total_su](https://raw.githubusercontent.com/COMCIFS/Powder_Dictionary/master/cif_pow.dic) Standard uncertainty of \_pd_meas.2theta_scan. + + +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + diff --git a/docs/dictionaries/_pd_phase.md b/docs/dictionaries/_pd_phase.md index 8bfcc779..df3f6d29 100644 --- a/docs/dictionaries/_pd_phase.md +++ b/docs/dictionaries/_pd_phase.md @@ -1,12 +1,11 @@ -[0]: # -[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core -[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd - [pdCIF][2]{:.label-cif} # \_pd_phase_block -A table of phases relevant to the current data block. Each phase is identified by its data block identifier. Please see the [IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) for further details. +A table of phases relevant to the current data block. Each phase is identified +by its data block identifier. Please see the +[IUCr page](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) for +further details. ## [\_pd_phase_block.id](https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd) @@ -15,3 +14,9 @@ A block ID code identifying a block containing phase information. ## \_pd_phase_block.scale Phase scale. + + +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + diff --git a/docs/dictionaries/_space_group.md b/docs/dictionaries/_space_group.md index 8b82f8b4..883be103 100644 --- a/docs/dictionaries/_space_group.md +++ b/docs/dictionaries/_space_group.md @@ -1,17 +1,25 @@ -[0]: # -[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core -[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd - [coreCIF][1]{:.label-cif} # \_space_group -Contains all the data items that refer to the space group as a whole. Please see the [IUCr page](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/CSPACE_GROUP.html) for further details. +Contains all the data items that refer to the space group as a whole. Please see +the +[IUCr page](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/CSPACE_GROUP.html) +for further details. ## [\_space_group.name_H-M_alt](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Ispace_group.name_H-M_alt.html) -The international Hermann-Mauguin space-group symbol as defined in International Tables for Crystallography Volume A. It allows any Hermann-Mauguin symbol to be given. +The international Hermann-Mauguin space-group symbol as defined in International +Tables for Crystallography Volume A. It allows any Hermann-Mauguin symbol to be +given. ## [\_space_group.IT_coordinate_system_code](https://www.iucr.org/__data/iucr/cifdic_html/3/CORE_DIC/Ispace_group.IT_coordinate_system_code.html) -A qualifier taken from the enumeration list identifying which setting in International Tables for Crystallography Volume A (2002) (IT) is used. +A qualifier taken from the enumeration list identifying which setting in +International Tables for Crystallography Volume A (2002) (IT) is used. + + +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + diff --git a/docs/easyscience.md b/docs/easyscience.md index 451be2ba..d15a61b7 100644 --- a/docs/easyscience.md +++ b/docs/easyscience.md @@ -1,13 +1,19 @@ # The EasyScience framework -EasyScience is a framework of software tools that can be used to build experimental data analysis packages. -For example, it has already been used in the development of [EasyDiffraction] and [EasyReflectometry]. Two more packages are about to be started: EasyImaging (Bragg edge imaging) and EasyDynamics (Quasielastic neutron scattering, QENS). +EasyScience is a framework of software tools that can be used to build +experimental data analysis packages. For example, it has already been used in +the development of [EasyDiffraction] and [EasyReflectometry]. Two more packages +are about to be started: EasyImaging (Bragg edge imaging) and EasyDynamics +(Quasielastic neutron scattering, QENS). -The framework consists of both front- and back-end elements, known as [EasyApp] and [EasyScience], respectively. -The front-end provides a shared library of graphical interface elements that can be used to build a graphical user interface. -The back-end offers a toolset to perform model-dependent analysis, including the ability to plug-in existing calculation engines. +The framework consists of both front- and back-end elements, known as [EasyApp] +and [EasyScience], respectively. The front-end provides a shared library of +graphical interface elements that can be used to build a graphical user +interface. The back-end offers a toolset to perform model-dependent analysis, +including the ability to plug-in existing calculation engines. -Below is a diagram illustrating the relationship between the modules of the EasyScience framework: +Below is a diagram illustrating the relationship between the modules of the +EasyScience framework: @@ -88,8 +94,9 @@ Below is a diagram illustrating the relationship between the modules of the Easy - + [EasyDiffraction]: https://easydiffraction.org [EasyReflectometry]: https://easyreflectometry.org [EasyApp]: https://github.com/easyscience/easyapp -[EasyScience]: https://github.com/easyscience/easyscience \ No newline at end of file +[EasyScience]: https://github.com/easyscience/easyscience + diff --git a/docs/experiment.md b/docs/experiment.md index 43163144..bbedf8e7 100644 --- a/docs/experiment.md +++ b/docs/experiment.md @@ -1,15 +1,16 @@ -[3]: glossary.md - # Experiment -This section describes different types of experimental data which EasyDiffraction can handle. +This section describes different types of experimental data which +EasyDiffraction can handle. ## CIF-based description -The following examples show the CIF data blocks for different types of diffraction experiments supported in EasyDiffraction. +The following examples show the CIF data blocks for different types of +diffraction experiments supported in EasyDiffraction. ### [pd-neut-cwl][3]{:.label-experiment} +
 data_hrpt
@@ -69,9 +70,11 @@ loop_
 164.85  109  41.2
 
+ ### [pd-neut-tof][3]{:.label-experiment} +
 data_wish
@@ -136,9 +139,11 @@ loop_
 103417.6  277.666   73.837
 
+ ### [sc-neut-cwl][3]{:.label-experiment} +
 data_heidi
@@ -183,6 +188,7 @@ loop_
 12 12 10    14.4074   11.3800
 
+ ## Other supported data files @@ -206,6 +212,7 @@ Here are some examples: ### example1.xye +
 # 2theta  intensity    su
@@ -222,9 +229,11 @@ Here are some examples:
   164.85     109      41.2
 
+ ### example2.xy +
 # 2theta  intensity
@@ -241,9 +250,11 @@ Here are some examples:
   164.85     109  
 
+ ### example3.xy +
 10  167.3    
@@ -259,3 +270,8 @@ Here are some examples:
 164.85  109     
 
+ + + +[3]: glossary.md + diff --git a/docs/getting-started.md b/docs/getting-started.md index daff7352..f9049bfc 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -2,18 +2,24 @@ ## Requirements -The EasyDiffraction library is developed in Python, so Python must be installed on your system. The library is compatible with Python versions 3.9 through 3.12. +The EasyDiffraction library is developed in Python, so Python must be installed +on your system. The library is compatible with Python versions 3.9 through 3.12. ## Environment setup optional { #environment-setup data-toc-label="Environment setup" } -We recommend using a virtual environment – an isolated Python runtime where any packages you install or update are contained within that environment. If you encounter issues, you can simply delete and recreate the environment. Setting it up is straightforward: +We recommend using a virtual environment – an isolated Python runtime where any +packages you install or update are contained within that environment. If you +encounter issues, you can simply delete and recreate the environment. Setting it +up is straightforward: -* Create a new virtual environment with: -```console -python3 -m venv venv -``` +- Create a new virtual environment with: + ```console + python3 -m venv venv + ``` -* Activate the environment with: + + +- Activate the environment with: === ":material-apple: macOS" ```console @@ -28,9 +34,12 @@ python3 -m venv venv . venv/bin/activate ``` -Your terminal should now print `(venv)` before the prompt, which is how you know that you are inside the virtual environment that you just created. + + +Your terminal should now print `(venv)` before the prompt, which is how you know +that you are inside the virtual environment that you just created. -* Exit the environment with: +- Exit the environment with: ``` deactivate ``` @@ -39,80 +48,104 @@ Your terminal should now print `(venv)` before the prompt, which is how you know ### From PyPI recommended { #from-pypi data-toc-label="From PyPI" } -EasyDiffraction is published on the Python Package Index (PyPI) repository and can be installed with the package installer for Python (pip), ideally by using a [virtual environment](#environment-setup). +EasyDiffraction is published on the Python Package Index (PyPI) repository and +can be installed with the package installer for Python (pip), ideally by using a +[virtual environment](#environment-setup). + +We recommend installing the latest release of EasyDiffraction with the `charts` +extras, which include optional dependencies used for simplified visualization of +charts and tables. This can be especially useful for running the Jupyter +Notebook examples. To do so, use the following command: -We recommend installing the latest release of EasyDiffraction with the `charts` extras, which include optional dependencies used for simplified visualization of charts and tables. This can be especially useful for running the Jupyter Notebook examples. To do so, use the following command: ```console pip install 'easydiffraction[charts]' ``` -If only the core functionality is needed, the library can be installed simply with: +If only the core functionality is needed, the library can be installed simply +with: + ```console pip install easydiffraction ``` To install a specific version of EasyDiffraction, e.g. 0.1.3, use: + ```console pip install 'easydiffraction==0.1.3' ``` Upgrading to the latest version can be done with: + ```console pip install --upgrade --force-reinstall easydiffraction ``` To show the currently installed version, use: + ```console pip show easydiffraction ``` ### From GitHub -Installing an unreleased version is not recommended and should only be done for testing purposes. +Installing an unreleased version is not recommended and should only be done for +testing purposes. + +Here is an example of how to install EasyDiffraction directly from our GitHub +repository, e.g., from the `develop` branch: -Here is an example of how to install EasyDiffraction directly from our GitHub repository, e.g., from the `develop` branch: ```console pip install git+https://github.com/EasyScience/EasyDiffractionLib@develop ``` To do the same with extra dependencies, use: + ```console pip install 'easydiffraction[charts] @ git+https://github.com/EasyScience/EasyDiffractionLib@develop' ``` ## Examples -We have a collection of Jupyter Notebook examples that demonstrate how to use EasyDiffraction for various tasks. These examples are presented in the [How to use](how-to-use/index.md#how-to-use) section of the documentation as static HTML pages. +We have a collection of Jupyter Notebook examples that demonstrate how to use +EasyDiffraction for various tasks. These examples are presented in the +[How to use](how-to-use/index.md#how-to-use) section of the documentation as +static HTML pages. -You can also run these Jupyter Notebook examples yourself either locally or in Google Colab. +You can also run these Jupyter Notebook examples yourself either locally or in +Google Colab. -These Jupyter Notebook examples can be downloaded either one by one from the [How to use](how-to-use/index.md#how-to-use) section or all together as a zip archive from the [EasyDiffraction releases](https://github.com/EasyScience/EasyDiffractionLib/releases/latest). +These Jupyter Notebook examples can be downloaded either one by one from the +[How to use](how-to-use/index.md#how-to-use) section or all together as a zip +archive from the +[EasyDiffraction releases](https://github.com/EasyScience/EasyDiffractionLib/releases/latest). ### Run locally -To run the examples locally, you need to install Jupyter Notebook or JupyterLab. Here are the steps to take in the case of Jupyter Notebook: +To run the examples locally, you need to install Jupyter Notebook or JupyterLab. +Here are the steps to take in the case of Jupyter Notebook: -* Install Jupyter Notebook: +- Install Jupyter Notebook: ```console pip install notebook ``` -* Download EasyDiffraction examples from GitHub for the latest release, e.g., using curl: +- Download EasyDiffraction examples from GitHub for the latest release, e.g., + using curl: ```console curl --location --remote-name https://github.com/EasyScience/EasyDiffractionLib/releases/latest/download/examples.zip ``` -* Unzip the downloaded archive: +- Unzip the downloaded archive: ```console unzip examples.zip ``` -* Run Jupyter Notebook server in the `examples/` directory: +- Run Jupyter Notebook server in the `examples/` directory: ```console jupyter notebook examples/ ``` -* Open your web browser and go to: +- Open your web browser and go to: ```console http://localhost:8888/ ``` -* Select one of the `*.ipynb` files. +- Select one of the `*.ipynb` files. ### Via Google Colab @@ -120,6 +153,10 @@ To run the examples locally, you need to install Jupyter Notebook or JupyterLab. To run the examples in Google Colab, you need to have a Google account. -Google Colab is a free cloud service that allows you to run Jupyter Notebooks online, enabling you to run the examples without installing anything on your local machine. +Google Colab is a free cloud service that allows you to run Jupyter Notebooks +online, enabling you to run the examples without installing anything on your +local machine. -In the top right corner of each example, under the [How to use](how-to-use/index.md#how-to-use) section, you will find a button to open that example in Google Colab :google-colab: +In the top right corner of each example, under the +[How to use](how-to-use/index.md#how-to-use) section, you will find a button to +open that example in Google Colab :google-colab: diff --git a/docs/glossary.md b/docs/glossary.md index b0db79cc..b324fc8e 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -1,25 +1,34 @@ -[0]: # -[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core -[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd - # Glossary -This page contains the most common abbreviations used in EasyDiffraction documentation. +This page contains the most common abbreviations used in EasyDiffraction +documentation. ## Dictionary type labels -* [coreCIF][1]{:.label-cif} Core CIF dictionary by the [IUCr](https://www.iucr.org). -* [pdCIF][2]{:.label-cif} Powder CIF dictionary by the [IUCr](https://www.iucr.org). -* [customCIF][0]{:.label-cif} Custom CIF dictionary by the EasyDiffraction developers. +- [coreCIF][1]{:.label-cif} Core CIF dictionary by the + [IUCr](https://www.iucr.org). +- [pdCIF][2]{:.label-cif} Powder CIF dictionary by the + [IUCr](https://www.iucr.org). +- [customCIF][0]{:.label-cif} Custom CIF dictionary by the EasyDiffraction + developers. ## Experiment type labels ### Neutron diffraction -* [pd-neut-cwl][0]{:.label-experiment} Powder neutron diffraction with constant wavelength. -* [pd-neut-tof][0]{:.label-experiment} Powder neutron diffraction with time-of-flight. -* [sc-neut-cwl][0]{:.label-experiment} Single crystal neutron diffraction with constant wavelength. +- [pd-neut-cwl][0]{:.label-experiment} Powder neutron diffraction with constant + wavelength. +- [pd-neut-tof][0]{:.label-experiment} Powder neutron diffraction with + time-of-flight. +- [sc-neut-cwl][0]{:.label-experiment} Single crystal neutron diffraction with + constant wavelength. ### X-ray diffraction -* [pd-xray][0]{:.label-experiment} Powder X-ray diffraction. +- [pd-xray][0]{:.label-experiment} Powder X-ray diffraction. + + +[0]: # +[1]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_core +[2]: https://www.iucr.org/resources/cif/dictionaries/browse/cif_pd + diff --git a/docs/how-to-use/index.md b/docs/how-to-use/index.md index 513e6113..8d691fac 100644 --- a/docs/how-to-use/index.md +++ b/docs/how-to-use/index.md @@ -1,8 +1,10 @@ # How to use -This section provides a collection of Jupyter Notebook examples that demonstrate how to use EasyDiffraction for various tasks. These examples are presented as static HTML pages. +This section provides a collection of Jupyter Notebook examples that demonstrate +how to use EasyDiffraction for various tasks. These examples are presented as +static HTML pages. -In the top right corner of each example, you will find +In the top right corner of each example, you will find -* a button to download the example as a Jupyter Notebook :material-download: -* a button to open that example in Google Colab :google-colab: +- a button to download the example as a Jupyter Notebook :material-download: +- a button to open that example in Google Colab :google-colab: diff --git a/docs/index.md b/docs/index.md index ee249904..7d0788ac 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,19 +1,30 @@ +![](assets/images/ed-logo_dark.svg#gh-dark-mode-only)![](assets/images/ed-logo_light.svg#gh-light-mode-only) + # Making diffraction data analysis easy ## About -EasyDiffraction is scientific software for calculating neutron powder diffraction patterns based on a structural model and refining its parameters against experimental data. +EasyDiffraction is scientific software for calculating neutron powder +diffraction patterns based on a structural model and refining its parameters +against experimental data. -EasyDiffraction is distributed as both a cross-platform desktop application and a Python library. +EasyDiffraction is distributed as both a cross-platform desktop application and +a Python library. -Here you can find instructions for using the EasyDiffraction Python library. Documentation for the EasyDiffraction graphical user interface can be found [elsewhere](https://docs.easydiffraction.org/app). +Here you can find instructions for using the EasyDiffraction Python library. +Documentation for the EasyDiffraction graphical user interface can be found +[elsewhere](https://docs.easydiffraction.org/app). -EasyDiffraction is part of the [EasyScience framework](https://easyscience.software), briefly described in the next section. +EasyDiffraction is part of the +[EasyScience framework](https://easyscience.software), briefly described in the +next section. ## License -EasyDiffraction is licensed under the [BSD 3-Clause License](https://raw.githubusercontent.com/EasyScience/EasyDiffractionLib/master/LICENSE). +EasyDiffraction is licensed under the +[BSD 3-Clause License](https://raw.githubusercontent.com/EasyScience/EasyDiffractionLib/master/LICENSE). ## Latest release -The latest release of EasyDiffraction Python library is [{{ vars.release_version }}](https://github.com/EasyScience/EasyDiffractionLib/releases/latest). +The latest release of EasyDiffraction Python library is +[{{ vars.release_version }}](https://github.com/EasyScience/EasyDiffractionLib/releases/latest). diff --git a/docs/model.md b/docs/model.md index fad000b5..06f035ad 100644 --- a/docs/model.md +++ b/docs/model.md @@ -1,5 +1,9 @@ # Model -EasyDiffraction allow you to load the crystallographic model in CIF format. The model is then used to calculate the diffraction pattern, which is compared to the experimental data. The model parameters can be refined to improve the agreement between the calculated and measured data. +EasyDiffraction allow you to load the crystallographic model in CIF format. The +model is then used to calculate the diffraction pattern, which is compared to +the experimental data. The model parameters can be refined to improve the +agreement between the calculated and measured data. -An example of the CIF-based model has been given in the [Project structure](project-structure.md) section. +An example of the CIF-based model has been given in the +[Project structure](project-structure.md) section. diff --git a/docs/project-structure.md b/docs/project-structure.md index 96282536..f1d3bf34 100644 --- a/docs/project-structure.md +++ b/docs/project-structure.md @@ -2,7 +2,10 @@ ## CIF-based project files -Example project structure for the constant wavelength powder neutron diffraction measurement is given below: +Example project structure for the constant wavelength powder neutron diffraction +measurement is given below: + +
@@ -19,10 +22,14 @@ Example project structure for the constant wavelength powder neutron diffraction
 
+ + Here is the content of the project files: ### project.cif + +
 data_La0.5Ba0.5CoO3
@@ -39,8 +46,12 @@ hrpt.cif
 
+ + ### models / lbco.cif + +
 data_lbco
@@ -71,8 +82,12 @@ O  O    0   0.5 0.5   1    Biso 1.4041
 
+ + ### experiments / hrpt.cif + +
 data_hrpt
@@ -132,3 +147,5 @@ loop_
 164.85  109  41.2
 
+ + diff --git a/tools/prepare_docs.sh b/tools/prepare_docs.sh index 0170c6d0..a21a9b8f 100755 --- a/tools/prepare_docs.sh +++ b/tools/prepare_docs.sh @@ -5,6 +5,8 @@ cp -R ../assets-docs/overrides/ overrides/ echo "\033[0;33m:::::: Add the extra files from the ../assets-branding\033[0m" mkdir -p docs/assets/images/ +cp ../assets-branding/EasyDiffraction/logos/ed-logo_dark.svg docs/assets/images/ +cp ../assets-branding/EasyDiffraction/logos/ed-logo_light.svg docs/assets/images/ cp ../assets-branding/EasyDiffraction/logos/edl-logo_dark.svg docs/assets/images/logo_dark.svg cp ../assets-branding/EasyDiffraction/logos/edl-logo_light.svg docs/assets/images/logo_light.svg cp ../assets-branding/EasyDiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png From 95047706a6d3a28af88688fa394656beff0ec41d Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Tue, 4 Feb 2025 12:44:15 +0100 Subject: [PATCH 13/43] Fix issues after reviewing PR --- .github/workflows/build-docs.yml | 15 ++++++--------- DEVELOPMENT.md | 6 ++---- tools/prepare_docs.sh | 6 ++---- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 991c00f4..affe5c0d 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -3,9 +3,9 @@ name: Build and deploy docs on: # Trigger the workflow on push push: - # Every branch - branches: - - '**' + # To the develop and master branches + branches: [develop, master] + # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -71,7 +71,7 @@ jobs: # https://www.mkdocs.org - name: Install MkDocs and its dependencies run: > - pip install mkdocs mkdocs-material 'mkdocs-autorefs<1.3.0' + pip install mkdocs mkdocs-material 'mkdocs-autorefs<1.3.0' mkdocs-jupyter mkdocs-plugin-inline-svg mkdocs-markdownextradata-plugin mkdocstrings-python @@ -100,7 +100,7 @@ jobs: cp assets-branding/EasyDiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png mkdir -p overrides/.icons/ cp assets-branding/EasyDiffraction/icons/ed-icon_bw.svg overrides/.icons/easydiffraction.svg - cp assets-branding/EasyScience/icons/es-icon_bw.svg overrides/.icons/easyscience.svg + cp assets-branding/EasyScienceOrg/icons/eso-icon_bw.svg overrides/.icons/easyscience.svg # Copy Jupyter notebooks from the project to the docs folder # The notebooks are used to generate the documentation @@ -119,10 +119,7 @@ jobs: # - assets-docs/mkdocs.yml - the common configuration (theme, plugins, etc.) # - docs/mkdocs.yml - the project-specific configuration (project name, TOC, etc.) - name: Create mkdocs.yml file - run: | - cp assets-docs/mkdocs.yml mkdocs.yml - echo "" >> mkdocs.yml - cat docs/mkdocs.yml >> mkdocs.yml + run: cat ../assets-docs/mkdocs.yml docs/mkdocs.yml > mkdocs.yml # Build the static files # Input: docs/ directory containing the Markdown files diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index cdb7ea78..ef24eb41 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -86,11 +86,9 @@ This is an example of a workflow that describes the development process. cp ../assets-branding/EasyDiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png mkdir -p overrides/.icons/ cp ../assets-branding/EasyDiffraction/icons/ed-icon_bw.svg overrides/.icons/easydiffraction.svg - cp ../assets-branding/EasyScience/icons/es-icon_bw.svg overrides/.icons/easyscience.svg + cp ../assets-branding/EasyScienceOrg/icons/eso-icon_bw.svg overrides/.icons/easyscience.svg cp -R examples/ docs/examples/ - cp ../assets-docs/mkdocs.yml mkdocs.yml - echo "" >> mkdocs.yml - cat docs/mkdocs.yml >> mkdocs.yml + cat ../assets-docs/mkdocs.yml docs/mkdocs.yml > mkdocs.yml ``` - Build documentation with MkDocs - static site generator ```console diff --git a/tools/prepare_docs.sh b/tools/prepare_docs.sh index a21a9b8f..da3ebbb1 100755 --- a/tools/prepare_docs.sh +++ b/tools/prepare_docs.sh @@ -12,12 +12,10 @@ cp ../assets-branding/EasyDiffraction/logos/edl-logo_light.svg docs/assets/image cp ../assets-branding/EasyDiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png mkdir -p overrides/.icons/ cp ../assets-branding/EasyDiffraction/icons/ed-icon_bw.svg overrides/.icons/easydiffraction.svg -cp ../assets-branding/EasyScience/icons/es-icon_bw.svg overrides/.icons/easyscience.svg +cp ../assets-branding/EasyScienceOrg/icons/eso-icon_bw.svg overrides/.icons/easyscience.svg echo "\033[0;33m:::::: Add Jupyter notebooks from the project to the docs/\033[0m" cp -R examples/ docs/examples/ echo "\033[0;33m:::::: Create the mkdocs.yml configuration file\033[0m" -cp ../assets-docs/mkdocs.yml mkdocs.yml -echo "" >> mkdocs.yml -cat docs/mkdocs.yml >> mkdocs.yml +cat ../assets-docs/mkdocs.yml docs/mkdocs.yml > mkdocs.yml From c4599832803b197376fe09b224a824462eef14e5 Mon Sep 17 00:00:00 2001 From: rozyczko Date: Tue, 4 Feb 2025 15:13:06 +0100 Subject: [PATCH 14/43] 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 4c9d938dde3c6b086edd994972b71285e224d38a Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Tue, 4 Feb 2025 17:45:30 +0100 Subject: [PATCH 15/43] Fix path in mkdocs.yml creation step --- .github/workflows/build-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index affe5c0d..e7f52a82 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -119,7 +119,7 @@ jobs: # - assets-docs/mkdocs.yml - the common configuration (theme, plugins, etc.) # - docs/mkdocs.yml - the project-specific configuration (project name, TOC, etc.) - name: Create mkdocs.yml file - run: cat ../assets-docs/mkdocs.yml docs/mkdocs.yml > mkdocs.yml + run: cat assets-docs/mkdocs.yml docs/mkdocs.yml > mkdocs.yml # Build the static files # Input: docs/ directory containing the Markdown files From 59a7ddfee59229db12c9f7d14521e6764a6f7510 Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Fri, 7 Feb 2025 15:17:17 +0100 Subject: [PATCH 16/43] _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 17/43] 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 18/43] 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 19/43] 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 20/43] 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 21/43] 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 22/43] 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 23/43] 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 24/43] 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 25/43] 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 26/43] 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 27/43] 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 28/43] 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 29/43] 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 30/43] 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 31/43] 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 32/43] 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 33/43] 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 34/43] 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 35/43] 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 36/43] 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 37/43] 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 38/43] 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 39/43] 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 From ac2ceff335275634e95d2aef4a491b6de36a7044 Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Fri, 4 Apr 2025 11:22:24 +0200 Subject: [PATCH 40/43] Documentation fix: assets location --- .github/workflows/build-docs.yml | 12 +++++------- DEVELOPMENT.md | 14 +++++++------- README.md | 6 +++--- docs/index.md | 2 +- tools/prepare_docs.sh | 14 +++++++------- 5 files changed, 23 insertions(+), 25 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index e7f52a82..2525b03d 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -93,14 +93,12 @@ jobs: run: | git clone https://github.com/easyscience/assets-branding.git mkdir -p docs/assets/images/ - cp assets-branding/EasyDiffraction/logos/ed-logo_dark.svg docs/assets/images/ - cp assets-branding/EasyDiffraction/logos/ed-logo_light.svg docs/assets/images/ - cp assets-branding/EasyDiffraction/logos/edl-logo_dark.svg docs/assets/images/logo_dark.svg - cp assets-branding/EasyDiffraction/logos/edl-logo_light.svg docs/assets/images/logo_light.svg - cp assets-branding/EasyDiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png + cp assets-branding/easydiffraction/logos/ed-logo-2_dark.svg docs/assets/images/ + cp assets-branding/easydiffraction/logos/ed-logo-2_light.svg docs/assets/images/ + cp assets-branding/easydiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png mkdir -p overrides/.icons/ - cp assets-branding/EasyDiffraction/icons/ed-icon_bw.svg overrides/.icons/easydiffraction.svg - cp assets-branding/EasyScienceOrg/icons/eso-icon_bw.svg overrides/.icons/easyscience.svg + cp assets-branding/easydiffraction/icons/ed-icon_bw.svg overrides/.icons/easydiffraction.svg + cp assets-branding/easyscience-org/icons/eso-logomark.svg overrides/.icons/easyscience.svg # Copy Jupyter notebooks from the project to the docs folder # The notebooks are used to generate the documentation diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index ef24eb41..3261fecb 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -79,14 +79,14 @@ This is an example of a workflow that describes the development process. cp -R ../assets-docs/includes/ includes/ cp -R ../assets-docs/overrides/ overrides/ mkdir -p docs/assets/images/ - cp ../assets-branding/EasyDiffraction/logos/ed-logo_dark.svg docs/assets/images/ - cp ../assets-branding/EasyDiffraction/logos/ed-logo_light.svg docs/assets/images/ - cp ../assets-branding/EasyDiffraction/logos/edl-logo_dark.svg docs/assets/images/logo_dark.svg - cp ../assets-branding/EasyDiffraction/logos/edl-logo_light.svg docs/assets/images/logo_light.svg - cp ../assets-branding/EasyDiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png + cp ../assets-branding/easydiffraction/logos/ed-logo-2_dark.svg docs/assets/images/ + cp ../assets-branding/easydiffraction/logos/ed-logo-2_light.svg docs/assets/images/ + + cp ../assets-branding/easydiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png mkdir -p overrides/.icons/ - cp ../assets-branding/EasyDiffraction/icons/ed-icon_bw.svg overrides/.icons/easydiffraction.svg - cp ../assets-branding/EasyScienceOrg/icons/eso-icon_bw.svg overrides/.icons/easyscience.svg + cp ../assets-branding/easydiffraction/icons/ed-icon_bw.svg overrides/.icons/easydiffraction.svg + cp ../assets-branding/easyscience-org/icons/eso-logomark.svg overrides/.icons/easyscience.svg cp -R examples/ docs/examples/ cat ../assets-docs/mkdocs.yml docs/mkdocs.yml > mkdocs.yml ``` diff --git a/README.md b/README.md index 891eab1b..40c6381c 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@

- + - + - EasyDiffraction + EasyDiffraction

diff --git a/docs/index.md b/docs/index.md index 7d0788ac..a22a4db6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -![](assets/images/ed-logo_dark.svg#gh-dark-mode-only)![](assets/images/ed-logo_light.svg#gh-light-mode-only) +![](assets/images/ed-logo-2_dark.svg#gh-dark-mode-only)![](assets/images/ed-logo-2_light.svg#gh-light-mode-only) # Making diffraction data analysis easy diff --git a/tools/prepare_docs.sh b/tools/prepare_docs.sh index da3ebbb1..7f03b5df 100755 --- a/tools/prepare_docs.sh +++ b/tools/prepare_docs.sh @@ -5,14 +5,14 @@ cp -R ../assets-docs/overrides/ overrides/ echo "\033[0;33m:::::: Add the extra files from the ../assets-branding\033[0m" mkdir -p docs/assets/images/ -cp ../assets-branding/EasyDiffraction/logos/ed-logo_dark.svg docs/assets/images/ -cp ../assets-branding/EasyDiffraction/logos/ed-logo_light.svg docs/assets/images/ -cp ../assets-branding/EasyDiffraction/logos/edl-logo_dark.svg docs/assets/images/logo_dark.svg -cp ../assets-branding/EasyDiffraction/logos/edl-logo_light.svg docs/assets/images/logo_light.svg -cp ../assets-branding/EasyDiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png +cp ../assets-branding/easydiffraction/logos/ed-logo-2_dark.svg docs/assets/images/ +cp ../assets-branding/easydiffraction/logos/ed-logo-2_light.svg docs/assets/images/ +# cp ../assets-branding/easydiffraction/logos/edl-logo_dark.svg docs/assets/images/logo_dark.svg +# cp ../assets-branding/easydiffraction/logos/edl-logo_light.svg docs/assets/images/logo_light.svg +cp ../assets-branding/easydiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png mkdir -p overrides/.icons/ -cp ../assets-branding/EasyDiffraction/icons/ed-icon_bw.svg overrides/.icons/easydiffraction.svg -cp ../assets-branding/EasyScienceOrg/icons/eso-icon_bw.svg overrides/.icons/easyscience.svg +cp ../assets-branding/easydiffraction/icons/ed-icon_bw.svg overrides/.icons/easydiffraction.svg +cp ../assets-branding/easyscience-org/icons/eso-logomark.svg overrides/.icons/easyscience.svg echo "\033[0;33m:::::: Add Jupyter notebooks from the project to the docs/\033[0m" cp -R examples/ docs/examples/ From f978c736a96a8979745a21750e0976e2e0a41b01 Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Fri, 4 Apr 2025 11:25:45 +0200 Subject: [PATCH 41/43] Documentation fix: icon location --- .github/workflows/build-docs.yml | 2 +- DEVELOPMENT.md | 2 +- tools/prepare_docs.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 2525b03d..874ea2e5 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -98,7 +98,7 @@ jobs: cp assets-branding/easydiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png mkdir -p overrides/.icons/ cp assets-branding/easydiffraction/icons/ed-icon_bw.svg overrides/.icons/easydiffraction.svg - cp assets-branding/easyscience-org/icons/eso-logomark.svg overrides/.icons/easyscience.svg + cp assets-branding/easyscience-org/icons/eso-icon.svg overrides/.icons/easyscience.svg # Copy Jupyter notebooks from the project to the docs folder # The notebooks are used to generate the documentation diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 3261fecb..7c1277cb 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -86,7 +86,7 @@ This is an example of a workflow that describes the development process. cp ../assets-branding/easydiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png mkdir -p overrides/.icons/ cp ../assets-branding/easydiffraction/icons/ed-icon_bw.svg overrides/.icons/easydiffraction.svg - cp ../assets-branding/easyscience-org/icons/eso-logomark.svg overrides/.icons/easyscience.svg + cp ../assets-branding/easyscience-org/icons/eso-icon.svg overrides/.icons/easyscience.svg cp -R examples/ docs/examples/ cat ../assets-docs/mkdocs.yml docs/mkdocs.yml > mkdocs.yml ``` diff --git a/tools/prepare_docs.sh b/tools/prepare_docs.sh index 7f03b5df..c651cb7f 100755 --- a/tools/prepare_docs.sh +++ b/tools/prepare_docs.sh @@ -12,7 +12,7 @@ cp ../assets-branding/easydiffraction/logos/ed-logo-2_light.svg docs/assets/imag cp ../assets-branding/easydiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png mkdir -p overrides/.icons/ cp ../assets-branding/easydiffraction/icons/ed-icon_bw.svg overrides/.icons/easydiffraction.svg -cp ../assets-branding/easyscience-org/icons/eso-logomark.svg overrides/.icons/easyscience.svg +cp ../assets-branding/easyscience-org/icons/eso-icon_bw.svg overrides/.icons/easyscience.svg echo "\033[0;33m:::::: Add Jupyter notebooks from the project to the docs/\033[0m" cp -R examples/ docs/examples/ From e034d9cf5531cb492bbfb5db735381e6186f7712 Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Fri, 4 Apr 2025 11:40:04 +0200 Subject: [PATCH 42/43] Documentation fix: icon name fix --- .github/workflows/build-docs.yml | 2 +- DEVELOPMENT.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 874ea2e5..e504fa1c 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -98,7 +98,7 @@ jobs: cp assets-branding/easydiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png mkdir -p overrides/.icons/ cp assets-branding/easydiffraction/icons/ed-icon_bw.svg overrides/.icons/easydiffraction.svg - cp assets-branding/easyscience-org/icons/eso-icon.svg overrides/.icons/easyscience.svg + cp assets-branding/easyscience-org/icons/eso-icon_bw.svg overrides/.icons/easyscience.svg # Copy Jupyter notebooks from the project to the docs folder # The notebooks are used to generate the documentation diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 7c1277cb..f0da00c6 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -86,7 +86,7 @@ This is an example of a workflow that describes the development process. cp ../assets-branding/easydiffraction/icons/ed-icon_256x256.png docs/assets/images/favicon.png mkdir -p overrides/.icons/ cp ../assets-branding/easydiffraction/icons/ed-icon_bw.svg overrides/.icons/easydiffraction.svg - cp ../assets-branding/easyscience-org/icons/eso-icon.svg overrides/.icons/easyscience.svg + cp ../assets-branding/easyscience-org/icons/eso-icon_bw.svg overrides/.icons/easyscience.svg cp -R examples/ docs/examples/ cat ../assets-docs/mkdocs.yml docs/mkdocs.yml > mkdocs.yml ``` From d563dada15cec0f566b4f5b26490e54ed9e3db06 Mon Sep 17 00:00:00 2001 From: Piotr Rozyczko Date: Fri, 4 Apr 2025 12:16:34 +0200 Subject: [PATCH 43/43] Documentation fix: build on tag creation --- .github/workflows/build-docs.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index e504fa1c..64be52ea 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -1,10 +1,10 @@ name: Build and deploy docs on: - # Trigger the workflow on push + # Triggers the workflow on tag creation push: - # To the develop and master branches - branches: [develop, master] + tags: + - 'v*' # Allows you to run this workflow manually from the Actions tab workflow_dispatch: