Skip to content

Fix/issue 327 single roi polus#330

Open
sameeul wants to merge 15 commits intoPolusAI:mainfrom
sameeul:fix/issue-327-single-roi-polus
Open

Fix/issue 327 single roi polus#330
sameeul wants to merge 15 commits intoPolusAI:mainfrom
sameeul:fix/issue-327-single-roi-polus

Conversation

@sameeul
Copy link
Copy Markdown
Member

@sameeul sameeul commented Mar 12, 2026

No description provided.

sameeul and others added 11 commits March 12, 2026 17:31
…les (PolusAI#327)

Make theEnvironment.singleROI the single source of truth for wholeslide
mode across all entry points and scan sites.

- dirs_and_files.cpp: set singleROI=true when wholeslide detected from
  directory structure, so downstream scan sites see the flag
- new_bindings_py.cpp: fill labelFiles with empty strings when
  single_roi=True; fix validation to allow empty seg list in that case;
  only check seg file existence when path is non-empty
- nyxus.py: allow mask_files=None when single_roi=True; pass [] instead
  of None to the C++ binding
- slideprops.cpp, phase1.cpp, phase2.cpp: replace independent spL==nullptr
  / fname_seg.empty() checks with theEnvironment.singleROI (3 sites in
  phase2.cpp)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Five pytest cases covering the fixed single_roi=True path in featurize_files:
- no mask files → succeeds, one row per image with label=1
- mask files supplied but single_roi=True → mask is ignored, results identical to no-mask case
- single_roi=False (segmented) → multiple rows per image (unchanged behavior)
- single_roi=False, no mask → raises IOError (unchanged behavior)
- single_roi=True results consistent with featurize_directory when no seg dir given

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The polus version of read_2D_dataset() has no Environment parameter, so
theEnvironment is undeclared there. The callers (featurize_directory_imp
et al.) already set env.singleROI before calling read_2D_dataset, making
this assignment redundant anyway.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nisotropic

This function has no Environment& parameter, so env.singleROI would fail
to compile. The variable was also never used — the function is wholeslide-
only by definition and feeds pixels unconditionally.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
gatherRoisMetrics_2_slideprops_2D and _3D have no Environment parameter
so env.singleROI doesn't compile there. p.fname_seg.empty() is the
correct local signal: in the wholeslide path labelFiles are empty strings,
so fname_seg is empty iff singleROI is true.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…anisotropic__OLD

Same issue as scan_trivial_wholeslide_anisotropic in phase2_2d.cpp:
no Environment parameter so env.singleROI doesn't compile, and the
variable was never used anyway — this is a wholevolume-only function.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use ROI_label instead of label (polus column name)
- featurize_directory wholeslide: pass int_dir as label_dir (same-dir
  detection) instead of '' which polus rejects with OSError

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…comparison

intensity_image legitimately differs in format (full path vs basename)
between the two code paths, so skip string columns in numeric comparison.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sameeul
Copy link
Copy Markdown
Member Author

sameeul commented Mar 25, 2026

Fixes #327

sameeul and others added 4 commits March 27, 2026 14:33
Merge conflict residue introduced a validation block that used
labelFiles before it was declared (its declaration is inside the else
branch). Remove the duplicate pre-check block; the segmented path's
existing validation inside the else branch is sufficient.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ctions

On Linux, Python's memory allocator reuses freed object addresses, so
id(new_nyx) can equal id(old_nyx). The pynyxus_cache returns the old
Environment whose singleROI=true (left over from a prior whole-slide
featurize_directory call). initialize_environment calls
compile_feature_settings() with that stale value, baking SINGLEROI=true
into all feature settings. When featurize_montage_imp later sets
singleROI=false, the settings were never refreshed, causing
ContourFeature::calculate to call buildWholeSlideContour (AABB corners)
instead of buildRegularContour, producing PERIMETER=22.0 for a
speckle-only mask.

Fix:
- Make compile_feature_settings() idempotent by clearing f_settings_
  and feature2settings_ at the start.
- Call compile_feature_settings() in every featurize_*_imp function
  right after singleROI is assigned, so SINGLEROI in feature settings
  always matches the current run mode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

1 participant