diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 7e920c3c..db64a3b1 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -25,7 +25,7 @@ jobs: - name: Suggestion to fix issues if: ${{ failure() }} run: | - echo "::notice::In project root run 'python.exe -m ruff . --fix' and commit changes to fix issues." + echo "::notice::In project root run 'python -m ruff check . --fix' and commit changes to fix issues." exit 1 Code_Testing: diff --git a/easydiffraction/Job.py b/easydiffraction/Job.py index c73cb2a2..ab924b20 100644 --- a/easydiffraction/Job.py +++ b/easydiffraction/Job.py @@ -4,12 +4,14 @@ import builtins import importlib.util +import re import time from copy import deepcopy from typing import TypeVar from typing import Union import numpy as np +from easyscience import global_object from easyscience.Datasets.xarray import xr # type: ignore # from easyscience.fitting.fitter import Fitter as CoreFitter @@ -255,6 +257,13 @@ def pattern(self): return self.sample._pattern return None + @property + def instrument(self): + ''' + Alias to self.parameters + ''' + return self.parameters + @property def phases(self) -> Phases: return self.sample.phases @@ -888,28 +897,98 @@ def is_notebook(self): ''' return hasattr(builtins, "__IPYTHON__") - def print_free_parameters(self): - ''' - Print the free parameters. - ''' - if importlib.util.find_spec("pandas") is not None: - parameters = {'names': [], 'values': [], 'errors': [], 'units': []} - for parameter in self.get_fit_parameters(): - parameters['names'].append(parameter.display_name) - parameters['values'].append(parameter.raw_value) - parameters['errors'].append(parameter.error) - parameters['units'].append(f'{parameter.unit:~P}') + def get_parent_name(self, unique_name: str) -> str: + ''' + Get the pretty name of the parameter. + ''' + full_name_items = global_object.map.find_path('DiffractionJob_0', unique_name) + str_name = '' + for item in full_name_items: + if re.match('^Phase_[0-9]+$', item): + phase_name = global_object.map.get_item_by_key(item).name + str_name += f".phases['{phase_name}']" + if re.match('^PeriodicLattice_[0-9]+$', item): + str_name += ".cell" + if re.match('^Site_[0-9]+$', item): + atom_site_name = global_object.map.get_item_by_key(item).name + str_name += f".atom_sites['{atom_site_name}']" + if re.match('^Instrument1D(CW|TOF)Parameters_[0-9]+$', item): + str_name += ".instrument" + if re.match('^Powder1DParameters_[0-9]+$', item): + str_name += ".pattern" + if re.match('^PointBackground_[0-9]+$', item): + container_idx = int(re.sub("\D", "", item)) - 1 + str_name += f".backgrounds[{container_idx}]" + if re.match('^BackgroundPoint_[0-9]+$', item): + name = global_object.map.get_item_by_key(item).name + str_name += f"['{name}']" + return str_name + + def get_full_parameter_name(self, unique_name: str, display_name: str, url: str) -> str: + parent_name = self.get_parent_name(unique_name) + if display_name == 'Biso': + display_name = 'b_iso_or_equiv' + elif display_name == 'Uiso': + display_name = 'u_iso_or_equiv' + if url and self.is_notebook(): + return f'{parent_name}.{display_name}' + return f'{parent_name}.{display_name}' + + def _parameters(self): + parameters = {'name': [], 'value': [], 'error': [], 'unit': [], 'min': [], 'max': [], 'vary': []} + for parameter in self.get_parameters(): + if parameter.enabled: + name = self.get_full_parameter_name(parameter.unique_name, parameter.display_name, parameter.url) + parameters['name'].append(name) + parameters['value'].append(parameter.raw_value) + parameters['error'].append(parameter.error) if parameter.error else parameters['error'].append('') + parameters['unit'].append(f'{parameter.unit:~P}') + parameters['min'].append(parameter.min) + parameters['max'].append(parameter.max) + parameters['vary'].append(parameter.free) if parameter.free else parameters['vary'].append('') + return parameters + + def _free_parameters(self): + parameters = {'name': [], 'value': [], 'error': [], 'unit': []} + for parameter in self.get_fit_parameters(): + name = self.get_full_parameter_name(parameter.unique_name, parameter.display_name, parameter.url) + parameters['name'].append(name) + parameters['value'].append(parameter.raw_value) + parameters['error'].append(parameter.error) + parameters['unit'].append(f'{parameter.unit:~P}') + return parameters + + def _show_parameters(self, parameters): + ''' + Show parameters. + ''' + if importlib.util.find_spec('pandas') is not None: df = pd.DataFrame(parameters) df.index += 1 - df.style.format(precision=5) if self.is_notebook(): - display(df) + display(df. + style. # apply styles from below + set_table_styles([dict(selector='th', props=[('text-align', 'left')])]). # align header to left + set_properties(subset=['name'], **{'text-align': 'left'}). # align column 'name' to left + format(precision=5)) # set precision else: print(df) else: - for parameter in self.get_fit_parameters(): + for parameter in self.get_parameters(): print(parameter) + def show_parameters(self): + ''' + Show all parameters (fixed and free). + ''' + self._show_parameters(self._parameters()) + + def show_free_parameters(self): + ''' + Show only free parameters. + ''' + self._show_parameters(self._free_parameters()) + ###### DUNDER METHODS ###### def __copy__(self): # Re-create the current object diff --git a/examples/Change_minimizer.ipynb b/examples/Change_minimizer.ipynb index 645dbe94..a6ac2352 100644 --- a/examples/Change_minimizer.ipynb +++ b/examples/Change_minimizer.ipynb @@ -38,8 +38,8 @@ "colab" ], "ExecuteTime": { - "end_time": "2024-10-21T21:25:39.406163Z", - "start_time": "2024-10-21T21:25:39.388783Z" + "end_time": "2024-10-28T10:50:40.979466Z", + "start_time": "2024-10-28T10:50:40.968260Z" } }, "source": [ @@ -70,8 +70,8 @@ "id": "33934041eaae166f", "metadata": { "ExecuteTime": { - "end_time": "2024-10-21T21:25:41.843997Z", - "start_time": "2024-10-21T21:25:39.408502Z" + "end_time": "2024-10-28T10:50:43.753157Z", + "start_time": "2024-10-28T10:50:40.981477Z" } }, "source": "import easydiffraction as ed", @@ -97,8 +97,8 @@ "id": "180e216d55b3f144", "metadata": { "ExecuteTime": { - "end_time": "2024-10-21T21:25:41.891178Z", - "start_time": "2024-10-21T21:25:41.881654Z" + "end_time": "2024-10-28T10:50:43.808239Z", + "start_time": "2024-10-28T10:50:43.797566Z" } }, "source": "job = ed.Job()", @@ -122,8 +122,8 @@ { "metadata": { "ExecuteTime": { - "end_time": "2024-10-21T21:25:42.333729Z", - "start_time": "2024-10-21T21:25:41.999972Z" + "end_time": "2024-10-28T10:50:44.202597Z", + "start_time": "2024-10-28T10:50:43.912369Z" } }, "cell_type": "code", @@ -154,8 +154,8 @@ "id": "5184de9d741bddb4", "metadata": { "ExecuteTime": { - "end_time": "2024-10-21T21:25:42.345081Z", - "start_time": "2024-10-21T21:25:42.338434Z" + "end_time": "2024-10-28T10:50:44.213165Z", + "start_time": "2024-10-28T10:50:44.206742Z" } }, "source": [ @@ -185,10 +185,10 @@ "_atom_site_occupancy\n", "_atom_site_adp_type\n", "_atom_site_B_iso_or_equiv\n", - "La La 0.00000000 0.00000000 0.00000000 0.5 Biso 0.49\n", - "Ba Ba 0.00000000 0.00000000 0.00000000 0.5 Biso 0.49\n", - "Co Co 0.5 0.5 0.5 1.00000000 Biso 0.26\n", - "O O 0.00000000 0.5 0.5 1.00000000 Biso 1.4\n" + "La La 0.00000000 0.00000000 0.00000000 0.5 Biso 0.1\n", + "Ba Ba 0.00000000 0.00000000 0.00000000 0.5 Biso 0.1\n", + "Co Co 0.5 0.5 0.5 1.00000000 Biso 0.1\n", + "O O 0.00000000 0.5 0.5 1.00000000 Biso 0.1\n" ] } ], @@ -205,18 +205,18 @@ "id": "238c54cda578c7e7", "metadata": { "ExecuteTime": { - "end_time": "2024-10-21T21:25:42.355337Z", - "start_time": "2024-10-21T21:25:42.349075Z" + "end_time": "2024-10-28T10:50:44.245274Z", + "start_time": "2024-10-28T10:50:44.238070Z" } }, "source": "job.show_crystal_structure(id='lbco')", "outputs": [ { "data": { - "application/3dmoljs_load.v0": "
\n

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n jupyter labextension install jupyterlab_3dmol

