restage 0.8.0__tar.gz → 0.8.2__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 (37) hide show
  1. {restage-0.8.0/src/restage.egg-info → restage-0.8.2}/PKG-INFO +2 -2
  2. {restage-0.8.0 → restage-0.8.2}/pyproject.toml +1 -1
  3. {restage-0.8.0 → restage-0.8.2}/src/restage/splitrun.py +51 -13
  4. {restage-0.8.0 → restage-0.8.2/src/restage.egg-info}/PKG-INFO +2 -2
  5. {restage-0.8.0 → restage-0.8.2}/src/restage.egg-info/requires.txt +1 -1
  6. {restage-0.8.0 → restage-0.8.2}/test/test_single.py +33 -5
  7. {restage-0.8.0 → restage-0.8.2}/.github/workflows/pip.yml +0 -0
  8. {restage-0.8.0 → restage-0.8.2}/.github/workflows/wheels.yml +0 -0
  9. {restage-0.8.0 → restage-0.8.2}/.gitignore +0 -0
  10. {restage-0.8.0 → restage-0.8.2}/README.md +0 -0
  11. {restage-0.8.0 → restage-0.8.2}/setup.cfg +0 -0
  12. {restage-0.8.0 → restage-0.8.2}/src/restage/__init__.py +0 -0
  13. {restage-0.8.0 → restage-0.8.2}/src/restage/bifrost_choppers.py +0 -0
  14. {restage-0.8.0 → restage-0.8.2}/src/restage/cache.py +0 -0
  15. {restage-0.8.0 → restage-0.8.2}/src/restage/config/__init__.py +0 -0
  16. {restage-0.8.0 → restage-0.8.2}/src/restage/config/default.yaml +0 -0
  17. {restage-0.8.0 → restage-0.8.2}/src/restage/cspec_choppers.py +0 -0
  18. {restage-0.8.0 → restage-0.8.2}/src/restage/database.py +0 -0
  19. {restage-0.8.0 → restage-0.8.2}/src/restage/emulate.py +0 -0
  20. {restage-0.8.0 → restage-0.8.2}/src/restage/energy.py +0 -0
  21. {restage-0.8.0 → restage-0.8.2}/src/restage/instr.py +0 -0
  22. {restage-0.8.0 → restage-0.8.2}/src/restage/mcpl.py +0 -0
  23. {restage-0.8.0 → restage-0.8.2}/src/restage/range.py +0 -0
  24. {restage-0.8.0 → restage-0.8.2}/src/restage/run.py +0 -0
  25. {restage-0.8.0 → restage-0.8.2}/src/restage/scan.py +0 -0
  26. {restage-0.8.0 → restage-0.8.2}/src/restage/tables.py +0 -0
  27. {restage-0.8.0 → restage-0.8.2}/src/restage.egg-info/SOURCES.txt +0 -0
  28. {restage-0.8.0 → restage-0.8.2}/src/restage.egg-info/dependency_links.txt +0 -0
  29. {restage-0.8.0 → restage-0.8.2}/src/restage.egg-info/entry_points.txt +0 -0
  30. {restage-0.8.0 → restage-0.8.2}/src/restage.egg-info/top_level.txt +0 -0
  31. {restage-0.8.0 → restage-0.8.2}/test/test_cache.py +0 -0
  32. {restage-0.8.0 → restage-0.8.2}/test/test_cache_ro.py +0 -0
  33. {restage-0.8.0 → restage-0.8.2}/test/test_database.py +0 -0
  34. {restage-0.8.0 → restage-0.8.2}/test/test_energy.py +0 -0
  35. {restage-0.8.0 → restage-0.8.2}/test/test_env_vars.py +0 -0
  36. {restage-0.8.0 → restage-0.8.2}/test/test_range.py +0 -0
  37. {restage-0.8.0 → restage-0.8.2}/test/test_scan.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: restage
3
- Version: 0.8.0
3
+ Version: 0.8.2
4
4
  Author-email: Gregory Tucker <gregory.tucker@ess.eu>
5
5
  License: BSD-3-Clause
6
6
  Classifier: License :: OSI Approved :: BSD License
@@ -17,7 +17,7 @@ Requires-Dist: zenlog>=1.1
17
17
  Requires-Dist: platformdirs>=3.11
18
18
  Requires-Dist: confuse
19
19
  Requires-Dist: psutil>=5.9.6
20
- Requires-Dist: mccode-antlr[hdf5]>=0.15.0
20
+ Requires-Dist: mccode-antlr[hdf5]>=0.15.1
21
21
  Provides-Extra: test
