AutoPumping 0.1.1__tar.gz → 0.1.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 (23) hide show
  1. {autopumping-0.1.1 → autopumping-0.1.2}/AutoPumping.egg-info/PKG-INFO +2 -1
  2. {autopumping-0.1.1 → autopumping-0.1.2}/AutoPumping.egg-info/SOURCES.txt +1 -0
  3. {autopumping-0.1.1 → autopumping-0.1.2}/AutoPumping.egg-info/requires.txt +1 -0
  4. {autopumping-0.1.1 → autopumping-0.1.2}/PKG-INFO +2 -1
  5. {autopumping-0.1.1 → autopumping-0.1.2}/auto_pumping/graph.py +15 -8
  6. {autopumping-0.1.1 → autopumping-0.1.2}/pyproject.toml +3 -2
  7. {autopumping-0.1.1 → autopumping-0.1.2}/test/test_graph.py +114 -0
  8. autopumping-0.1.2/test/test_safety.py +103 -0
  9. {autopumping-0.1.1 → autopumping-0.1.2}/AutoPumping.egg-info/dependency_links.txt +0 -0
  10. {autopumping-0.1.1 → autopumping-0.1.2}/AutoPumping.egg-info/top_level.txt +0 -0
  11. {autopumping-0.1.1 → autopumping-0.1.2}/LICENSE +0 -0
  12. {autopumping-0.1.1 → autopumping-0.1.2}/README.md +0 -0
  13. {autopumping-0.1.1 → autopumping-0.1.2}/auto_pumping/__init__.py +0 -0
  14. {autopumping-0.1.1 → autopumping-0.1.2}/auto_pumping/__main__.py +0 -0
  15. {autopumping-0.1.1 → autopumping-0.1.2}/auto_pumping/config.py +0 -0
  16. {autopumping-0.1.1 → autopumping-0.1.2}/auto_pumping/dummy.py +0 -0
  17. {autopumping-0.1.1 → autopumping-0.1.2}/auto_pumping/executor.py +0 -0
  18. {autopumping-0.1.1 → autopumping-0.1.2}/auto_pumping/safety.py +0 -0
  19. {autopumping-0.1.1 → autopumping-0.1.2}/auto_pumping/ui.py +0 -0
  20. {autopumping-0.1.1 → autopumping-0.1.2}/setup.cfg +0 -0
  21. {autopumping-0.1.1 → autopumping-0.1.2}/test/test_config.py +0 -0
  22. {autopumping-0.1.1 → autopumping-0.1.2}/test/test_executor.py +0 -0
  23. {autopumping-0.1.1 → autopumping-0.1.2}/test/test_ui.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: AutoPumping
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: A tool to automate pumping of vacuum systems
5
5
  Author-email: Cameron Devine <cameron.devine@alleninstitute.org>
6
6
  License-Expression: BSD-3-Clause
@@ -18,6 +18,7 @@ Requires-Dist: nicegui
18
18
  Requires-Dist: pyvis
19
19
  Provides-Extra: dev
20
20
  Requires-Dist: pytest; extra == "dev"
21
+ Requires-Dist: pytest-mock; extra == "dev"
21
22
  Requires-Dist: bump-my-version; extra == "dev"
22
23
  Provides-Extra: docs
23
24
  Requires-Dist: jsonschema2md; extra == "docs"
@@ -17,4 +17,5 @@ auto_pumping/ui.py
17
17
  test/test_config.py
18
18
  test/test_executor.py
19
19
  test/test_graph.py
20
+ test/test_safety.py
20
21
  test/test_ui.py
@@ -6,6 +6,7 @@ pyvis
6
6
 
7
7
  [dev]
8
8
  pytest
9
+ pytest-mock
9
10
  bump-my-version
10
11
 
11
12
  [docs]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: AutoPumping
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: A tool to automate pumping of vacuum systems
5
5
  Author-email: Cameron Devine <cameron.devine@alleninstitute.org>
6
6
  License-Expression: BSD-3-Clause
@@ -18,6 +18,7 @@ Requires-Dist: nicegui
18
18
  Requires-Dist: pyvis
19
19
  Provides-Extra: dev
20
20
  Requires-Dist: pytest; extra == "dev"
21
+ Requires-Dist: pytest-mock; extra == "dev"
21
22
  Requires-Dist: bump-my-version; extra == "dev"
22
23
  Provides-Extra: docs
23
24
  Requires-Dist: jsonschema2md; extra == "docs"
@@ -1,5 +1,3 @@
1
- import re
2
-
3
1
  from networkx import DiGraph, dijkstra_path, dijkstra_path_length, relabel_nodes
4
2
  from yaml import Node
5
3
  from .config import ValveState, PumpState, Inequality, StrictModel
@@ -264,12 +262,7 @@ class PumpingGraph:
264
262
  return PlanStep(pump=pump, state=state)
265
263
  raise ValueError("No difference between states")
266
264
 