\n
\n", + "application/3dmoljs_load.v0": "
\n

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n jupyter labextension install jupyterlab_3dmol

\n
\n", "text/html": [ - "
\n", - "

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n", + "

\n", + "

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n", " jupyter labextension install jupyterlab_3dmol

\n", "
\n", "" ] @@ -292,8 +292,8 @@ "id": "8a1823930f0346e5", "metadata": { "ExecuteTime": { - "end_time": "2024-10-21T21:25:42.448576Z", - "start_time": "2024-10-21T21:25:42.359024Z" + "end_time": "2024-10-28T10:50:44.328229Z", + "start_time": "2024-10-28T10:50:44.255314Z" } }, "source": "job.add_experiment_from_file('data/hrpt.xye')", @@ -311,8 +311,8 @@ "id": "f1dfee8a4bee7672", "metadata": { "ExecuteTime": { - "end_time": "2024-10-21T21:25:42.592722Z", - "start_time": "2024-10-21T21:25:42.452771Z" + "end_time": "2024-10-28T10:50:44.450097Z", + "start_time": "2024-10-28T10:50:44.332384Z" } }, "source": [ @@ -26054,9 +26054,9 @@ } }, "text/html": [ - "
", + "application/3dmoljs_load.v0": "
\n

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n jupyter labextension install jupyterlab_3dmol

