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

Beta release 2024 #573

Merged
merged 23 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d56ea0e
Update version and logos before beta release
MBartkowiakSTFC Oct 10, 2024
30a16b3
Change version number in the documentation
MBartkowiakSTFC Oct 10, 2024
604d88e
Correct progress bar final value
MBartkowiakSTFC Oct 10, 2024
1dba67a
Correct Grid plotter with different axes
MBartkowiakSTFC Oct 10, 2024
2de7ab6
Merge branch 'protos' of https://github.com/ISISNeutronMuon/MDANSE in…
MBartkowiakSTFC Oct 11, 2024
d69b75f
Merge branch 'protos' of https://github.com/ISISNeutronMuon/MDANSE in…
MBartkowiakSTFC Oct 11, 2024
14f2458
Flip the Heatmap 2D plot to match the axes
MBartkowiakSTFC Oct 11, 2024
650bd37
Make LAMMPS converter read new trajectories
MBartkowiakSTFC Oct 14, 2024
c308c93
Correct ProjectionWidget error reporting
MBartkowiakSTFC Oct 14, 2024
23f813d
Reduce the log level of Action fail message
MBartkowiakSTFC Oct 14, 2024
c7a4a23
Clean up debug print messages
MBartkowiakSTFC Oct 14, 2024
19db6d3
Extend LAMMPS converter to work with atomic style
MBartkowiakSTFC Oct 14, 2024
4176a0a
Improve error output of the self van Hove function
MBartkowiakSTFC Oct 15, 2024
cd7924f
Solve issues #577 and #576
MBartkowiakSTFC Oct 15, 2024
b0649cd
Solve issue #580, remove cross from Preview tab
MBartkowiakSTFC Oct 15, 2024
d6946b2
Fix AverageStructure ASE Atom failing on isotopes
MBartkowiakSTFC Oct 15, 2024
95074f3
Correct the index dataset of RootMeanSquareFluctuation
MBartkowiakSTFC Oct 15, 2024
4b2966d
Enable multicore runs of Temperature analysis
MBartkowiakSTFC Oct 15, 2024
7c3191f
Highlight vectors in QVectorWidget with wrong number of elements
MBartkowiakSTFC Oct 15, 2024
46757a6
Introduce placeholder values in InstrumentDetails
MBartkowiakSTFC Oct 15, 2024
ff07fe8
Update the changelog. Disable PlotterTemplate for now
MBartkowiakSTFC Oct 15, 2024
0abac6f
fix to omega window plotting for IR job
ChiCheng45 Oct 15, 2024
dd68dd4
Correct the DensityProfile limits
MBartkowiakSTFC Oct 15, 2024
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
12 changes: 12 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
version 2.0.0b1 - 2024-10-15
--------------------------
* ADDED van Hove functions (self function and distinct function)
* FIXED Eccentricity analysis to give correct results
* ADDED Infrared analysis (only for molecules at the moment)
* FIXED MolecularTrace analysis data axes to make data plottable
* CHANGED the plotting interface to allow overplotting curves
* ADDED instrument profiles for storing user parameters
* ADDED logging in the code and a logger tab in the GUI
* ADDED charge information to the stored trajectory data
* ADDED support for H5MD trajectories

version 2.0.0 - 2024-02-15
--------------------------
* CHANGED programming language to Python 3
Expand Down
2 changes: 1 addition & 1 deletion Doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
# project = 'MDANSE'
# copyright = '2015-2022, Eric Pellegrini'
author = 'Eric Pellegrini'
release = '2.0.0a1'
release = '2.0.0b1'
version = '2.0'

# -- General configuration ---------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions Doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Welcome to MDANSE's documentation!
.. note::
This is the documentation of the MDANSE 2.0 release.
The documentation, just like the code itself, is still under development.
MDANSE 2 has currently (October 2024) just reached the first beta release.

**Useful links**: `MDANSE Project Website <https://www.isis.stfc.ac.uk/Pages/MDANSEproject.aspx>`_ | `MDANSE GitHub Page <https://github.com/ISISNeutronMuon/MDANSE>`_

