Skip to content

Commit 2bccf2d

Browse files
fix tets
1 parent b02e796 commit 2bccf2d

File tree

11 files changed

+106
-58
lines changed

11 files changed

+106
-58
lines changed

CHANGELOG.md

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,41 @@
22

33
Some big changes internally
44

5+
#### Highlights
6+
7+
- Users have been very creative in adapting the Pioreactor hardware and software to different bioreactors. We have a new tool you can use: adding custom bioreactors models to incorporate into the Pioreactor software! There is a new `.pioreactor/models/` directory where you can place custom bioreactors. For example:
8+
9+
```
10+
model_name: custom_100ml
11+
model_version: "1.0"
12+
display_name: "Custom 100 mL, v1.0"
13+
reactor_capacity_ml: 100.0
14+
reactor_max_fill_volume_ml: 95.0
15+
reactor_diameter_mm: 50.0
16+
max_temp_to_reduce_heating: 80.0
17+
max_temp_to_disable_heating: 85.0
18+
max_temp_to_shutdown: 90.0
19+
```
20+
21+
This data will be used throughout the software (including in the UI) to support other bioreactor shapes and sizes. Let us know what else you would like to see!
22+
23+
- adding mcp server
24+
25+
#### Enhancements
526
- time range filter in export data page
627
- ability to change the pause between LEDs and OD snapshot
7-
- fix export data sorting
8-
- fix UI profile editing crashing
928
- `pios X --experiments <experiment>` can be used to select workers on the leader command line.
10-
- ideally, if a published setting is settable: true, there should be a cli option to set it.
11-
- adding mcp server
29+
- ideally, if a `published_setting` is `settable: True`, there should be a CLI option to set it. We've added a bunch of new CLI options to existing jobs.
30+
- new `/unit_api/capabilities` and `/api/units/<name>/capabilities` to get lots of details about what a Pioreactor can run.
31+
32+
#### Breaking changes
1233
- adding `/experiments/<exp>` to the end of endpoint `/api/workers/unit1/jobs/settings/job_name/stirring/`
1334
- removed `/api/workers/jobs/stop/experiments/<exp>`, use `/api/workers/$broadcast/jobs/stop/experiments/<exp>` instead.
1435
- removed `/api/experiments/<experiment>/jobs/settings/job_name/<job_name>`, use `/workers/$broadcast/jobs/settings/job_name/<job_name>/experiments/<experiment>`
15-
- New external models in .pioreactor/models
36+
37+
#### Bug fixes
38+
- fix export data sorting
39+
- fix UI profile editing crashing
1640

1741
### 25.7.2
1842

core/pioreactor/actions/od_blank.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
import click
1212
from msgspec.json import encode
13-
1413
from pioreactor import pubsub
1514
from pioreactor import structs
1615
from pioreactor import types as pt
@@ -90,7 +89,7 @@ def od_statistics(
9089
f"OD reading for PD Channel {channel} is 0.0 - that shouldn't be. Is there a loose connection, or an extra channel in the configuration's [od_config.photodiode_channel] section?"
9190
)
9291

93-
logger.debug(f"observed data: {od_reading_series}")
92+
logger.debug(f"observed data: {readings}")
9493
logger.debug(f"measured mean: {means}")
9594
logger.debug(f"measured variances: {variances}")
9695

core/pioreactor/background_jobs/dosing_automation.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,6 @@ def pause_between_subdoses() -> float:
5252
return d
5353

5454

55-
def is_20ml() -> bool:
56-
return whoami.get_pioreactor_model() == "pioreactor_20ml"
57-
58-
5955
"""
6056
Calculators should ideally be state-less
6157
"""
@@ -205,7 +201,7 @@ class DosingAutomationJob(AutomationJob):
205201

206202
@classproperty
207203
def MAX_VIAL_VOLUME_TO_STOP(cls) -> float:
208-
return 18.0 if is_20ml() else 38.0
204+
return whoami.get_pioreactor_model().reactor_max_fill_volume_ml
209205