\n
\n", "text/html": [ - "
\n", - "

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n", + "

\n", + "

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n", " jupyter labextension install jupyterlab_3dmol

\n", "
\n", "" ] @@ -284,37 +297,43 @@ ] }, { - "metadata": {}, "cell_type": "markdown", - "source": "Load experimentally measured data from a file in XYE format", - "id": "1f6fe2b5622240c0" + "id": "1f6fe2b5622240c0", + "metadata": {}, + "source": [ + "Load experimentally measured data from a file in XYE format" + ] }, { "cell_type": "code", "id": "8a1823930f0346e5", "metadata": { "ExecuteTime": { - "end_time": "2024-10-23T12:44:16.420874Z", - "start_time": "2024-10-23T12:44:16.322137Z" + "end_time": "2024-10-28T10:47:38.771405Z", + "start_time": "2024-10-28T10:47:38.677653Z" } }, - "source": "job.add_experiment_from_file('data/hrpt.xye')", + "source": [ + "job.add_experiment_from_file('data/hrpt.xye')" + ], "outputs": [], "execution_count": 7 }, { - "metadata": {}, "cell_type": "markdown", - "source": "Display the experimentally measured data", - "id": "5c276b8592833bdf" + "id": "5c276b8592833bdf", + "metadata": {}, + "source": [ + "Display the experimentally measured data" + ] }, { "cell_type": "code", "id": "f1dfee8a4bee7672", "metadata": { "ExecuteTime": { - "end_time": "2024-10-23T12:44:16.577210Z", - "start_time": "2024-10-23T12:44:16.433993Z" + "end_time": "2024-10-28T10:47:38.921506Z", + "start_time": "2024-10-28T10:47:38.781150Z" } }, "source": [ @@ -26056,9 +26075,9 @@ } }, "text/html": [ - "
", + "application/3dmoljs_load.v0": "
\n

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n jupyter labextension install jupyterlab_3dmol

\n
\n", "text/html": [ - "
\n", - "

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n", + "

\n", + "

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n", " jupyter labextension install jupyterlab_3dmol

\n", "
\n", "" ] @@ -294,8 +294,8 @@ "id": "8a1823930f0346e5", "metadata": { "ExecuteTime": { - "end_time": "2024-10-21T21:26:06.659683Z", - "start_time": "2024-10-21T21:26:06.537278Z" + "end_time": "2024-10-28T10:50:41.623113Z", + "start_time": "2024-10-28T10:50:41.506845Z" } }, "source": "job.add_experiment_from_file('data/wish.xye')", @@ -313,8 +313,8 @@ "id": "f1dfee8a4bee7672", "metadata": { "ExecuteTime": { - "end_time": "2024-10-21T21:26:06.818694Z", - "start_time": "2024-10-21T21:26:06.663880Z" + "end_time": "2024-10-28T10:50:42.003456Z", + "start_time": "2024-10-28T10:50:41.848993Z" } }, "source": [ @@ -31176,9 +31176,9 @@ } }, "text/html": [ - "
", + "application/3dmoljs_load.v0": "
\n

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n jupyter labextension install jupyterlab_3dmol

\n
\n", "text/html": [ - "
\n", - "

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n", + "

\n", + "

You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\n", " jupyter labextension install jupyterlab_3dmol

\n", "
\n", "" ] @@ -380,8 +380,8 @@ "id": "8a1823930f0346e5", "metadata": { "ExecuteTime": { - "end_time": "2024-10-21T21:25:57.372943Z", - "start_time": "2024-10-21T21:25:57.247481Z" + "end_time": "2024-10-28T10:51:49.377933Z", + "start_time": "2024-10-28T10:51:49.222185Z" } }, "source": "job.add_experiment_from_file('data/sepd.xye')", @@ -399,8 +399,8 @@ "id": "f1dfee8a4bee7672", "metadata": { "ExecuteTime": { - "end_time": "2024-10-21T21:25:57.585139Z", - "start_time": "2024-10-21T21:25:57.377127Z" + "end_time": "2024-10-28T10:51:49.625427Z", + "start_time": "2024-10-28T10:51:49.382850Z" } }, "source": [ @@ -46158,9 +46158,9 @@ } }, "text/html": [ - "