AI-generated: macsima() uses the OME plane positions as pixel padding widths, truncated
まだ誰も着手していません。
評価
調査の方向性
src/spatialdata_io/readers/macsima.py の _get_translations() から始め、続いて MultiChannelImage._pad_images() と test_get_translations_returns_correct_values を読みます。readers/_utils/_utils.py にある既存の物理サイズの参照も確認します。maintainers または実際の MACSima データから、プレーンの位置がピクセルオフセットなのか物理的な長さなのかを確認し、そのうえで、選択した解釈と丸められたパディングの挙動を対象とする回帰テストまたはデータベースのテストを追加します。
索引モデルが issue の本文から書いたものです。
説明
[!NOTE]
AI-generated issue, opened from #418 and not verified against real MACSima data. The
code pointers are accurate; the question at the end needs someone who knows what the
MACSima software writes into these fields.
What the code does
_get_translations() reads the position of the first plane of the OME metadata and turns it
into an integer — src/spatialdata_io/readers/macsima.py:
translations = {"translation_x": int(position_x), "translation_y": int(position_y)}
The values end up on ChannelMetadata.translation_x / translation_y and are consumed by
MultiChannelImage._pad_images(), which normalises them against their minimum and uses the
result directly as da.pad widths, i.e. as a number of pixels:
normalized_translations_x = [metadata.translation_x - min_translation_x for metadata in channel_metadata]
...
pad_width = ((0, 0), (pad_y_prepend, pad_y_append), (pad_x_prepend, pad_x_append))
img = da.pad(img, pad_width, mode="constant", constant_values=0)
Two things look off
1. int() truncates towards zero instead of rounding. int(0.9) == 0 and
int(-0.9) == 0, so a plane at x = 10.7 is placed at 10 and the direction of the error
depends on the sign of the position. After the normalisation against the minimum the residual
is below one pixel per channel, so this alone is minor — round() would halve the worst case
and make it sign-symmetric.
2. The positions are physical coordinates, but they are used as pixel counts. In OME,
Plane.position_x comes with a Plane.position_x_unit, and Pixels.physical_size_x gives the
size of a pixel in the same kind of unit (17.0 µm in the OMAP test data). Nothing in the
reader converts between the two, so if a MACSima file writes stage positions in micrometres the
padding is off by the pixel size — a factor of 17 for these datasets — rather than by a fraction
of a pixel. If instead the software writes pixel offsets there (position_x_unit is
REFERENCEFRAME, the OME default, i.e. unspecified, in the files I looked at), the current code
is right and only point 1 applies.
Both small test datasets (OMAP10_small, OMAP23_small) have position_x = None on every
plane, so _get_translations() returns (0, 0) there and this path is exercised by unit tests
only, never by the data-based ones.
What a fix would entail
Depending on the answer to "what unit does MACSima write":
- if the positions are already in pixels: replace
int(...)withround(...)in
_get_translations()and extendtest_get_translations_returns_correct_valueswith a
fractional case (e.g.position_x=10.7, position_y=0.9→{"translation_x": 11, "translation_y": 1}); - if they are physical lengths: read
position_x_unit/position_y_unitand
Pixels.physical_size_x/physical_size_yalongside the positions, convert to pixels
(ome_typesexposes the unit enums;parse_physical_size()in
readers/_utils/_utils.pyalready does this kind of lookup for the physical size), and round
at the end._get_translations()currently only receives theOMEobject, which is enough for
both.ChannelMetadata.translation_xstays anint, so_pad_images()is unaffected. - either way, it would be good to have a data-based test: none of the datasets currently in CI
has plane positions, so this would need either a file with real positions or a synthetic TIFF
written withtifffile.imwrite(..., metadata={...})in the style of
test_images_with_invalid_ome_metadata_are_excluded.
Context
#418 originally rounded the positions as part of fixing the regressions from #411, but that
changes reader output on a point nobody has confirmed, so it was pulled out of the PR and filed
here instead. The current behaviour on main is unchanged: truncation.
- 主要言語
- Python
- スター
- 103
- フォーク
- 65
- 平均マージ
- 1時間 8分
- マージ済み PR(30日)
- 3
環境構築
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
scverse/spatialdata-io のほかの issue
-
documentation
難易度 2/5 半日 初心者へのやさしさ 65/100
scverse/spatialdata-io#161 · コメント 13 件 ·
-
bug
難易度 3/5 1〜2日 初心者へのやさしさ 58/100
scverse/spatialdata-io#422 ·
-
難易度 5/5 1週間以上 初心者へのやさしさ 48/100
scverse/spatialdata-io#409 · リアクション 1 件 ·
-
難易度 3/5 1〜2日 初心者へのやさしさ 52/100
scverse/spatialdata-io#408 ·
-
xenium
難易度 4/5 3〜5日 初心者へのやさしさ 52/100
scverse/spatialdata-io#407 ·
scverse/spatialdata-io の issue をすべて見る
似ている issue
-
correction metadata
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
acl-org/acl-anthology#10104 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
bug status/needs-triage
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
prowler-cloud/prowler#12885 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
Bug in GaussianTailProbabilityCalibrator: running_statistics=False still uses a windowed varianceオープンbug good first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
selimfirat/pysad#107 ·
メンテナーはふだん 1 日以内に返信
-
bug ci-failure high priority
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
vllm-project/vllm-omni#8194 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
メンテナーはふだん 1 日以内に返信