Skip to content

Commit a4d2403

Browse files
authored
Merge pull request #15 from ISISComputingGroup/Ticket8523_Remove_use_of_arrange
Ticket8523 remove use of arrange
2 parents e472f3e + 63d2e1e commit a4d2403

13 files changed

+583
-270
lines changed

emuloop.py

Lines changed: 143 additions & 81 deletions
Large diffs are not rendered by default.

emulooptime.py

Lines changed: 140 additions & 87 deletions
Large diffs are not rendered by default.

example_loop.py

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,35 @@
1-
import numpy as np
1+
from typing import Generator, Optional
2+
23
from genie_python import genie as g
34
from genie_python.genie_script_generator import ScriptDefinition, cast_parameters_to
45

6+
from script_utilities import get_steps
7+
8+
9+
def inclusive_float_range_with_step_flip(start: float, stop: float, step: float) -> Generator:
10+
"""
11+
If we are counting downwards from start to stop automatically flips step to be negative.
12+
Inclusive of stop. Only tested for float values.
13+
14+
Parameters:
15+
start (float): the value to start the range from
16+
stop (float): the value to stop the range at
17+
step (float): the steps to take from start to stop
18+
19+
Returns:
20+
The range from start to stop including all steps in between.
21+
22+
Examples:
23+
>>> inclusive_float_range_with_step_flip(0.5, 2, 0.5) == [0.5, 1, 1.5, 2]
24+
>>> inclusive_float_range_with_step_flip(2, 0.5, 0.5) == [2, 1.5, 1, 0.5]
25+
"""
26+
# Get the modulo so we know to stop early like arrange if the steps don't fit evenly.
27+
yield from get_steps(start, step, stop)
28+
529

630
class DoRun(ScriptDefinition):
731
@cast_parameters_to(start_temp=float, stop_temp=float, step_temp=float)
8-
def run(self, start_temp=1.0, stop_temp=1.0, step_temp=0.5):
32+
def run(self, start_temp: float = 1.0, stop_temp: float = 1.0, step_temp: float = 0.5) -> None:
933
# Execute the loop once
1034
if start_temp == stop_temp:
1135
step_temp = 1.0
@@ -16,30 +40,37 @@ def run(self, start_temp=1.0, stop_temp=1.0, step_temp=0.5):
1640
else:
1741
stop_temp -= small_amount
1842
# Regular range can't use floats
19-
for temp in np.arange(start_temp, stop_temp, step_temp):
43+
for temp in inclusive_float_range_with_step_flip(start_temp, stop_temp, step_temp):
2044
g.cset("temperature", temp)
2145
g.begin(quiet=True)
2246
g.waitfor_time(seconds=30)
2347
g.end(quiet=True)
2448

2549
@cast_parameters_to(start_temp=float, stop_temp=float, step_temp=float)
26-
def parameters_valid(self, start_temp=1.0, stop_temp=1.0, step_temp=0.5):
50+
def parameters_valid(
51+
self, start_temp: float = 1.0, stop_temp: float = 1.0, step_temp: float = 0.5
52+
) -> Optional[str]:
2753
errors = ""
2854
if start_temp == 0 or stop_temp == 0:
2955
errors += "Cannot go to zero kelvin\n"
3056
if start_temp < stop_temp and step_temp < 0.0:
3157
errors += "Stepping backwards when stop temp is higher than start temp\n"
3258
elif start_temp > stop_temp and step_temp > 0.0:
3359
errors += "Stepping forward when stop temp is lower than start temp\n"
60+
if errors != "":
61+
return errors
62+
return None
3463

3564
@cast_parameters_to(start_temp=float, stop_temp=float, step_temp=float)
36-
def estimate_time(self, start_temp=1.0, stop_temp=1.0, step_temp=0.5):
65+
def estimate_time(
66+
self, start_temp: float = 1.0, stop_temp: float = 1.0, step_temp: float = 0.5
67+
) -> int:
3768
if stop_temp >= start_temp:
3869
steps = round((stop_temp - start_temp) / step_temp)
3970
estimated_time = 30 + steps * 30
4071
return estimated_time
4172
else:
4273
return 0
4374

