Skip to content

[METEOR-1481] [feat] Add METEOR support for JEOL JIB-4700F#3248

Merged
pieleric merged 2 commits intodelmic:masterfrom
pieleric:feat-add-meteor-support-for-jeol-jib-4700f
Oct 23, 2025
Merged

[METEOR-1481] [feat] Add METEOR support for JEOL JIB-4700F#3248
pieleric merged 2 commits intodelmic:masterfrom
pieleric:feat-add-meteor-support-for-jeol-jib-4700f

Conversation

@pieleric
Copy link
Member

@pieleric pieleric commented Oct 20, 2025

Provided by Damien McGrouther on behalf of JEOL.
Some adjustments to fix some small issues, and get to use the new SampleStage functionality.

Provided by Damien McGrouther on behalf of JEOL.
@pieleric pieleric requested review from K4rishma and Copilot October 20, 2025 20:35
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds support for the JEOL JIB-4700F microscope in the METEOR system by implementing the MeteorJeol1PostureManager class and providing a complete simulator configuration.

Key Changes:

  • Implements MeteorJeol1PostureManager with JEOL-specific stage transformation logic between SEM and FM imaging positions
  • Adds simulator configuration file meteor-jeol.odm.yaml with hardware component definitions and calibration parameters

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/odemis/acq/move.py Adds MeteorJeol1PostureManager class with JEOL-specific stage transformations and posture switching logic
install/linux/usr/share/odemis/sim/meteor-jeol.odm.yaml Provides complete simulator configuration for JEOL JIB-4700F including stage, camera, light source, and optical components
Comments suppressed due to low confidence (1)

src/odemis/acq/move.py:1

  • The comment references 'tescan' but this method is in the MeteorJeol1PostureManager class. Update the comment to reference JEOL instead of Tescan.
# -*- coding: utf-8 -*-

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@coderabbitai
Copy link

coderabbitai bot commented Oct 20, 2025

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Adds JEOL1 support by introducing MeteorJeol1PostureManager, a SampleStage wrapper, and JEOL-specific SEM⇄Meteor coordinate transformations and posture handling. Wires the new posture manager into the MicroscopePostureManager factory for stage_version "jeol_1". Includes a simulator YAML config for METEOR JEOL hardware and a unit test suite (TestMeteorJeol1Move) validating posture switches, grid/area target computations, and the SEM↔Meteor transform behavior.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant PM as MeteorJeol1PostureManager
    participant SS as SampleStage
    participant Stage

    User->>PM: request posture switch (e.g., FM_IMAGING)
    activate PM
    PM->>PM: getTargetPosition(target_label)
    Note over PM: compute target from SEM grid centers\nor use current stage-bare position
    PM->>PM: _transformFromSEMToMeteor(pos)
    Note over PM: apply tilt corrections\nmap SEM (x,y,z,rx,rz) → Meteor/FM axes
    PM->>SS: update sample-stage coordinates
    PM->>Stage: issue sub-move to stage (returns Future)
    Stage-->>PM: future handle
    PM-->>User: posture switch future
    deactivate PM

    %% Transformation examples
    User->>PM: transform SEM→Meteor (sem_pos)
    PM->>PM: _transformFromSEMToMeteor(sem_pos)
    PM-->>User: meteor_pos

    User->>PM: transform Meteor→SEM (meteor_pos)
    PM->>PM: _transformFromMeteorToSEM(meteor_pos)
    PM-->>User: sem_pos
Loading

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title "METEOR-1481 [feat] Add METEOR support for JEOL JIB-4700F" directly and clearly describes the main objective of the changeset. The raw summary confirms that the primary change is adding a new posture manager for JEOL1 hardware, creating a YAML configuration for the METEOR JEOL simulator, and adding corresponding test cases. The title is specific, concise, and uses standard conventions for ticket references and feature prefixes. It successfully communicates the core purpose of the PR—adding METEOR support for a specific JEOL model—without unnecessary noise or vagueness.
Description Check ✅ Passed The pull request description is related to the changeset and provides meaningful information about the changes. It identifies the contribution as being provided on behalf of JEOL, which aligns with the core objective of adding JEOL hardware support. The description also specifically mentions the use of "new SampleStage functionality," which directly corresponds to the introduction of a new SampleStage wrapper and its integration into the JEOL1 workflow. While the description is brief and uses somewhat general terms like "adjustments," it is sufficiently specific and related to the actual changes to pass the lenient criteria for this check.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7622f76 and 533d35b.

