Skip to content
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

651 energy change fixes #676

Merged
merged 8 commits into from
Dec 2, 2024
Merged

651 energy change fixes #676

merged 8 commits into from
Dec 2, 2024

Conversation

rtuck99
Copy link
Contributor

@rtuck99 rtuck99 commented Nov 26, 2024

This fixes energy change issues discovered during beamline testing #651

See also DiamondLightSource/dodal#918

  1. Energy changes should now result in the VFM yaw and lateral position (x-offset) being set depending on the mirror stripe.
    Previously the yaw was unset and the lateral position adjusted according to a lookup-table that was effectively single-valued.
  2. The energy change, and individual DCM changes are now serialized because they cannot be done in parallel
  3. The timeouts for the yaw, lat operations are increased to 30s from 10s
  4. Mirror voltage changes are now serialized instead of being attempted in parallel
  5. Energy changes are now done in robot_load_then_centre regardless of whether a robot load and/or chi change is performed or not

Instructions to reviewer on how to test:

  1. Energy changes work on beamline
  2. Unit tests pass

Checks for reviewer

  • Would the PR title make sense to a scientist on a set of release notes
  • If a new device has been added does it follow the standards
  • If changing the API for a pre-existing device, ensure that any beamlines using this device have updated their Bluesky plans accordingly
  • Have the connection tests for the relevant beamline(s) been run via dodal connect ${BEAMLINE}

Copy link

codecov bot commented Nov 26, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 86.44%. Comparing base (06a635a) to head (63b4d6f).
Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #676   +/-   ##
=======================================
  Coverage   86.44%   86.44%           
=======================================
  Files         102      102           
  Lines        6935     6935           
=======================================
  Hits         5995     5995           
  Misses        940      940           
Components Coverage Δ
i24 SSX 71.94% <ø> (ø)
hyperion 96.84% <100.00%> (ø)
other 94.15% <ø> (ø)

Copy link
Contributor

@DominicOram DominicOram left a comment

Choose a reason for hiding this comment

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

Great, thanks A few comments.

offset_mm = undulator_dcm.dcm_fixed_offset_mm
LOGGER.info(f"Adjusting DCM offset to {offset_mm} mm")
yield from bps.abs_set(dcm.offset_in_mm, offset_mm, group=DCM_GROUP)
yield from bps.abs_set(dcm.offset_in_mm, offset_mm, wait=True)
Copy link
Contributor

Choose a reason for hiding this comment

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

Should: The offset is now being set in the undulator_dcm, why are we doing it again here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That was something that got merged in from the beamline changes which I forgot to remove. I think it should be done here

Copy link
Contributor

Choose a reason for hiding this comment

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

Must: But, from memory, we needed that on the beamline because we needed the DCM energy to be set before we could set the DCM offset? So if we do this here we will need a wait for UNDULATOR_GROUP (which is poorly named as it is moving the DCM too) to finish first. I think that then costs us some time as we'll be ending up waiting on the undulator here too.

Should: Additionally, if we're going to do it here the wait=True is frustrating because AFAIK we don't need to wait on this to have finished before we start changing things on the mirrors as they're entirely separate devices.

General point: This is why I think we should push this further into the device, if we push it all the way into the DCM itself it's more obvious about what is the minimum thing we're waiting on.

yield from bps.trigger(mirror.apply_stripe)

# yaw, lat cannot be done simultaneously
Copy link
Contributor

Choose a reason for hiding this comment

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

Why can't yaw and lat be done simultaneously? They look like two separate motor PVs?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yaw and lat are compound axes of the front and back motors, so moving one will cancel any move of the other

Copy link
Contributor

Choose a reason for hiding this comment

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

Great, thank, I've added this to the comment

Comment on lines +73 to +80
yield from bps.abs_set(
mirror.x_mm, mirror_config["lat_mm"], wait=True, timeout=YAW_LAT_TIMEOUT_S
)

