@@ -98,6 +98,7 @@ public class CurationManager implements PlausibilityMonitor.WarningListener {
9898 private JCheckBox terminalNearAncestorCheckbox ;
9999 private JCheckBox radiusJumpsCheckbox ;
100100 private JCheckBox radiusMonoCheckbox ;
101+ private JCheckBox invalidRadiusCheckbox ;
101102 private JCheckBox zExtentCheckbox ;
102103 private JCheckBox uncertainTerminalCheckbox ;
103104 private JCheckBox intensityValleyCheckbox ;
@@ -817,8 +818,8 @@ private JPanel buildOnDemandParamsPanel() {
817818 final int savedLeft = c .insets .left ;
818819 c .insets .left += sectionChildIndent (onDemandHeaderCheckbox );
819820
820- // Path overlap
821- final PlausibilityCheck .PathOverlap overlapCheck = monitor .getDeepCheck (PlausibilityCheck .PathOverlap .class );
821+ // Crossovers
822+ final PlausibilityCheck .Crossovers overlapCheck = monitor .getDeepCheck (PlausibilityCheck .Crossovers .class );
822823 // On-demand check UI controls
823824 overlapCheckbox = new JCheckBox ("Cross-over detection: max proximity" , overlapCheck != null && overlapCheck .isEnabled ());
824825 overlapCheckbox .setToolTipText ("Detects regions where distinct paths run suspiciously close, suggesting duplicate tracing" );
@@ -829,7 +830,7 @@ private JPanel buildOnDemandParamsPanel() {
829830 if (overlapCheck != null ) overlapCheck .setProximityUm ((Double ) overlapSpinner .getValue ());
830831 });
831832 final JButton overlapHist = (overlapCheck == null ) ? null
832- : CurationHistograms .button ("Path overlap " ,
833+ : CurationHistograms .button ("Crossovers " ,
833834 paths -> monitor .measure (overlapCheck , paths ),
834835 this ::currentPaths ,
835836 () -> ((Number ) overlapSpinner .getValue ()).doubleValue (),
@@ -935,6 +936,15 @@ private JPanel buildOnDemandParamsPanel() {
935936 CurationHistograms .Side .RIGHT_FLAGGED , p );
936937 addCheckRow (p , c , radiusMonoCheckbox , spinnerWithHistogram (radiusMonoSpinner , radiusMonoHist ));
937938
939+ // Invalid radii (zero/NaN) -- flag-only, no threshold
940+ final PlausibilityCheck .InvalidRadius invalidRadiusCheck =
941+ monitor .getDeepCheck (PlausibilityCheck .InvalidRadius .class );
942+ invalidRadiusCheckbox = new JCheckBox ("Invalid thickness: flag" ,
943+ invalidRadiusCheck != null && invalidRadiusCheck .isEnabled ());
944+ invalidRadiusCheckbox .setToolTipText ("Flags paths containing nodes with zero, negative, or NaN radius (typically un-fitted nodes)" );
945+ wireCheckbox (invalidRadiusCheckbox , null , invalidRadiusCheck );
946+ addCheckRow (p , c , invalidRadiusCheckbox , null );
947+
938948 // Image signal quality
939949 final PlausibilityCheck .SignalQuality signalCheck = monitor .getDeepCheck (PlausibilityCheck .SignalQuality .class );
940950 signalQualityCheckbox = new JCheckBox ("Path signal quality: min contrast" ,
@@ -1050,7 +1060,7 @@ private JPanel buildOnDemandParamsPanel() {
10501060 // Collect and wire section-level toggling
10511061 onDemandCheckboxes = List .of (overlapCheckbox , bundledPathsCheckbox ,
10521062 terminalNearAncestorCheckbox , zExtentCheckbox ,
1053- radiusJumpsCheckbox , radiusMonoCheckbox ,
1063+ radiusJumpsCheckbox , radiusMonoCheckbox , invalidRadiusCheckbox ,
10541064 signalQualityCheckbox , uncertainTerminalCheckbox ,
10551065 intensityValleyCheckbox );
10561066 wireSectionHeader (onDemandHeaderCheckbox , onDemandCheckboxes );
@@ -1542,11 +1552,11 @@ private void syncUIFromMonitor() {
15421552 constantRadiiCheckbox .setSelected (cr .isEnabled ());
15431553 }
15441554 // Deep checks
1545- final PlausibilityCheck .PathOverlap po = monitor .getDeepCheck (PlausibilityCheck .PathOverlap .class );
1546- if (po != null ) {
1547- overlapSpinner .setValue (po .getProximityUm ());
1548- overlapCheckbox .setSelected (po .isEnabled ());
1549- overlapSpinner .setEnabled (po .isEnabled ());
1555+ final PlausibilityCheck .Crossovers co = monitor .getDeepCheck (PlausibilityCheck .Crossovers .class );
1556+ if (co != null ) {
1557+ overlapSpinner .setValue (co .getProximityUm ());
1558+ overlapCheckbox .setSelected (co .isEnabled ());
1559+ overlapSpinner .setEnabled (co .isEnabled ());
15501560 }
15511561 final PlausibilityCheck .RadiusJumps rj = monitor .getDeepCheck (PlausibilityCheck .RadiusJumps .class );
15521562 if (rj != null ) {
@@ -1560,6 +1570,10 @@ private void syncUIFromMonitor() {
15601570 radiusMonoCheckbox .setSelected (rm .isEnabled ());
15611571 radiusMonoSpinner .setEnabled (rm .isEnabled ());
15621572 }
1573+ final PlausibilityCheck .InvalidRadius ir = monitor .getDeepCheck (PlausibilityCheck .InvalidRadius .class );
1574+ if (ir != null && invalidRadiusCheckbox != null ) {
1575+ invalidRadiusCheckbox .setSelected (ir .isEnabled ());
1576+ }
15631577 final PlausibilityCheck .SignalQuality sq =
15641578 monitor .getDeepCheck (PlausibilityCheck .SignalQuality .class );
15651579 if (signalQualityCheckbox != null && sq != null ) {
@@ -1942,12 +1956,13 @@ private static String getDocAnchor(final String checkName) {
19421956 case "Tortuosity consistency" -> "#tortuosity-max-mismatch-at-fork" ;
19431957 case "Constant radii" -> "#uniform-thickness-flag" ;
19441958 // On-demand (deep) checks
1945- case "Path overlap " -> "#cross-over-detection-max-proximity" ;
1959+ case "Crossovers " -> "#cross-over-detection-max-proximity" ;
19461960 case "Bundled paths" -> "#bundle-detection-max-angle-" ;
19471961 case "Missed-fork candidate" -> "#missed-fork-candidate-max-proximity" ;
19481962 case "Z-extent ratio" -> "#z-extent-min-ratio" ;
19491963 case "Thickness jumps" -> "#thickness-jumps-max-ratio" ;
19501964 case "Thickness inversions" -> "#thickness-inversions-min-run-length" ;
1965+ case "Invalid radius" -> "#invalid-thickness-flag" ;
19511966 case "Path signal quality" -> "#path-signal-quality-min-contrast" ;
19521967 case "Tip signal quality" -> "#tip-signal-quality-min-contrast" ;
19531968 case "Path signal quality dips" -> "#path-signal-quality-dips-min-drop" ;
0 commit comments