22
22
  Requires-Dist: pytest; extra == "test"
23
23
  Requires-Dist: chopcal; extra == "test"
@@ -9,7 +9,7 @@ dependencies = [
9
9
  'platformdirs>=3.11',
10
10
  'confuse',
11
11
  'psutil>=5.9.6',
12
- 'mccode-antlr[hdf5]>=0.15.0',
12
+ 'mccode-antlr[hdf5]>=0.15.1',
13
13
  ]
14
14
  readme = "README.md"
15
15
  license = {text = "BSD-3-Clause"}
@@ -1,6 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from pathlib import Path
4
+ from typing import Optional
5
+
4
6
  from .tables import SimulationEntry, InstrEntry
5
7
 
6
8
  def mcpl_parameters_split(s: str) -> list[tuple[str, str]]:
@@ -13,6 +15,8 @@ def si_int(s: str) -> int:
13
15
  'Ki': 2 ** 10, 'Mi': 2 ** 20, 'Gi': 2 ** 30, 'Ti': 2 ** 40, 'Pi': 2 ** 50
14
16
  }
15
17
  def int_mult(x: str, mult: int = 1):
18
+ if len(x) == 0 and mult > 1:
19
+ return mult
16
20
  return int(x) * mult if x.isnumeric() else int(float(x) * mult)
17
21
 
18
22
  def do_parse():
@@ -24,7 +28,7 @@ def si_int(s: str) -> int:
24
28
  return int_mult(s)
25
29
  value = do_parse()
26
30
  if value < 0:
27
- logger.info('Negative value encountered')
31
+ raise ValueError(f'Negative {value=} encountered')
28
32
  elif value > 2**53:
29
33
  logger.info(
30
34
  'McStas/McXtrace parse integer inputs as doubles,'
@@ -33,6 +37,17 @@ def si_int(s: str) -> int:
33
37
  )
34
38
  return value
35
39
 
40
+ def si_int_limits(s: str) -> tuple[Optional[int], int, Optional[int]]:
41
+ low, high = None, None
42
+ min_seps, max_seps = (']', '-', '}'), ('[', '+', '{')
43
+ if any(x in s for x in min_seps):
44
+ low, s = s.split(next(x for x in min_seps if x in s), maxsplit=1)
45
+ low = si_int(low)
46
+ if any(x in s for x in max_seps):
47
+ s, high = s.split(next(x for x in max_seps if x in s), maxsplit=1)
48
+ high = si_int(high)
49
+ return low, si_int(s), high
50
+
36
51
  def make_splitrun_parser():
37
52
  from argparse import ArgumentParser
38
53
  parser = ArgumentParser('splitrun')
@@ -40,7 +55,8 @@ def make_splitrun_parser():
40
55
  aa('instrument', type=str, default=None,
41
56
  help='Instrument `.instr` file name or serialised HDF5 or JSON Instr object')
42
57
  aa('parameters', nargs='*', type=str, default=None)
43
- aa('-n', '--ncount', type=si_int, default=None, help='Number of neutrons to simulate')
58
+ aa('-n', '--ncount', type=si_int_limits, default=None, metavar='[MIN-]COUNT[+MAX]',
59
+ help='COUNT {number}[kMGTP] target, MIN MAX replace missing --nmin --nmax')
44
60
  aa('-m', '--mesh', action='store_true', default=False, help='N-dimensional mesh scan')
45
61
  aa('-d', '--dir', type=str, default=None, help='Output directory')
46
62
  aa('-s', '--seed', type=int, default=None, help='Random number generator seed')
@@ -49,16 +65,16 @@ def make_splitrun_parser():
49
65
  help='Enable gravitation for all trajectories')
50
66
  aa('--bufsiz', type=si_int, default=None, help='Monitor_nD list/buffer-size')
51
67
  aa('--format', type=str, default=None, help='Output data files using FORMAT')
52
- aa('--nmin', type=int, default=None,
53
- help='Minimum number of particles to simulate during first instrument simulations')
54
- aa('--nmax', type=int, default=None,
55
- help='Maximum number of particles to simulate during first instrument simulations')
68
+ aa('--nmin', type=si_int, default=None, metavar='MIN',
69
+ help='MIN {number}[kMGTP] rays per first-instrument simulation')
70
+ aa('--nmax', type=si_int, default=None, metavar='MAX',
71
+ help='MAX {number}[kMGTP] rays per first-instrument simulation')
56
72
  aa('--dryrun', action='store_true', default=False,
57
73
  help='Do not run any simulations, just print the commands')
