-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
470 Full experiment plan to replace execute request #538
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great, thank you! I think the only major issue is the WarningException
thing otherwise just cleaning up. I think the failing test and some of the linting can be fixed by https://github.com/DiamondLightSource/mx-bluesky/pull/506/files. See also https://gerrit.diamond.ac.uk/c/gda/gda-mx/+/42628/comments/8c916387_22898ce5
@@ -77,6 +77,12 @@ class SmargonSpeedException(Exception): | |||
pass | |||
|
|||
|
|||
class CrystalNotFoundException(Exception): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Must: This should inherit from WarningException
otherwise GDA will pick the exception up and stop UDC for it.
yield from bps.mv( | ||
fgs_composite.sample_motors.stub_offsets, StubPosition.CURRENT_AS_CENTER | ||
) | ||
finally: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should: I think in general it's preferable to use https://nsls-ii.github.io/bluesky/generated/bluesky.preprocessors.finalize_wrapper.html as it better handles the GeneratorExit
case for when the RE
wants to interrupt a plan to pause/stop. We don't do this currently but might as well think bear it in mind.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will look at doing this for the multipin changes as I will need to move that anyway
if not oav_params: | ||
oav_params = OAVParameters(context="xrayCentring") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to refactor the OAVParams
out as I don't really see why we need them for the rotation now. It's a different issue but leaving this as a note to myself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
set_mock_value(smargon.z.user_readback, 0.0) | ||
set_mock_value(smargon.x.high_limit_travel, 2) | ||
set_mock_value(smargon.x.low_limit_travel, -2) | ||
set_mock_value(smargon.y.high_limit_travel, 2) | ||
set_mock_value(smargon.y.low_limit_travel, -2) | ||
set_mock_value(smargon.z.high_limit_travel, 2) | ||
set_mock_value(smargon.z.low_limit_travel, -2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could: I feel like we should either put this in a loop:
for motor in [smargon.x, smargon.y, smargon.z]:
set_mock_value(motor.user_readback, 0.0)
set_mock_value(motor.low_limit_travel, -2)
set_mock_value(motor.high_limit_travel, 2)
or add it into patch_async_motor
zocalo_environment: str = Field(default=CONST.ZOCALO_ENV) | ||
beamline: str = Field(default=CONST.I03.BEAMLINE, pattern=r"BL\d{2}[BIJS]") | ||
det_dist_to_beam_converter_path: str = Field( | ||
default=CONST.PARAM.DETECTOR.BEAM_XY_LUT_PATH | ||
) | ||
insertion_prefix: str = Field( | ||
default=CONST.I03.INSERTION_PREFIX, pattern=r"SR\d{2}[BIJS]" | ||
) | ||
detector_distance_mm: float | None = Field(default=None, gt=0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another reminder to myself to write an issue cleaning this up
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
class MoveException(Exception): | ||
pass | ||
|
||
feature_controlled = _get_feature_controlled( | ||
fgs_composite_with_panda_pcap, | ||
test_fgs_params_panda_zebra, | ||
) | ||
mock_zocalo_trigger(fgs_composite_with_panda_pcap.zocalo, []) | ||
move_xyz.side_effect = MoveException() | ||
|
||
with pytest.raises(MoveException): | ||
with pytest.raises(CrystalNotFoundException): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could: I'm not a big fan of this change because we're relying on the fact the code is producing an error as is. Previously we were deliberately injecting an error in because we wanted to test with it, which seems more explicit but not that big a deal
def find_a_pin(pin_tip_detection): | ||
def set_good_position(): | ||
set_mock_value(pin_tip_detection.triggered_tip, (100, 110)) | ||
return NullStatus() | ||
|
||
return set_good_position |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could: I think you can clean this up a bit using AsyncStatus
and partials:
from functools import partial
from ophyd_async.core import AsyncStatus
@AsyncStatus.wrap
async def find_a_pin(pin_tip_detection):
set_mock_value(pin_tip_detection.triggered_tip, (100, 110))
...
composite.pin_tip_detection.trigger = MagicMock(
side_effect=partial(find_a_pin, composite.pin_tip_detection)
)
I think the use of AsyncStatus
is a should as we're trying to move away from ophyd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dont_find_pin
isn't used anyway as in the end I rewrote the test using the run engine simulator so I will remove it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think the use of partial
and AsyncStatus
is cleaner than the nested functions and NullStatus
but not worth holding things up on
return set_good_position | ||
|
||
|
||
def dont_find_pin(pin_tip_detection): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should: I don't think this is used? Can we remove it?
def compare_actual_and_expected( | ||
id, expected_values, fetch_datacollection_attribute, column_map: dict | None = None | ||
): | ||
results = "\n" | ||
for k, v in expected_values.items(): | ||
actual = fetch_datacollection_attribute( | ||
id, column_map[k.lower()] if column_map else k | ||
) | ||
if isinstance(actual, Decimal): | ||
actual = float(actual) | ||
if isinstance(v, float): | ||
actual_v = actual == pytest.approx(v) | ||
else: | ||
actual_v = actual == v | ||
if not actual_v: | ||
results += f"expected {k} {v} == {actual}\n" | ||
assert results == "\n", results | ||
|
||
|
||
def compare_comment( | ||
fetch_datacollection_attribute, data_collection_id, expected_comment | ||
): | ||
actual_comment = fetch_datacollection_attribute( | ||
data_collection_id, DATA_COLLECTION_COLUMN_MAP["comments"] | ||
) | ||
match = re.search(" Zocalo processing took", actual_comment) | ||
truncated_comment = actual_comment[: match.start()] if match else actual_comment | ||
assert truncated_comment == expected_comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should: Are these exactly the same as those in test_ispyb_dev_connection.py
? Can we move them to somewhere common?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I have moved them
|
||
|
||
@pytest.mark.s03 | ||
def test_execute_load_centre_collect_full_plan( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Must: Running this I get an error:
FAILED tests/system_tests/hyperion/external_interaction/test_load_centre_collect_full_plan.py::test_execute_load_centre_collect_full_plan - AssertionError:
expected beamSizeAtSampleX 0.1 == 0.02
assert '\nexpected beamSizeAtSampleX 0.1 == 0.02\n' == '\n'
Strings contain only whitespace, escaping them using repr()
- '\n'
+ '\nexpected beamSizeAtSampleX 0.1 == 0.02\n'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Otherwise, love this test though, thank you!
971ad3e
to
35c78b6
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #538 +/- ##
==========================================
+ Coverage 78.01% 78.12% +0.11%
==========================================
Files 91 93 +2
Lines 6754 6799 +45
==========================================
+ Hits 5269 5312 +43
- Misses 1485 1487 +2
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, thank you!
This fix addresses #470
It also requires GDA jython script change (gerrit change request https://gerrit.diamond.ac.uk/c/gda/gda-mx/+/42628)
To test:
Confirm unit tests pass, and additional system test
test_load_centre_collect_full_plan
workThis code change should support single and multiple rotations, and will be enabled if the property
gda.mx.hyperion.load_centre_collect.enabled
is set totrue
in domain.properties