📒 Files selected for processing (3)
  • install/linux/usr/share/odemis/sim/meteor-jeol-sim.odm.yaml (1 hunks)
  • src/odemis/acq/move.py (2 hunks)
  • src/odemis/acq/test/move_test.py (2 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/odemis/acq/move.py (2)

2017-2034: Consider parking focus before stage moves (safety consistency)

Other posture managers park the focus before large stage moves to avoid collisions. Even if JEOL software adds interlocks, parking reduces risk and aligns behavior.

Example:

@@
-        # Move stage directly (the JEOL software takes care of the safety aspects)
+        # Optionally park focus for safety consistency (like other vendors)
+        try:
+            focus = model.getComponent(role='focus')
+            focus_md = focus.getMetadata()
+            focus_deactive = focus_md[model.MD_FAV_POS_DEACTIVE]
+            if not isNearPosition(focus.position.value, focus_deactive, focus.axes):
+                self._run_sub_move(future, focus, focus_deactive)
+        except Exception:
+            logging.debug("Focus component not available; continuing without parking.")
+
+        # Move stage (JEOL software provides additional safeties)
         target_position = self.getTargetPosition(target_posture)
         self._run_sub_move(future, self.stage, target_position)

2035-2044: Docstring mentions Tescan in JEOL method

This JEOL-specific method says “For tescan…”, which is misleading. Replace with a JEOL-specific note that the method is unused and intentionally unimplemented.

-        """Transform the shift from stage bare to chamber coordinates.
-        Used for moving the stage vertically in the chamber.
-        For tescan, the z-axis is already aligned with the chamber axis,
-        so this function returns the input.
+        """JEOL: chamber-vertical transform not used.
+        Left unimplemented intentionally for JEOL1 configuration.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c5c1254 and 6cc58ba.

📒 Files selected for processing (2)
  • install/linux/usr/share/odemis/sim/meteor-jeol.odm.yaml (1 hunks)
  • src/odemis/acq/move.py (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/odemis/acq/move.py (1)
src/odemis/driver/actuator.py (1)
  • axes (3130-3132)
🪛 Ruff (0.14.1)
src/odemis/acq/move.py

1878-1878: Avoid specifying long messages outside the exception class

(TRY003)


1928-1930: Avoid specifying long messages outside the exception class

(TRY003)


1942-1942: Avoid specifying long messages outside the exception class

(TRY003)


2024-2024: Avoid specifying long messages outside the exception class

(TRY003)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build (ubuntu-24.04)
  • GitHub Check: build (ubuntu-22.04)
🔇 Additional comments (3)
src/odemis/acq/move.py (2)

98-99: Factory dispatch: JEOL1 wired correctly

Selecting MeteorJeol1PostureManager when CALIB.version == "jeol_1" looks correct and keeps behavior consistent with other vendors.


1934-2016: No critical issues found; recommendation stands but cannot be fully verified in sandbox

The transform methods are newly implemented for JEOL systems and follow the same mathematical pattern as the tested Tescan implementation (which validates bidirectional consistency in test_switching_consistency with places=4 tolerance). Mathematical symmetry is correct: forward/reverse operations properly invert signs for dx/dy/dz, and tilt corrections are consistently inverted.

However, no JEOL-specific fixture tests exist. Your recommendation to validate with JEOL calibration constants and grid center ranges is sound—the Tescan equivalent has such tests. Since the odemis simulator is unavailable in this environment, manual verification using the fixture script (or creating a JEOL-specific test class mirroring TestMeteorTescan1Move.test_switching_consistency) would confirm grid positions map correctly between SEM/FM imaging areas.

install/linux/usr/share/odemis/sim/meteor-jeol.odm.yaml (1)

50-58: Version tag aligns with factory dispatch

CALIB.version "jeol_1" correctly triggers MeteorJeol1PostureManager selection. LGTM.

@pieleric pieleric changed the title [feat] Add METEOR support for JEOL JIB-4700F [METEOR-1481] [feat] Add METEOR support for JEOL JIB-4700F Oct 20, 2025
Copy link
Contributor

@K4rishma K4rishma left a comment

Choose a reason for hiding this comment

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

Should we add test cases for this driver in move_test.py ?

@pieleric pieleric force-pushed the feat-add-meteor-support-for-jeol-jib-4700f branch from 6cc58ba to c07ab88 Compare October 22, 2025 09:50
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (3)
install/linux/usr/share/odemis/sim/meteor-jeol-sim.odm.yaml (2)

77-77: FAV_POS_DEACTIVE.z violates stage range constraints.

The FAV_POS_DEACTIVE position has z: 0.0, which is outside the valid stage z range (either [0, 41.5e-3] or [4e-3, 41.5e-3] depending on line 38). If the minimum is 4e-3 as suggested by SEM_IMAGING_RANGE (line 70), then this loading position is invalid and could cause movement failures or detection issues.

Based on learnings from past review comments.

Apply this diff to place the loading position within valid range:

-        FAV_POS_DEACTIVE: {"x": 0.0, "y": 0.0, "z": 0.0, "rx": 0.0, "rz": 0.0 }
+        FAV_POS_DEACTIVE: {"x": 0.0, "y": 0.0, "z": 8.5e-3, "rx": 0.0, "rz": 0.0 }

Using 8.5e-3 (the z_0 reference value) is recommended as it matches the GRID centers and provides a safe loading height.


33-41: Stage z range minimum inconsistency.

The stage z range on line 38 starts at 0.e-3, but the SEM_IMAGING_RANGE on line 70 starts at 4.e-3. This inconsistency should be resolved. Based on the context and the SEM imaging requirements, the stage z minimum should likely be 4.e-3.

Apply this diff to correct the stage z range:

-            "z": [0.e-3, 41.5e-3],  # m
+            "z": [4.e-3, 41.5e-3],  # m
src/odemis/acq/move.py (1)

1911-1913: Use elif instead of second if for clearer control flow.

The second if on line 1913 should be elif to make it clear that these are mutually exclusive branches. While the current logic happens to work correctly (because when target_pos_lbl == LOADING, none of the nested conditions on lines 1914-1923 will match), using elif makes the intent explicit and prevents potential issues if the code is modified later.

Apply this diff:

         if target_pos_lbl == LOADING:
             end_pos = stage_md[model.MD_FAV_POS_DEACTIVE]
-        if current_position in [LOADING, SEM_IMAGING]:
+        elif current_position in [LOADING, SEM_IMAGING]:
             if target_pos_lbl in [SEM_IMAGING, GRID_1]:
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6cc58ba and c07ab88.

📒 Files selected for processing (3)
  • install/linux/usr/share/odemis/sim/meteor-jeol-sim.odm.yaml (1 hunks)
  • src/odemis/acq/move.py (2 hunks)
  • src/odemis/acq/test/move_test.py (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/odemis/acq/move.py (1)
src/odemis/driver/actuator.py (1)
  • axes (3130-3132)
src/odemis/acq/test/move_test.py (1)
src/odemis/acq/move.py (11)
  • MicroscopePostureManager (81-291)
  • MeteorPostureManager (294-779)
  • getCurrentPostureLabel (110-117)
  • getCurrentPostureLabel (361-386)
  • getCurrentGridLabel (388-422)
  • _transformFromSEMToMeteor (483-491)
  • _transformFromSEMToMeteor (875-915)
  • _transformFromSEMToMeteor (1112-1142)
  • _transformFromSEMToMeteor (1337-1386)
  • _transformFromSEMToMeteor (1644-1691)
  • _transformFromSEMToMeteor (1939-1980)
🪛 Ruff (0.14.1)
src/odemis/acq/move.py

1878-1878: Avoid specifying long messages outside the exception class

(TRY003)


1933-1935: Avoid specifying long messages outside the exception class

(TRY003)


1947-1947: Avoid specifying long messages outside the exception class

(TRY003)


2029-2029: Avoid specifying long messages outside the exception class

(TRY003)

src/odemis/acq/test/move_test.py

407-407: Mutable class attributes should be annotated with typing.ClassVar

(RUF012)


676-676: Do not catch blind exception: Exception

(BLE001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: lint
  • GitHub Check: build (ubuntu-22.04)
  • GitHub Check: build (ubuntu-24.04)
🔇 Additional comments (5)
src/odemis/acq/move.py (5)

98-99: LGTM! Factory wiring correctly implemented.

The JEOL 1 stage version is properly wired to instantiate MeteorJeol1PostureManager, following the established pattern for other stage versions.


1939-1980: LGTM! Tilt-based transformation correctly implemented.

The SEM-to-Meteor transformation properly accounts for tilt-dependent corrections using the z_offset and the difference in tilt angles between SEM and FM postures. The math follows the established pattern from other METEOR systems (similar to Tescan).


1982-2020: LGTM! Reverse transformation correctly implemented.

The Meteor-to-SEM transformation correctly reverses the forward transformation, applying the inverse tilt corrections. The symmetry with _transformFromSEMToMeteor is correct.


2022-2038: LGTM! Simple and appropriate delegation to JEOL software.

The implementation correctly delegates safety handling to the JEOL control software by performing a direct stage move. This is an appropriate design choice for JEOL systems where the external controller manages collision avoidance and movement safety.


1888-1892: LGTM! Sample stage creation follows TFS3 pattern.

The create_sample_stage method correctly instantiates the SampleStage wrapper, consistent with the TFS3 implementation. This enables proper coordinate transformations for the sample plane.

@pieleric
Copy link
Member Author

Should we add test cases for this driver in move_test.py ?

Yes! I've just added some now.

@pieleric pieleric force-pushed the feat-add-meteor-support-for-jeol-jib-4700f branch from c07ab88 to 7622f76 Compare October 22, 2025 10:02
@pieleric pieleric requested a review from K4rishma October 22, 2025 10:02
Make sure the target position that SwitchSamplePosition() goes to is the
same as reported by getTargetPosition(). Especially, in FM IMAGING mode,
if the user switched GRID, it would go to SEM IMAGING.

Make use of the sample stage. So the microscope file can be simplified.
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