210206
@classproperty
211207
def MAX_VIAL_VOLUME_TO_WARN(cls) -> float:
@@ -550,7 +546,7 @@ def _init_alt_media_fraction(self, alt_media_fraction: float | None) -> None:
550546
if alt_media_fraction is None:
551547
with local_persistent_storage("alt_media_fraction") as cache:
552548
self.alt_media_fraction = cache.get(
553-
self.experiment, config.getfloat("bioreactor", "alt_media_fraction", fallback=0.0)
549+
self.experiment, config.getfloat("bioreactor", "initial_alt_media_fraction", fallback=0.0)
554550
)
555551
else:
556552
self.alt_media_fraction = float(alt_media_fraction)
@@ -596,7 +592,7 @@ def _init_liquid_volume(
596592
# look in database first, fallback to config
597593
with local_persistent_storage("current_volume_ml") as cache:
598594
self.current_volume_ml = cache.get(
599-
self.experiment, config.getfloat("bioreactor", "current_volume_ml", fallback=14)
595+
self.experiment, config.getfloat("bioreactor", "initial_volume_ml", fallback=14)
600596
)
601597
else:
602598
self.current_volume_ml = float(current_volume_ml)

core/pioreactor/cluster_management/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
from pioreactor.config import leader_hostname
1616
from pioreactor.exc import BashScriptError
1717
from pioreactor.logging import create_logger
18-
from pioreactor.models import registered_models
1918
from pioreactor.mureq import HTTPErrorStatus
2019
from pioreactor.mureq import HTTPException
2120
from pioreactor.pubsub import delete_from_leader
@@ -72,6 +71,8 @@ def add_worker(
7271
Add a new pioreactor worker to the cluster. The pioreactor should already have the worker image installed and is turned on.
7372
"""
7473
# validate combo against registry
74+
from pioreactor.models import registered_models
75+
7576
if (model_name, model_version) not in registered_models:
7677
click.echo(
7778
f"Invalid model/version: {model_name} v{model_version}."

core/pioreactor/models.py

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,40 +14,47 @@
1414

1515

1616
## Built-in Pioreactor models with hard-coded defaults
17+
18+
PIOREACTOR_20ml__v1_0 = Model(
19+
model_name="pioreactor_20ml",
20+
model_version="1.0",
21+
display_name="Pioreactor 20ml, v1.0",
22+
reactor_capacity_ml=20.0,
23+
reactor_max_fill_volume_ml=18.0,
24+
reactor_diameter_mm=27.0,
25+
max_temp_to_reduce_heating=63.0,
26+
max_temp_to_disable_heating=65.0,
27+
max_temp_to_shutdown=66.0,
28+
)
29+
30+
PIOREACTOR_20ml__v1_1 = Model(
31+
model_name="pioreactor_20ml",
32+
model_version="1.1",
33+
display_name="Pioreactor 20ml, v1.1",
34+
reactor_capacity_ml=20.0,
35+
reactor_max_fill_volume_ml=18.0,
36+
reactor_diameter_mm=27.0,
37+
max_temp_to_reduce_heating=78.0,
38+
max_temp_to_disable_heating=80.0,
39+
max_temp_to_shutdown=85.0,
40+
)
41+
42+
PIOREACTOR_40ml__v1_0 = Model(
43+
model_name="pioreactor_40ml",
44+
model_version="1.0",
45+
display_name="Pioreactor 40ml, v1.0",
46+
reactor_capacity_ml=40.0,
47+
reactor_max_fill_volume_ml=38.0,
48+
reactor_diameter_mm=27.0,
49+
max_temp_to_reduce_heating=78.0,
50+
max_temp_to_disable_heating=80.0,
51+
max_temp_to_shutdown=85.0,
52+
)
53+
1754
CORE_MODELS = {
18-
("pioreactor_20ml", "1.0"): Model(
19-
model_name="pioreactor_20ml",
20-
model_version="1.0",
21-
display_name="Pioreactor 20ml, v1.0",
22-
reactor_capacity_ml=20.0,
23-
reactor_max_fill_volume_ml=18.0,
24-
reactor_diameter_mm=27.0,
25-
max_temp_to_reduce_heating=63.0,
26-
max_temp_to_disable_heating=65.0,
27-
max_temp_to_shutdown=66.0,
28-
),
29-
("pioreactor_20ml", "1.1"): Model(
30-
model_name="pioreactor_20ml",
31-
model_version="1.1",
32-
display_name="Pioreactor 20ml, v1.1",
33-
reactor_capacity_ml=20.0,
34-
reactor_max_fill_volume_ml=18.0,
35-
reactor_diameter_mm=27.0,
36-
max_temp_to_reduce_heating=78.0,
37-
max_temp_to_disable_heating=80.0,
38-
max_temp_to_shutdown=85.0,
39-
),
40-
("pioreactor_40ml", "1.0"): Model(
41-
model_name="pioreactor_40ml",
42-
model_version="1.0",
43-
display_name="Pioreactor 40ml, v1.0",
44-
reactor_capacity_ml=40.0,
45-
reactor_max_fill_volume_ml=38.0,
46-
reactor_diameter_mm=27.0,
47-
max_temp_to_reduce_heating=78.0,
48-
max_temp_to_disable_heating=80.0,
49-
max_temp_to_shutdown=85.0,
50-
),
55+
("pioreactor_20ml", "1.0"): PIOREACTOR_20ml__v1_0,
56+
("pioreactor_20ml", "1.1"): PIOREACTOR_20ml__v1_1,
57+
("pioreactor_40ml", "1.0"): PIOREACTOR_40ml__v1_0,
5158
}
5259

5360

core/pioreactor/whoami.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,3 +238,5 @@ def check_firstboot_successful() -> bool:
238238
os.environ["BLINKA_FORCEBOARD"] = "RASPBERRY_PI_3A_PLUS" # Raspberry Pi 3 Model A Plus Rev 1.0
239239
os.environ["FIRMWARE"] = "1.0"
240240
os.environ["HARDWARE"] = "1.2"
241+
os.environ["MODEL_NAME"] = "pioreactor_40ml"
242+
os.environ["MODEL_VERSION"] = "1.0"

core/tests/test_execute_experiment_profile.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import pytest
88
from msgspec.json import encode
99
from msgspec.yaml import decode
10-
1110
from pioreactor.actions.leader.experiment_profile import _verify_experiment_profile
1211
from pioreactor.actions.leader.experiment_profile import execute_experiment_profile
1312
from pioreactor.actions.leader.experiment_profile import hours_to_seconds
@@ -30,8 +29,8 @@
3029
from pioreactor.pubsub import publish
3130
from pioreactor.pubsub import subscribe_and_callback
3231
from pioreactor.structs import RawODReading
33-
from tests.conftest import capture_requests
3432
from pioreactor.utils.timing import current_utc_datetime
33+
from tests.conftest import capture_requests
3534

3635

3736
def test_hours_to_seconds() -> None:
@@ -583,7 +582,11 @@ def test_execute_experiment_profile_when_action_simple(mock__load_experiment_pro
583582
# Simulate OD value
584583
publish(
585584
f"pioreactor/unit1/{experiment}/od_reading/od1",
586-
encode(RawODReading(od=2.5, angle="90", timestamp=current_utc_datetime(), channel="1")),
585+
encode(
586+
RawODReading(
587+
od=2.5, angle="90", timestamp=current_utc_datetime(), channel="1", ir_led_intensity=80
588+
)
589+
),
587590
retain=True,
588591
)
589592

@@ -625,7 +628,11 @@ def test_execute_experiment_profile_when_action_with_if(mock__load_experiment_pr
625628
# Simulate OD value
626629
publish(
627630
f"pioreactor/unit1/{experiment}/od_reading/od1",
628-
encode(RawODReading(od=2.5, angle="90", timestamp=current_utc_datetime(), channel="1")),
631+
encode(
632+
RawODReading(
633+
od=2.5, angle="90", timestamp=current_utc_datetime(), channel="1", ir_led_intensity=80
634+
)
635+
),
629636
retain=True,
630637
)
631638

core/tests/test_growth_rate_calculating.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ def __call__(self):
446446
"timestamp": "2021-06-06T15:08:12.081153Z",
447447
"channel": "1",
448448
"calibrated": 0,
449+
"ir_led_intensity": 80,
449450
}
450451
},
451452
"timestamp": "2021-06-06T15:08:12.081153Z",
@@ -507,6 +508,7 @@ def __call__(self):
507508
"timestamp": "2021-06-06T15:08:12.081153Z",
508509
"channel": "1",
509510
"calibrated": 0,
511+
"ir_led_intensity": 80,
510512
}
511513
},
512514
"timestamp": "2021-06-06T15:08:12.081153Z",

core/tests/test_od_reading.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1354,7 +1354,7 @@ def float_to_od_readings_struct(ch: pt.PdChannel, v: float) -> structs.ODReading
13541354
timestamp=current_utc_datetime(),
13551355
ods={
13561356
ch: structs.RawODReading(
1357-
ir_led_intensity=80, od=v, angle="90", channel=ch, timestamp=current_utc_datetime()
1357+
ir_led_intensity=50, od=v, angle="90", channel=ch, timestamp=current_utc_datetime()
13581358
)
13591359
},
13601360
)

core/tests/test_parser.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import pytest
88
from msgspec.json import encode
9-
109
from pioreactor import structs
1110
from pioreactor.experiment_profiles.parser import parse_profile_expression
1211
from pioreactor.experiment_profiles.parser import parse_profile_expression_to_bool
@@ -66,7 +65,11 @@ def test_mqtt_fetches() -> None:
6665

6766
publish(
6867
f"pioreactor/{unit}/{experiment}/od_reading/od1",
69-
encode(structs.RawODReading(timestamp=datetime.utcnow(), angle="90", od=1.2, channel="2")),
68+
encode(
69+
structs.RawODReading(
70+
timestamp=datetime.utcnow(), angle="90", od=1.2, channel="2", ir_led_intensity=90
71+
)
72+
),
7073
retain=True,
7174
)
7275

@@ -107,7 +110,11 @@ def test_mqtt_fetches_with_env() -> None:
107110

108111
publish(
109112
f"pioreactor/{unit}/{experiment}/od_reading/od1",
110-
encode(structs.RawODReading(timestamp=datetime.utcnow(), angle="90", od=1.2, channel="2")),
113+
encode(
114+
structs.RawODReading(
115+
timestamp=datetime.utcnow(), angle="90", od=1.2, channel="2", ir_led_intensity=80
116+
)
117+
),
111118
retain=True,
112119
)
113120

@@ -174,7 +181,11 @@ def test_mqtt_fetches_with_calculations() -> None:
174181
experiment = "_testing_experiment"
175182
publish(
176183
f"pioreactor/{unit}/{experiment}/od_reading/od1",
177-
encode(structs.RawODReading(timestamp=datetime.utcnow(), angle="90", od=1.2, channel="2")),
184+
encode(
185+
structs.RawODReading(
186+
timestamp=datetime.utcnow(), angle="90", od=1.2, channel="2", ir_led_intensity=80
187+
)
188+
),
178189
retain=True,
179190
)
180191

0 commit comments

Comments
 (0)