Expand Down
41 changes: 23 additions & 18 deletions Doc/pages/H_start.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ Use `pip` to install the MDANSE package from the specified GitHub repository:

pip install MDANSE

The MDANSE package contains all the code needed to perform trajectory conversion
and analysis using MDANSE, but none of the visualisation tools.

Install MDANSE_GUI Package
~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand All @@ -66,14 +69,9 @@ Similarly, install the MDANSE_GUI package using `pip`:

pip install MDANSE_GUI

Run MDANSE
~~~~~~~~~~

You can now start using MDANSE by running the following command:

.. code-block:: bash

mdanse_gui
From now on, the `mdanse_gui` command will be available to start
the graphical interface of MDANSE, which makes it easier to create
valid inputs for different analysis types.

Run MDANSE
~~~~~~~~~~
Expand All @@ -84,13 +82,20 @@ You can now start using MDANSE by running the following command:

mdanse_gui

This will launch the MDANSE Graphical User Interface (GUI), and you can start using MDANSE for your
analysis.

Note for Windows Users: On Windows, the command to run MDANSE may need to be:

.. code-block:: bash

python3 mdanse_gui

That's it! You have successfully installed MDANSE and are ready to use it for your data analysis needs.
This will launch the MDANSE Graphical User Interface (GUI),
and you can start using MDANSE for your analysis.

MDANSE Scripts
~~~~~~~~~~~~~~

If you intend to run your analysis on a remote platform
(e.g. a cluster), most likely you will have limited options
of using the GUI there. However, you can still prepare
a script using MDANSE_GUI on your own computer, save it
and transfer it to the other computer to run the analysis
there. You will need to change the file paths in the script,
but all the other parameters should be transferable. One
of the design principles of MDANSE 2 is that the scripts
should not depend on any settings stored locally on
a specific computer, but should instead contain all the
information needed to run a specific analysis type.
Binary file removed MDANSE/Doc/_static/mdanse_logo.png
Binary file not shown.
2 changes: 1 addition & 1 deletion MDANSE/Doc/conf_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
# The full version, including alpha/beta/rc tags.
release = "1.0"

html_logo = "_static/mdanse_logo.png"
# html_logo = "_static/mdanse_logo.png"

inheritance_graph_attrs = dict(size='""')

Expand Down
2 changes: 1 addition & 1 deletion MDANSE/Doc/conf_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
# The full version, including alpha/beta/rc tags.
release = "1.0"

html_logo = "_static/mdanse_logo.png"
# html_logo = "_static/mdanse_logo.png"

inheritance_graph_attrs = dict(size='""')

Expand Down
Binary file removed MDANSE/Doc/mdanse_logo.png
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,42 @@ def parse(self):
self["bonds"].append([at1, at2])
self["bonds"] = np.array(self["bonds"], dtype=np.int32)

if re.match("^\s*Atoms\s*$", line):
if re.match("^\s*Atoms\s*$", line.split("#")[0]):
if not "#" in line:
num_of_columns = len(lines[i + 2].split())
if num_of_columns <= 5:
type_index = 1
charge_index = None
line_limit = 6
else:
type_index = 2
charge_index = 3
line_limit = 7
else:
if "charge" in line.split("#")[-1]:
type_index = 1
charge_index = 2
line_limit = 6
elif "atomic" in line.split("#")[-1]:
type_index = 1
charge_index = None
line_limit = 6
elif "full" in line.split("#")[-1]:
type_index = 2
charge_index = 3
line_limit = 7
else:
type_index = 2
charge_index = 3
line_limit = 7
if self["n_atoms"] is not None:
self["atom_types"] = self["n_atoms"] * [0]
self["charges"] = self["n_atoms"] * [0.0]
for j in range(self["n_atoms"]):
atoks = lines[i + j + 1].split()
self["atom_types"][j] = int(atoks[2])
if len(atoks) >= 7:
self["charges"][j] = float(atoks[3])
self["atom_types"][j] = int(atoks[type_index])
if len(atoks) >= line_limit and charge_index is not None:
self["charges"][j] = float(atoks[charge_index])