58
74
  aa('--parallel', action='store_true', default=False,
59
- help='Use MPI multi-process parallelism (primary instrument only at the moment)')
75
+ help='Use MPI multi-process parallelism')
60
76
  aa('--gpu', action='store_true', default=False,
61
- help='Use GPU OpenACC parallelism (primary instrument only at the moment)')
77
+ help='Use GPU OpenACC parallelism')
62
78
  aa('--process-count', type=int, default=0,
63
79
  help='MPI process count, 0 == System Default')
64
80
  # splitrun controlling parameters
@@ -119,6 +135,31 @@ def parse_splitrun_precision(unparsed: list[str]) -> dict[str, float]:
119
135
  precision[k] = float(v)
120
136
  return precision
121
137
 
138
+ def args_fixup(args):
139
+ """Ensure that arguments match expectations
140
+
141
+ - MCPL input and output instance parameters should be dictionaries if present.
142
+ - NCOUNT needs to be separated into (MIN, COUNT, MAX) values, with multiple
143
+ specifications of either MIN or MAX checked for consistency
144
+ """
145
+ if args.mcpl_input_parameters is not None:
146
+ args.mcpl_input_parameters = dict(args.mcpl_input_parameters)
147
+ if args.mcpl_output_parameters is not None:
148
+ args.mcpl_output_parameters = dict(args.mcpl_output_parameters)
149
+
150
+ if args.ncount is not None:
151
+ nmin, ncount, nmax = args.ncount
152
+ if args.nmin and nmin and args.nmin != nmin:
153
+ raise ValueError(f'Invalid repeated nmin specification: {nmin} != {args.nmin}')
154
+ if args.nmax and nmax and args.nmax != nmax:
155
+ raise ValueError(f'Invalid repeated nmax specification: {nmax} != {args.nmax}')
156
+ if nmin and not args.nmin:
157
+ args.nmin = nmin
158
+ if nmax and not args.nmax:
159
+ args.nmax = nmax
160
+ args.ncount = ncount
161
+
162
+ return args
122
163
 
123
164
  def parse_splitrun(parser):
124
165
  from .range import parse_scan_parameters
@@ -126,11 +167,8 @@ def parse_splitrun(parser):
126
167
  import sys
127
168
  sys.argv[1:] = sort_args(sys.argv[1:])
128
169
 
129
- args = parser.parse_args()
130
- if args.mcpl_input_parameters is not None:
131
- args.mcpl_input_parameters = dict(args.mcpl_input_parameters)
132
- if args.mcpl_output_parameters is not None:
133
- args.mcpl_output_parameters = dict(args.mcpl_output_parameters)
170
+ args = args_fixup(parser.parse_args())
171
+
134
172
  parameters = parse_scan_parameters(args.parameters)
135
173
  precision = parse_splitrun_precision(args.P)
136
174
  return args, parameters, precision
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: restage
3
- Version: 0.8.0
3
+ Version: 0.8.2
4
4
  Author-email: Gregory Tucker <gregory.tucker@ess.eu>
5
5
  License: BSD-3-Clause
6
6
  Classifier: License :: OSI Approved :: BSD License
@@ -17,7 +17,7 @@ Requires-Dist: zenlog>=1.1
17
17
  Requires-Dist: platformdirs>=3.11
18
18
  Requires-Dist: confuse
19
19
  Requires-Dist: psutil>=5.9.6
20
- Requires-Dist: mccode-antlr[hdf5]>=0.15.0
20
+ Requires-Dist: mccode-antlr[hdf5]>=0.15.1
21
21
  Provides-Extra: test
22
22
  Requires-Dist: pytest; extra == "test"
23
23
  Requires-Dist: chopcal; extra == "test"
@@ -2,7 +2,7 @@ zenlog>=1.1
2
2
  platformdirs>=3.11
3
3
  confuse
4
4
  psutil>=5.9.6
5
- mccode-antlr[hdf5]>=0.15.0
5
+ mccode-antlr[hdf5]>=0.15.1
6
6
 
7
7
  [test]
8
8
  pytest
@@ -45,17 +45,28 @@ class SingleTestCase(unittest.TestCase):
45
45
  self.assertEqual(args.split_at, 'here')
46
46
  self.assertTrue(args.mesh)
47
47
 
