Skip to content
This repository was archived by the owner on Sep 2, 2024. It is now read-only.

368 generalise ispyb handling to rotation scans#711

Merged
d-perl merged 48 commits into
mainfrom
368_generalise_ispyb_handling
Jul 27, 2023
Merged

368 generalise ispyb handling to rotation scans#711
d-perl merged 48 commits into
mainfrom
368_generalise_ispyb_handling

Conversation

@d-perl

@d-perl d-perl commented Jun 7, 2023

Copy link
Copy Markdown
Contributor

Fixes #368

To test:

@codecov

codecov Bot commented Jun 7, 2023

Copy link
Copy Markdown

Codecov Report

Merging #711 (2f3a95f) into main (3ea6e6f) will decrease coverage by 0.07%.
The diff coverage is 96.06%.

@@            Coverage Diff             @@
##             main     #711      +/-   ##
==========================================
- Coverage   94.45%   94.38%   -0.07%     
==========================================
  Files          37       40       +3     
  Lines        1875     2013     +138     
==========================================
+ Hits         1771     1900     +129     
- Misses        104      113       +9     
Files Changed Coverage Δ
...l_interaction/callbacks/rotation/ispyb_callback.py 66.66% <66.66%> (ø)
...ernal_interaction/callbacks/ispyb_callback_base.py 95.74% <95.74%> (ø)
...temis/external_interaction/ispyb/store_in_ispyb.py 97.24% <97.32%> (+0.33%) ⬆️
...emis/device_setup_plans/read_hardware_for_setup.py 100.00% <100.00%> (ø)
...rc/artemis/experiment_plans/fast_grid_scan_plan.py 93.10% <100.00%> (-0.41%) ⬇️
src/artemis/experiment_plans/rotation_scan_plan.py 100.00% <100.00%> (ø)
...ternal_interaction/callbacks/fgs/ispyb_callback.py 95.45% <100.00%> (-2.59%) ⬇️
...ernal_interaction/callbacks/fgs/zocalo_callback.py 98.46% <100.00%> (ø)
...callbacks/rotation/rotation_callback_collection.py 100.00% <100.00%> (ø)
...emis/external_interaction/ispyb/ispyb_dataclass.py 100.00% <100.00%> (+1.81%) ⬆️
... and 5 more

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@DominicOram DominicOram left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few initial comments, can pick the review up again later this week. Also, would be good to have some unit test coverage around the new stuff, even if it's just asserting happy path stuff


