moreniius 0.5.1__tar.gz → 0.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. {moreniius-0.5.1 → moreniius-0.6.0}/.github/workflows/pip.yml +1 -1
  2. {moreniius-0.5.1/src/moreniius.egg-info → moreniius-0.6.0}/PKG-INFO +3 -3
  3. {moreniius-0.5.1 → moreniius-0.6.0}/pyproject.toml +3 -4
  4. {moreniius-0.5.1 → moreniius-0.6.0}/src/moreniius/mccode/mccode.py +36 -10
  5. {moreniius-0.5.1 → moreniius-0.6.0}/src/moreniius/moreniius.py +4 -2
  6. {moreniius-0.5.1 → moreniius-0.6.0}/src/moreniius/writer.py +13 -4
  7. {moreniius-0.5.1 → moreniius-0.6.0/src/moreniius.egg-info}/PKG-INFO +3 -3
  8. {moreniius-0.5.1 → moreniius-0.6.0}/src/moreniius.egg-info/requires.txt +2 -1
  9. {moreniius-0.5.1 → moreniius-0.6.0}/tests/test_nexus_structure.py +3 -3
  10. {moreniius-0.5.1 → moreniius-0.6.0}/.github/workflows/wheels.yml +0 -0
  11. {moreniius-0.5.1 → moreniius-0.6.0}/.gitignore +0 -0
  12. {moreniius-0.5.1 → moreniius-0.6.0}/README.md +0 -0
  13. {moreniius-0.5.1 → moreniius-0.6.0}/setup.cfg +0 -0
  14. {moreniius-0.5.1 → moreniius-0.6.0}/src/moreniius/__init__.py +0 -0
  15. {moreniius-0.5.1 → moreniius-0.6.0}/src/moreniius/additions.py +0 -0
  16. {moreniius-0.5.1 → moreniius-0.6.0}/src/moreniius/mccode/__init__.py +0 -0
  17. {moreniius-0.5.1 → moreniius-0.6.0}/src/moreniius/mccode/comp.py +0 -0
  18. {moreniius-0.5.1 → moreniius-0.6.0}/src/moreniius/mccode/instance.py +0 -0
  19. {moreniius-0.5.1 → moreniius-0.6.0}/src/moreniius/mccode/instr.py +0 -0
  20. {moreniius-0.5.1 → moreniius-0.6.0}/src/moreniius/mccode/orientation.py +0 -0
  21. {moreniius-0.5.1 → moreniius-0.6.0}/src/moreniius/nexus_structure.py +0 -0
  22. {moreniius-0.5.1 → moreniius-0.6.0}/src/moreniius/nxoff.py +0 -0
  23. {moreniius-0.5.1 → moreniius-0.6.0}/src/moreniius/utils.py +0 -0
  24. {moreniius-0.5.1 → moreniius-0.6.0}/src/moreniius.egg-info/SOURCES.txt +0 -0
  25. {moreniius-0.5.1 → moreniius-0.6.0}/src/moreniius.egg-info/dependency_links.txt +0 -0
  26. {moreniius-0.5.1 → moreniius-0.6.0}/src/moreniius.egg-info/entry_points.txt +0 -0
  27. {moreniius-0.5.1 → moreniius-0.6.0}/src/moreniius.egg-info/top_level.txt +0 -0
  28. {moreniius-0.5.1 → moreniius-0.6.0}/tests/test_motorized_positions.py +0 -0
@@ -15,7 +15,7 @@ jobs:
15
15
  fail-fast: false
16
16
  matrix:
17
17
  platform: [windows-latest, macos-latest, ubuntu-latest]
18
- python-version: ["3.9", "3.10", "3.11", "3.12"]
18
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
19
19
 
20
20
  steps:
21
21
  - uses: actions/checkout@v4
@@ -1,12 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: moreniius
3
- Version: 0.5.1
3
+ Version: 0.6.0
4
4
  Author-email: Gregory Tucker <gregory.tucker@ess.eu>
5
5
  Classifier: License :: OSI Approved :: BSD License
6
6
  Classifier: Development Status :: 2 - Pre-Alpha
7
7
  Classifier: Programming Language :: Python :: 3
8
8
  Classifier: Programming Language :: Python :: 3 :: Only
9
- Classifier: Programming Language :: Python :: 3.9
10
9
  Classifier: Programming Language :: Python :: 3.10
11
10
  Classifier: Programming Language :: Python :: 3.11
12
11
  Classifier: Programming Language :: Python :: 3.12
@@ -14,8 +13,9 @@ Classifier: Programming Language :: Python :: 3.13
14
13
  Description-Content-Type: text/markdown
15
14
  Requires-Dist: zenlog>=1.1
16
15
  Requires-Dist: platformdirs>=3.11
17
- Requires-Dist: mccode-antlr[hdf5]>=0.15.1
16
+ Requires-Dist: mccode-antlr[hdf5]>=0.16.1
18
17
  Requires-Dist: nexusformat>=1.0.6
18
+ Requires-Dist: networkx
19
19
 
20
20
  # moreniius
21
21
  A project to contain custom components required to use `eniius` to produce `NeXus Structure` `JSON` from `mccode-antlr` simulated instruments.
@@ -7,8 +7,9 @@ name = "moreniius"
7
7
  dependencies = [
8
8
  'zenlog>=1.1',
9
9
  'platformdirs>=3.11',
10
- 'mccode-antlr[hdf5]>=0.15.1',
11
- 'nexusformat>=1.0.6'
10
+ 'mccode-antlr[hdf5]>=0.16.1',
11
+ 'nexusformat>=1.0.6',
12
+ 'networkx'
12
13
  ]
13
14
  readme = "README.md"
14
15
  authors = [
@@ -19,7 +20,6 @@ classifiers = [
19
20
  "Development Status :: 2 - Pre-Alpha",
20
21
  "Programming Language :: Python :: 3",
21
22
  "Programming Language :: Python :: 3 :: Only",
22
- "Programming Language :: Python :: 3.9",
23
23
  "Programming Language :: Python :: 3.10",
24
24
  "Programming Language :: Python :: 3.11",
25
25
  "Programming Language :: Python :: 3.12",
@@ -41,7 +41,6 @@ legacy_tox_ini = """
41
41
  py312
42
42
  py311
43
43
  py310
44
- py39
45
44
  type
46
45
 
47
46
  [testenv]
@@ -1,5 +1,7 @@
1
1
  from zenlog import log
2
2
  from dataclasses import dataclass, field
3
+ from networkx import DiGraph
4
+ from typing import Union
3
5
  from mccode_antlr.instr import Orient
4
6
  from .instr import NXInstr
5
7
 
@@ -9,9 +11,11 @@ log.level('error')
9
11
  @dataclass
10
12
  class NXMcCode:
11
13
  nx_instr: NXInstr
12
- origin_name: str = None
14
+ origin_name: Union[str, None] = None
13
15
  indexes: dict[str, int] = field(default_factory=dict)
14
16
  orientations: dict[str, Orient] = field(default_factory=dict)
17
+ graph: Union[DiGraph, None] = None
18
+ reversed_graph: Union[DiGraph, None] = None
15
19
 
16
20
  def __post_init__(self):
17
21
  from copy import deepcopy
@@ -37,30 +41,52 @@ class NXMcCode:
37
41
  for name in self.orientations:
38
42
  self.orientations[name] = self.orientations[name] - origin
39
43
 
44
+ if self.graph is None:
45
+ self.graph = self.build_graph()
46
+ if self.reversed_graph is None:
47
+ self.reversed_graph = self.graph.reverse(copy=True)
48
+
40
49
  def transformations(self, name):
41
50
  from .orientation import NXOrient
42
51
  return NXOrient(self.nx_instr, self.orientations[name]).transformations(name)
43
52
 
53
+ def inputs(self, name):
54
+ """Return the other end of edges ending at the named node"""
55
+ return list(self.reversed_graph[name])
56
+
57
+ def outputs(self, name):
58
+ """Return the other end of edges starting at the named node"""
59
+ return list(self.graph[name])
60
+
44
61
  def component(self, name, only_nx=True):
45
62
  """Return a NeXus NXcomponent corresponding to the named McStas component instance"""
46
63
  from .instance import NXInstance
47
64
  instance = self.nx_instr.instr.components[self.indexes[name]]
48
65
  transformations = self.transformations(name)
49
- nx = NXInstance(self.nx_instr, instance, self.indexes[name], transformations, only_nx=only_nx)
50
- if transformations and nx.nx['transformations'] != transformations:
66
+ nxinst = NXInstance(self.nx_instr, instance, self.indexes[name], transformations, only_nx=only_nx)
67
+ if transformations and nxinst.nx['transformations'] != transformations:
51
68
  # if the component modifed the transformations group, make sure we don't use our version again
52
69
  del self.orientations[name]
53
- return nx
70
+ if len(inputs := self.inputs(name)):
71
+ nxinst.nx.attrs['inputs'] = inputs
72
+ if len(outputs := self.outputs(name)):
73
+ nxinst.nx.attrs['outputs'] = outputs
74
+ return nxinst
54
75
 
55
76
  def instrument(self, only_nx=True):
56
- from .instr import NXInstr
57
77
  from nexusformat.nexus import NXinstrument
58
78
  nx = NXinstrument() # this is a NeXus class
59
79
  nx['mcstas'] = self.nx_instr.to_nx()
60
- # hack the McCode component index into the name of the NeXus group
61
- width = len(str(max(self.indexes.values())))
62
- for name, index in self.indexes.items():
63
- nx_name = f'{index:0{width}d}_{name}'
64
- nx[nx_name] = self.component(name, only_nx=only_nx).nx
80
+ for name in self.indexes.keys():
81
+ nx[name] = self.component(name, only_nx=only_nx).nx
65
82
 
66
83
  return nx
84
+
85
+ def build_graph(self):
86
+ # FIXME expand this to a full-description if/when McCode includes graph information
87
+ graph = DiGraph()
88
+ names = [x.name for x in self.nx_instr.instr.components]
89
+ graph.add_nodes_from(names)
90
+ # By default, any McCode instrument is a linear object:
91
+ graph.add_edges_from([(names[i], names[i+1]) for i in range(len(names)-1)])
92
+ return graph
@@ -1,4 +1,5 @@
1
1
  from __future__ import annotations
2
+ from networkx import Graph
2
3
  from mccode_antlr.instr import Instr
3
4
 
4
5
 
@@ -13,12 +14,13 @@ class MorEniius:
13
14
  origin: str | None = None,
14
15
  only_nx: bool = False,
15
16
  nxlog_root: str | None = None,
16
- absolute_depends_on: bool = False
17
+ absolute_depends_on: bool = False,
18
+ graph: Graph | None = None,
17
19
  ):
18
20
  from nexusformat.nexus import NXfield
19
21
  from .mccode import NXMcCode, NXInstr
20
22
  nxlog_root = nxlog_root or '/entry/parameters'
21
- nx_mccode = NXMcCode(NXInstr(instr, nxlog_root=nxlog_root), origin_name=origin)
23
+ nx_mccode = NXMcCode(NXInstr(instr, nxlog_root=nxlog_root), origin_name=origin, graph=graph)
22
24
  nxs_obj = nx_mccode.instrument(only_nx=only_nx)
23
25
  nxs_obj['name'] = NXfield(value=instr.name)
24
26
  return cls(nxs_obj, only_nx=only_nx, absolute_depends_on=absolute_depends_on)
@@ -2,7 +2,7 @@ from zenlog import log
2
2
 
3
3
 
4
4
  def convert_types(obj, only_nx=True):
5
- from numpy import dtype, ndarray
5
+ from numpy import dtype, ndarray, array
6
6
  from nexusformat.nexus import NXattr
7
7
  py_data_type = type(obj)
8
8
  np_data_type = dtype(py_data_type)
@@ -24,11 +24,16 @@ def convert_types(obj, only_nx=True):
24
24
  val = val.tolist()
25
25
  if obj.dtype == 'object':
26
26
  (tp, vl) = (dtype(type(obj.nxdata)).name, val)
27
+ # If still 'object', this will throw an error below
28
+ if tp == 'object' and isinstance(val, list):
29
+ tp = dtype(type(val[0])).name
27
30
  else:
28
31
  (tp, vl) = (obj.dtype, val)
29
32
  elif not only_nx and hasattr(obj, 'to_json_dict'):
30
33
  # Shoe-horn in an object-defined dictionary:
31
34
  tp, vl = None, obj.to_json_dict()
35
+ elif isinstance(obj, list):
36
+ return convert_types(array(obj))
32
37
  else:
33
38
  raise RuntimeError(f'unrecognised type {py_data_type} / {np_data_type} for {repr(obj)}')
34
39
  else:
@@ -38,7 +43,7 @@ def convert_types(obj, only_nx=True):
38
43
  elif tp == 'float64':
39
44
  tp = 'double'
40
45
  elif tp == 'object':
41
- raise RuntimeError(f'Internal logical error attempting to convert {obj}')
46
+ raise RuntimeError(f'Internal logical error attempting to convert {obj} of type {type(obj)}')
42
47
  elif tp == 'int':
43
48
  tp = 'int64'
44
49
  elif tp == 'float':
@@ -124,8 +129,12 @@ class Writer:
124
129
  attrs = [dict(name='NX_class', dtype='string', values=obj.nxclass)]
125
130
  if len(list(obj)):
126
131
  entry['children'] = self._to_json_dict(obj, only_nx=only_nx, absolute_depends_on=absolute_depends_on)
127
- for n, v in obj.attrs.items():
128
- typ, val = convert_types(v, only_nx)
132
+ for n in obj.attrs:
133
+ typ, val = convert_types(obj.attrs[n], only_nx)
134
+ # FIXME accessing an attribute value via the dict values gives
135
+ # a NXattr object *not* the underlying value!?
136
+ # for n, v in obj.attrs.items():
137
+ # typ, val = convert_types(v, only_nx)
129
138
  if absolute_depends_on and n == 'depends_on' and '/' != val[0]:
130
139
  val = _to_absolute(top_obj.nxpath, val)
131
140
  attrs.append(dict(name=n, dtype=typ, values=val) if typ else val)
@@ -1,12 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: moreniius
3
- Version: 0.5.1
3
+ Version: 0.6.0
4
4
  Author-email: Gregory Tucker <gregory.tucker@ess.eu>
5
5
  Classifier: License :: OSI Approved :: BSD License
6
6
  Classifier: Development Status :: 2 - Pre-Alpha
7
7
  Classifier: Programming Language :: Python :: 3
8
8
  Classifier: Programming Language :: Python :: 3 :: Only
9
- Classifier: Programming Language :: Python :: 3.9
10
9
  Classifier: Programming Language :: Python :: 3.10
11
10
  Classifier: Programming Language :: Python :: 3.11
12
11
  Classifier: Programming Language :: Python :: 3.12
@@ -14,8 +13,9 @@ Classifier: Programming Language :: Python :: 3.13
14
13
  Description-Content-Type: text/markdown
15
14
  Requires-Dist: zenlog>=1.1
16
15
  Requires-Dist: platformdirs>=3.11
17
- Requires-Dist: mccode-antlr[hdf5]>=0.15.1
16
+ Requires-Dist: mccode-antlr[hdf5]>=0.16.1
18
17
  Requires-Dist: nexusformat>=1.0.6
18
+ Requires-Dist: networkx
19
19
 
20
20
  # moreniius
21
21
  A project to contain custom components required to use `eniius` to produce `NeXus Structure` `JSON` from `mccode-antlr` simulated instruments.
@@ -1,4 +1,5 @@
1
1
  zenlog>=1.1
2
2
  platformdirs>=3.11
3
- mccode-antlr[hdf5]>=0.15.1
3
+ mccode-antlr[hdf5]>=0.16.1
4
4
  nexusformat>=1.0.6
5
+ networkx
@@ -28,7 +28,7 @@ class NexusStrctureTestCase(unittest.TestCase):
28
28
  END
29
29
  """
30
30
  self.instr = parse_mcstas_instr(instr)
31
- self.structures = {'2_mon0': m0, '5_mon1': m1}
31
+ self.structures = {'mon0': m0, 'mon1': m1}
32
32
 
33
33
  def test_moreniius(self):
34
34
  from moreniius import MorEniius
@@ -72,7 +72,7 @@ class NexusStrctureTestCase(unittest.TestCase):
72
72
  nx = nx['children'][3]
73
73
  for x in group_keys:
74
74
  self.assertTrue(x in nx)
75
- self.assertEqual(nx['name'], '2_mon0')
75
+ self.assertEqual(nx['name'], 'mon0')
76
76
  self.assertEqual(len(nx['children']), 4) # removed mcstas child
77
77
  nx = nx['children'][1] # this is now a NXdata group
78
78
  self.assertTrue('attributes' in nx)
@@ -80,7 +80,7 @@ class NexusStrctureTestCase(unittest.TestCase):
80
80
  self.assertEqual(nx['attributes'][0]['name'], 'NX_class')
81
81
  self.assertEqual(nx['attributes'][0]['values'], 'NXdata')
82
82
  nx = nx['children'][0]
83
- self.assertEqual(self.structures['2_mon0'], nx)
83
+ self.assertEqual(self.structures['mon0'], nx)
84
84
 
85
85
 
86
86
  if __name__ == '__main__':
File without changes
File without changes
File without changes