267
- def make_plan(self, start_state, **goal_state_data):
268
- if not isinstance(start_state, NodeModel):
269
- start_state = NodeModel(**start_state)
270
- if not isinstance(start_state, UUID):
271
- start_state = self._find_state(start_state)
272
- assert start_state is not None, f"Cannot find state {start_state}"
265
+ def _make_plan(self, start_state, **goal_state_data):
273
266
  goal_lengths = sorted(
274
267
  [
275
268
  (
@@ -290,6 +283,20 @@ class PumpingGraph:
290
283
  yield PlanStep(wait=edge_data["wait"])
291
284
  yield self._state_diff(start_node_data, end_node_data)
292
285
 
286
+ def make_plan(self, start_state, **goal_state_data):
287
+ if not isinstance(start_state, NodeModel):
288
+ start_state = NodeModel(**start_state)
289
+ start_state_id = self._find_state(start_state)
290
+ assert start_state_id is not None, f"Cannot find state {start_state}"
291
+ plan = list(self._make_plan(start_state_id, **goal_state_data))
292
+ if plan[0].valve is not None and plan[0].valve == plan[1].valve:
293
+ plan = plan[2:]
294
+ elif plan[0].pump is not None and plan[0].pump == plan[1].pump:
295
+ plan = plan[2:]
296
+ elif plan[0].stage is not None and plan[1].stage == start_state.stage:
297
+ plan = plan[2:]
298
+ return plan
299
+
293
300
  def draw(self, output_file=None, port=8000):
294
301
  net = Network(height="100vh", width="100%", directed=True)
295
302
  graph = relabel_nodes(self._graph, str, copy=True)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "AutoPumping"
7
- version = "0.1.1"
7
+ version = "0.1.2"
8
8
  description = "A tool to automate pumping of vacuum systems"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -30,6 +30,7 @@ dependencies = [
30
30
  [project.optional-dependencies]
31
31
  dev = [
32
32
  "pytest",
33
+ "pytest-mock",
33
34
  "bump-my-version",
34
35
  ]
35
36
  docs = [
@@ -40,7 +41,7 @@ docs = [
40
41
  packages = ["auto_pumping"]
41
42
 
42
43
  [tool.bumpversion]
43
- current_version = "0.1.1"
44
+ current_version = "0.1.2"
44
45
  commit = true
45
46
  # The CI publish job only runs for tags of the form `v<version>`.
46
47
  tag = true
@@ -268,3 +268,117 @@ def test_make_plan(graph):
268
268
  PlanStep(valve="VA", state="open"),
269
269
  PlanStep(stage="microscope"),
270
270
  ]
271
+
272
+
273
+ @mark.parametrize(
274
+ "state",
275
+ [
276
+ {
277
+ "valves": {
278
+ "VA": "closed",
279
+ "VB": "closed",
280
+ "VE": "closed",
281
+ "VT": "open",
282
+ "VF": "open",
283
+ "VR": "closed",
284
+ "VV1": "closed",
285
+ },
286
+ "pumps": {
287
+ "roughing": "on",
288
+ "turbo": "on",
289
+ },
290
+ "gauges": {
291
+ "PLL": (4.5e-5, 0.1),
292
+ },
293
+ "stage": "loadlock",
294
+ },
295
+ {
296
+ "valves": {
297
+ "VA": "closed",
298
+ "VB": "closed",
299
+ "VE": "open",
300
+ "VT": "open",
301
+ "VF": "open",
302
+ "VR": "closed",
303
+ "VV1": "closed",
304
+ },
305
+ "pumps": {
306
+ "roughing": "on",
307
+ "turbo": "on",
308
+ },
309
+ "gauges": {
310
+ "PLL": (9e-6, 4.5e-5),
311
+ },
312
+ "stage": "loadlock",
313
+ },
314
+ ],
315
+ )
316
+ def test_make_plan_no_loops(graph, state):
317
+ plan = list(graph.make_plan(state, name="imaging"))
318
+ assert plan is not None
319
+ for i in range(len(plan) - 1):
320
+ step1 = plan[i]
321
+ step2 = plan[i + 1]
322
+ assert step1.valve is None or step1.valve != step2.valve
323
+ assert step1.pump is None or step1.pump != step2.pump
324
+
325
+
326
+ @mark.parametrize(
327
+ "plan, steps_removed",
328
+ [
329
+ (
330
+ [
331
+ PlanStep(valve="VF", state="closed"),
332
+ PlanStep(valve="VF", state="open"),
333
+ PlanStep(wait={"PLL": Inequality(LE=0.1)}),
334
+ PlanStep(pump="roughing", state="off"),
335
+ ],
336
+ 2,
337
+ ),
338
+ (
339
+ [
340
+ PlanStep(valve="VR", state="closed"),
341
+ PlanStep(valve="VF", state="open"),
342
+ PlanStep(valve="VR", state="open"),
343
+ ],
344
+ 0,
345
+ ),
346
+ (
347
+ [
348
+ PlanStep(pump="roughing", state="off"),
349
+ PlanStep(pump="roughing", state="on"),
350
+ PlanStep(valve="VR", state="closed"),
351
+ ],
352
+ 2,
353
+ ),
354
+ (
355
+ [
356
+ PlanStep(pump="turbo", state="off"),
357
+ PlanStep(pump="roughing", state="off"),
358
+ PlanStep(valve="VV1", state="open"),
359
+ ],
360
+ 0,
361
+ ),
362
+ (
363
+ [
364
+ PlanStep(stage="loadlock"),
365
+ PlanStep(stage="microscope"),
366
+ PlanStep(valve="VR", state="closed"),
367
+ ],
368
+ 2,
369
+ ),
370
+ (
371
+ [
372
+ PlanStep(stage="loadlock"),
373
+ PlanStep(stage="exchange"),
374
+ PlanStep(valve="VA", state="closed"),
375
+ ],
376
+ 0,
377
+ ),
378
+ ],
379
+ )
380
+ def test_remove_redundant_steps(graph, plan, steps_removed):
381
+ graph._make_plan = lambda *args, **kwargs: plan
382
+ graph._find_state = lambda *args, **kwargs: True
383
+ assert graph.make_plan({"stage": "microscope"}) == plan[steps_removed:]
384
+
@@ -0,0 +1,103 @@
1
+ from auto_pumping.safety import SafetyMachine
2
+ from auto_pumping.config import PumpState, ValveState
3
+ from pytest import mark
4
+
5
+
6
+ @mark.parametrize(
7
+ "valve_states, turbo_current, gauge_pressure, VF_open_time, can_open_VT",
8
+ [
9
+ (
10
+ {
11
+ "VT": ValveState.CLOSED,
12
+ "VA": ValveState.CLOSED,
13
+ "VB": ValveState.CLOSED,
14
+ "VF": ValveState.OPEN,
15
+ "VR": ValveState.CLOSED,
16
+ "VE": ValveState.CLOSED,
17
+ "VV1": ValveState.CLOSED,
18
+ },
19
+ 0.55,
20
+ 0.09,
21
+ 11,
22
+ True,
23
+ ),
24
+ (
25
+ {
26
+ "VT": ValveState.CLOSED,
27
+ "VA": ValveState.CLOSED,
28
+ "VB": ValveState.CLOSED,
29
+ "VF": ValveState.OPEN,
30
+ "VR": ValveState.CLOSED,
31
+ "VE": ValveState.CLOSED,
32
+ "VV1": ValveState.CLOSED,
33
+ },
34
+ 0.55,
35
+ 0.09,
36
+ 9,
37
+ False,
38
+ ),
39
+ (
40
+ {
41
+ "VT": ValveState.CLOSED,
42
+ "VA": ValveState.CLOSED,
43
+ "VB": ValveState.CLOSED,
44
+ "VF": ValveState.OPEN,
45
+ "VR": ValveState.CLOSED,
46
+ "VE": ValveState.CLOSED,
47
+ "VV1": ValveState.CLOSED,
48
+ },
49
+ 0.65,
50
+ 0.09,
51
+ 11,
52
+ False,
53
+ ),
54
+ (
55
+ {
56
+ "VT": ValveState.CLOSED,
57
+ "VA": ValveState.CLOSED,
58
+ "VB": ValveState.CLOSED,
59
+ "VF": ValveState.OPEN,
60
+ "VR": ValveState.CLOSED,
61
+ "VE": ValveState.CLOSED,
62
+ "VV1": ValveState.CLOSED,
63
+ },
64
+ 0.55,
65
+ 1.1,
66
+ 11,
67
+ False,
68
+ ),
69
+ (
70
+ {
71
+ "VT": ValveState.CLOSED,
72
+ "VA": ValveState.CLOSED,
73
+ "VB": ValveState.CLOSED,
74
+ "VF": ValveState.CLOSED,
75
+ "VR": ValveState.CLOSED,
76
+ "VE": ValveState.CLOSED,
77
+ "VV1": ValveState.CLOSED,
78
+ },
79
+ 0.55,
80
+ 0.09,
81
+ 11,
82
+ False,
83
+ ),
84
+ ],
85
+ )
86
+ def test_crossover_VT_open(config, mocker, valve_states, turbo_current, gauge_pressure, VF_open_time, can_open_VT):
87
+ time = mocker.patch("auto_pumping.safety.time", return_value=100)
88
+
89
+ mock_pumping_system = mocker.Mock()
90
+ mock_pumping_system.get_valve_state.side_effect = valve_states.get
91
+ mock_pumping_system.get_pump_state.return_value = PumpState.ON
92
+ mock_pumping_system.get_pump_current.side_effect = lambda pump: turbo_current if pump == "turbo" else None
93
+ mock_pumping_system.get_pump_voltage.side_effect = lambda pump: 24 if pump == "turbo" else None
94
+ mock_pumping_system.get_pump_flow.return_value = None
95
+ mock_pumping_system.get_pump_speed.side_effect = lambda pump: 1000 if pump == "turbo" else None
96
+ mock_pumping_system.get_gauge_pressure.return_value = gauge_pressure
97
+ mock_pumping_system.get_stage_position.return_value = "loadlock"
98
+
99
+ safety_machine = SafetyMachine(config, mock_pumping_system)
100
+
101
+ time.return_value += VF_open_time
102
+
103
+ assert safety_machine.can_actuate_valve("VT", "open") == can_open_VT
File without changes
File without changes
File without changes
File without changes