moreniius 0.2.0__tar.gz → 0.2.1__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 (27) hide show
  1. {moreniius-0.2.0/src/moreniius.egg-info → moreniius-0.2.1}/PKG-INFO +3 -3
  2. {moreniius-0.2.0 → moreniius-0.2.1}/pyproject.toml +2 -2
  3. {moreniius-0.2.0 → moreniius-0.2.1}/src/moreniius/additions.py +58 -30
  4. {moreniius-0.2.0 → moreniius-0.2.1}/src/moreniius/mccode/comp.py +2 -0
  5. {moreniius-0.2.0 → moreniius-0.2.1}/src/moreniius/mccode/instance.py +4 -4
  6. {moreniius-0.2.0 → moreniius-0.2.1/src/moreniius.egg-info}/PKG-INFO +3 -3
  7. {moreniius-0.2.0 → moreniius-0.2.1}/src/moreniius.egg-info/requires.txt +2 -2
  8. {moreniius-0.2.0 → moreniius-0.2.1}/tests/test_nexus_structure.py +6 -3
  9. {moreniius-0.2.0 → moreniius-0.2.1}/.github/workflows/pip.yml +0 -0
  10. {moreniius-0.2.0 → moreniius-0.2.1}/.github/workflows/wheels.yml +0 -0
  11. {moreniius-0.2.0 → moreniius-0.2.1}/.gitignore +0 -0
  12. {moreniius-0.2.0 → moreniius-0.2.1}/README.md +0 -0
  13. {moreniius-0.2.0 → moreniius-0.2.1}/setup.cfg +0 -0
  14. {moreniius-0.2.0 → moreniius-0.2.1}/src/moreniius/__init__.py +0 -0
  15. {moreniius-0.2.0 → moreniius-0.2.1}/src/moreniius/mccode/__init__.py +0 -0
  16. {moreniius-0.2.0 → moreniius-0.2.1}/src/moreniius/mccode/instr.py +0 -0
  17. {moreniius-0.2.0 → moreniius-0.2.1}/src/moreniius/mccode/mccode.py +0 -0
  18. {moreniius-0.2.0 → moreniius-0.2.1}/src/moreniius/mccode/orientation.py +0 -0
  19. {moreniius-0.2.0 → moreniius-0.2.1}/src/moreniius/moreniius.py +0 -0
  20. {moreniius-0.2.0 → moreniius-0.2.1}/src/moreniius/nexus_structure.py +0 -0
  21. {moreniius-0.2.0 → moreniius-0.2.1}/src/moreniius/nxoff.py +0 -0
  22. {moreniius-0.2.0 → moreniius-0.2.1}/src/moreniius/utils.py +0 -0
  23. {moreniius-0.2.0 → moreniius-0.2.1}/src/moreniius/writer.py +0 -0
  24. {moreniius-0.2.0 → moreniius-0.2.1}/src/moreniius.egg-info/SOURCES.txt +0 -0
  25. {moreniius-0.2.0 → moreniius-0.2.1}/src/moreniius.egg-info/dependency_links.txt +0 -0
  26. {moreniius-0.2.0 → moreniius-0.2.1}/src/moreniius.egg-info/entry_points.txt +0 -0
  27. {moreniius-0.2.0 → moreniius-0.2.1}/src/moreniius.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: moreniius
3
- Version: 0.2.0
3
+ Version: 0.2.1
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,8 +8,8 @@ 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.6.0
12
- Requires-Dist: nexusformat==1.0.2
11
+ Requires-Dist: mccode-antlr[hdf5]==0.7.0
12
+ Requires-Dist: nexusformat==1.0.6
13
13
 
14
14
  # moreniius
15
15
  A project to contain custom components required to use `eniius` to produce `NeXus Structure` `JSON` from `mccode-antlr` simulated instruments.
@@ -8,8 +8,8 @@ dependencies = [
8
8
  'zenlog==1.1,',
9
9
  'platformdirs==3.11',
10
10
  "importlib_metadata; python_version<'3.8'",
11
- 'mccode-antlr[hdf5]==0.6.0',
12
- 'nexusformat==1.0.2'
11
+ 'mccode-antlr[hdf5]==0.7.0',
12
+ 'nexusformat==1.0.6'
13
13
  ]
14
14
  readme = "README.md"