44-
def get_help(self):
75+
def get_help(self) -> str:
4576
return "An example config to show a looping mechanism"

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
genie_python>=15.1.0-rc1

script_utilities.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from typing import Generator
2+
3+
import numpy as np
4+
5+
6+
def get_steps(start: float, step: float, stop: float) -> Generator[float, None, None]:
7+
modulo = abs(stop - start) % abs(step)
8+
if stop > start:
9+
vstop = stop - modulo
10+
else:
11+
vstop = stop + modulo
12+
for i in np.linspace(start, vstop, int(abs(vstop - start) / abs(step)) + 1):
13+
if ((i >= start) and (i <= stop)) or (
14+
(i >= stop) and (i <= start)
15+
): # Check inserted here to ensure scan remains within defined range
16+
yield i

test_emu/test_casters.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import unittest
22

3-
import numpy as np
4-
from emu import float_or_keep as float_or_keep_emu
5-
from emu import magnet_device_type as magnet_device_type_emu
6-
from emu import magnet_devices as magnet_devices_emu
73
from hamcrest import assert_that, calling, raises
84

95
from emuloop import cast_custom_expression as cast_custom_expression_emuloop
106
from emuloop import float_or_keep as float_or_keep_emuloop
117
from emuloop import magnet_device_type as magnet_device_type_emuloop
128
from emuloop import magnet_devices as magnet_devices_emuloop
9+
from emulooptime import float_or_keep as float_or_keep_emu
10+
from emulooptime import magnet_device_type as magnet_device_type_emu
11+
from emulooptime import magnet_devices as magnet_devices_emu
12+
from script_utilities import get_steps
1313

1414

1515
class TestMagnetCaster(unittest.TestCase):
@@ -82,7 +82,7 @@ def test_GIVEN_keep_different_cases_WHEN_cast_THEN_return_none(self):
8282
self.assertIsNone(float_or_keep_emuloop(keep.upper()))
8383

8484
def test_GIVEN_string_convertable_to_float_WHEN_cast_THEN_return_casted_value(self):
85-
for float_val in np.arange(4.0, 5.0, 0.2):
85+
for float_val in get_steps(4.0, 0.2, 5.0):
8686
self.assertEqual(float_or_keep_emu(str(float_val)), float_val)
8787
self.assertEqual(float_or_keep_emuloop(str(float_val)), float_val)
8888

test_emu/test_emu_param_validation.py

Lines changed: 0 additions & 49 deletions
This file was deleted.

test_emu/test_emuloop_param_validation.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ def setUp(self):
4747
"start_temperature": "keep",
4848
"stop_temperature": "keep",
4949
"step_temperature": "1",
50-
"start_field": "keep",
51-
"stop_field": "keep",
50+
"start_field": "1",
51+
"stop_field": "1",
5252
"step_field": "1",
5353
"custom": "None",
5454
"mevents": "10",
@@ -61,8 +61,8 @@ def setUp(self):
6161
"start_temperature": "keep",
6262
"stop_temperature": "1.0",
6363
"step_temperature": "1",
64-
"start_field": "keep",
65-
"stop_field": "keep",
64+
"start_field": "1",
65+
"stop_field": "1",
6666
"step_field": "1",
6767
"custom": "None",
6868
"mevents": "10",
@@ -75,8 +75,8 @@ def setUp(self):
7575
"start_temperature": "1.0",
7676
"stop_temperature": "keep",
7777
"step_temperature": "1",
78-
"start_field": "keep",
79-
"stop_field": "keep",
78+
"start_field": "1",
79+
"stop_field": "1",
8080
"step_field": "1",
8181
"custom": "None",
8282
"mevents": "10",
@@ -89,12 +89,12 @@ def setUp(self):
8989
"start_temperature": "keep",
9090
"stop_temperature": "keep",
9191
"step_temperature": "1",
92-
"start_field": "keep",
93-
"stop_field": "1.0",
92+
"start_field": "1",
93+
"stop_field": "keep",
9494
"step_field": "1",
9595
"custom": "None",
9696
"mevents": "10",
97-
"magnet_device": "TF",
97+
"magnet_device": "N/A",
9898
},
9999
start_stop_must_both_be_keep_error_message.format("field"),
100100
),
@@ -103,12 +103,12 @@ def setUp(self):
103103
"start_temperature": "keep",
104104
"stop_temperature": "keep",
105105
"step_temperature": "1",
106-
"start_field": "1.0",
107-
"stop_field": "keep",
106+
"start_field": "keep",
107+
"stop_field": "1",
108108
"step_field": "1",
109109
"custom": "None",
110110
"mevents": "10",
111-
"magnet_device": "TF",
111+
"magnet_device": "N/A",
112112
},
113113
start_stop_must_both_be_keep_error_message.format("field"),
114114
),

