restage 0.4.0__tar.gz → 0.4.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.
- {restage-0.4.0/src/restage.egg-info → restage-0.4.1}/PKG-INFO +1 -1
- {restage-0.4.0 → restage-0.4.1}/src/restage/bifrost_choppers.py +6 -5
- {restage-0.4.0 → restage-0.4.1}/src/restage/cache.py +2 -1
- {restage-0.4.0 → restage-0.4.1}/src/restage/energy.py +11 -6
- {restage-0.4.0 → restage-0.4.1}/src/restage/instr.py +4 -18
- {restage-0.4.0 → restage-0.4.1/src/restage.egg-info}/PKG-INFO +1 -1
- {restage-0.4.0 → restage-0.4.1}/test/test_energy.py +36 -28
- {restage-0.4.0 → restage-0.4.1}/test/test_single.py +7 -0
- {restage-0.4.0 → restage-0.4.1}/.github/workflows/pip.yml +0 -0
- {restage-0.4.0 → restage-0.4.1}/.github/workflows/wheels.yml +0 -0
- {restage-0.4.0 → restage-0.4.1}/.gitignore +0 -0
- {restage-0.4.0 → restage-0.4.1}/README.md +0 -0
- {restage-0.4.0 → restage-0.4.1}/pyproject.toml +0 -0
- {restage-0.4.0 → restage-0.4.1}/setup.cfg +0 -0
- {restage-0.4.0 → restage-0.4.1}/src/restage/__init__.py +0 -0
- {restage-0.4.0 → restage-0.4.1}/src/restage/cspec_choppers.py +0 -0
- {restage-0.4.0 → restage-0.4.1}/src/restage/database.py +0 -0
- {restage-0.4.0 → restage-0.4.1}/src/restage/emulate.py +0 -0
- {restage-0.4.0 → restage-0.4.1}/src/restage/mcpl.py +0 -0
- {restage-0.4.0 → restage-0.4.1}/src/restage/range.py +0 -0
- {restage-0.4.0 → restage-0.4.1}/src/restage/run.py +0 -0
- {restage-0.4.0 → restage-0.4.1}/src/restage/scan.py +0 -0
- {restage-0.4.0 → restage-0.4.1}/src/restage/splitrun.py +0 -0
- {restage-0.4.0 → restage-0.4.1}/src/restage/tables.py +0 -0
- {restage-0.4.0 → restage-0.4.1}/src/restage.egg-info/SOURCES.txt +0 -0
- {restage-0.4.0 → restage-0.4.1}/src/restage.egg-info/dependency_links.txt +0 -0
- {restage-0.4.0 → restage-0.4.1}/src/restage.egg-info/entry_points.txt +0 -0
- {restage-0.4.0 → restage-0.4.1}/src/restage.egg-info/requires.txt +0 -0
- {restage-0.4.0 → restage-0.4.1}/src/restage.egg-info/top_level.txt +0 -0
- {restage-0.4.0 → restage-0.4.1}/test/test_cache.py +0 -0
- {restage-0.4.0 → restage-0.4.1}/test/test_database.py +0 -0
- {restage-0.4.0 → restage-0.4.1}/test/test_range.py +0 -0
- {restage-0.4.0 → restage-0.4.1}/test/test_scan.py +0 -0
|
@@ -82,9 +82,7 @@ def bandwidth_chopper_speeds_phases(energy_minimum: float):
|
|
|
82
82
|
return SOURCE_FREQUENCY, phase, -SOURCE_FREQUENCY, phase
|
|
83
83
|
|
|
84
84
|
|
|
85
|
-
def calculate(order: float, time: float, energy: float, names:
|
|
86
|
-
if names is None or len(names) != 6:
|
|
87
|
-
names = ['ps1', 'ps2', 'fo1', 'fo2', 'bw1', 'bw2']
|
|
85
|
+
def calculate(order: float, time: float, energy: float, names: tuple[str, ...]):
|
|
88
86
|
a, b, c, d, e, f = names
|
|
89
87
|
s, p = 'speed', 'phase'
|
|
90
88
|
r = dict()
|
|
@@ -94,9 +92,12 @@ def calculate(order: float, time: float, energy: float, names: list[str] | None
|
|
|
94
92
|
return r
|
|
95
93
|
|
|
96
94
|
|
|
97
|
-
def main(order: float, time: float, energy: float, names:
|
|
95
|
+
def main(order: float, time: float, energy: float, names: tuple[str, ...] | None = None):
|
|
98
96
|
if names is None or len(names) != 6:
|
|
99
|
-
names =
|
|
97
|
+
# names = ('ps1', 'ps2', 'fo1', 'fo2', 'bw1', 'bw2')
|
|
98
|
+
names = ('pulse_shaping_chopper_1', 'pulse_shaping_chopper_2',
|
|
99
|
+
'frame_overlap_chopper_1', 'frame_overlap_chopper_2',
|
|
100
|
+
'bandwidth_chopper_1', 'bandwidth_chopper_2')
|
|
100
101
|
rep = calculate(order, time, energy, names)
|
|
101
102
|
print(' '.join([f'{k}={v}' for k, v in rep.items()]))
|
|
102
103
|
|
|
@@ -2,7 +2,6 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from mccode_antlr.instr import Instr
|
|
4
4
|
from .tables import InstrEntry, SimulationTableEntry, SimulationEntry
|
|
5
|
-
from mccode_antlr.compiler.c import CBinaryTarget
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
def setup_database(named: str):
|
|
@@ -54,6 +53,8 @@ def _compile_instr(entry: InstrEntry, instr: Instr, config: dict | None = None,
|
|
|
54
53
|
generator = MCSTAS_GENERATOR
|
|
55
54
|
|
|
56
55
|
output = directory_under_module_data_path('bin')
|
|
56
|
+
# TODO consider adding `dump_source=True` _and_ putting the resulting file into
|
|
57
|
+
# the cache in order to make debugging future problems a tiny bit easier.
|
|
57
58
|
binary_path = compile_instrument(instr, target, output, generator=generator, config=config)
|
|
58
59
|
entry.mccode_version = __version__
|
|
59
60
|
entry.binary_path = str(binary_path)
|
|
@@ -10,13 +10,15 @@ def get_and_remove(d: dict, k: str, default=None):
|
|
|
10
10
|
return default
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
def one_generic_energy_to_chopper_parameters(
|
|
13
|
+
def one_generic_energy_to_chopper_parameters(
|
|
14
|
+
calculate_choppers, chopper_names: tuple[str, ...],
|
|
15
|
+
time: float, order: int, parameters: dict):
|
|
14
16
|
if any(x in parameters for x in ('ei', 'wavelength', 'lambda', 'energy', 'e')):
|
|
15
17
|
ei = get_and_remove(parameters, 'ei', get_and_remove(parameters, 'energy', get_and_remove(parameters, 'e')))
|
|
16
18
|
if ei is None:
|
|
17
19
|
wavelength = get_and_remove(parameters, 'wavelength', get_and_remove(parameters, 'lambda'))
|
|
18
20
|
ei = _wavelength_angstrom_to_energy_mev(wavelength)
|
|
19
|
-
choppers = calculate_choppers(order, time, ei)
|
|
21
|
+
choppers = calculate_choppers(order, time, ei, names=chopper_names)
|
|
20
22
|
parameters.update(choppers)
|
|
21
23
|
return parameters
|
|
22
24
|
|
|
@@ -24,25 +26,28 @@ def one_generic_energy_to_chopper_parameters(calculate_choppers, time: float, or
|
|
|
24
26
|
def bifrost_translate_energy_to_chopper_parameters(parameters: dict):
|
|
25
27
|
from itertools import product
|
|
26
28
|
from .bifrost_choppers import calculate
|
|
27
|
-
|
|
29
|
+
choppers = tuple(f'{a}_chopper_{b}' for a, b in product(['pulse_shaping', 'frame_overlap', 'bandwidth'], [1, 2]))
|
|
30
|
+
# names = [a+b for a, b in product(('ps', 'fo', 'bw'), ('1', '2'))]
|
|
31
|
+
for name in product(choppers, ('speed', 'phase')):
|
|
28
32
|
name = ''.join(name)
|
|
29
33
|
if name not in parameters:
|
|
30
34
|
parameters[name] = 0
|
|
31
35
|
order = get_and_remove(parameters, 'order', 14)
|
|
32
36
|
time = get_and_remove(parameters, 'time', get_and_remove(parameters, 't', 170/180/(2 * 15 * 14)))
|
|
33
|
-
return one_generic_energy_to_chopper_parameters(calculate, time, order, parameters)
|
|
37
|
+
return one_generic_energy_to_chopper_parameters(calculate, choppers, time, order, parameters)
|
|
34
38
|
|
|
35
39
|
|
|
36
40
|
def cspec_translate_energy_to_chopper_parameters(parameters: dict):
|
|
37
41
|
from itertools import product
|
|
38
42
|
from .cspec_choppers import calculate
|
|
39
|
-
|
|
43
|
+
choppers = ('bw1', 'bw2', 'bw3', 's', 'p', 'm1', 'm2')
|
|
44
|
+
for name in product(choppers, ('speed', 'phase')):
|
|
40
45
|
name = ''.join(name)
|
|
41
46
|
if name not in parameters:
|
|
42
47
|
parameters[name] = 0
|
|
43
48
|
time = get_and_remove(parameters, 'time', 0.004)
|
|
44
49
|
order = get_and_remove(parameters, 'order', 16)
|
|
45
|
-
return one_generic_energy_to_chopper_parameters(calculate, time, order, parameters)
|
|
50
|
+
return one_generic_energy_to_chopper_parameters(calculate, choppers, time, order, parameters)
|
|
46
51
|
|
|
47
52
|
|
|
48
53
|
def no_op_translate_energy_to_chopper_parameters(parameters: dict):
|
|
@@ -6,10 +6,9 @@ from __future__ import annotations
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
from typing import Union
|
|
8
8
|
from mccode_antlr.instr import Instr
|
|
9
|
-
from mccode_antlr.reader import Registry
|
|
10
9
|
|
|
11
10
|
|
|
12
|
-
def load_instr(filepath: Union[str, Path]
|
|
11
|
+
def load_instr(filepath: Union[str, Path]) -> Instr:
|
|
13
12
|
"""Loads an Instr object from a .instr file or a HDF5 file"""
|
|
14
13
|
from mccode_antlr.io import load_hdf5
|
|
15
14
|
from mccode_antlr.loader import load_mcstas_instr
|
|
@@ -19,23 +18,10 @@ def load_instr(filepath: Union[str, Path], extra_registries: list[Registry] | No
|
|
|
19
18
|
if not filepath.exists() or not filepath.is_file():
|
|
20
19
|
raise ValueError('The provided filepath does not exist or is not a file')
|
|
21
20
|
|
|
22
|
-
# FIXME this hack should be removed ASAP
|
|
23
|
-
if extra_registries is None:
|
|
24
|
-
from mccode_antlr.reader import GitHubRegistry
|
|
25
|
-
mcpl_input_once_registry = GitHubRegistry(
|
|
26
|
-
name='mcpl_input_once',
|
|
27
|
-
url='https://github.com/g5t/mccode-mcpl-input-once',
|
|
28
|
-
version='main',
|
|
29
|
-
filename='pooch-registry.txt'
|
|
30
|
-
)
|
|
31
|
-
extra_registries = [mcpl_input_once_registry]
|
|
32
|
-
|
|
33
21
|
if filepath.suffix == '.instr':
|
|
34
|
-
return load_mcstas_instr(filepath
|
|
22
|
+
return load_mcstas_instr(filepath)
|
|
35
23
|
|
|
36
|
-
|
|
37
|
-
instr.registries += tuple(extra_registries)
|
|
38
|
-
return instr
|
|
24
|
+
return load_hdf5(filepath)
|
|
39
25
|
|
|
40
26
|
|
|
41
27
|
def collect_parameter_dict(instr: Instr, kwargs: dict, strict: bool = True) -> dict:
|
|
@@ -60,7 +46,7 @@ def collect_parameter_dict(instr: Instr, kwargs: dict, strict: bool = True) -> d
|
|
|
60
46
|
for k, v in kwargs.items():
|
|
61
47
|
if k not in parameters:
|
|
62
48
|
if strict:
|
|
63
|
-
raise ValueError(f"Parameter {k} is not a valid parameter name")
|
|
49
|
+
raise ValueError(f"Parameter {k} is not a valid parameter name. Valid names are: {', '.join(parameters)}")
|
|
64
50
|
continue
|
|
65
51
|
if not isinstance(v, Value):
|
|
66
52
|
expected_type = parameters[k].data_type
|
|
@@ -1,20 +1,31 @@
|
|
|
1
1
|
import unittest
|
|
2
2
|
|
|
3
|
+
|
|
4
|
+
def parameters(names: tuple[str, ...]):
|
|
5
|
+
from itertools import product
|
|
6
|
+
return tuple(x + y for x, y in product(names, ('speed', 'phase')))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
CHOPPER_NAMES = ('pulse_shaping', 'frame_overlap', 'bandwidth')
|
|
10
|
+
CHOPPERS = tuple(f'{name}_chopper_{no}' for name in CHOPPER_NAMES for no in (1, 2))
|
|
11
|
+
OLD_CHOPPERS = tuple(f'{name}{no}' for name in ('ps', 'fo', 'bw') for no in (1, 2))
|
|
12
|
+
|
|
13
|
+
|
|
3
14
|
class BIFROSTEnergyTestCase(unittest.TestCase):
|
|
4
15
|
def setUp(self):
|
|
5
16
|
from mccode_antlr.loader import parse_mcstas_instr
|
|
6
17
|
instr = f"""DEFINE INSTRUMENT this_IS_NOT_BIFROST(
|
|
7
|
-
|
|
18
|
+
pulse_shaping_chopper_1speed, pulse_shaping_chopper_1phase, pulse_shaping_chopper_2speed, pulse_shaping_chopper_2phase, frame_overlap_chopper_1speed, frame_overlap_chopper_1phase, bandwidth_chopper_1speed, bandwidth_chopper_1phase, bandwidth_chopper_2speed, bandwidth_chopper_2phase
|
|
8
19
|
)
|
|
9
20
|
TRACE
|
|
10
21
|
COMPONENT origin = Arm() AT (0, 0, 0) ABSOLUTE
|
|
11
|
-
COMPONENT
|
|
12
|
-
COMPONENT
|
|
13
|
-
COMPONENT
|
|
14
|
-
COMPONENT
|
|
15
|
-
COMPONENT
|
|
16
|
-
COMPONENT
|
|
17
|
-
COMPONENT sample = Arm() AT (0, 0, 80) RELATIVE
|
|
22
|
+
COMPONENT pulse_shaping_chopper_1 = DiskChopper(theta_0=170, radius=0.35, nu=pulse_shaping_chopper_1speed, phase=pulse_shaping_chopper_1phase) AT (0, 0, 1) RELATIVE PREVIOUS
|
|
23
|
+
COMPONENT pulse_shaping_chopper_2 = DiskChopper(theta_0=170, radius=0.35, nu=pulse_shaping_chopper_2speed, phase=pulse_shaping_chopper_2phase) AT (0, 0, 0.02) RELATIVE pulse_shaping_chopper_1
|
|
24
|
+
COMPONENT frame_overlap_chopper_1 = DiskChopper(theta_0=110, radius=0.35, nu=frame_overlap_chopper_1speed, phase=frame_overlap_chopper_1phase) AT (0, 0, 12) RELATIVE pulse_shaping_chopper_2
|
|
25
|
+
COMPONENT frame_overlap_chopper_2 = DiskChopper(theta_0=115, radius=0.35, nu=frame_overlap_chopper_1speed, phase=frame_overlap_chopper_1phase) AT (0, 0, 4) RELATIVE frame_overlap_chopper_1
|
|
26
|
+
COMPONENT bandwidth_chopper_1 = DiskChopper(theta_0=110, radius=0.35, nu=bandwidth_chopper_1speed, phase=bandwidth_chopper_1phase) AT (0, 0, 80) RELATIVE frame_overlap_chopper_2
|
|
27
|
+
COMPONENT bandwidth_chopper_2 = DiskChopper(theta_0=115, radius=0.35, nu=bandwidth_chopper_2speed, phase=bandwidth_chopper_2phase) AT (0, 0, 0.02) RELATIVE bandwidth_chopper_1
|
|
28
|
+
COMPONENT sample = Arm() AT (0, 0, 80) RELATIVE bandwidth_chopper_2
|
|
18
29
|
END
|
|
19
30
|
"""
|
|
20
31
|
self.instr = parse_mcstas_instr(instr)
|
|
@@ -46,8 +57,8 @@ class BIFROSTEnergyTestCase(unittest.TestCase):
|
|
|
46
57
|
e = y * 0.5 + 1.7
|
|
47
58
|
self.assertAlmostEqual(x, e)
|
|
48
59
|
|
|
49
|
-
|
|
50
|
-
npts, names, points = parameters_to_scan(
|
|
60
|
+
scan_parameters = dict(order=order, time=time, ei=ei)
|
|
61
|
+
npts, names, points = parameters_to_scan(scan_parameters, grid=True)
|
|
51
62
|
self.assertEqual(npts, 47*11)
|
|
52
63
|
self.assertEqual(names, ['order', 'time', 'ei'])
|
|
53
64
|
all_points = list(points)
|
|
@@ -68,7 +79,7 @@ class BIFROSTEnergyTestCase(unittest.TestCase):
|
|
|
68
79
|
from restage.energy import energy_to_chopper_translator
|
|
69
80
|
from restage.energy import bifrost_translate_energy_to_chopper_parameters
|
|
70
81
|
from restage.range import MRange, Singular, parameters_to_scan
|
|
71
|
-
|
|
82
|
+
|
|
72
83
|
|
|
73
84
|
translator = energy_to_chopper_translator(self.instr.name)
|
|
74
85
|
self.assertEqual(translator, bifrost_translate_energy_to_chopper_parameters)
|
|
@@ -76,36 +87,33 @@ class BIFROSTEnergyTestCase(unittest.TestCase):
|
|
|
76
87
|
order = Singular(14, 1)
|
|
77
88
|
time = MRange(0.0001, 0.002248, 0.0002)
|
|
78
89
|
ei = MRange(1.7, 24.7, 0.5)
|
|
79
|
-
|
|
90
|
+
scan_parameters = dict(order=order, time=time, ei=ei)
|
|
80
91
|
|
|
81
|
-
spts, names, points = parameters_to_scan(
|
|
92
|
+
spts, names, points = parameters_to_scan(scan_parameters, grid=True)
|
|
82
93
|
|
|
83
94
|
self.assertEqual(47*11, spts)
|
|
84
95
|
self.assertEqual(names, ['order', 'time', 'ei'])
|
|
85
96
|
|
|
86
|
-
|
|
87
|
-
|
|
97
|
+
chopper_parameters = parameters(CHOPPERS)
|
|
88
98
|
for point in points:
|
|
89
99
|
kv = {k: v for k, v in zip(names, point)}
|
|
90
100
|
translated = translator(kv)
|
|
91
|
-
for x in
|
|
92
|
-
self.assertTrue(
|
|
101
|
+
for x in chopper_parameters:
|
|
102
|
+
self.assertTrue(x in translated)
|
|
93
103
|
|
|
94
|
-
self.assertEqual(len(translated), len(
|
|
95
|
-
self.assertAlmostEqual(translated['
|
|
96
|
-
self.assertAlmostEqual(translated['
|
|
97
|
-
self.assertAlmostEqual(translated['
|
|
98
|
-
self.assertAlmostEqual(translated['
|
|
99
|
-
self.assertAlmostEqual(translated['
|
|
100
|
-
self.assertAlmostEqual(translated['
|
|
104
|
+
self.assertEqual(len(translated), len(chopper_parameters))
|
|
105
|
+
self.assertAlmostEqual(translated['bandwidth_chopper_1speed'], 14.0)
|
|
106
|
+
self.assertAlmostEqual(translated['bandwidth_chopper_2speed'], -14.0)
|
|
107
|
+
self.assertAlmostEqual(translated['frame_overlap_chopper_1speed'], 14.0)
|
|
108
|
+
self.assertAlmostEqual(translated['frame_overlap_chopper_1speed'], 14.0)
|
|
109
|
+
self.assertAlmostEqual(translated['pulse_shaping_chopper_1speed'], 14*14.0)
|
|
110
|
+
self.assertAlmostEqual(translated['pulse_shaping_chopper_2speed'], 14*14.0)
|
|
101
111
|
|
|
102
112
|
def test_calculations(self):
|
|
103
113
|
from itertools import product
|
|
104
114
|
from chopcal import bifrost as mcstas_bifrost_calculation
|
|
105
115
|
from restage.energy import bifrost_translate_energy_to_chopper_parameters
|
|
106
116
|
|
|
107
|
-
pars = [x+y for x, y in product(('ps1', 'ps2', 'fo1', 'fo2', 'bw1', 'bw2'), ('speed', 'phase'))]
|
|
108
|
-
|
|
109
117
|
shortest_time = 0.0001 # this is approximately twice the opening time of the pulse shaping choppers at 15*14 Hz
|
|
110
118
|
# Normal operation Shortest full-height pulse Shorter pulses reduce height
|
|
111
119
|
# /-----\ /\
|
|
@@ -129,8 +137,8 @@ class BIFROSTEnergyTestCase(unittest.TestCase):
|
|
|
129
137
|
kv = {'order': order, 'time': time, 'ei': energy}
|
|
130
138
|
translated = bifrost_translate_energy_to_chopper_parameters(kv)
|
|
131
139
|
from_mcstas = mcstas_bifrost_calculation(energy, 0., time)
|
|
132
|
-
for x in
|
|
133
|
-
self.assertAlmostEqual(from_mcstas[
|
|
140
|
+
for o, x in zip(parameters(OLD_CHOPPERS), parameters(CHOPPERS)):
|
|
141
|
+
self.assertAlmostEqual(from_mcstas[o], translated[x])
|
|
134
142
|
|
|
135
143
|
|
|
136
144
|
if __name__ == '__main__':
|
|
@@ -218,6 +218,13 @@ class SplitRunTestCase(unittest.TestCase):
|
|
|
218
218
|
shutil.rmtree(self.dir)
|
|
219
219
|
|
|
220
220
|
def test_simple_scan(self):
|
|
221
|
+
"""This test requires MCPL shared libraries to work
|
|
222
|
+
|
|
223
|
+
For some unexplored reason, MCPL shared libraries are not found in their
|
|
224
|
+
default installed location, /usr/local/lib64/libmcpl.so; so this test must
|
|
225
|
+
be invoked with that location specified, e.g.,
|
|
226
|
+
$ LD_LIBRARY_PATH=/usr/local/lib64 pytest test/test_single.py -k test_simple_scan
|
|
227
|
+
"""
|
|
221
228
|
# Scanning a1 and a2 with a2=2*a1 should produce approximately the same intensity for all points
|
|
222
229
|
# as long as a1 is between the limits of min_a1 and max_a1
|
|
223
230
|
from restage.splitrun import splitrun
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|