if np.trace(np.abs(self["unit_cell"])) < 1e-8:
# print(f"Concatenated: {np.concatenate([x_inputs, y_inputs, z_inputs])}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
from abc import abstractmethod
import traceback

from MDANSE.Framework.AtomMapping import AtomLabel
from .InputFileConfigurator import InputFileConfigurator
Expand All @@ -35,7 +36,7 @@ def configure(self, filepath: str) -> None:
try:
self.parse()
except Exception as e:
self.error_status = "File parsing error"
self.error_status = f"File parsing error {e}: {traceback.format_exc()}"

@abstractmethod
def parse(self) -> None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,13 @@ def configure(self, value):
elements = []
masses = []
names = []
group_indices = []
for i, v in enumerate(groups.values()):
names.append("group_%d" % i)
elements.append(v["elements"])
indexes.append(v["indexes"])
masses.append(v["masses"])
group_indices.append(i)

atomSelectionConfig["indexes"] = indexes
atomSelectionConfig["elements"] = elements
Expand All @@ -145,6 +147,7 @@ def configure(self, value):
atomSelectionConfig["unique_names"] = sorted(set(atomSelectionConfig["names"]))

self["level"] = value
self["group_indices"] = group_indices

@staticmethod
def find_parent(atom, level):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#

import numpy as np

from MDANSE.Framework.Configurators.IConfigurator import IConfigurator
from MDANSE.Framework.Projectors.IProjector import IProjector
Expand Down Expand Up @@ -62,13 +63,26 @@ def configure(self, value):
self.error_status = f"the projector {mode} is unknown"
return
else:
if mode == "NullProjector":
self.error_status = "OK"
return
try:
self["projector"].set_axis(axis)
vector = [float(x) for x in axis]
except ValueError:
self.error_status = f"Could not convert {axis} to numbers"
return
else:
if np.allclose(vector, 0):
self.error_status = f"Vector of 0 length does not define projection"
return
try:
self["projector"].set_axis(vector)
except ProjectorError:
self.error_status = f"Axis {axis} is wrong for this projector"
self.error_status = f"Axis {vector} is wrong for this projector"
return
else:
self["axis"] = self["projector"].axis

self.error_status = "OK"