LOGGER.info(f"Adjusting {mirror.name} yaw to {mirror_config['yaw_mrad']}")
yield from bps.abs_set(
mirror.yaw_mrad, mirror_config["yaw_mrad"], wait=True, timeout=YAW_LAT_TIMEOUT_S
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Could: Rather than ask the device for it's settings based on the energy and then apply them in the plan could we just put it all into the device and allow us to do mirror.set(energy_kev) with the device handling the rest? This seems like it could be cleaner?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The yaw and lat are part of the dcm, they change because of the mirror stripe change which is the VFM and a separate device, unless we want to roll up the VFM into the undulator_dcm to make it vfm_undulator_dcm?

# DCM Perp pitch
# DCM offset
# wait for other DCM motions and energy change to complete before changing offset
yield from bps.wait(DCM_GROUP, timeout=30)
Copy link
Contributor

Choose a reason for hiding this comment

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

Could: Similar to above, given the offest_mm is now being done in the undulator_dcm should we do all these moves in the device side to avoid the logic being split over so many places?

Copy link
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 think it should be done in the undulator_dcm, I'm beginning to think the opposite, that the undulator_dcm should just be a dumb device and everything be orchestrated in this plan.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's cleaner to put all the logic for a particular device into the device so a plan just needs to do yield from bps.set(dcm, energy) and the dcm handles all of it's rolls/pitches etc. Especially as IMHO the asyncio syntax for ordering operations is cleaner than the wait=GROUP syntax. But I think either way that's outside of the scope here, sorry for bringing it up in the first place


LOGGER.info(f"Adjusting {mirror.name} yaw to {mirror_config['yaw_mrad']}")
yield from bps.abs_set(
mirror.yaw_mrad, mirror_config["yaw_mrad"], wait=True, timeout=YAW_LAT_TIMEOUT_S
Copy link
Contributor

Choose a reason for hiding this comment

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

Should: It's misleading that the LAT_TIMEOUT is also being used on yaw

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's why is called YAW_LAT_TIMEOUT and not LAT_TIMEOUT

Copy link
Contributor

Choose a reason for hiding this comment

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

D'oh, sorry

@@ -178,12 +182,23 @@ def robot_load_then_xray_centre(
parameters,
)
LOGGER.info("Pin not loaded, loading and centring")
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Unrelated to this PR, I know but it's odd this message is logged after the fact

Comment on lines 191 to 192
yield from set_energy_plan(
demand_energy_ev / 1000,
Copy link
Contributor

Choose a reason for hiding this comment

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

Could: Given we're now doing this same logic in the robot load (the only other place this plan is called) maybe we could just change set_energy_plan to take an optional in kev and move the if and /1000 into there?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I should have done this - fewer tests and simpler code!

Comment on lines 88 to 91
assert (
multi_rotation.demand_energy_ev
== parameters.robot_load_then_centre.demand_energy_ev
), "Setting a different energy for gridscan and rotation is not supported"
Copy link
Contributor

Choose a reason for hiding this comment

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

Should: We should be able to support this quite easily. Can you make an issue for it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

@DominicOram DominicOram left a comment

Choose a reason for hiding this comment

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

Thanks. Still some comments, sorry.

yield from bps.trigger(mirror.apply_stripe)

# yaw, lat cannot be done simultaneously
Copy link
Contributor

Choose a reason for hiding this comment

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

Great, thank, I've added this to the comment

offset_mm = undulator_dcm.dcm_fixed_offset_mm
LOGGER.info(f"Adjusting DCM offset to {offset_mm} mm")
yield from bps.abs_set(dcm.offset_in_mm, offset_mm, group=DCM_GROUP)
yield from bps.abs_set(dcm.offset_in_mm, offset_mm, wait=True)
Copy link
Contributor

Choose a reason for hiding this comment

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

Must: But, from memory, we needed that on the beamline because we needed the DCM energy to be set before we could set the DCM offset? So if we do this here we will need a wait for UNDULATOR_GROUP (which is poorly named as it is moving the DCM too) to finish first. I think that then costs us some time as we'll be ending up waiting on the undulator here too.

Should: Additionally, if we're going to do it here the wait=True is frustrating because AFAIK we don't need to wait on this to have finished before we start changing things on the mirrors as they're entirely separate devices.

General point: This is why I think we should push this further into the device, if we push it all the way into the DCM itself it's more obvious about what is the minimum thing we're waiting on.

# DCM Perp pitch
# DCM offset
# wait for other DCM motions and energy change to complete before changing offset
yield from bps.wait(DCM_GROUP, timeout=30)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's cleaner to put all the logic for a particular device into the device so a plan just needs to do yield from bps.set(dcm, energy) and the dcm handles all of it's rolls/pitches etc. Especially as IMHO the asyncio syntax for ordering operations is cleaner than the wait=GROUP syntax. But I think either way that's outside of the scope here, sorry for bringing it up in the first place

Copy link
Contributor

@noemifrisina noemifrisina left a comment

Choose a reason for hiding this comment

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

lgtm, changes were addressed, please resolve the conflicts

@rtuck99 rtuck99 force-pushed the 651_energy_change_fixes branch from a15adef to 63b4d6f Compare December 2, 2024 15:38
@rtuck99 rtuck99 dismissed DominicOram’s stale review December 2, 2024 15:50

DO is currently on leave. Changes addressed

@rtuck99 rtuck99 merged commit 396940c into main Dec 2, 2024
22 checks passed
@rtuck99 rtuck99 deleted the 651_energy_change_fixes branch December 2, 2024 15:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants