-
Notifications
You must be signed in to change notification settings - Fork 31
Generalize stage motion calibration to include stage translation #150
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
Generalize stage motion calibration to include stage translation #150
Conversation
…hese 3 lines took ~3h
Co-authored-by: Stef Smeets <[email protected]>
Co-authored-by: Stef Smeets <[email protected]>
… FastADT-track-multi
# Conflicts: # src/instamatic/experiments/fast_adt/experiment.py # src/instamatic/gui/fast_adt_frame.py
…n python 3.9 & 3.10
|
Unless I see critical comments or strong suggestions, I will be merging this branch by the next week. |
stefsmeets
left a 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.
Could be fun to give the SimuMicroscope speed settings. This should not be too difficult, as an arbitrary speed is already available:
| speed = 20.0 # degree / sec |
When I programmed this I was interested to have the illusion of something happening over time and not too slow so I have to sit around forever, rather than have an accurate representation of the speed setting.
| NativeTestCase(input_value=int(1), output_type=int) | ||
|
|
||
|
|
||
| @pytest.mark.parametrize('test_case', NativeTestCase.INSTANCES) |
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.
Wow, a bit too much magic here for my tastes, this is a cool way of parametrizing tests.
I wonder if you can make it more magic by implementing __iter__() on InstanceAutoTracker to turn it into an iterable (https://docs.python.org/3/library/collections.abc.html#collections.abc.Iterable) and get rid of the INSTANCES attribute.
| @pytest.mark.parametrize('test_case', NativeTestCase.INSTANCES) | |
| @pytest.mark.parametrize('test_case', NativeTestCase) |
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 IterableType(type):
def __iter__(self) -> Iterator:
yield from self.INSTANCES
class InstanceAutoTracker(metaclass=IterableType):
"""Track cls instances: useful for @pytest.mark.parametrize dataclasses"""
def __init_subclass__(cls, **kwargs) -> None:
super().__init_subclass__(**kwargs)
cls.INSTANCES: list[Self] = []
def __post_init__(self) -> None:
self.__class__.INSTANCES.append(self)Learning metaclasses in Python opens some door that maybe should remain closed 😎 . I definitely do not think skipping one class variable call is worth added complexity and removed transparency, as cool as it is, though.
Context
In #136 I introduce a new calibration routine:
instamatic.calibrate_stage_rotation. Building on the assumption that the stage speed scales linearly with speed setting, it uses a very simple model for estimating rotation speed:time = (pace * span + windup) / speed + delay. With that I created a FastADT frame capable of rotating with desired rotation speed, speed that is expressed not in arbitrary microscope units but rather in degree / second – or, to be more precise, the pace is expressed in seconds / degree.I needed to have similar calibration for sliding the stage along X and Y axis. I noticed that the model and general idea would be exactly the same as for the rotation. Therefore, instead of adding new logic, I generalized the
CalibRotationSpeedtoCalibMotionSpeedand used it to introduce a completely new calibration routineinstamatic.calibrate_stage_translationthat, when run with-a x,-a yor-a zis used to calibrate the speed of x, y, or z, respectively.Calibrating translation speed is something that I need specifically for my application in the future. I am aware that many microscopes do not have an option to modify stage speed.
instamatic.calibrate_stage_translationrespects that: whenever it detects that setting with speed is unavailable, it will simply calibrate what is the current speed of the stage and use a simpler model:time = pace * span + delay. Stages will this model will not be particularly useful for the slow-sliding experiment (and I do plan to implement a generic replacement), however they are supported just as well by the code.In addition to generalizing the calibration routing that, if needed, could be also used for other motors or even processes in general, this PR fixes some standing issues with calibration, in particular, a bunch of issues with typing and mypy complaints resolving around the calibration. Given that in the code
speedcan befloat(FEI),int(Jeol, rotation) orNone(Jeol, translation), I am quite proud to say I lowered the number of unique mypy errors to like ~5.I also vastly improved plotting post-calibration. Now after it is complete, the plot shows both fitted and experimental points. This is useful especially when there is anything wrong with calibration; for example, when testing on the simulated TEM, this allowed me to easily realize that the speed settings are accepted but do not affect translation speed. Maybe this is desirable because it makes simulator behavior more consistent, but this remains something to be discussed.
Just as before, the calibration is also accompanied by tqdm progress bar, logging and printing messages. The final messages were generalized and slightly modified to work with low values of paces for translation (they are expressed in seconds per nanometer and around 1e-6 on my Tecnai):
Minor changes
instamatic.calibrate_stage_translation;CalibStageMotion: renamed methods:speed_time_to_span>time_speed_to_span,plan_rotation>plan_motion;FloatOptions: rewritten to a new separate and more descriptiveNumericDomain, now also frozen for consistency;NumericDomain: moved to newsrc/instamatic/utils/domains.py;instamatic.utils.native: added anativefunction to quickly convertnp.integertoint,np.floatingtofloat;paceandwindupkeywords instead ofalpha_paceandalpha_windup;tests/config/calibration/calib_stage_rotation.yaml: modified to reflect this change.Code maintenance
calibrate_stage_rotation.py: generalized tocalibrate_stage_motion.pybase for newcalibrate_stage_translation.py;calibrate_stage_motion.py: vastly improved typing and some docstrings;calibrate_stage_motion.py: moved data fitting mechanism inside newCalibStageMotion.from_data;tests/test_utils.py: added tests forsrc/instamatic/utils/domains.py:NumericDomainandnative.py:native;config.md: improve the quality of PETS prefix example in the config documentation.