def get_information(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,14 @@ def configure(self, value):
return

try:
generator.generate()
generator_success = generator.generate()
except:
self.error_status = "Q Vector parameters were parsed correctly, but caused an error. Invalid values?"
return
else:
if not generator_success:
self.error_status = "Q Vector parameters were parsed correctly, but caused an error. Invalid values?"
return

if not "q_vectors" in generator.configuration:
self.error_status = "Wrong inputs for q-vector generation. At the moment there are no valid Q points."
Expand Down
43 changes: 37 additions & 6 deletions MDANSE/Src/MDANSE/Framework/Converters/LAMMPS.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,18 @@ def parse_first_step(self, aliases, config):
elif line.startswith("ITEM: ATOMS"):
keywords = line.split()[2:]

self._id = keywords.index("id")
self._type = keywords.index("type")
if "id" in keywords:
self._id = keywords.index("id")
else:
self._id = None
if "type" in keywords:
self._type = keywords.index("type")
else:
self._type = None
if "element" in keywords:
self._element = keywords.index("element")
else:
self._element = None
try:
self._charge = keywords.index("q")
except ValueError:
Expand Down Expand Up @@ -194,12 +204,28 @@ def parse_first_step(self, aliases, config):
self._itemsPosition["ATOMS"] = [comp + 1, comp + self._nAtoms + 1]
for i in range(self._nAtoms):
temp = self._file.readline().split()
idx = int(temp[self._id]) - 1
ty = int(temp[self._type]) - 1
if self._id is not None:
idx = int(temp[self._id]) - 1
else:
idx = int(i)
if self._type is not None:
ty = int(temp[self._type]) - 1
else:
try:
ty = int(config["atom_types"][i]) - 1
except IndexError:
LOG.error(
f"Failed to find index [{i}] in list of len {len(config['atom_types'])}"
)
label = str(config["elements"][ty][0])
mass = str(config["elements"][ty][1])
name = "{:s}_{:d}".format(str(config["elements"][ty][0]), idx)
self._rankToName[int(temp[0]) - 1] = name
try:
temp_index = int(temp[0])
except ValueError:
self._rankToName[i] = name
else:
self._rankToName[temp_index - 1] = name
g.add_node(idx, label=label, mass=mass, atomName=name)

if config["n_bonds"] is not None:
Expand Down Expand Up @@ -335,7 +361,12 @@ def run_step(self, index):
range(self._itemsPosition["ATOMS"][0], self._itemsPosition["ATOMS"][1])
):
temp = self._file.readline().split()
idx = self._nameToIndex[self._rankToName[int(temp[0]) - 1]]
try:
temp_index = int(temp[0])
except ValueError:
idx = i
else:
idx = self._nameToIndex[self._rankToName[temp_index - 1]]
coords[idx, :] = np.array(
[temp[self._x], temp[self._y], temp[self._z]], dtype=np.float64
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def put_into_dict(name, obj):
try:
string = obj[:][0].decode()
except:
LOG.warning(f"Decode failed for {name}: {obj}")
LOG.debug(f"Decode failed for {name}: {obj}")
else:
try:
meta_dict[name] = json_decoder.decode(string)
Expand Down
37 changes: 25 additions & 12 deletions MDANSE/Src/MDANSE/Framework/Jobs/AverageStructure.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,26 @@ def initialize(self):

self._ase_atoms = Atoms()

trajectory = self.configuration["trajectory"]["instance"]

frame_range = range(
self.configuration["frames"]["first"],
self.configuration["frames"]["last"] + 1,
self.configuration["frames"]["step"],
)

try:
unit_cells = [
trajectory.unit_cell(frame)._unit_cell for frame in frame_range
]
except:
raise ValueError(
"Unit cell needs to be defined for the AverageStructure analysis. "
"You can add a unit cell using TrajectoryEditor."
)
else:
self._unit_cells = unit_cells

def run_step(self, index):
"""
Runs a single step of the job.
Expand Down Expand Up @@ -135,7 +155,10 @@ def combine(self, index, x):
# The symbol of the atom.
element = self.configuration["atom_selection"]["names"][index]

the_atom = Atom(element, x)
try:
the_atom = Atom(element, x)
except KeyError:
the_atom = Atom(str(element).strip("0123456789"), x)

self._ase_atoms.append(the_atom)

Expand All @@ -152,17 +175,7 @@ def finalize(self):
self.configuration["frames"]["step"],
)

try:
unit_cells = [
trajectory.unit_cell(frame)._unit_cell for frame in frame_range
]
except:
raise ValueError(
"Unit cell needs to be defined for the AverageStructure analysis. "
"You can add a unit cell using TrajectoryEditor."
)

average_unit_cell = np.mean(unit_cells, axis=0) * self._conversion_factor
average_unit_cell = np.mean(self._unit_cells, axis=0) * self._conversion_factor

self._ase_atoms.set_cell(average_unit_cell)

Expand Down
3 changes: 2 additions & 1 deletion MDANSE/Src/MDANSE/Framework/Jobs/DensityProfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ def run_step(self, index):
conf = self.configuration["trajectory"]["instance"].configuration(frame_index)

box_coords = conf.to_box_coordinates()
box_coords = box_coords - np.floor(box_coords)

axis_index = self.configuration["axis"]["index"]
axis = conf.unit_cell.direct[axis_index, :]
Expand All @@ -146,7 +147,7 @@ def run_step(self, index):

for k, v in self._indexes_per_element.items():
h = np.histogram(
box_coords[v, axis_index], bins=self._n_bins, range=[-0.5, 0.5]
box_coords[v, axis_index], bins=self._n_bins, range=[0.0, 1.0]
)
dp_per_frame[k] = h[0]

Expand Down
Loading