Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added option to change the coloring for NaN values #21

Merged
merged 17 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .reuse/dep5
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Files:
pydidas/resources/*.png
resources/*.png
resources/*.svg
resources/*.ico
resources/graphics_for_gui/*
resources/documentation/dev_guide/*
Copyright: 2023 - 2024, Helmholtz-Zentrum Hereon
Expand Down
24 changes: 22 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,33 @@
.. SPDX-License-Identifier: CC0-1.0


v24.03.25
v24.xx.yy
=========


Improvements
------------
- Improved the naming and tooltips of scan parameters with respect to the
file numbers and indices.
- Added the ParameterCollection creation the the ParameterCollectionMixin
class initialization.


Bugfixes
--------
- Fixed a display issue in the title of the logging dockable widget.
- Fixed an issue in the pyFAI calibration frame where the supported file
formats where not correctly available in the file dialog.
- Fixed an issue with settings the X-ray energy / wavelength in the
DiffractionExperimentContext on the command line with wrong data types.
- Fixed an issue with convenience type conversions in the Parameter class.
- Fixed an issue with possibly joining queues twice on exit of WorkerController.


v24.03.25
=========

Improvements
------------
- Changed a number of filenames and paths (mainly in the documentation) to
reduce the total length of the file names.
- Updated files to new black 2024 style.
Expand Down
2 changes: 1 addition & 1 deletion formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def check_version_tags(directory: Optional[Path] = None):
with open(_directory.joinpath("pydidas", "version.py"), "r") as f:
_line = [_line for _line in f.readlines() if _line.startswith("__version__")]
_version = _line[0].split("=")[1].strip().strip('"')
_timed_print(f"Starting version tag check.", new_lines=1)
_timed_print("Starting version tag check.", new_lines=1)
with open(_directory.joinpath("CHANGELOG.rst"), "r") as f:
_changelog_lines = f.readlines()
_changelog_okay = f"v{_version}" in [_line.strip() for _line in _changelog_lines]
Expand Down
4 changes: 2 additions & 2 deletions pydidas/apps/directory_spy_app.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file is part of pydidas.
#
# Copyright 2023, Helmholtz-Zentrum Hereon
# Copyright 2023 - 2024, Helmholtz-Zentrum Hereon
# SPDX-License-Identifier: GPL-3.0-only
#
# pydidas is free software: you can redistribute it and/or modify
Expand All @@ -21,7 +21,7 @@
"""

__author__ = "Malte Storm"
__copyright__ = "Copyright 2023, Helmholtz-Zentrum Hereon"
__copyright__ = "Copyright 2023 - 2024, Helmholtz-Zentrum Hereon"
__license__ = "GPL-3.0-only"
__maintainer__ = "Malte Storm"
__status__ = "Production"
Expand Down
4 changes: 2 additions & 2 deletions pydidas/contexts/diff_exp/diff_exp.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,10 @@ def set_param_value(self, param_key: str, value: object):
"""
self._check_key(param_key)
if param_key == "xray_energy":
self.params["xray_energy"].value = value
self.params.set_value("xray_energy", value)
self.params["xray_wavelength"].value = LAMBDA_IN_A_TO_E / value
elif param_key == "xray_wavelength":
self.params["xray_wavelength"].value = value
self.params.set_value("xray_wavelength", value)
self.params["xray_energy"].value = LAMBDA_IN_A_TO_E / value
else:
self.params.set_value(param_key, value)
Expand Down
18 changes: 11 additions & 7 deletions pydidas/core/generic_params/generic_params_scan.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,26 +86,30 @@
"scan_start_index": {
"type": int,
"default": 0,
"name": "Starting index",
"name": "First filename number",
"choices": None,
"unit": "",
"allow_None": False,
"tooltip": (
"The starting index offset for the index used to identify data "
"points in the scan."
"The number of the first file to be used in processing. This number "
"will be applied as offset in the scan naming pattern to identify "
"the respective filename for scan points."
),
},
"scan_index_stepping": {
"type": int,
"default": 1,
"name": "Index stepping",
"name": "Frame index stepping",
"choices": None,
"unit": "",
"allow_None": False,
"tooltip": (
"The stepping of the index. A value of n corresponds to only using "
"every n-th index. For example, an index stepping of 3 with an offset "
"of 5 would process the frames 5, 8, 11, 14 etc."
"The stepping of the index in frames. A value of n corresponds to only "
"using every n-th index. For example, an index stepping of 3 with an "
"offset of 5 would process the frames 5, 8, 11, 14 etc. \n"
"Please note that the index stepping refers to the frames, not the "
"filenames. In the case of container files (e.g. hdf5), the index "
"stepping will skip process every n-th frame, not every n-th file."
),
},
"scan_multi_image_handling": {
Expand Down
7 changes: 3 additions & 4 deletions pydidas/core/object_with_parameter_collection.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file is part of pydidas.
#
# Copyright 2023, Helmholtz-Zentrum Hereon
# Copyright 2023 - 2024, Helmholtz-Zentrum Hereon
# SPDX-License-Identifier: GPL-3.0-only
#
# pydidas is free software: you can redistribute it and/or modify
Expand All @@ -22,7 +22,7 @@
"""

__author__ = "Malte Storm"
__copyright__ = "Copyright 2023, Helmholtz-Zentrum Hereon"
__copyright__ = "Copyright 2023 - 2024, Helmholtz-Zentrum Hereon"
__license__ = "GPL-3.0-only"
__maintainer__ = "Malte Storm"
__status__ = "Production"
Expand All @@ -35,7 +35,6 @@

from qtpy import QtCore

from .parameter_collection import ParameterCollection
from .parameter_collection_mixin import ParameterCollectionMixIn
from .pydidas_q_settings_mixin import PydidasQsettingsMixin

Expand All @@ -54,7 +53,7 @@ class ObjectWithParameterCollection(
def __init__(self):
QtCore.QObject.__init__(self)
PydidasQsettingsMixin.__init__(self)
self.params = ParameterCollection()
ParameterCollectionMixIn.__init__(self)
self._config = {}

def __copy__(self) -> Self:
Expand Down
83 changes: 43 additions & 40 deletions pydidas/core/parameter.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file is part of pydidas.
#
# Copyright 2023, Helmholtz-Zentrum Hereon
# Copyright 2023 - 2024, Helmholtz-Zentrum Hereon
# SPDX-License-Identifier: GPL-3.0-only
#
# pydidas is free software: you can redistribute it and/or modify
Expand All @@ -21,23 +21,23 @@
"""

__author__ = "Malte Storm"
__copyright__ = "Copyright 2023, Helmholtz-Zentrum Hereon"
__copyright__ = "Copyright 2023 - 2024, Helmholtz-Zentrum Hereon"
__license__ = "GPL-3.0-only"
__maintainer__ = "Malte Storm"
__status__ = "Production"
__all__ = ["Parameter"]


import numbers
import warnings
from collections.abc import Iterable
from numbers import Integral, Real
from pathlib import Path
from typing import Dict, List, Self, Set, Tuple, Type, Union
from typing import Any, Dict, List, Self, Set, Tuple, Type, Union

from .hdf5_key import Hdf5key


def _get_base_class(cls) -> type:
def _get_base_class(cls: Any) -> Union[type, Real, Integral, None]:
"""
Filter numerical classes and return the corresponding abstract base class.

Expand All @@ -53,14 +53,14 @@ def _get_base_class(cls) -> type:
Returns
-------
object
The base class of the input class if the inpu.
The base class of the input class if the input.
"""
if cls is None:
return None
if numbers.Integral.__subclasscheck__(cls):
return numbers.Integral
if numbers.Real.__subclasscheck__(cls):
return numbers.Real
if issubclass(cls, Integral):
return Integral
if issubclass(cls, Real):
return Real
return cls


Expand All @@ -70,7 +70,7 @@ class Parameter:

The Parameter has the following properties which can be accessed.
Only the value and choices properties can be edited at runtime, all other
properties are fixed at instanciation.
properties are fixed at instantiation.

+------------+-----------+-------------------------------------------+
| property | editable | description |
Expand Down Expand Up @@ -104,7 +104,7 @@ class Parameter:
+------------+-----------+-------------------------------------------+

Parameters can be passed either as a complete meta_dict or as individual
keyword arguments. The meta_dict will take precendence.
keyword arguments. The meta_dict will take precedence.

Parameters
----------
Expand All @@ -120,7 +120,7 @@ class Parameter:
The default value. The data type must be of the same type as
param_type. None is only accepted if param_type is None as well.
meta : Union[dict, None], optional
A dictionary with meta data. Any keys specified as meta will
A dictionary with metadata. Any keys specified as meta will
overwrite the kwargs dictionary. This is added merely as
convenience to facility copying Parameter instances. If None,
this entry will be ignored. The default is None.
Expand Down Expand Up @@ -171,13 +171,13 @@ def __init__(
self.__process_choices_input(kwargs)
self.value = kwargs.get("value", self.__meta["default"])

def __process_default_input(self, default: Type):
def __process_default_input(self, default: object):
"""
Process the default value.

Parameters
----------
default : Type
default : object
The default attribute passed to init.

Raises
Expand Down Expand Up @@ -206,7 +206,7 @@ def __process_choices_input(self, kwargs: Dict):
TypeError
If choices is not of an accepted type (None, list, tuple)
ValueError
If the default has been set and it is not in choices.
If the default has been set, and it is not in choices.
"""
_choices = kwargs.get("choices", None)
if not (isinstance(_choices, (list, tuple, set)) or _choices is None):
Expand All @@ -224,7 +224,7 @@ def __process_choices_input(self, kwargs: Dict):

def __typecheck(self, val: object) -> bool:
"""
Check the type of a new input.
Check the type of new input.

Parameters
----------
Expand Down Expand Up @@ -268,19 +268,22 @@ def __convenience_type_conversion(self, value: object) -> object:
Returns
-------
value : any
The value with the above mentioned type conversions applied.
The value with the above-mentioned type conversions applied.
"""
if isinstance(value, str):
if self.__type == Path:
value = Path(value)
elif self.__type == Hdf5key:
value = Hdf5key(value)
if self.__type == numbers.Real and not self.__meta["allow_None"]:
return float(value)
if isinstance(value, list) and self.__type == tuple:
return tuple(value)
if isinstance(value, tuple) and self.__type == list:
return list(value)
if self.__type in [Real, Integral] and not self.__meta["allow_None"]:
try:
value = float(value) if self.__type == Real else int(value)
except ValueError:
pass
finally:
return value
if isinstance(value, Iterable) and self.__type in [list, set, tuple]:
return self.__type(value)
return value

@property
Expand Down Expand Up @@ -310,7 +313,7 @@ def allow_None(self) -> bool:
@property
def refkey(self) -> str:
"""
Return the paramter reference key.
Return the parameter reference key.

Returns
-------
Expand Down Expand Up @@ -356,9 +359,9 @@ def tooltip(self) -> str:
_t = self.__meta["tooltip"]
if self.unit:
_t += f" (unit: {self.unit})"
if self.dtype == numbers.Integral:
if self.dtype == Integral:
_t += " (type: integer)"
elif self.dtype == numbers.Real:
elif self.dtype == Real:
_t += " (type: float)"
elif self.dtype == str:
_t += " (type: str)"
Expand All @@ -375,13 +378,6 @@ def choices(self) -> Union[None, List]:
"""
Get or set the allowed choices for the Parameter value.

Parameters
----------
choices : Union[list, tuple, set]
A list or tuple of allowed choices. A check will be performed that
all entries correspond to the defined data type and that the
curent parameter value is one of the allowed choices.

Returns
-------
Union[list, None]
Expand All @@ -394,11 +390,18 @@ def choices(self, choices: Union[None, List, Tuple, Set]):
"""
Update the allowed choices of a Parameter.

Parameters
----------
choices : Union[list, tuple, set]
A list or tuple of allowed choices. A check will be performed that
all entries correspond to the defined data type and that the
current parameter value is one of the allowed choices.

Raises
------
TypeError
If the supplied choices are not of datatype list or tuple.
ValueErrror
ValueError
If any choice in choices does not pass the datatype check.
ValueError
If the current Parameter value is not included in the list of
Expand Down Expand Up @@ -505,9 +508,9 @@ def value_for_export(self) -> object:
return None
if self.__type in (str, Hdf5key, Path):
return str(self.value)
if self.__type == numbers.Integral:
if self.__type == Integral:
return int(self.value)
if self.__type == numbers.Real:
if self.__type == Real:
return float(self.value)
if self.__type in (list, tuple, dict):
return self.value
Expand Down Expand Up @@ -542,7 +545,7 @@ def restore_default(self):

def copy(self) -> Self:
"""
A method to get the a copy of the Parameter object.
A method to get a copy of the Parameter object.

Returns
-------
Expand Down Expand Up @@ -575,7 +578,7 @@ def dump(self) -> Tuple:
_default = self.__meta["default"]
if self.choices is not None and self.__meta["default"] not in self.choices:
_default = self.value
return (self.__refkey, self.__type, _default, _meta)
return self.__refkey, self.__type, _default, _meta

def export_refkey_and_value(self) -> Tuple:
"""
Expand All @@ -587,7 +590,7 @@ def export_refkey_and_value(self) -> Tuple:
tuple
The tuple of (refkey, value as pickleable format)
"""
return (self.__refkey, self.value_for_export)
return self.__refkey, self.value_for_export

def __str__(self) -> str:
"""
Expand Down
Loading
Loading