test_emu/test_emuloop_range.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,36 @@ def test_GIVEN_inverted_float_range_WHEN_get_range_THEN_inclusive_AND_expected_v
2323
returned_range.append(i)
2424
# THEN inclusive AND expected values
2525
self.assertEqual([2, 1.5, 1, 0.5], returned_range)
26+
27+
def test_GIVEN_float_range_AND_difference_not_divisible_by_step_WHEN_get_range_matches_arrange(
28+
self,
29+
):
30+
start, stop, step = 1, 2, 0.3
31+
# WHEN get range
32+
returned_range = []
33+
for i in inclusive_float_range_with_step_flip(start, stop, step):
34+
returned_range.append(i)
35+
# THEN inclusive AND expected values
36+
self.assertEqual([1, 1.3, 1.6, 1.9], returned_range)
37+
38+
def test_GIVEN_inverted_float_range_AND_difference_not_divisible_by_step_WHEN_get_range_matches_arrange(
39+
self,
40+
):
41+
start, stop, step = 2, 1, 0.3
42+
# WHEN get range
43+
returned_range = []
44+
for i in inclusive_float_range_with_step_flip(start, stop, step):
45+
returned_range.append(i)
46+
# THEN inclusive AND expected values
47+
self.assertEqual([2, 1.7, 1.4, 1.1], returned_range)
48+
49+
def test_GIVEN_inverted_float_range_AND_difference_not_divisible_by_step_AND_negative_step_WHEN_get_range_matches_arrange(
50+
self,
51+
):
52+
start, stop, step = 2, 1, -0.3
53+
# WHEN get range
54+
returned_range = []
55+
for i in inclusive_float_range_with_step_flip(start, stop, step):
56+
returned_range.append(i)
57+
# THEN inclusive AND expected values
58+
self.assertEqual([2, 1.7, 1.4, 1.1], returned_range)

test_emu/test_emuloop_run.py

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
class TestRun(unittest.TestCase):
1111
def setUp(self):
1212
self.script_definition = DoRun()
13-
self.script_definition.check_mevents_and_begin_waitfor_mevents_end = MagicMock()
13+
self.check_mevents_mock = MagicMock()
14+
self.script_definition.check_mevents_and_begin_waitfor_mevents_end = self.check_mevents_mock
1415
inst.reset_mock()
1516

