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 5b44bc71..ea081740 100644 --- a/src/easydiffraction/calculators/cryspy/calculator.py +++ b/src/easydiffraction/calculators/cryspy/calculator.py @@ -449,9 +449,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 if 'excluded_points' in kwargs: @@ -492,8 +491,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 @@ -559,10 +558,10 @@ 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) + 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) @@ -609,7 +608,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: @@ -637,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 @@ -771,10 +771,8 @@ def replaceExpCif(self, edCif, currentExperimentName): calcExperimentsDict = calcExperimentsObj.get_dictionary() calcDictBlockName = f'pd_{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] @@ -799,20 +797,22 @@ 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] + 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] @@ -848,7 +848,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': scales[idx] * dependent[idx, :] / normalization, + 'profile': dependent[idx, :] / (normalization * len(scales)), 'components': {'total': dependent[idx, :]}, 'profile_scale': scales[idx], } @@ -888,13 +888,14 @@ 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) + # print("===========================================") + # print(" RUNNING PROFILE CALCULATION") + # print("===========================================") is_tof = False if self.model.PREFIX.lower() == 'tof': is_tof = True @@ -904,15 +905,52 @@ 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 + 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 + exp_name_model = key + break + + if not exp_name_model: + # no exp defined, default + 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 + + # assure correct exp_name_model prefix. + # for cwl it is 'pd_', for tof it is '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 = self.model.PREFIX + '_' + 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 - 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'): @@ -920,9 +958,10 @@ def _do_run(self, model, polarized, x_array, crystals, phase_list, bg): 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] + 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( @@ -930,6 +969,8 @@ def _do_run(self, model, polarized, x_array, crystals, phase_list, bg): ) 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 @@ -940,12 +981,18 @@ def _do_run(self, model, polarized, x_array, crystals, phase_list, bg): # 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, 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 54ed7a2e..2288cb20 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,10 +62,1388 @@ def __init__( self['cifDict'] = cifDict self['parentIndex'] = 0 self['parentName'] = '' - self['units'] = units + 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, + unit='Å', + 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, + unit='°', + 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 @@ -180,7 +1558,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 +1578,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 4ba7e29d..1001c8de 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: """ @@ -453,9 +453,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( @@ -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: @@ -793,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, 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 affb8dd1..133b7fa9 100644 --- a/src/easydiffraction/io/cif.py +++ b/src/easydiffraction/io/cif.py @@ -15,6 +15,7 @@ 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 @@ -242,9 +243,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 +276,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 +291,12 @@ 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 +340,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('Some fractional co-ordinates rounded to ideal values to avoid issues with finite precision.') @@ -538,11 +537,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 @@ -567,7 +566,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) @@ -599,7 +598,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' @@ -613,11 +612,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 @@ -642,7 +641,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) @@ -1063,8 +1062,123 @@ 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 + + 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: + # Adds empty brackets for standard uncertainty for free params + paramStr = f'{value}()' + else: + # Adds brackets with standard uncertainty for free params + _, _, 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 + 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 + + 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: + # Adds brackets with standard uncertainty for free params + _, _, 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 + 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: + paramStr = str(value) + + 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 toStdDevSmallestPrecision(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"]}' + 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 diff --git a/src/easydiffraction/io/cif_reader.py b/src/easydiffraction/io/cif_reader.py index 195e5bb1..3822872d 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 = ( @@ -149,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 @@ -310,8 +320,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: - return float(value), float(error) # 1.23(4) + # 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 diff --git a/src/easydiffraction/job/experiment/backgrounds/background.py b/src/easydiffraction/job/experiment/backgrounds/background.py index ebd18837..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.Variable import Descriptor +from easyscience.Objects.variable import DescriptorStr as Descriptor class Background(BaseCollection): @@ -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..f00c51a3 100644 --- a/src/easydiffraction/job/experiment/backgrounds/point.py +++ b/src/easydiffraction/job/experiment/backgrounds/point.py @@ -8,8 +8,8 @@ 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.ObjectClasses import Parameter +from easyscience.Objects.variable import DescriptorNumber as Descriptor +from easyscience.Objects.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 ffaf9bca..f1c5b6ee 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.ObjectClasses import Descriptor -from easyscience.Objects.ObjectClasses 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 @@ -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 @@ -260,6 +260,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: @@ -357,7 +362,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 @@ -580,19 +585,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 @@ -601,28 +606,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) @@ -644,7 +649,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..ab2608ca 100644 --- a/src/easydiffraction/job/experiment/pd_1d.py +++ b/src/easydiffraction/job/experiment/pd_1d.py @@ -14,8 +14,8 @@ 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.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 @@ -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, }, @@ -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] @@ -550,13 +556,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 +573,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..ce9b5360 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.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 f416357e..e610602f 100644 --- a/src/easydiffraction/job/job.py +++ b/src/easydiffraction/job/job.py @@ -143,6 +143,7 @@ def __init__( self.datastore._simulations = self.sample self.interface = self.sample._interface + self.experiment.interface = self.interface self.analysis = analysis self.update_experiment_type() @@ -159,6 +160,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: @@ -340,12 +342,12 @@ def update_experiment_type(self) -> None: # axis if self.type.is_tof: self._x_axis_name = 'time' - if self.experiment.pattern is not None: - self.experiment.pattern.zero_shift.unit = 'μs' + # if self.pattern is not None: + # self.pattern.zero_shift.convert_unit('μs') else: self._x_axis_name = 'tth' - if self.experiment.pattern is not None: - self.experiment.pattern.zero_shift.unit = 'degree' + if self.pattern is not None: + self.pattern.zero_shift.convert_unit('degree') def update_exp_type(self) -> None: """ @@ -442,7 +444,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() # update the kwargs with new pointers self._kwargs['_parameters'] = self.experiment.parameters @@ -454,20 +459,29 @@ def add_experiment_from_file(self, file_url: str) -> None: pattern = self.experiment.pattern phases = self.sample.phases name = self.sample.name - self.sample = Sample(name, parameters=parameters, pattern=pattern, phases=phases) - # self.update_experiment_type() - # self.update_interface() + + 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 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 @@ -477,7 +491,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: """ @@ -657,8 +671,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 @@ -783,16 +797,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}'") @@ -1044,8 +1058,9 @@ 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['unit'].append(f'{parameter.unit:~P}') + parameters['value'].append(parameter.value) + # 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) @@ -1057,8 +1072,9 @@ 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['unit'].append(f'{parameter.unit:~P}') + parameters['value'].append(parameter.value) + # parameters['unit'].append(f'{parameter.unit:~P}') + parameters['unit'].append(f'{parameter.unit}') parameters['error'].append(parameter.error) return parameters diff --git a/src/easydiffraction/job/model/phase.py b/src/easydiffraction/job/model/phase.py index bf0a0e8e..45687e1d 100644 --- a/src/easydiffraction/job/model/phase.py +++ b/src/easydiffraction/job/model/phase.py @@ -15,6 +15,12 @@ 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 + 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 def add_atom(self, *args, **kwargs): diff --git a/src/easydiffraction/job/model/site.py b/src/easydiffraction/job/model/site.py index 577c7f12..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.ObjectClasses import Descriptor -from easyscience.Objects.ObjectClasses 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 @@ -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/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__': 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( 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}')" ] }, {