Skip to content

Add multi-source image metadata to IjImage info#192

Open
yzx9 wants to merge 9 commits into
mainfrom
feat/info-generalize
Open

Add multi-source image metadata to IjImage info#192
yzx9 wants to merge 9 commits into
mainfrom
feat/info-generalize

Conversation

@yzx9

@yzx9 yzx9 commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Introduces an info field on IjImage (Java + Python), populated from the image's metadata, tracked in equals and the snapshot Difference so metadata changes surface in diffs, and rendered as a filtered Metadata block in perception output.

Java: buildImageMetadata assembles the "Info" property, every other String-valued property, and FileInfo.description into one deduped block (LinkedHashSet, whole-string equality), capped at 4000 chars. info is part of IjImage.equals and of the IjImage.Difference FromTo.

Python: IjImage gains info, IjImageDifference gains the matching FromTo field, and _describe appends a Metadata block after the structured fields, dropping OME keys that duplicate them (SizeX/SizeY/SizeZ/SizeC/SizeT, PhysicalSize* and units, BitsPerSample/BitsPerPixel/SignificantBits, PixelType). The raw info is preserved on the model.

Assisted-by: Claude-Code:GLM-5.2

python -m copilotj.plugin take-snapshot
# Summary of Snapshot #1
Current image: cells3d.tif
Screen size: 1920x1080
GUI scale: 1.00
## Windows
- ImageJ Main Window
- Image: cells3d.tif (id: 1, type: 16-bit grayscale (unsigned), size: 15MB, Path: /Users/yzx9/Downloads/cells3d.tif)
  Image dimension: 256x256x120 voxels, stack size: 120 (1 channels, 120 slices, 1 frames)
  Width: 256.00  , Height: 256.00  , Depth: 120.00
  Resolution: 1.0 pixels per
  Metadata:
  ImageDescription: {"shape": [60, 2, 256, 256]}
  Software: tifffile.py
  {"shape": [60, 2, 256, 256]}

yzx9 and others added 9 commits June 30, 2026 14:18
JAVA8_HOME was only for ad-hoc Java 8 downgrade checks and is not needed to
build: the core targets Java 8 bytecode via the JDK 21 compiler's --release
flag, and the dev mvn exec:exec fork cannot run on Java 8 anyway (--add-opens
is Java 9+). Remove pkgs.jdk8 from both devShells and the justfile note.
- vite ^6.4.3 -> ^8.0.12 (resolves to 8.0.16; now Rolldown + Oxc + Lightning CSS)
- @tailwindcss/vite ^4.2.1 -> ^4.2.2 (required: Vite 8 support landed in 4.2.2)
- tailwindcss ^4.2.1 -> ^4.2.2 (lockstep with the vite plugin)
- @vitejs/plugin-vue ^5.2.4 -> ^6.0.7 (current major; 5.x also declares vite ^8)

No vite.config.ts / tsconfig / Node changes needed (Node already >=22.12 in the
nix shell, CI, and Dockerfile). vue-tsc, vite build, and prettier all pass.
Bumps [pypdf](https://github.com/py-pdf/pypdf) from 6.12.2 to 6.13.3.
- [Release notes](https://github.com/py-pdf/pypdf/releases)
- [Changelog](https://github.com/py-pdf/pypdf/blob/main/CHANGELOG.md)
- [Commits](py-pdf/pypdf@6.12.2...6.13.3)

---
updated-dependencies:
- dependency-name: pypdf
  dependency-version: 6.13.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
fiji/fiji 'master' (the Fiji-Stable line) currently parents to pom-scijava 40.0.0, so this keeps the plugin aligned with the stable distribution while staying on Java 8 (no nix/CI toolchain change). Moves off 38.0.1: imglib2 6.3.0 -> 7.1.5, imagej2 2.15.0 -> 2.17.0, jackson 2.16.1 -> 2.18.0.

Supersedes Dependabot #115 (38.0.1 -> 44.0.0), which would raise the build's Java floor from 8 to 11.
syntax_error_counter in LeaderDriven.run() was never reset, so it tracked cumulative ReAct syntax errors across a whole dialog and could abort a task after 3 scattered, fully-recovered errors. Reset it to 0 at the recovery send_correction (the single choke point where the agent_resp-is-None branch routes), matching the existing tool_retry_counter reset idiom. A model that is genuinely stuck still aborts after max_syntax_errors consecutive errors.

Adds a regression test (test_leader_syntax_reset.py) covering both the cumulative-with-recovery case (now completes) and the 3-consecutive case (still aborts).

Assisted-by: Claude-Code:GLM-5.2
- BooleanParameterSchema.validate() now returns null on success to
  match its siblings, and the Javadoc on ParameterSchema.validate() is
  corrected to match the implementation (null = valid).
- StringParameterSchema enum constructor rejects null entries while
  still accepting blank strings, which are legitimate AWT Choice/List
  item labels passed by ChoiceNode/ListNode.getActions().

Assisted-by: Claude-Code:GLM-5.2
nodeToSimpleMap printed every combined word to stdout, polluting output
during JSON tree serialization. Drop the stray debug statement.

Assisted-by: Claude-Code:GLM-5.2
Add JUnit 5 unit tests (83 tests, all passing) for the six pure-logic
classes with no ImageJ/runtime coupling: Trie, JsonBase64ImageTruncator,
FromTo, BoundedLog, FlexibleLocalDateTimeDeserializer, and the
Action/ParameterSchema hierarchy. JaCoCo coverage runs through the
existing pom-scijava setup.

Build wiring:
- plugin/pom.xml: junit-jupiter test dependency (version via the
  inherited junit-jupiter.version property).
- justfile: test-plugin and test-cov-plugin targets.
- .github/workflows/test.yaml: java-test CI job (JDK 21).

Assisted-by: Claude-Code:GLM-5.2
Introduces an info field on IjImage (Java + Python), populated from the image's metadata, tracked in equals and the snapshot Difference so metadata changes surface in diffs, and rendered as a filtered Metadata block in perception output.

Java: buildImageMetadata assembles the "Info" property, every other String-valued property, and FileInfo.description into one deduped block (LinkedHashSet, whole-string equality), capped at 4000 chars. info is part of IjImage.equals and of the IjImage.Difference FromTo.

Python: IjImage gains info, IjImageDifference gains the matching FromTo field, and _describe appends a Metadata block after the structured fields, dropping OME keys that duplicate them (SizeX/SizeY/SizeZ/SizeC/SizeT, PhysicalSize* and units, BitsPerSample/BitsPerPixel/SignificantBits, PixelType). The raw info is preserved on the model.

Assisted-by: Claude-Code:GLM-5.2
@yzx9 yzx9 requested a review from 00JackLu July 1, 2026 08:40
@00JackLu

00JackLu commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

I suggest if you detect the ImageDescription: {"shape": [60, 2, 256, 256]}, should block stack size: 120 (1 channels, 120 slices, 1 frames);

@yzx9

yzx9 commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator Author

@00JackLu I completely understand your concerns, but there is one issue here: this image actually has 120 frames. It is not 60x2, despite what the shape field in the description appears to suggest.

In general, this PR is intended to fill in the missing information. We did not perform any specific checks on the image data to reconcile it with the description.

It may be worth adding an extra commit with more context to help the LLM understand why these two pieces of information appear to be different or even contradictory.

@yzx9 yzx9 changed the base branch from dev to main July 3, 2026 02:29
@yzx9 yzx9 added the enhancement New feature or request label Jul 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants