moreniius 0.2.3__tar.gz → 0.2.5__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 (29) hide show
  1. {moreniius-0.2.3 → moreniius-0.2.5}/.github/workflows/pip.yml +1 -1
  2. {moreniius-0.2.3 → moreniius-0.2.5}/.github/workflows/wheels.yml +3 -3
  3. {moreniius-0.2.3/src/moreniius.egg-info → moreniius-0.2.5}/PKG-INFO +3 -3
  4. {moreniius-0.2.3 → moreniius-0.2.5}/pyproject.toml +1 -1
  5. {moreniius-0.2.3 → moreniius-0.2.5}/src/moreniius/mccode/instr.py +27 -5
  6. {moreniius-0.2.3 → moreniius-0.2.5}/src/moreniius/mccode/orientation.py +1 -2
  7. {moreniius-0.2.3 → moreniius-0.2.5}/src/moreniius/utils.py +19 -2
  8. {moreniius-0.2.3 → moreniius-0.2.5}/src/moreniius/writer.py +0 -2
  9. {moreniius-0.2.3 → moreniius-0.2.5/src/moreniius.egg-info}/PKG-INFO +3 -3
  10. {moreniius-0.2.3 → moreniius-0.2.5}/src/moreniius.egg-info/requires.txt +1 -1
  11. moreniius-0.2.5/tests/test_motorized_positions.py +111 -0
  12. moreniius-0.2.3/tests/test_motorized_positions.py +0 -24
  13. {moreniius-0.2.3 → moreniius-0.2.5}/.gitignore +0 -0
  14. {moreniius-0.2.3 → moreniius-0.2.5}/README.md +0 -0
  15. {moreniius-0.2.3 → moreniius-0.2.5}/setup.cfg +0 -0
  16. {moreniius-0.2.3 → moreniius-0.2.5}/src/moreniius/__init__.py +0 -0
  17. {moreniius-0.2.3 → moreniius-0.2.5}/src/moreniius/additions.py +0 -0
  18. {moreniius-0.2.3 → moreniius-0.2.5}/src/moreniius/mccode/__init__.py +0 -0
  19. {moreniius-0.2.3 → moreniius-0.2.5}/src/moreniius/mccode/comp.py +0 -0
  20. {moreniius-0.2.3 → moreniius-0.2.5}/src/moreniius/mccode/instance.py +0 -0
  21. {moreniius-0.2.3 → moreniius-0.2.5}/src/moreniius/mccode/mccode.py +0 -0
  22. {moreniius-0.2.3 → moreniius-0.2.5}/src/moreniius/moreniius.py +0 -0
  23. {moreniius-0.2.3 → moreniius-0.2.5}/src/moreniius/nexus_structure.py +0 -0
  24. {moreniius-0.2.3 → moreniius-0.2.5}/src/moreniius/nxoff.py +0 -0
  25. {moreniius-0.2.3 → moreniius-0.2.5}/src/moreniius.egg-info/SOURCES.txt +0 -0
  26. {moreniius-0.2.3 → moreniius-0.2.5}/src/moreniius.egg-info/dependency_links.txt +0 -0
  27. {moreniius-0.2.3 → moreniius-0.2.5}/src/moreniius.egg-info/entry_points.txt +0 -0
  28. {moreniius-0.2.3 → moreniius-0.2.5}/src/moreniius.egg-info/top_level.txt +0 -0
  29. {moreniius-0.2.3 → moreniius-0.2.5}/tests/test_nexus_structure.py +0 -0
@@ -20,7 +20,7 @@ jobs:
20
20
  steps:
21
21
  - uses: actions/checkout@v4
22
22
 
23
- - uses: actions/setup-python@v4
23
+ - uses: actions/setup-python@v5
24
24
  with:
25
25
  python-version: ${{ matrix.python-version }}
26
26
 
@@ -26,7 +26,7 @@ jobs:
26
26
  - name: Check metadata
27
27
  run: pipx run twine check dist/*
28
28
 
29
- - uses: actions/upload-artifact@v3
29
+ - uses: actions/upload-artifact@v4
30
30
  with:
31
31
  path: dist/*
32
32
 
@@ -42,9 +42,9 @@ jobs:
42
42
  if: github.event_name == 'release' && github.event.action == 'published'
43
43
 
44
44
  steps:
45
- - uses: actions/setup-python@v4
45
+ - uses: actions/setup-python@v5
46
46
 
47
- - uses: actions/download-artifact@v3
47
+ - uses: actions/download-artifact@v4
48
48
  with:
49
49
  name: artifact
50
50
  path: dist
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: moreniius
3
- Version: 0.2.3
3
+ Version: 0.2.5
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
@@ -8,7 +8,7 @@ Description-Content-Type: text/markdown
8
8
  Requires-Dist: zenlog>=1.1
9
9
  Requires-Dist: platformdirs>=3.11
10
10
  Requires-Dist: importlib_metadata; python_version < "3.8"
11
- Requires-Dist: mccode-antlr[hdf5]>=0.7.1
11
+ Requires-Dist: mccode-antlr[hdf5]>=0.9.2
12
12
  Requires-Dist: nexusformat>=1.0.6
13
13
 
14
14
  # moreniius
@@ -8,7 +8,7 @@ dependencies = [
8
8
  'zenlog>=1.1',
9
9
  'platformdirs>=3.11',
10
10
  "importlib_metadata; python_version<'3.8'",
11
- 'mccode-antlr[hdf5]>=0.7.1',
11
+ 'mccode-antlr[hdf5]>=0.9.2',
12
12
  'nexusformat>=1.0.6'
13
13
  ]
14
14
  readme = "README.md"
@@ -2,7 +2,7 @@ from zenlog import log
2
2
  from dataclasses import dataclass, field
3
3
  from mccode_antlr.instr import Instr
4
4
  from mccode_antlr.common import Expr
5
- from nexusformat.nexus import NXfield, NXcollection
5
+ from nexusformat.nexus import NXfield, NXgroup, NXcollection
6
6
 
7
7
 
8
8
  @dataclass
@@ -15,7 +15,8 @@ class NXInstr:
15
15
  """Start the C translation to ensure McCode-oddities are handled before any C-code parsing."""
16
16
  from mccode_antlr.common import ShapeType, DataType, Value
17
17
  from mccode_antlr.translators.target import MCSTAS_GENERATOR
18
- from mccode_antlr.translators.c import CTargetVisitor, CDeclaration
18
+ from mccode_antlr.translators.c import CTargetVisitor
19
+ from mccode_antlr.translators.c_listener import CDeclarator
19
20
  from mccode_antlr.translators.c_listener import evaluate_c_defined_expressions
20
21
  config = dict(default_main=True, enable_trace=False, portable=False, include_runtime=True,
21
22
  embed_instrument_file=False, verbose=False, output=None)
@@ -25,9 +26,9 @@ class NXInstr:
25
26
  # translator.component_uservars is a dictionary of lists for each component type of `CDeclaration` objects.
26
27
 
27
28
  # only worry about instrument level variables for the moment, and convert the CDeclarations into Expr objects
28
- def c_declaration_to_expr(dec: CDeclaration) -> Expr:
29
+ def c_declaration_to_expr(dec: CDeclarator) -> Expr:
29
30
  expr = Expr(Value(None)) if dec.init is None else Expr.parse(dec.init)
30
- expr.data_type = DataType.from_name(dec.type)
31
+ expr.data_type = DataType.from_name(dec.dtype)
31
32
  if dec.is_pointer or dec.is_array:
32
33
  expr.shape_type = ShapeType.vector
33
34
  return expr
@@ -83,8 +84,29 @@ class NXInstr:
83
84
  'expression' in nx_args[0]:
84
85
  not_expr = [x for x in nx_args[0] if x != 'expression']
85
86
  if len(not_expr) == 1:
87
+ not_expr_arg = nx_args[0][not_expr[0]]
88
+ # if isinstance(not_expr_arg, NXfield):
89
+ # # We have and want an NXfield, but it might be missing attributes specified in the nx_kwargs
90
+ # # Passing the keywords to the NXfield constructor versus this method is not identical,
91
+ # # since some keyword arguments are reserved (and only some of which are noted)
92
+ # # Explicit keywords, used in the constructor:
93
+ # # value, name, shape, dtype, group, attrs
94
+ # # Keywords extracted from the kwargs dict, if present (and all controlling HDF5 file attributes?):
95
+ # # chunks, compression, compression_opts, fillvalue, fletcher32, maxshape, scaleoffset, shuffle
96
+ # # For now, just assume all keywords provided here are _actually_ attributes for the NXfield
97
+ # # which is an extension of a dict, but can *not* use the update method, since the __setitem__
98
+ # # method is overridden to wrap inputs in NXattr objects :/
99
+ # for k, v in nx_kwargs.items():
100
+ # not_expr_arg.attrs[k] = v
101
+ # return not_expr_arg
102
+
86
103
  # TODO make this return an nx_class once we're sure that nx_kwargs is parseable (no mccode_antlr.Expr)
87
- return nx_class(nx_args[0][not_expr[0]], **nx_kwargs)
104
+ if all(x in not_expr_arg for x in ('module', 'config')):
105
+ # This is a file-writer stream directive? So make a group
106
+ return NXgroup(entries={not_expr[0]: not_expr_arg}, **nx_kwargs)
107
+ print('!!')
108
+ print(not_expr_arg)
109
+ return nx_class(not_expr_arg, **nx_kwargs)
88
110
  else:
89
111
  raise RuntimeError('Not sure what I should do here')
90
112
  return nx_class(*nx_args, **nx_kwargs)
@@ -18,6 +18,7 @@ class NXPart:
18
18
  return self.instr.make_nx(nx_class, *args, **kwargs)
19
19
 
20
20
  def make_translation(self, norm, vec, dep):
21
+ # if `norm` is a link or NXlog, we should make a group not an NXfield
21
22
  return self.make_nx(NXfield, norm, vector=vec, depends_on=dep, transformation_type='translation', units='m')
22
23
 
23
24
  def translations(self, dep: str, name: str) -> list[tuple[str, NXfield]]:
@@ -28,7 +29,6 @@ class NXPart:
28
29
  pos = self.o.position()
29
30
  if any(isinstance(c, (Expr, Value)) for c in (pos.x, pos.y, pos.z)):
30
31
  translations = []
31
- print(f'{pos.x=} {pos.y=} {pos.z=}')
32
32
  for n, c, v in (('x', pos.x, [1, 0, 0]), ('y', pos.y, [0, 1, 0]), ('z', pos.z, [0, 0, 1])):
33
33
  if c != Expr.parse('0'):
34
34
  next_name = f'{name}_{n}'
@@ -51,7 +51,6 @@ class NXPart:
51
51
  print(repr(self.o))
52
52
  raise NotImplementedError()
53
53
 
54
- # print(f'rotation {axis}, {angle}')
55
54
  # handle the case where angle is not a constant?
56
55
  return self.make_nx(NXfield, angle, vector=axis, depends_on=dep, transformation_type='rotation', units=angle_unit)
57
56
 
@@ -1,5 +1,5 @@
1
1
  from mccode_antlr.instr import Instance
2
- from nexusformat.nexus import NXevent_data
2
+ from nexusformat.nexus import NXevent_data, NXfield
3
3
 
4
4
  class NotNXdict:
5
5
  """Wrapper class to prevent NXfield-parsing of the held dictionary"""
@@ -12,6 +12,10 @@ class NotNXdict:
12
12
  def __repr__(self):
13
13
  return f"NotNXdict<{self.value}>"
14
14
 
15
+ def __str__(self):
16
+ from json import dumps
17
+ return dumps(self.value)
18
+
15
19
 
16
20
  def outer_transform_dependency(transformations):
17
21
  """For a NXtransformations group, find the most-dependent transformation name
@@ -36,7 +40,20 @@ def outer_transform_dependency(transformations):
36
40
  obj = getattr(transformations, name)
37
41
  if not hasattr(obj, 'depends_on'):
38
42
  raise ValueError(f'{name} in {names} dependency chain missing "depends_on" attribute')
39
- return obj.depends_on
43
+ if isinstance(obj.depends_on, NXfield):
44
+ # obj.depends_on is an NXfield object; which has a number of properties
45
+ # nxgroup - the parent group
46
+ # dtype - string or numpy dtype
47
+ # shape - list or tuple of ints
48
+ # attrs - dict of attributes
49
+ # nxdata - a scalar or numpy array or string
50
+ # nxpath - string, where this object is in the tree
51
+ # nxroot - the root NXgroup object containing this object
52
+ # I _think_ we *always* want the data stored in this object
53
+ return obj.depends_on.nxdata
54
+ elif isinstance(obj.depends_on, str):
55
+ return obj.depends_on
56
+ raise ValueError(f"depends_on attribute of {name} is not an NXfield or str")
40
57
 
41
58
  # depends = {name: getattr(transformations, name).depends_on for name in names}
42
59
  depends = {name: depends_on_per(name) for name in names}
@@ -113,7 +113,6 @@ class Writer:
113
113
  if absolute_depends_on and 'depends_on' == name and not obj.nxdata.startswith('/'):
114
114
  obj.nxdata = _to_absolute(top_obj.nxpath, obj.nxdata)
115
115
  if obj.nxclass == 'NXfield':
116
- # print(f'to_json_dict for NXfield {name=}')
117
116
  typ, val = convert_types(obj.nxdata, only_nx)
118
117
  # typ is None if obj.nxdata is a NotNXdict (such that val _is_ the contained dict)
119
118
  entry = dict(module='dataset', config=dict(name=name, values=val, type=typ)) if typ else val
@@ -123,7 +122,6 @@ class Writer:
123
122
  if len(list(obj)):
124
123
  entry['children'] = self._to_json_dict(obj, only_nx=only_nx, absolute_depends_on=absolute_depends_on)
125
124
  for n, v in obj.attrs.items():
126
- # print(f'to_json_dict for attribute of {name=}, named {n=}')
127
125
  typ, val = convert_types(v, only_nx)
128
126
  if absolute_depends_on and n == 'depends_on' and '/' != val[0]:
129
127
  val = _to_absolute(top_obj.nxpath, val)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: moreniius
3
- Version: 0.2.3
3
+ Version: 0.2.5
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
@@ -8,7 +8,7 @@ Description-Content-Type: text/markdown
8
8
  Requires-Dist: zenlog>=1.1
9
9
  Requires-Dist: platformdirs>=3.11
10
10
  Requires-Dist: importlib_metadata; python_version < "3.8"
11
- Requires-Dist: mccode-antlr[hdf5]>=0.7.1
11
+ Requires-Dist: mccode-antlr[hdf5]>=0.9.2
12
12
  Requires-Dist: nexusformat>=1.0.6
13
13
 
14
14
  # moreniius
@@ -1,6 +1,6 @@
1
1
  zenlog>=1.1
2
2
  platformdirs>=3.11
3
- mccode-antlr[hdf5]>=0.7.1
3
+ mccode-antlr[hdf5]>=0.9.2
4
4
  nexusformat>=1.0.6
5
5
 
6
6
  [:python_version < "3.8"]
@@ -0,0 +1,111 @@
1
+
2
+ def make_motorized_instrument():
3
+ from mccode_antlr.assembler import Assembler
4
+ from mccode_antlr.reader import MCSTAS_REGISTRY, LocalRegistry
5
+ from mccode_to_kafka.writer import da00_dataarray_config, da00_variable_config
6
+
7
+ inst = Assembler('inst', registries=[MCSTAS_REGISTRY])
8
+ inst.parameter('double ex/"m"=0')
9
+ inst.parameter('double phi/"degree"=0')
10
+
11
+ inst.component('origin', 'Arm', at=(0, 0, 0))
12
+ inst.component('source', 'Source_simple', at=[(0, 0, 0), 'origin'])
13
+ inst.component('xpos', 'Arm', at=[('ex', 0, 0), 'source'])
14
+ inst.component('zrot', 'Arm', at=[(0, 0, 0), 'xpos'], rotate=[(0, 0, 'phi'), 'xpos'])
15
+ inst.component('aposrot', 'Arm', at=(1, 2, 3), rotate=(45, 55, 60))
16
+
17
+ return inst.instrument
18
+
19
+
20
+ def test_motorized_instrument():
21
+ import moreniius
22
+ motorized = make_motorized_instrument()
23
+ nx = moreniius.MorEniius.from_mccode(motorized, origin='origin', only_nx=False, absolute_depends_on=True)
24
+ assert nx is not None
25
+ #TODO add actual tests for the contents of, e.g., the dumped NeXus Structure
26
+ ns = nx.to_nexus_structure()
27
+
28
+ expected = {
29
+ 'entry': {
30
+ 'type': 'group',
31
+ 'children': 1,
32
+ 'next': 0,
33
+ 'attributes': [{'name': 'NX_class', 'dtype': 'string', 'values': 'NXentry'}]
34
+ },
35
+ 'instrument': {
36
+ 'type': 'group',
37
+ 'children': 7,
38
+ 'next': 0,
39
+ 'attributes': [{'name': 'NX_class', 'dtype': 'string', 'values': 'NXinstrument'}]
40
+ },
41
+ }
42
+ for name, has in expected.items():
43
+ assert 'children' in ns
44
+ assert len(ns['children']) >= has['next']
45
+ ns = ns['children'][has['next']]
46
+ assert all(x in ns for x in ('type', 'name', 'children', 'attributes'))
47
+ assert ns['name'] == name
48
+ assert ns['attributes'] == has['attributes']
49
+ assert len(ns['children']) == has['children']
50
+
51
+ xpos = ns['children'][3]
52
+ zrot = ns['children'][4]
53
+ aposrot = ns['children'][5]
54
+
55
+
56
+ from json import dumps
57
+
58
+ for cns in (xpos, zrot, aposrot):
59
+ assert 'children' in cns
60
+ assert 'transformations' in [c['name'] for c in cns['children'] if 'name' in c]
61
+ t = [c for c in cns['children'] if 'name' in c and c['name'] == 'transformations'][0]
62
+ assert 'children' in t
63
+ t = t['children']
64
+ for c in t:
65
+ # Each child can _either_ be a dataset, with 'module' at its top level
66
+ # Or a group, with 'name', etc. at its top level
67
+
68
+ if 'module' in c:
69
+ # this transformation is static, and a dataset
70
+ assert 'dataset' == c['module']
71
+ assert all(x in c for x in ('config', 'attributes'))
72
+ assert all(x in c['config'] for x in ('name', 'values', 'type'))
73
+ attrs = c['attributes']
74
+ assert len(attrs) == 4
75
+ assert all(all(x in a for x in ('name', 'values', 'dtype')) for a in attrs)
76
+ assert all(a['name'] in ('vector', 'depends_on', 'transformation_type', 'units') for a in attrs)
77
+ else:
78
+ # this transformation is dynamic and a group
79
+ assert all(x in c for x in ('name', 'type', 'children', 'attributes'))
80
+ assert 'group' == c['type']
81
+ attrs = c['attributes']
82
+ assert len(attrs) == 1
83
+ attr = attrs[0]
84
+ assert all(x in attr for x in ('name', 'dtype', 'values'))
85
+ assert 'NX_class' == attr['name']
86
+ assert 'NXgroup' == attr['values']
87
+
88
+ # The children should contain a link to the log ... is the order important?
89
+ # Must the number of children always be the same?
90
+ assert all('module' in cc for cc in c['children'])
91
+ assert sum('link' == cc['module'] for cc in c['children']) <= 1
92
+ for cc in c['children']:
93
+ if 'link' == cc['module']:
94
+ assert all(x in cc['config'] for x in ('name', 'source'))
95
+ else:
96
+ assert all(x in cc['config'] for x in ('name', 'values', 'type'))
97
+ assert cc['config']['name'] in ('vector', 'depends_on', 'transformation_type', 'units')
98
+
99
+ # for name, has in expected.items():
100
+ # print({x : list(ns[x]) for x in ns})
101
+ # assert all(x in ns for x in has)
102
+ # assert len(ns['children']) == 1
103
+ # assert ns['name'] == name
104
+ # ns = ns['children'][0]
105
+
106
+ #
107
+ # instr = ns['entry']['instrument']
108
+ # #
109
+ # print(dumps(xpos, indent=2))
110
+ # print(dumps(zrot, indent=1))
111
+ # print(dumps(aposrot, indent=1))
@@ -1,24 +0,0 @@
1
-
2
- def make_motorized_instrument():
3
- from mccode_antlr.assembler import Assembler
4
- from mccode_antlr.reader import MCSTAS_REGISTRY, LocalRegistry
5
- from mccode_to_kafka.writer import da00_dataarray_config, da00_variable_config
6
-
7
- inst = Assembler('inst', registries=[MCSTAS_REGISTRY])
8
- inst.parameter('double ex/"m"=0')
9
- inst.parameter('double phi/"degree"=0')
10
-
11
- inst.component('origin', 'Arm', at=(0, 0, 0))
12
- inst.component('source', 'Source_simple', at=[(0, 0, 0), 'origin'])
13
- inst.component('xpos', 'Arm', at=[('ex', 0, 0), 'source'])
14
- inst.component('zrot', 'Arm', at=[(0, 0, 0), 'xpos'], rotate=[(0, 0, 'phi'), 'xpos'])
15
-
16
- return inst.instrument
17
-
18
-
19
- def test_motorized_instrument():
20
- import moreniius
21
- motorized = make_motorized_instrument()
22
- nx = moreniius.MorEniius.from_mccode(motorized, origin='origin', only_nx=False, absolute_depends_on=True)
23
- assert nx is not None
24
- #TODO add actual tests for the contents of, e.g., the dumped NeXus Structure
File without changes
File without changes
File without changes