1617
@patch.dict("sys.modules", inst=inst)
@@ -34,9 +35,7 @@ def test_GIVEN_both_temp_field_scans_WHEN_run_THEN_scans_run_once_for_each_set(
3435
inst.lf0.assert_called_once()
3536
self.assertEqual(inst.settemp.call_count, 10)
3637
self.assertEqual(inst.setmag.call_count, 10 * 10)
37-
self.assertEqual(
38-
self.script_definition.check_mevents_and_begin_waitfor_mevents_end.call_count, 10 * 10
39-
)
38+
self.assertEqual(self.check_mevents_mock.call_count, 10 * 10)
4039

4140
@patch.dict("sys.modules", inst=inst)
4241
@patch("six.moves.builtins.eval")
@@ -59,9 +58,7 @@ def test_GIVEN_temp_scan_field_point_WHEN_run_THEN_setmag_called_once_AND_scan_r
5958
inst.lf0.assert_called_once()
6059
self.assertEqual(inst.settemp.call_count, 10)
6160
inst.setmag.assert_called_once()
62-
self.assertEqual(
63-
self.script_definition.check_mevents_and_begin_waitfor_mevents_end.call_count, 10
64-
)
61+
self.assertEqual(self.check_mevents_mock.call_count, 10)
6562

6663
@patch.dict("sys.modules", inst=inst)
6764
@patch("six.moves.builtins.eval")
@@ -84,9 +81,7 @@ def test_GIVEN_field_scan_temp_point_WHEN_run_THEN_settemp_called_once_AND_scan_
8481
inst.tf0.assert_called_once()
8582
inst.settemp.assert_called_once()
8683
self.assertEqual(inst.setmag.call_count, 10)
87-
self.assertEqual(
88-
self.script_definition.check_mevents_and_begin_waitfor_mevents_end.call_count, 10
89-
)
84+
self.assertEqual(self.check_mevents_mock.call_count, 10)
9085

9186
@patch.dict("sys.modules", inst=inst)
9287
@patch("six.moves.builtins.eval")
@@ -109,7 +104,7 @@ def test_GIVEN_both_field_and_temp_points_WHEN_run_THEN_temp_mag_run_called_once
109104
inst.tf0.assert_called_once()
110105
inst.settemp.assert_called_once()
111106
inst.setmag.assert_called_once()
112-
self.script_definition.check_mevents_and_begin_waitfor_mevents_end.assert_called_once()
107+
self.check_mevents_mock.assert_called_once()
113108

114109
@patch.dict("sys.modules", inst=inst)
115110
@patch("six.moves.builtins.eval")
@@ -132,9 +127,7 @@ def test_GIVEN_one_of_start_stop_field_is_keep_AND_temp_scan_WHEN_run_THEN_setma
132127
inst.tf0.assert_not_called()
133128
self.assertEqual(inst.settemp.call_count, 10)
134129
inst.setmag.assert_not_called()
135-
self.assertEqual(
136-
self.script_definition.check_mevents_and_begin_waitfor_mevents_end.call_count, 10
137-
)
130+
self.assertEqual(self.check_mevents_mock.call_count, 10)
138131

139132
@patch.dict("sys.modules", inst=inst)
140133
@patch("six.moves.builtins.eval")
@@ -157,7 +150,7 @@ def test_GIVEN_one_of_start_stop_field_is_keep_AND_temp_point_WHEN_run_THEN_setm
157150
inst.tf0.assert_not_called()
158151
inst.settemp.assert_called_once()
159152
inst.setmag.assert_not_called()
160-
self.script_definition.check_mevents_and_begin_waitfor_mevents_end.assert_called_once()
153+
self.check_mevents_mock.assert_called_once()
161154

162155
@patch.dict("sys.modules", inst=inst)
163156
@patch("six.moves.builtins.eval")
@@ -180,9 +173,7 @@ def test_GIVEN_one_of_start_stop_temp_is_keep_AND_field_scan_WHEN_run_THEN_sette
180173
inst.tf0.assert_called_once()
181174
self.assertEqual(inst.setmag.call_count, 10)
182175
inst.settemp.assert_not_called()
183-
self.assertEqual(
184-
self.script_definition.check_mevents_and_begin_waitfor_mevents_end.call_count, 10
185-
)
176+
self.assertEqual(self.check_mevents_mock.call_count, 10)
186177

187178
@patch.dict("sys.modules", inst=inst)
188179
@patch("six.moves.builtins.eval")
@@ -205,7 +196,7 @@ def test_GIVEN_one_of_start_stop_temp_is_keep_AND_field_point_WHEN_run_THEN_sett
205196
inst.tf0.assert_called_once()
206197
inst.setmag.assert_called_once()
207198
inst.settemp.assert_not_called()
208-
self.script_definition.check_mevents_and_begin_waitfor_mevents_end.assert_called_once()
199+
self.check_mevents_mock.assert_called_once()
209200

210201
@patch.dict("sys.modules", inst=inst)
211202
@patch("six.moves.builtins.eval")
@@ -228,7 +219,7 @@ def test_GIVEN_keep_temp_and_field_WHEN_run_THEN_settemp_and_setmag_not_called_A
228219
inst.tf0.assert_not_called()
229220
inst.setmag.assert_not_called()
230221
inst.settemp.assert_not_called()
231-
self.script_definition.check_mevents_and_begin_waitfor_mevents_end.assert_called_once()
222+
self.check_mevents_mock.assert_called_once()
232223

233224

234225
class TestEmuRunHelpers(unittest.TestCase):

0 commit comments

Comments
 (0)