diff --git a/MDANSE/Src/Framework/Converters/ASE.py b/MDANSE/Src/Framework/Converters/ASE.py index 169bd18677..50f5982c7e 100644 --- a/MDANSE/Src/Framework/Converters/ASE.py +++ b/MDANSE/Src/Framework/Converters/ASE.py @@ -321,6 +321,8 @@ class ASEInteractiveConverter(InteractiveConverter): Converts any trajectory to a HDF trajectory using the ASE io module. """ + category = ("InteractiveConverter",) + label = "ASE" input_files = collections.OrderedDict() diff --git a/MDANSE/Src/Framework/Converters/Converter.py b/MDANSE/Src/Framework/Converters/Converter.py index c0cab7499d..472b814e59 100644 --- a/MDANSE/Src/Framework/Converters/Converter.py +++ b/MDANSE/Src/Framework/Converters/Converter.py @@ -22,6 +22,8 @@ class InteractiveConverter(IJob): + category = ("InteractiveConverter",) + _converter_registry = {} _next_number = 1 diff --git a/MDANSE/Src/Framework/Converters/DL_POLY.py b/MDANSE/Src/Framework/Converters/DL_POLY.py index 7cfd711769..a3cfb3a77d 100644 --- a/MDANSE/Src/Framework/Converters/DL_POLY.py +++ b/MDANSE/Src/Framework/Converters/DL_POLY.py @@ -379,7 +379,10 @@ class DL_POLY(Converter): "label": "Input HISTORY file", }, ) - settings["atom_aliases"] = ("python_object", {"default": {}}) + settings["atom_aliases"] = ( + "PythonObjectConfigurator", + {"default": {}, "label": "Atom aliases (Python dictionary)"}, + ) settings["fold"] = ( "BooleanConfigurator", {"default": False, "label": "Fold coordinates into box"}, diff --git a/MDANSE/Src/Framework/Converters/XPLOR.py b/MDANSE/Src/Framework/Converters/XPLOR.py index 9cf3741de4..b25348d96d 100644 --- a/MDANSE/Src/Framework/Converters/XPLOR.py +++ b/MDANSE/Src/Framework/Converters/XPLOR.py @@ -17,7 +17,7 @@ from MDANSE.Framework.Converters.DCD import DCD -class XPLORConverter(DCD): +class XPLOR(DCD): """ Converts an Xplor trajectory to a HDF trajectory. """ diff --git a/MDANSE/Src/Framework/Jobs/DistanceHistogram.py b/MDANSE/Src/Framework/Jobs/DistanceHistogram.py index 62ba99ff0c..cefc074c48 100644 --- a/MDANSE/Src/Framework/Jobs/DistanceHistogram.py +++ b/MDANSE/Src/Framework/Jobs/DistanceHistogram.py @@ -31,6 +31,11 @@ class DistanceHistogram(IJob): type = None + category = ( + "Analysis", + "Structure", + ) + settings = collections.OrderedDict() settings["trajectory"] = ("HDFTrajectoryConfigurator", {}) settings["frames"] = ( diff --git a/MDANSE_GUI/Src/PyQtGUI/BackEnd.py b/MDANSE_GUI/Src/PyQtGUI/BackEnd.py index a735ae40ad..6550b9705f 100644 --- a/MDANSE_GUI/Src/PyQtGUI/BackEnd.py +++ b/MDANSE_GUI/Src/PyQtGUI/BackEnd.py @@ -129,8 +129,8 @@ def checkConverters(self): self._reverse_converters = {} for key, conv in Converter.indirect_subclass_dictionary().items(): ic(f"key:{key}, val:{conv}") - self._converters.append(conv) - self._reverse_converters[str(conv)] = Converter.create(str(key)) + self._converters.append(key) + self._reverse_converters[str(key)] = Converter.create(str(key)) self.lock.unlock() def getConverters(self): diff --git a/MDANSE_GUI/Src/PyQtGUI/InputWidgets/AtomSelectionWidget.py b/MDANSE_GUI/Src/PyQtGUI/InputWidgets/AtomSelectionWidget.py index ad4c48753c..3b51d62ac0 100644 --- a/MDANSE_GUI/Src/PyQtGUI/InputWidgets/AtomSelectionWidget.py +++ b/MDANSE_GUI/Src/PyQtGUI/InputWidgets/AtomSelectionWidget.py @@ -32,7 +32,7 @@ class SelectionDialog(QDialog): class AtomSelectionWidget(WidgetBase): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - default_value = "atom_symbol *" + default_value = "all" self._value = default_value self.field = QLineEdit(default_value, self._base) browse_button = QPushButton("Atom selection creator", self._base) diff --git a/MDANSE_GUI/Src/PyQtGUI/InputWidgets/AtomTransmutationWidget.py b/MDANSE_GUI/Src/PyQtGUI/InputWidgets/AtomTransmutationWidget.py index 11092f0ed5..340f450658 100644 --- a/MDANSE_GUI/Src/PyQtGUI/InputWidgets/AtomTransmutationWidget.py +++ b/MDANSE_GUI/Src/PyQtGUI/InputWidgets/AtomTransmutationWidget.py @@ -39,7 +39,7 @@ def add_line(self): line_base = QWidget(self._base) line_layout = QHBoxLayout(line_base) line_base.setLayout(line_layout) - default_value = "atom_symbol *" + default_value = "all" starter = QLabel("Transmute ", line_base) leftfield = QLineEdit(default_value, self._base) spacer = QLabel(" to ", line_base) diff --git a/MDANSE_GUI/Src/PyQtGUI/InputWidgets/RangeWidget.py b/MDANSE_GUI/Src/PyQtGUI/InputWidgets/RangeWidget.py new file mode 100644 index 0000000000..f354f5cf6e --- /dev/null +++ b/MDANSE_GUI/Src/PyQtGUI/InputWidgets/RangeWidget.py @@ -0,0 +1,79 @@ +# ************************************************************************** +# +# MDANSE: Molecular Dynamics Analysis for Neutron Scattering Experiments +# +# @file Src/PyQtGUI/InputWidgets/FramesWidget.py +# @brief Implements module/class/test FramesWidget +# +# @homepage https://www.isis.stfc.ac.uk/Pages/MDANSEproject.aspx +# @license GNU General Public License v3 or higher (see LICENSE) +# @copyright Institut Laue Langevin 2013-now +# @copyright ISIS Neutron and Muon Source, STFC, UKRI 2021-now +# @authors Scientific Computing Group at ILL (see AUTHORS) +# +# ************************************************************************** + +from qtpy.QtWidgets import QLineEdit, QSpinBox, QLabel +from qtpy.QtCore import Slot, Signal +from qtpy.QtGui import QDoubleValidator, QIntValidator + +from MDANSE_GUI.PyQtGUI.InputWidgets.WidgetBase import WidgetBase + + +class RangeWidget(WidgetBase): + def __init__(self, *args, **kwargs): + super().__init__(*args, layout_type="QGridLayout", **kwargs) + source_object = kwargs.get("source_object", None) + num_type = kwargs.get("valueType", int) + if num_type is int: + step_val = 1 + else: + step_val = 0.1 + labels = [ + QLabel("From", self._base), + QLabel("to", self._base), + QLabel("in steps of", self._base), + ] + fields = [ + QLineEdit(str(num_type(0)), self._base), + QLineEdit(str(num_type(5)), self._base), + QLineEdit(str(num_type(step_val)), self._base), + ] + if num_type is int: + validators = [QIntValidator(parent_field) for parent_field in fields] + else: + validators = [QDoubleValidator(parent_field) for parent_field in fields] + for field_num in range(3): + self._layout.addWidget(labels[field_num], 0, 2 * field_num) + self._layout.addWidget(fields[field_num], 0, 2 * field_num + 1) + fields[field_num].setValidator(validators[field_num]) + fields[field_num].textChanged.connect(self.updateValue) + self._fields = fields + self._validators = validators + self._num_type = num_type + self.default_labels() + self.update_labels() + + def default_labels(self): + """Each Widget should have a default tooltip and label, + which will be set in this method, unless specific + values are provided in the settings of the job that + is being configured.""" + if self._label_text == "": + self._label_text = "RangeWidget" + if self._tooltip == "": + self._tooltip = "Values to be used, given as (First, Last, StepSize)" + + def value_from_configurator(self): + if self._configurator.check_dependencies(): + minval, maxval = self._configurator._mini, self._configurator._maxi + print(f"Configurator min/max: {minval}, {maxval}") + if maxval is None: + return + for val in self._validators: + val.setBottom(-abs(maxval)) + val.setTop(abs(maxval)) + + def get_widget_value(self): + val = [self._num_type(field.text()) for field in self._fields] + return val diff --git a/MDANSE_GUI/Src/PyQtGUI/InputWidgets/__init__.py b/MDANSE_GUI/Src/PyQtGUI/InputWidgets/__init__.py index 4119c85fd0..5219b11004 100644 --- a/MDANSE_GUI/Src/PyQtGUI/InputWidgets/__init__.py +++ b/MDANSE_GUI/Src/PyQtGUI/InputWidgets/__init__.py @@ -34,6 +34,7 @@ "FloatWidget", "StringWidget", "FramesWidget", + "RangeWidget", "HDFTrajectoryWidget", "DummyWidget", "InterpolationOrderWidget", diff --git a/MDANSE_GUI/Src/PyQtGUI/MolecularViewer/AtomProperties.py b/MDANSE_GUI/Src/PyQtGUI/MolecularViewer/AtomProperties.py index d5fab27638..32e6d657d3 100644 --- a/MDANSE_GUI/Src/PyQtGUI/MolecularViewer/AtomProperties.py +++ b/MDANSE_GUI/Src/PyQtGUI/MolecularViewer/AtomProperties.py @@ -140,16 +140,14 @@ def initialise_from_database( index_list = [] for nat, atom in enumerate(atoms): row = [] - rgb = [int(x) for x in element_database["atoms"][atom]["color"].split(";")] + rgb = [int(x) for x in element_database[atom]["color"].split(";")] index_list.append(self.add_colour(rgb)) row.append(QStandardItem(str(nat + 1))) # atom number row.append( - QStandardItem(str(element_database["atoms"][atom]["symbol"])) + QStandardItem(str(element_database[atom]["symbol"])) ) # chemical element name row.append( - QStandardItem( - str(round(element_database["atoms"][atom]["atomic_radius"], 2)) - ) + QStandardItem(str(round(element_database[atom]["atomic_radius"], 2))) ) row.append( QStandardItem( diff --git a/MDANSE_GUI/Src/PyQtGUI/MolecularViewer/MolecularViewer.py b/MDANSE_GUI/Src/PyQtGUI/MolecularViewer/MolecularViewer.py index 63ef038661..ef4af87986 100644 --- a/MDANSE_GUI/Src/PyQtGUI/MolecularViewer/MolecularViewer.py +++ b/MDANSE_GUI/Src/PyQtGUI/MolecularViewer/MolecularViewer.py @@ -25,8 +25,9 @@ from vtkmodules.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor from MDANSE.Framework.InputData.HDFTrajectoryInputData import HDFTrajectoryInputData +from MDANSE.Chemistry import ATOMS_DATABASE as CHEMICAL_ELEMENTS -from MDANSE_GUI.PyQtGUI.MolecularViewer.database import CHEMICAL_ELEMENTS +# from MDANSE_GUI.PyQtGUI.MolecularViewer.database import CHEMICAL_ELEMENTS from MDANSE_GUI.PyQtGUI.MolecularViewer.readers import hdf5wrapper from MDANSE_GUI.PyQtGUI.MolecularViewer.Dummy import PyConnectivity from MDANSE_GUI.PyQtGUI.MolecularViewer.Contents import TrajectoryAtomData @@ -544,8 +545,7 @@ def set_coordinates(self, frame: int): self._polydata.SetPoints(atoms) covalent_radii = [ - CHEMICAL_ELEMENTS["atoms"][at]["covalent_radius"] - for at in self._reader.atom_types + CHEMICAL_ELEMENTS[at]["covalent_radius"] for at in self._reader.atom_types ] self.set_connectivity_builder(coords, covalent_radii) chemical_bonds = self._fixed_bonds @@ -599,7 +599,7 @@ def set_reader(self, reader, frame=0): # this returs a list of indices, mapping colours to atoms self._atom_scales = np.array( - [CHEMICAL_ELEMENTS["atoms"][at]["vdw_radius"] for at in self._atoms] + [CHEMICAL_ELEMENTS[at]["vdw_radius"] for at in self._atoms] ).astype(np.float32) scalars = ndarray_to_vtkarray( diff --git a/MDANSE_GUI/Src/PyQtGUI/SubclassViewer.py b/MDANSE_GUI/Src/PyQtGUI/SubclassViewer.py index f6e9fdbac9..132d383017 100644 --- a/MDANSE_GUI/Src/PyQtGUI/SubclassViewer.py +++ b/MDANSE_GUI/Src/PyQtGUI/SubclassViewer.py @@ -128,6 +128,7 @@ def parentsFromCategories(self, category_tuple): self._categories[cat_string] = current_node else: current_node = self._categories[cat_string] + parent = current_node return current_node diff --git a/MDANSE_GUI/Src/PyQtGUI/Widgets/ActionDialog.py b/MDANSE_GUI/Src/PyQtGUI/Widgets/ActionDialog.py index 188aea4fb1..b7d2268420 100644 --- a/MDANSE_GUI/Src/PyQtGUI/Widgets/ActionDialog.py +++ b/MDANSE_GUI/Src/PyQtGUI/Widgets/ActionDialog.py @@ -59,6 +59,7 @@ "StringConfigurator": StringWidget, "IntegerConfigurator": IntegerWidget, "FramesConfigurator": FramesWidget, + "RangeConfigurator": RangeWidget, "HDFTrajectoryConfigurator": HDFTrajectoryWidget, "InterpolationOrderConfigurator": InterpolationOrderWidget, "OutputFilesConfigurator": OutputFilesWidget, diff --git a/MDANSE_GUI/Src/PyQtGUI/Widgets/ConvertDialog.py b/MDANSE_GUI/Src/PyQtGUI/Widgets/ConvertDialog.py index b52b34305a..dfe59f5729 100644 --- a/MDANSE_GUI/Src/PyQtGUI/Widgets/ConvertDialog.py +++ b/MDANSE_GUI/Src/PyQtGUI/Widgets/ConvertDialog.py @@ -84,7 +84,7 @@ def __init__(self, *args, converter: IJob = "Dummy", **kwargs): ] ) else: - converter_instance = converter() + converter_instance = converter converter_instance.build_configuration() settings = converter_instance.settings self.converter_instance = converter_instance diff --git a/MDANSE_GUI/Src/PyQtGUI/Widgets/GeneralWidgets.py b/MDANSE_GUI/Src/PyQtGUI/Widgets/GeneralWidgets.py index a89ce469ff..d331b89651 100644 --- a/MDANSE_GUI/Src/PyQtGUI/Widgets/GeneralWidgets.py +++ b/MDANSE_GUI/Src/PyQtGUI/Widgets/GeneralWidgets.py @@ -277,25 +277,25 @@ def createInputField(*args, **kwargs): Returns: [QWidget, GeneralInput] pair """ - kind = kwargs.get("kind", "str") + kind = kwargs.get("kind", "String") - if kind == "str": + if kind == "StringConfigurator": result = InputFactory.createSingle(*args, **kwargs) - elif kind == "int" or kind == "integer": + elif kind == "PythonObjectConfigurator": result = InputFactory.createSingle(*args, **kwargs) - elif kind == "range" or kind == "intrange": - result = InputFactory.createMultiple(*args, **kwargs) - elif kind == "arange" or kind == "floatrange": + elif kind == "IntegerConfigurator": + result = InputFactory.createSingle(*args, **kwargs) + elif kind == "RangeConfigurator": result = InputFactory.createMultiple(*args, **kwargs) - elif kind == "float": + elif kind == "FloatConfigurator": result = InputFactory.createSingle(*args, **kwargs) - elif kind == "single_choice": + elif kind == "SingleChoiceConfigurator": result = InputFactory.createCombo(*args, **kwargs) - elif kind == "bool" or kind == "boolean": + elif kind == "BooleanConfigurator": result = InputFactory.createBool(*args, **kwargs) - elif kind == "input_file": + elif kind == "InputFileConfigurator": result = InputFactory.createFile(*args, direction="in", **kwargs) - elif kind == "single_output_file": + elif kind == "SingleOutputFileConfigurator": result = InputFactory.createFile(*args, direction="out", **kwargs) else: result = InputFactory.createBlank(*args, **kwargs) @@ -326,7 +326,7 @@ def createBlank(*args, **kwargs): the users that the requested input field could not be constructed. """ - kind = kwargs.get("kind", "str") + kind = kwargs.get("kind", "String") base, layout = InputFactory.createBase( label=f"MISSING TYPE:{kind}", tooltip="This is not handled by the MDANSE GUI correctly! Please report the problem to the authors.", @@ -341,7 +341,7 @@ def createFile(*args, direction="in", **kwargs): direction -- if 'in', create a FileDialog for an exisitng file, if 'out', a FileDialog for creating a new file. """ - kind = kwargs.get("kind", "str") + kind = kwargs.get("kind", "String") default_value = kwargs.get("default", "") tooltip_text = kwargs.get("tooltip", "Specify a path to an existing file.") file_association = kwargs.get("wildcard", "") @@ -373,7 +373,7 @@ def createBool(*args, **kwargs): """Creates an input field for a logical variable, which is currently implemented as a check box. """ - kind = kwargs.get("kind", "bool") + kind = kwargs.get("kind", "Boolean") default_value = kwargs.get("default", False) tooltip_text = kwargs.get("tooltip", None) ic(kind) @@ -406,13 +406,13 @@ def createSingle(*args, **kwargs): ic(kwargs) base, layout = InputFactory.createBase(*args, **kwargs) field = QLineEdit(base) - if kind == "int" or kind == "integer": + if "Integer" in kind: data_handler = GeneralInput(data_type=int, **kwargs) validator = QIntValidator(field) - elif kind == "float": + elif "Float" in kind: data_handler = GeneralInput(data_type=float, **kwargs) validator = QDoubleValidator(field) - elif kind == "str": + else: data_handler = GeneralInput(data_type=str, **kwargs) validator = None if validator is not None: @@ -432,7 +432,7 @@ def createMultiple(*args, **kwargs): For numerical values, it adds a QValidator instance to filter out invalid inputs. """ - kind = kwargs.get("kind", "str") + kind = kwargs.get("kind", "String") default_value = kwargs.get("default", None) tooltip_text = kwargs.get("tooltip", None) minval = kwargs.get("mini", None) @@ -447,13 +447,13 @@ def createMultiple(*args, **kwargs): main_handler = InputGroup(base) for nfield in range(number_of_fields): field = QLineEdit(base) - if kind == "int" or kind == "integer": + if "Integer" in kind: data_handler = GeneralInput(data_type=int, **kwargs) validator = QIntValidator(field) - elif kind == "float": + elif "Float" in kind: data_handler = GeneralInput(data_type=float, **kwargs) validator = QDoubleValidator(field) - elif kind == "str": + else: data_handler = GeneralInput(data_type=str, **kwargs) validator = None if validator is not None: @@ -470,7 +470,7 @@ def createMultiple(*args, **kwargs): def createCombo(*args, **kwargs): """For the variable where one option has to be picked from a list of possible values, we create a ComboBox""" - kind = kwargs.get("kind", "str") + kind = kwargs.get("kind", "String") default_value = kwargs.get("default", False) tooltip_text = kwargs.get("tooltip", None) option_list = kwargs.get("choices", [])