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": "
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
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
You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\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
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
You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\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
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
You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\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
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
You appear to be running in JupyterLab (or JavaScript failed to load for some other reason). You need to install the 3dmol extension:
\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