@pytest.mark.s03()
@patch("bluesky.plan_stubs.wait")
def test_ispyb_deposition_in_plan(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great test, thank you!
Should: Can we set the dev config here like we do in the test_ispyb_dev_connection so that it runs with the environment variable being set. We should move the path to the dev config into the constants area at the same time.

with ispyb.open(self.ISPYB_CONFIG_PATH) as conn:
return self._store_scan_data(conn)

def end_deposition(self, success: str, reason: str):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should: Is the only difference between this and the grid one how many dcids we have? Feels like we can move some more logic into the parent here

Comment on lines +259 to +265
data_collection_group_id = self._store_data_collection_group_table(conn)
self.data_collection_group_id = data_collection_group_id
data_collection_id = self._store_data_collection_table(
conn, data_collection_group_id
)
self.data_collection_id = data_collection_id
self._store_position_table(conn, data_collection_id)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should: The logic of "store group, store dc, store position" is the same for all these. Can that go in the parent class?

@d-perl d-perl Jun 15, 2023

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess, but I think it would be more complicated given subtle differences - 3d grid scan does dc and position twice, and they have different return types. I personally think it's not worth changing three sets of three simple statements for one set of logic based on how many dcids we have.

self.datacollection_ids = None
self.datacollection_group_id = None
self.grid_ids = None
def __init__(self, ispyb_config, parameters=None) -> None:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: The parent class doesn't need parameters to be passed in

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should: Every subclass needs an experiment_type, let's pass this in here

@d-perl
d-perl requested a review from DominicOram June 22, 2023 15:30

@DominicOram DominicOram left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly good, thanks. Some suggestions for improvements in the code. Also, when running the new system test I get src/artemis/experiment_plans/tests/test_rotation_scan_plan.py::test_ispyb_deposition_in_plan - AttributeError: armed

"zebra": zebra,
"detector_motion": detector_motion,
"backlight": backlight,
"eiger": i03.eiger(wait_for_connection=False),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could: I should have advertised this more widely but I think this is no longer necessary. Feel free to modify here or we can wait for #825

zebra.pc.arm_demand.set = mock_arm_disarm

devices = {
"eiger": i03.eiger(wait_for_connection=False, fake_with_ophyd_sim=True),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could: As above with waiting for connection

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this one wasn't necessary anyway, it's an ophyd sim device... haha...

self.ispyb.append_to_comment(crystal_summary)

raw_centre = np.array([*(raw_results[0]["centre_of_mass"])])
adjusted_centre = raw_centre - np.array([0.5, 0.5, 0.5])

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

Comment on lines +22 to +29
E.g.:
nexus_file_handler_callback = NexusFileHandlerCallback(parameters)
RE.subscribe(nexus_file_handler_callback)
Or decorate a plan using bluesky.preprocessors.subs_decorator.

See: https://blueskyproject.io/bluesky/callbacks.html#ways-to-invoke-callbacks

Usually used as part of an FGSCallbackCollection.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should: This has incorrect references to Nexus/FGS

from artemis.parameters.plan_specific.fgs_internal_params import FGSInternalParameters


class RotationISPyBHandlerCallback(CallbackBase):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should: 90% of the code in here is the same as the FGS one, I feel like we could have a common inheritence for them?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure


@patch("ispyb.open", new_callable=mock_open)
def test_store_grid_scan(ispyb_conn, dummy_ispyb, dummy_params):
def test_store_rotation_scan(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should: I think we're mocking out a bit too much here, which is why we're getting such poor coverage on StoreRotationInIspyb. Can we either in this test or in a new test mock just the upserts?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really understand. As fast as I can tell we are only mocking the connection (which is necessary at least for tests which run in CI) and nothing else? low coverage seems more down to not testing _mutate_data_collection_params_for_experiment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean that later in this test we have lots of when(x).y().thenReturn(z), which means we're never really testing any of the functionality of x.y(). I think it's fine to leave it for now though,given we have the additional tests on the mutate

LOGGER.warning("No xtal snapshot paths sent to ISPyB!")
super().__init__(ispyb_config, "SAD")

def _mutate_data_collection_params_for_experiment(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should: I think a few additional simple tests just covering this function would be good

Comment on lines +307 to +312
ispyb_params: GridscanIspybParams | None = None
data_collection_ids: tuple[int, ...] | None = None
upper_left: list[int] | None = None
y_steps: int | None = None
y_step_size: int | None = None
grid_ids: tuple[int, ...] | None = None

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should: As above, avoid class variables

# not an annotation but specified as field encoder in DetectorParams:
detector_field_keys.append("detector")
ispyb_field_keys = list(IspybParams.__annotations__.keys()) + list(
GridscanIspybParams.__annotations__.keys()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should: This should be the RotationIspybParams right?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you write a test that would have caught this too

super().__init__(**args)

@staticmethod
def _artemis_param_key_definitions() -> tuple[list[str], list[str], list[str]]:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should: I feel like we've moved too much of this function to be in each different class, when only a small part of it is different for each. Could we only move the different part please?

@d-perl
d-perl requested a review from DominicOram July 26, 2023 13:21

@DominicOram DominicOram left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor issue in logging but once I fixed that this worked. Thank you very much, sorry for the long delay on it!

@d-perl
d-perl merged commit 997ea2e into main Jul 27, 2023
@d-perl
d-perl deleted the 368_generalise_ispyb_handling branch July 27, 2023 12:11
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make ispyb handler deal with different experiment types

2 participants