moreniius 0.5.2__py3-none-any.whl → 0.6.1__py3-none-any.whl
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.
- moreniius/mccode/comp.py +77 -14
- moreniius/mccode/mccode.py +36 -10
- moreniius/moreniius.py +4 -2
- moreniius/writer.py +13 -4
- {moreniius-0.5.2.dist-info → moreniius-0.6.1.dist-info}/METADATA +4 -3
- {moreniius-0.5.2.dist-info → moreniius-0.6.1.dist-info}/RECORD +9 -9
- {moreniius-0.5.2.dist-info → moreniius-0.6.1.dist-info}/WHEEL +0 -0
- {moreniius-0.5.2.dist-info → moreniius-0.6.1.dist-info}/entry_points.txt +0 -0
- {moreniius-0.5.2.dist-info → moreniius-0.6.1.dist-info}/top_level.txt +0 -0
moreniius/mccode/comp.py
CHANGED
|
@@ -95,27 +95,41 @@ def diskchopper_translator(nxinstance):
|
|
|
95
95
|
return nxinstance.make_nx(NXdisk_chopper, slit_edges=NXfield(nx_slit_edges, units='degrees'), **resolve_parameter_links(pars))
|
|
96
96
|
|
|
97
97
|
|
|
98
|
-
def
|
|
99
|
-
|
|
98
|
+
def _ellipse_vertices_faces(major_x, minor_x, offset_x, major_y, minor_y, offset_y, l, n=10):
|
|
99
|
+
"""
|
|
100
|
+
Create vertices and faces for an elliptical guide with given parameters.
|
|
101
|
+
|
|
102
|
+
Parameters
|
|
103
|
+
----------
|
|
104
|
+
major_x : float
|
|
105
|
+
Major axis half-length in the x-direction.
|
|
106
|
+
minor_x : float
|
|
107
|
+
Minor axis half-length in the x-direction.
|
|
108
|
+
offset_x : float
|
|
109
|
+
Offset from the end of the ellipse to the guide entrance in the x-direction.
|
|
110
|
+
major_y : float
|
|
111
|
+
Major axis half-length in the y-direction.
|
|
112
|
+
minor_y : float
|
|
113
|
+
Minor axis half-length in the y-direction.
|
|
114
|
+
offset_y : float
|
|
115
|
+
Offset from the end of the ellipse to the guide entrance in the y-direction.
|
|
116
|
+
l : float
|
|
117
|
+
Length of the guide. l <= 2*major_x - offset_x and l <= 2*major_y - offset_y
|
|
118
|
+
n : int, optional
|
|
119
|
+
Number of segments along the length of the guide. Default is 10.
|
|
120
|
+
"""
|
|
100
121
|
from numpy import arange, sqrt
|
|
101
|
-
from moreniius.nxoff import NXoff
|
|
102
|
-
if not '"mid"' == nxinstance.obj.get_parameter('dimensionsAt'):
|
|
103
|
-
log.warn('Only midpoint geometry supported by Elliptic_guide_gravity translator')
|
|
104
|
-
log.info(f'The current guide has {nxinstance.obj.get_parameter("dimensionsAt")} specified')
|
|
105
122
|
|
|
106
|
-
def ellipse_width(minor,
|
|
107
|
-
major = sqrt((distance / 2) ** 2 + minor ** 2)
|
|
123
|
+
def ellipse_width(minor, major, at):
|
|
108
124
|
return 0 if abs(at) > major else minor * sqrt(1 - (at / major) ** 2)
|
|
109
125
|
|
|
110
|
-
pars = dict(xw='xwidth', xi='linxw', xo='loutxw', yw='yheight', yi='linyh', yo='loutyh', l='l')
|
|
111
|
-
p = {k: nxinstance.parameter(v) for k, v in pars.items()}
|
|
112
|
-
n = 10
|
|
113
126
|
rings = arange(n + 1) / n
|
|
114
127
|
faces, vertices = [], []
|
|
115
128
|
for x in rings:
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
129
|
+
z = x * l
|
|
130
|
+
w = ellipse_width(minor_x, major_x, offset_x - minor_x + z)
|
|
131
|
+
h = ellipse_width(minor_y, major_y, offset_y - minor_y + x)
|
|
132
|
+
|
|
119
133
|
vertices.extend([[-w, -h, z], [-w, h, z], [w, h, z], [w, -h, z]])
|
|
120
134
|
|
|
121
135
|
# These are only the guide faces (that is, the inner faces of the sides of the guide housing)
|
|
@@ -124,6 +138,55 @@ def elliptic_guide_gravity_translator(nxinstance):
|
|
|
124
138
|
j0, j1, j2, j3, j4, j5, j6, j7 = [4 * i + k for k in range(8)]
|
|
125
139
|
faces.extend([[j0, j1, j5, j4], [j1, j2, j6, j5], [j2, j3, j7, j6], [j3, j0, j4, j7]])
|
|
126
140
|
|
|
141
|
+
return vertices, faces
|
|
142
|
+
|
|
143
|
+
def _ellipse_parameters_from_widths(nxinstance):
|
|
144
|
+
from numpy import sqrt
|
|
145
|
+
|
|
146
|
+
def parameters(which, w, i, o, l):
|
|
147
|
+
foci = i + l + o
|
|
148
|
+
offset = foci / 2 - i
|
|
149
|
+
if 'mid' in which:
|
|
150
|
+
minor = w / 2
|
|
151
|
+
major = sqrt(foci ** 2 + minor ** 2) / 2
|
|
152
|
+
else:
|
|
153
|
+
t, b = (o, i) if 'entrance' in which else (i, o)
|
|
154
|
+
t += l
|
|
155
|
+
w /= 2
|
|
156
|
+
b = sqrt(b * b + w * w / 4) + sqrt(t * t + w * w / 4)
|
|
157
|
+
major = b / 2
|
|
158
|
+
minor = sqrt(b * b - foci * foci) / 2
|
|
159
|
+
return major, minor, offset
|
|
160
|
+
|
|
161
|
+
pars = dict(xw='xwidth', xi='linxw', xo='loutxw', yw='yheight', yi='linyh', yo='loutyh', l='l')
|
|
162
|
+
p = {k: nxinstance.parameter(v) for k, v in pars.items()}
|
|
163
|
+
|
|
164
|
+
dim_at = str(nxinstance.obj.get_parameter('dimensionsAt').value)
|
|
165
|
+
major_x, minor_x, offset_x = parameters(dim_at, p['xw'], p['xi'], p['xo'], p['l'])
|
|
166
|
+
major_y, minor_y, offset_y = parameters(dim_at, p['yw'], p['yi'], p['yo'], p['l'])
|
|
167
|
+
|
|
168
|
+
return major_x, minor_x, offset_x, major_y, minor_y, offset_y, p['l']
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def elliptic_guide_gravity_translator(nxinstance):
|
|
172
|
+
from nexusformat.nexus import NXguide
|
|
173
|
+
from moreniius.nxoff import NXoff
|
|
174
|
+
|
|
175
|
+
ellipse_pars = [f'{f}{s}' for f in ('majorAxis', 'minorAxis', 'majorAxisOffset') for s in ('xw', 'yh')]
|
|
176
|
+
if all(nxinstance.obj.defines_parameter(p) for p in ellipse_pars):
|
|
177
|
+
# we can use the specified ellipse parameters directly
|
|
178
|
+
major_x = nxinstance.parameter('majorAxisxw')
|
|
179
|
+
minor_x = nxinstance.parameter('minorAxisxw')
|
|
180
|
+
offset_x = nxinstance.parameter('majorAxisOffsetxw')
|
|
181
|
+
major_y = nxinstance.parameter('majorAxisyh')
|
|
182
|
+
minor_y = nxinstance.parameter('minorAxisyh')
|
|
183
|
+
offset_y = nxinstance.parameter('majorAxisOffsetyh')
|
|
184
|
+
l = nxinstance.parameter('l')
|
|
185
|
+
else:
|
|
186
|
+
major_x, minor_x, offset_x, major_y, minor_y, offset_y, l = _ellipse_parameters_from_widths(nxinstance)
|
|
187
|
+
|
|
188
|
+
vertices, faces = _ellipse_vertices_faces(major_x, minor_x, offset_x, major_y, minor_y, offset_y, l, n=10)
|
|
189
|
+
|
|
127
190
|
nx_vertices = [[nxinstance.expr2nx(expr) for expr in vector] for vector in vertices]
|
|
128
191
|
nx_faces = [[nxinstance.expr2nx(expr) for expr in face] for face in faces]
|
|
129
192
|
|
moreniius/mccode/mccode.py
CHANGED
|
@@ -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
|
-
|
|
50
|
-
if transformations and
|
|
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
|
-
|
|
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
|
-
|
|
61
|
-
|
|
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
|
moreniius/moreniius.py
CHANGED
|
@@ -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)
|
moreniius/writer.py
CHANGED
|
@@ -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
|
|
128
|
-
typ, val = convert_types(
|
|
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,21 +1,22 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: moreniius
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.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
|
|
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
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
14
14
|
Description-Content-Type: text/markdown
|
|
15
15
|
Requires-Dist: zenlog>=1.1
|
|
16
16
|
Requires-Dist: platformdirs>=3.11
|
|
17
|
-
Requires-Dist: mccode-antlr[hdf5]>=0.
|
|
17
|
+
Requires-Dist: mccode-antlr[hdf5]>=0.16.1
|
|
18
18
|
Requires-Dist: nexusformat>=1.0.6
|
|
19
|
+
Requires-Dist: networkx
|
|
19
20
|
|
|
20
21
|
# moreniius
|
|
21
22
|
A project to contain custom components required to use `eniius` to produce `NeXus Structure` `JSON` from `mccode-antlr` simulated instruments.
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
moreniius/__init__.py,sha256=33SUBkXWhH5rog5oaGJr1Kwqjhwz97w4E0Da7rArYi4,154
|
|
2
2
|
moreniius/additions.py,sha256=6Hhhc4LDUsnBj27Iil-EFFzQm1xd2M45hfcVQYEjxiI,17615
|
|
3
|
-
moreniius/moreniius.py,sha256=
|
|
3
|
+
moreniius/moreniius.py,sha256=UZgQycAed5OWIqxYXZLaD68YUHFgQ8fVb-aCP6hvT9Q,1544
|
|
4
4
|
moreniius/nexus_structure.py,sha256=C_ohhilsE6xdfSpFVhsFEK9EC3sBXPGWxCIGk_4UFvI,1853
|
|
5
5
|
moreniius/nxoff.py,sha256=WHp9wYNn_4Hcx8Nzi9rpX1p8_iwI-AdgTQouSAEG8N4,3288
|
|
6
6
|
moreniius/utils.py,sha256=R81eHjc0EWjMsP-Z8WI9sZkc_QY357z_aYziflQAUEU,9238
|
|
7
|
-
moreniius/writer.py,sha256=
|
|
7
|
+
moreniius/writer.py,sha256=zgrbo7RfAriAGrOpPhFHSwwn3yWG4_ZJndIi6HhTzss,6815
|
|
8
8
|
moreniius/mccode/__init__.py,sha256=1QiZdh90G3gp_WlVpdJB_ZGauoW0GJEQ13Nelaqa5JE,151
|
|
9
|
-
moreniius/mccode/comp.py,sha256=
|
|
9
|
+
moreniius/mccode/comp.py,sha256=iaOooI2nIevA0Vhz5jZQJCqXYgmZ3jMm0s3gUtR8Unc,9637
|
|
10
10
|
moreniius/mccode/instance.py,sha256=yydYeMGITlZrVWBVYregBWQ0Sd_2A71hgoyCrLLW-Jk,8058
|
|
11
11
|
moreniius/mccode/instr.py,sha256=D4B3ylD4BMfkiP5t2hx5xop9c7yk7QVSleT1wvpK17E,6161
|
|
12
|
-
moreniius/mccode/mccode.py,sha256=
|
|
12
|
+
moreniius/mccode/mccode.py,sha256=0Ck9xFUHU3EkBGTNIXelMgtLA1JXOs976Sj2wXfMQng,4237
|
|
13
13
|
moreniius/mccode/orientation.py,sha256=khT0jTMXyXkPCoEpDg-eLKulF-J2wIqNhUi1NzFWvto,3907
|
|
14
|
-
moreniius-0.
|
|
15
|
-
moreniius-0.
|
|
16
|
-
moreniius-0.
|
|
17
|
-
moreniius-0.
|
|
18
|
-
moreniius-0.
|
|
14
|
+
moreniius-0.6.1.dist-info/METADATA,sha256=ebjFHY4-LTTdtCnv5Y03-VWOme6vrOYSZHz4pQKU0pg,946
|
|
15
|
+
moreniius-0.6.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
16
|
+
moreniius-0.6.1.dist-info/entry_points.txt,sha256=Ga3k4P4fyBt5_dJ03Oapic2Qlgqv9jufQGdxWiz_j2A,63
|
|
17
|
+
moreniius-0.6.1.dist-info/top_level.txt,sha256=RzMo23UfVhgQeuOYeS5P9I0qVbxx4Gbe6Roc29Mr02c,10
|
|
18
|
+
moreniius-0.6.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|