48
+ def test_negative_count_throws(self):
49
+ from restage.splitrun import si_int, si_int_limits
50
+ with self.assertRaises(ValueError):
51
+ si_int('-10')
52
+ with self.assertRaises(ValueError):
53
+ si_int_limits('10--4+10') # '10--4+10' -> ('10', '-4+10') -> (10, '-4', '10')
54
+ with self.assertRaises(ValueError):
55
+ # This is probably a parsing error, but would raise a negative error
56
+ # in si_int, so is fine. '-10]-2[-1' -> ('','10]-2[-1') -> Error on int('')
57
+ si_int_limits('-10]-2[-1')
58
+
48
59
  def test_mccode_flags(self):
49
- args = self.parser.parse_args(['test.instr', '-s', '123456', '-n', '-1', '-d', '/a/dir', '-t', '-g'])
60
+ args = self.parser.parse_args(['test.instr', '-s', '123456', '-n', '1', '-d', '/a/dir', '-t', '-g'])
50
61
  self.assertEqual(args.seed, 123456)
51
- self.assertEqual(args.ncount, -1)
62
+ self.assertEqual(args.ncount, (None, 1, None))
52
63
  self.assertEqual(args.dir, '/a/dir')
53
64
  self.assertEqual(args.trace, True)
54
65
  self.assertEqual(args.gravitation, True)
55
66
 
56
67
  args = self.parser.parse_args(['test.instr', '-s=99999', '-n=10000', '-d=/b/dir'])
57
68
  self.assertEqual(args.seed, 99999)
58
- self.assertEqual(args.ncount, 10000)
69
+ self.assertEqual(args.ncount, (None, 10000, None))
59
70
  self.assertEqual(args.dir, '/b/dir')
60
71
  self.assertEqual(args.trace, False)
61
72
  self.assertEqual(args.gravitation, False)
@@ -63,7 +74,7 @@ class SingleTestCase(unittest.TestCase):
63
74
  args = self.parser.parse_args(['test.instr', '--seed', '888', '--ncount', '4', '--dir', '/c/dir', '--trace',
64
75
  '--gravitation', '--bufsiz', '1000', '--format', 'NEXUS'])
65
76
  self.assertEqual(args.seed, 888)
66
- self.assertEqual(args.ncount, 4)
77
+ self.assertEqual(args.ncount, (None, 4, None))
67
78
  self.assertEqual(args.dir, '/c/dir')
68
79
  self.assertEqual(args.trace, True)
69
80
  self.assertEqual(args.gravitation, True)
@@ -73,13 +84,30 @@ class SingleTestCase(unittest.TestCase):
73
84
  args = self.parser.parse_args(['test.instr', '--seed=777', '--ncount=5', '--dir=/d/dir', '--bufsiz=2000',
74
85
  '--format=RAW'])
75
86
  self.assertEqual(args.seed, 777)
76
- self.assertEqual(args.ncount, 5)
87
+ self.assertEqual(args.ncount, (None, 5, None))
77
88
  self.assertEqual(args.dir, '/d/dir')
78
89
  self.assertEqual(args.trace, False)
79
90
  self.assertEqual(args.gravitation, False)
80
91
  self.assertEqual(args.bufsiz, 2000)
81
92
  self.assertEqual(args.format, 'RAW')
82
93
 
94
+ def test_ncount_varieties(self):
95
+ args = self.parser.parse_args(['test.instr', '--ncount=5'])
96
+ self.assertEqual(args.ncount, (None, 5, None))
97
+ args = self.parser.parse_args(['test.instr', '-n' ,'4k'])
98
+ self.assertEqual(args.ncount, (None, 4000, None))
99
+ args = self.parser.parse_args(['test.instr', '-n', '3-2+1'])
100
+ self.assertEqual(args.ncount, (3, 2, 1))
101
+ args = self.parser.parse_args(['test.instr', '-n', '1M]1G[1T'])
102
+ self.assertEqual(args.ncount, (10**6, 10**9, 10**12))
103
+ args = self.parser.parse_args(['test.instr', '-n', '1Ki}Mi{2Gi'])
104
+ self.assertEqual(args.ncount, (2**10, 2**20, 2**31))
105
+ args = self.parser.parse_args(['t.instr', '-n', '1.1M', '--nmin', 'M', '--nmax', '2M'])
106
+ self.assertEqual(args.ncount, (None, 1100000, None))
107
+ self.assertEqual(args.nmin, 1000000)
108
+ self.assertEqual(args.nmax, 2000000)
109
+
110
+
83
111
  def test_parameters(self):
84
112
  from restage.range import MRange, Singular, parameters_to_scan, parse_scan_parameters
85
113
  args = self.parser.parse_args(['test.instr', 'a=1.0', 'b=2', 'c=3:5', 'd=blah', 'e=/data', '-m'])
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