15
15
  authors = [
@@ -14,13 +14,15 @@ COMPONENT_TYPE_NAME_TO_NEXUS['ESS_butterfly'] = 'NXmoderator'
14
14
  # full detector during the readout-construction.
15
15
  BIFROST_DETECTOR_MODULES = {}
16
16
 
17
+ BIFROST_DETECTOR_TOPIC = 'bifrost_detector'
18
+
17
19
 
18
20
  def readout_translator(instance):
19
21
  """BIFROST specific Readout Master, should be deprecated in favour of ReadoutCAEN"""
20
22
  from numpy import einsum, ndarray, array
21
23
  from nexusformat.nexus import NXdetector, NXcylindrical_geometry
22
24
  from .utils import ev44_event_data_group
23
- stream = ev44_event_data_group(source='caen', topic='SimulatedEvents')
25
+ stream = ev44_event_data_group(source='caen', topic=BIFROST_DETECTOR_TOPIC)
24
26
 
25
27
  readout_pos, readout_rot = instance.obj.orientation.position_parts(), instance.obj.orientation.rotation_parts()
26
28
 
@@ -28,29 +30,47 @@ def readout_translator(instance):
28
30
  total = sum(counts)
29
31
  points = [geometry.vertices.shape[0] for _, _, geometry in BIFROST_DETECTOR_MODULES.values()]
30
32
  total_points = sum(points)
31
- cylinders = ndarray((total, 3), dtype='int32')
32
- vertices = ndarray((total_points, 3), dtype='float32')
33
+ all_cylinders = ndarray((total, 3), dtype='int32')
34
+ all_vertices = ndarray((total_points, 3), dtype='float32')
33
35
  detector_number = ndarray((total,), dtype='int32')
34
36
 
35
37
  offset = 0
36
38
 
37
39
  for module_pos, module_rot, geometry in BIFROST_DETECTOR_MODULES.values():
38
40
  # Find the vector and rotation matrix linking the two coordinate systems
39
- v = instance.instr.expr2nx(tuple((readout_pos - module_pos).position())) # this is a mccode-antlr Vector
40
- R1 = array(instance.instr.expr2nx(tuple(module_rot.inverse().rotation()))).reshape((3, 3))
41
- R2 = array(instance.instr.expr2nx(tuple(readout_rot.rotation()))).reshape((3, 3))
42
41
  #
43
- verts = einsum('ij,kj->ki', R1, geometry.vertices)
44
- verts = verts + v
45
- verts = einsum('ij,kj->ki', R2, verts)
42
+ # - The geometry is defined in the module coordinate system, where any point is p' = (x', y', z').
43
+ # - There is a rotation matrix rot1 that relates a vector in _a_ global coordinate system to the module
44
+ # Such that
45
+ # x' = rot1 x_global
46
+ # Or
47
+ # x_global = rot1.inv() x'
48
+ # - Similarly, there is a rotation matrix rot2 that relates a vector in the same global coordinate system to
49
+ # the readout's coordinate system.
50
+ # x = rot2 x_global
51
+ # - In this global coordinate system, the module position and readout positions have a vector connecting them
52
+ # v = p_module - p_readout
53
+ #
54
+ # - So, to express the geometry in the readout's coordinate system, we convert p' to the global coordinate
55
+ # system, add the difference vector between the two coordinate systems, then convert the result to the
56
+ # readout coordinate system:
57
+ # p = rot2 (v + rot1.inv() p')
58
+ #
59
+ v = instance.instr.expr2nx(tuple((module_pos - readout_pos).position())) # this is a mccode-antlr Vector
60
+ rot1 = array(instance.instr.expr2nx(tuple(module_rot.inverse().rotation()))).reshape((3, 3))
61
+ rot2 = array(instance.instr.expr2nx(tuple(readout_rot.rotation()))).reshape((3, 3))
62
+ #
63
+ vertices = einsum('ij,kj->ki', rot1, geometry.vertices)
64
+ vertices = vertices + v
65
+ vertices = einsum('ij,kj->ki', rot2, vertices)
46
66
  #
47
- cyls = offset + geometry.cylinders
48
- vertices[offset:(offset + verts.shape[0])] = verts
49
- cylinders[geometry.detector_number - 1, :] = cyls
67
+ cylinders = offset + geometry.cylinders
68
+ all_vertices[offset:(offset + vertices.shape[0])] = vertices
69
+ all_cylinders[geometry.detector_number - 1, :] = cylinders
50
70
  detector_number[geometry.detector_number - 1] = geometry.detector_number
51
- offset += verts.shape[0]
71
+ offset += vertices.shape[0]
52
72
 
53
- geometry = NXcylindrical_geometry(vertices=vertices, cylinders=cylinders, detector_number=detector_number)
73
+ geometry = NXcylindrical_geometry(vertices=all_vertices, cylinders=all_cylinders, detector_number=detector_number)
54
74
 
55
75
  return NXdetector(data=stream, geometry=geometry)
56
76
 
@@ -158,22 +178,25 @@ def detector_tubes_offsets_and_one_cylinder(self):
158
178
 
159
179
  halfi = (width - 2 * radius) / 2
160
180
  di = np.linspace(-halfi, halfi, ni)
161
- dj = np.linspace(-height / 2, height / 2, nj)
181
+
182
+ half_pixel = height / (nj + 1) / 2 # half the size of one pixel along the tube
183
+ dj = -np.linspace(-height / 2 + half_pixel, height / 2 - half_pixel, nj)
162
184
  Dj, Di = np.meshgrid(dj, di)
163
185
 
164
186
  arc, triplet = analyzer - 1, cassette - 1 # naming from ICD 01 v6 indexing of triplets
165
187
 
166
188
  diameter = f'2 * {radius}' if isinstance(radius, str) else 2 * radius
167
189
 
168
- pars['detector_number'] = [[pixel_fun(nj, arc, triplet, tube, position) for position in range(nj)] for tube in
169
- range(ni)]
170
- pars['data'] = ev44_event_data_group(bifrost_source_20230704(arc, triplet), 'SimulatedEvents')
190
+ detector_number = [[pixel_fun(nj, arc, triplet, tube, position) for position in range(nj)] for tube in range(ni)]
191
+
192
+ pars['detector_number'] = np.array(detector_number).astype('int32')
193
+ pars['data'] = ev44_event_data_group(bifrost_source_20230704(arc, triplet), BIFROST_DETECTOR_TOPIC)
171
194
  pars['x_pixel_offset'] = NXfield(Di, units='m')
172
195
  pars['y_pixel_offset'] = NXfield(Dj, units='m')
173
196
  pars['x_pixel_size'] = NXfield(diameter, units='m')
174
197
  pars['y_pixel_size'] = NXfield(height / nj, units='m')
175
198
  pars['diameter'] = NXfield(diameter, units='m')
176
- pars['type'] = f'{ni} He3 tubes in series' if self.nx_parameter('wires_in_series') else f'{ni} He3 tubes'
199
+ pars['type'] = f'{ni} He3 tubes in series' if self.nx_parameter('wires_in_series', True) else f'{ni} He3 tubes'
177
200
 
178
201
  # use NXcylindrical_geometry to define the detectors, which requires:
179
202
  # vertices - (i, 3) -- points relative to the detector position defining each cylinder in the detector
@@ -187,8 +210,7 @@ def detector_tubes_offsets_and_one_cylinder(self):
187
210
  # detector_number: (k,) -- maps the cylinders in cylinder by index with a detector id
188
211
  #
189
212
  # We're allowed to specify a single cylinder then le the x/y/z_offset position that pixel repeatedly:
190
- dy = (dj[1] - dj[0]) / 2
191
- vertices = NXfield([[0, -dy, 0], [radius, -dy, 0], [0, dy, 0]], units='m')
213
+ vertices = NXfield([[0, -half_pixel, 0], [radius, -half_pixel, 0], [0, half_pixel, 0]], units='m')
192
214
  cylinders = [[0, 1, 2]]
193
215
  geometry = NXcylindrical_geometry(vertices=vertices, cylinders=cylinders)
194
216
 
@@ -240,7 +262,7 @@ def detector_tubes_offsets_and_one_cylinder(self):
240
262
  # cylinders = [[k, k+1, k+2] for k in [tube * 2 * (nj + 1) + 2 * j for tube in range(ni) for j in range(nj)]]
241
263
  # detector_number = [pixel_fun(nj, arc, triplet, tube, j) for tube in range(ni) for j in range(nj)]
242
264
  #
243
- # pars['data'] = ev44_event_data_group(bifrost_source_20230704(arc, triplet), 'SimulatedEvents')
265
+ # pars['data'] = ev44_event_data_group(bifrost_source_20230704(arc, triplet), BIFROST_DETECTOR_TOPIC)
244
266
  # pars['type'] = f'{ni} He3 tubes in series' if self.nx_parameter('wires_in_series') else f'{ni} He3 tubes'
245
267
  #
246
268
  # geometry = NXcylindrical_geometry(vertices=vertices, cylinders=cylinders, detector_number=detector_number)
@@ -272,8 +294,9 @@ def detector_tubes_only_cylinder(self):
272
294
  nj = self.nx_parameter('no') # corresponds to 'height' and McStas 'y' axis
273
295
  width, height, radius = [self.nx_parameter(n) for n in ('width', 'height', 'radius')]
274
296
  halfi = (width - 2 * radius) / 2
297
+ # signs of di and dj verified by examining plots of detector positions
275
298
  di = np.linspace(-halfi, halfi, ni)
276
- dj = np.linspace(-height / 2, height / 2, nj+1)
299
+ dj = -np.linspace(-height / 2, height / 2, nj+1)
277
300
 
278
301
  # use NXcylindrical_geometry to define the detectors, which requires:
279
302
  # vertices - (i, 3) -- points relative to the detector position defining each cylinder in the detector
@@ -290,10 +313,11 @@ def detector_tubes_only_cylinder(self):
290
313
  arc, triplet = analyzer - 1, cassette - 1 # naming from ICD 01 v6 indexing of triplets
291
314
 
292
315
  vertices = NXfield([v for x in di for y in dj for v in [[x, y, 0], [x, y, radius]]], units='m')
293
- cylinders = [[k, k+1, k+2] for k in [tube * 2 * (nj + 1) + 2 * j for tube in range(ni) for j in range(nj)]]
294
- detector_number = [pixel_fun(nj, arc, triplet, tube, j) for tube in range(ni) for j in range(nj)]
316
+ cylinders = np.array([[k, k+1, k+2] for k in [tube * 2 * (nj + 1) + 2 * j for tube in range(ni) for j in range(nj)]]).astype('int32')
317
+ detector_number = np.array([pixel_fun(nj, arc, triplet, tube, j) for tube in range(ni) for j in range(nj)]).astype('int32')
295
318
 
296
- pars['type'] = f'{ni} He3 tubes in series' if self.nx_parameter('wires_in_series') else f'{ni} He3 tubes'
319
+ pars['data'] = ev44_event_data_group(bifrost_source_20230704(arc, triplet), BIFROST_DETECTOR_TOPIC)
320
+ pars['type'] = f'{ni} He3 tubes in series' if self.nx_parameter('wires_in_series', True) else f'{ni} He3 tubes'
297
321
 
298
322
  geometry = NXcylindrical_geometry(vertices=vertices, cylinders=cylinders, detector_number=detector_number)
299
323
 
@@ -302,13 +326,16 @@ def detector_tubes_only_cylinder(self):
302
326
  from nexusformat.nexus import NXdata
303
327
  from moreniius.utils import NotNXdict
304
328
  from json import loads
305
- pars['data'] = NXdata(data=NotNXdict(loads(md.value)))
329
+ stream = loads(md.value)
330
+ name = stream.get('module', 'metadata')
331
+ pars[name] = NXdata(data=NotNXdict(stream))
306
332
 
307
333
  return NXdetector(**pars, geometry=geometry)
308
334
 
309
335
 
310
336
  def bifrost_detector_collector(self):
311
- nx_obj = detector_tubes_only_cylinder(self)
337
+ # nx_obj = detector_tubes_only_cylinder(self) # each pixel is a cylinder
338
+ nx_obj = detector_tubes_offsets_and_one_cylinder(self) # all pixels share one cylinder
312
339
  # stash the object parts
313
340
  pos, rot = self.obj.orientation.position_parts(), self.obj.orientation.rotation_parts()
314
341
  BIFROST_DETECTOR_MODULES[str(self.obj.when)] = pos, rot, nx_obj.geometry
@@ -326,16 +353,17 @@ def bifrost_detector_collector(self):
326
353
  #
327
354
  # # parameters to be filled-in
328
355
  # pars = {}
329
- # # pars['data'] = ev44_event_data_group(bifrost_source_20230704(arc, triplet), 'SimulatedEvents')
356
+ # # pars['data'] = ev44_event_data_group(bifrost_source_20230704(arc, triplet), BIFROST_DETECTOR_TOPIC)
330
357
  # # pars['type'] = f'{ni} He3 tubes in series' if self.nx_parameter('wires_in_series') else f'{ni} He3 tubes'
331
358
  # pars['geometry'] = geometry.to_nexus()
332
359
  # return NXmonitor(**pars)
333
360
 
334
361
 
335
362
  # Patch-in the new methods
336
- register_translator('Readout', readout_translator)
363
+ # register_translator('Readout', readout_translator)
337
364
  register_translator('Monochromator_Rowland', monochromator_rowland_translator)
338
365
  register_translator('Detector_tubes', bifrost_detector_collector)
366
+ register_translator('Detector_time_tubes', bifrost_detector_collector)
339
367
  register_translator('Frame_monitor', monitor_translator)
340
368
 
341
369
  log.debug('moreniius.mccode.NXInstance translators extended')
@@ -118,6 +118,8 @@ def elliptic_guide_gravity_translator(nxinstance):
118
118
  z = x * p['l']
119
119
  vertices.extend([[-w, -h, z], [-w, h, z], [w, h, z], [w, -h, z]])
120
120
 
121
+ # These are only the guide faces (that is, the inner faces of the sides of the guide housing)
122
+ # The entry and exit are not guide faces and therefore are NOT represented here!
121
123
  for i in range(n):
122
124
  j0, j1, j2, j3, j4, j5, j6, j7 = [4 * i + k for k in range(8)]
123
125
  faces.extend([[j0, j1, j5, j4], [j1, j2, j6, j5], [j2, j3, j7, j6], [j3, j0, j4, j7]])
@@ -71,7 +71,7 @@ class NXInstance:
71
71
  nx: Union[None, dict, NXfield] = None
72
72
  dump_mcstas: bool = False
73
73
 
74
- def parameter(self, name):
74
+ def parameter(self, name, default=None):
75
75
  """
76
76
  Pull out a named instance parameter -- if it's value is not a constant, attempt to evaluate it
77
77
  using the Instr declare and initialize sections
@@ -79,7 +79,7 @@ class NXInstance:
79
79
  par = self.obj.get_parameter(name)
80
80
  if par is None:
81
81
  log.warn(f'It appears that {self.obj.type.name} does not define the parameter {name}')
82
- return None
82
+ return default
83
83
 
84
84
  expr = par.value
85
85
  # log.info(f'get parameter {name} which is {par} and expr {repr(expr)}')
@@ -100,9 +100,9 @@ class NXInstance:
100
100
  def expr2nx(self, expr: Expr):
101
101
  return self.instr.expr2nx(expr)
102
102
 
103
- def nx_parameter(self, name):
103
+ def nx_parameter(self, name, default=None):
104
104
  """Retrieve the named instance parameter and convert to a NeXus compatible value"""
105
- return self.expr2nx(self.parameter(name))
105
+ return self.expr2nx(self.parameter(name, default))
106
106
 
107
107
  def make_nx(self, nx_class, *args, **kwargs):
108
108
  return self.instr.make_nx(nx_class, *args, **kwargs)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: moreniius
3
- Version: 0.2.0
3
+ Version: 0.2.1
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,8 +8,8 @@ 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.6.0
12
- Requires-Dist: nexusformat==1.0.2
11
+ Requires-Dist: mccode-antlr[hdf5]==0.7.0
12
+ Requires-Dist: nexusformat==1.0.6
13
13
 
14
14
  # moreniius
15
15
  A project to contain custom components required to use `eniius` to produce `NeXus Structure` `JSON` from `mccode-antlr` simulated instruments.
@@ -1,7 +1,7 @@
1
1
  zenlog==1.1
2
2
  platformdirs==3.11
3
- mccode-antlr[hdf5]==0.6.0
4
- nexusformat==1.0.2
3
+ mccode-antlr[hdf5]==0.7.0
4
+ nexusformat==1.0.6
5
5
 
6
6
  [:python_version < "3.8"]
7
7
  importlib_metadata
@@ -6,9 +6,12 @@ class NexusStrctureTestCase(unittest.TestCase):
6
6
  def setUp(self):
7
7
  from json import dumps
8
8
  from mccode_antlr.loader import parse_mcstas_instr
9
- from mccode_to_kafka.writer import nexus_structure, edge
10
- m0 = nexus_structure('mon0', shape=[edge(10, 0.5, 10.5, 't', 'usec', 'monitor')])
11
- m1 = nexus_structure('mon1', shape=[edge(10, 1.5, 11.5, 't', 'usec', 'monitor')])
9
+ from mccode_to_kafka.writer import da00_variable_config, da00_dataarray_config
10
+ t0 = {'name': 't', 'unit': 'usec', 'label': 'monitor', 'data': {'first': 0.5, 'last': 10.5, 'size': 11}}
11
+ t1 = {'name': 't', 'unit': 'usec', 'label': 'monitor', 'data': {'first': 1.5, 'last': 11.5, 'size': 11}}
12
+ m0 = da00_dataarray_config(topic='mon0', source='mccode-to-kafka', constants=[da00_variable_config(**t0)])
13
+ m1 = da00_dataarray_config(topic='mon1', source='mccode-to-kafka', constants=[da00_variable_config(**t1)])
14
+
12
15
  instr = f"""DEFINE INSTRUMENT chopper_spectrometer(
13
16
  ch1speed, ch2speed, ch1phase, ch2phase
14
17
  )
File without changes
File without changes
File without changes