{
 "exported_at": "2026-10-28T23:53:39.442889+00:00",
 "exported_by": {
  "app": "quantetta-a web",
  "code": {
   "git_commit": "",
   "dirty": false
  }
 },
 "recording_short": "mouse_2609_150ms_control_MiCAM",
 "header": {
  "short": "mouse_2609_150ms_control_MiCAM",
  "label": "Open-Source Low-Cost Cardiac Optical Mapping System: mouse_2609_150ms_control_MiCAM",
  "facts": "100 \u00d7 100 px, 2,047 frames, 0.977 kHz, pixel size not stated, deposit checks: negative values",
  "run_short": "2aec1b88",
  "run_when": "2026-10-28 18:59 UTC",
  "params_version": 3,
  "commit": "0aee293",
  "dirty": true,
  "workers": 4,
  "sig_short": "0187eb93",
  "run_status": "done",
  "protocol_name": "Mouse whole heart optical mapping (Luther lab)"
 },
 "parameters": "% Mouse whole heart optical mapping (Luther lab), v3, read-only\n% set by developer (not a domain scientist); provisional, REVIEW_NEEDED 16\nbaseline_frames  = 901;     % >= 2 x slowest cycle (22, images): ok\npad_frames       = 500;     % each side, outside the window\nspatial_sigma    = 1.0;     % px, Gaussian, phase only\nspatial_truncate = 4.0;     % kernel radius, sigma\nlowpass          = [];      % none\npolarity         = 1;       % measured, skew of dV/dt\nrotor_threshold  = 0.9;     % turns, |winding| per plaquette\nrotor_erode_px   = 3;       % px from tissue edge ignored\nlink_px          = 4.0;     % tracking, max step per frame\nmax_gap          = 5;       % frames a track may vanish\nmin_cycles       = 1.0;     % own rotations, min_frames = 150\npair_dist_px     = 3.0;     % opposite-charge pairing\npaired_frac      = 0.5;     % max paired fraction of a track\nrender_step      = 4;       % movie only",
 "segments": [
  {
   "name": "whole_recording",
   "label": "Whole recording",
   "short": "whole recording",
   "defined": "0\u20132,047",
   "analysed": "500\u20131,547",
   "analysed_range": [
    500,
    1547
   ],
   "start": 0,
   "end": 2047,
   "cycle": "22 (10% of pixels)",
   "expected": "not stated",
   "bounded": "recording start \u2192 recording end",
   "defined_by": "admission (project lead); no comparison defined",
   "citation": null,
   "provisional": true
  }
 ],
 "metrics": {
  "maps": {
   "activation": "runs/2aec1b88-1bc3-430f-9d57-a9ddcf39928c/activation_map.png",
   "dominant_frequency": "runs/2aec1b88-1bc3-430f-9d57-a9ddcf39928c/dominant_frequency_map.png"
  },
  "frames": 1047,
  "tracks": 337,
  "cv_cm_s": null,
  "apd50_ms": 22.517911975435005,
  "apd90_ms": 58.341862845445235,
  "segments": {
   "whole_recording": {
    "beats": {
     "note": null,
     "beats": 8,
     "per_beat": [
      {
       "cv": {
        "method": "1/|grad T| on a 1 px Gaussian-smoothed max-dV/dt activation map; finite differences",
        "plane_fit": {
         "direction_deg": 97.06386302011042,
         "speed_px_per_frame": 2.1777025260230816
        },
        "pixels_used": 1114,
        "pixels_total": 1114,
        "iqr_px_per_frame": [
         0.10806597024094947,
         0.23239969812160452
        ],
        "median_px_per_frame": 0.15384549373459727
       },
       "apd_ms": {
        "apd50": {
         "iqr": [
          6.1412487205731825,
          38.89457523029682
         ],
         "median": 16.37666325486182
        },
        "apd90": {
         "iqr": [
          8.18833162743091,
          45.03582395087001
         ],
         "median": 20.470829068577277
        }
       },
       "window": [
        500,
        610
       ],
       "apd_frames": {
        "apd50": {
         "iqr": [
          6.0,
          38.0
         ],
         "median": 16.0,
         "defined_frac": 0.3267504488330341
        },
        "apd90": {
         "iqr": [
          8.0,
          44.0
         ],
         "median": 20.0,
         "defined_frac": 0.2881508078994614
        }
       },
       "upstroke_frame": 524,
       "activation_coverage": 0.1114,
       "activation_spread_ms": 102.35414534288638,
       "activation_spread_frames": 100.0
      },
      {
       "cv": {
        "method": "1/|grad T| on a 1 px Gaussian-smoothed max-dV/dt activation map; finite differences",
        "plane_fit": {
         "direction_deg": -105.46115931820133,
         "speed_px_per_frame": 1.692450978842342
        },
        "pixels_used": 1111,
        "pixels_total": 1114,
        "iqr_px_per_frame": [
         0.24877999766140763,
         3.0984055639581145
        ],
        "median_px_per_frame": 1.5012441896465185
       },
       "apd_ms": {
        "apd50": {
         "iqr": [
          13.306038894575229,
          27.635619242579324
         ],
         "median": 21.49437052200614
        },
        "apd90": {
         "iqr": [
          40.941658137154555,
          63.45957011258956
         ],
         "median": 58.341862845445235
        }
       },
       "window": [
        610,
        760
       ],
       "apd_frames": {
        "apd50": {
         "iqr": [
          13.0,
          27.0
         ],
         "median": 21.0,
         "defined_frac": 0.9685816876122083
        },
        "apd90": {
         "iqr": [
          40.0,
          62.0
         ],
         "median": 57.0,
         "defined_frac": 0.9649910233393177
        }
       },
       "upstroke_frame": 640,
       "activation_coverage": 0.1114,
       "activation_spread_ms": 55.27123848515865,
       "activation_spread_frames": 54.0
      },
      {
       "cv": {
        "method": "1/|grad T| on a 1 px Gaussian-smoothed max-dV/dt activation map; finite differences",
        "plane_fit": {
         "direction_deg": -124.9340998089325,
         "speed_px_per_frame": 0.8616456700968296
        },
        "pixels_used": 1108,
        "pixels_total": 1114,
        "iqr_px_per_frame": [
         0.229371886834557,
         3.37660584410455
        ],
        "median_px_per_frame": 1.7036131904878955
       },
       "apd_ms": {
        "apd50": {
         "iqr": [
          13.306038894575229,
          28.659160696008186
         ],
         "median": 22.517911975435005
        },
        "apd90": {
         "iqr": [
          41.96519959058342,
          65.50665301944728
         ],
         "median": 59.365404298874104
        }
       },
       "window": [
        760,
        908
       ],
       "apd_frames": {
        "apd50": {
         "iqr": [
          13.0,
          28.0
         ],
         "median": 22.0,
         "defined_frac": 0.9730700179533214
        },
        "apd90": {
         "iqr": [
          41.0,
          64.0
         ],
         "median": 58.0,
         "defined_frac": 0.9694793536804309
        }
       },
       "upstroke_frame": 790,
       "activation_coverage": 0.1114,
       "activation_spread_ms": 53.940634595700935,
       "activation_spread_frames": 52.69999999999982
      },
      {
       "cv": {
        "method": "1/|grad T| on a 1 px Gaussian-smoothed max-dV/dt activation map; finite differences",
        "plane_fit": {
         "direction_deg": -128.899343996631,
         "speed_px_per_frame": 0.6029690049378923
        },
        "pixels_used": 1108,
        "pixels_total": 1114,
        "iqr_px_per_frame": [
         0.16642311052657985,
         2.9788929494506498
        ],
        "median_px_per_frame": 1.400056425370554
       },
       "apd_ms": {
        "apd50": {
         "iqr": [
          16.37666325486182,
          41.96519959058342
         ],
         "median": 24.56499488229273
        },
        "apd90": {
         "iqr": [
          47.85056294779938,
          75.74206755373592
         ],
         "median": 61.41248720573183
        }
       },
       "window": [
        908,
        1060
       ],
       "apd_frames": {
        "apd50": {
         "iqr": [
          16.0,
          41.0
         ],
         "median": 24.0,
         "defined_frac": 0.9685816876122083
        },
        "apd90": {
         "iqr": [
          46.75,
          74.0
         ],
         "median": 60.0,
         "defined_frac": 0.9443447037701975
        }
       },
       "upstroke_frame": 938,
       "activation_coverage": 0.1114,
       "activation_spread_ms": 83.93039918116683,
       "activation_spread_frames": 82.0
      },
      {
       "cv": {
        "method": "1/|grad T| on a 1 px Gaussian-smoothed max-dV/dt activation map; finite differences",
        "plane_fit": {
         "direction_deg": -142.95475049115552,
         "speed_px_per_frame": 0.5101779622579411
        },
        "pixels_used": 1105,
        "pixels_total": 1114,
        "iqr_px_per_frame": [
         0.15359310387252575,
         3.0562860249583883
        ],
        "median_px_per_frame": 1.5543552493330322
       },
       "apd_ms": {
        "apd50": {
         "iqr": [
          13.306038894575229,
          36.33572159672467
         ],
         "median": 23.541453428863868
        },
        "apd90": {
         "iqr": [
          54.247697031729786,
          75.74206755373592
         ],
         "median": 61.41248720573183
        }
       },
       "window": [
        1060,
        1210
       ],
       "apd_frames": {
        "apd50": {
         "iqr": [
          13.0,
          35.5
         ],
         "median": 23.0,
         "defined_frac": 0.9326750448833034
        },
        "apd90": {
         "iqr": [
          53.0,
          74.0
         ],
         "median": 60.0,
         "defined_frac": 0.8456014362657092
        }
       },
       "upstroke_frame": 1090,
       "activation_coverage": 0.1114,
       "activation_spread_ms": 115.6601842374616,
       "activation_spread_frames": 113.0
      },
      {
       "cv": {
        "method": "1/|grad T| on a 1 px Gaussian-smoothed max-dV/dt activation map; finite differences",
        "plane_fit": {
         "direction_deg": -117.13546570231759,
         "speed_px_per_frame": 0.9842594760534598
        },
        "pixels_used": 1108,
        "pixels_total": 1114,
        "iqr_px_per_frame": [
         0.1727902936014619,
         3.2521273841951652
        ],
        "median_px_per_frame": 1.6191141246653964
       },
       "apd_ms": {
        "apd50": {
         "iqr": [
          13.306038894575229,
          29.682702149437052
         ],
         "median": 22.517911975435005
        },
        "apd90": {
         "iqr": [
          42.98874104401228,
          62.43602865916069
         ],
         "median": 58.341862845445235
        }
       },
       "window": [
        1210,
        1360
       ],
       "apd_frames": {
        "apd50": {
         "iqr": [
          13.0,
          29.0
         ],
         "median": 22.0,
         "defined_frac": 0.895870736086176
        },
        "apd90": {
         "iqr": [
          42.0,
          61.0
         ],
         "median": 57.0,
         "defined_frac": 0.8752244165170556
        }
       },
       "upstroke_frame": 1240,
       "activation_coverage": 0.1114,
       "activation_spread_ms": 84.9539406345957,
       "activation_spread_frames": 83.0
      },
      {
       "cv": {
        "method": "1/|grad T| on a 1 px Gaussian-smoothed max-dV/dt activation map; finite differences",
        "plane_fit": {
         "direction_deg": -69.55837112966296,
         "speed_px_per_frame": 2.977601940867358
        },
        "pixels_used": 1106,
        "pixels_total": 1114,
        "iqr_px_per_frame": [
         0.2907766136285297,
         3.289218870433565
        ],
        "median_px_per_frame": 1.7610394916466179
       },
       "apd_ms": {
        "apd50": {
         "iqr": [
          16.37666325486182,
          33.776867963152505
         ],
         "median": 23.541453428863868
        },
        "apd90": {
         "iqr": [
          42.98874104401228,
          64.2272262026612
         ],
         "median": 58.341862845445235
        }
       },
       "window": [
        1360,
        1510
       ],
       "apd_frames": {
        "apd50": {
         "iqr": [
          16.0,
          33.0
         ],
         "median": 23.0,
         "defined_frac": 0.9730700179533214
        },
        "apd90": {
         "iqr": [
          42.0,
          62.75
         ],
         "median": 57.0,
         "defined_frac": 0.9676840215439856
        }
       },
       "upstroke_frame": 1390,
       "activation_coverage": 0.1114,
       "activation_spread_ms": 47.441146366427745,
       "activation_spread_frames": 46.34999999999991
      },
      {
       "cv": {
        "method": "1/|grad T| on a 1 px Gaussian-smoothed max-dV/dt activation map; finite differences",
        "plane_fit": {
         "direction_deg": 74.9927438291005,
         "speed_px_per_frame": 2.3383314256588736
        },
        "pixels_used": 1105,
        "pixels_total": 1114,
        "iqr_px_per_frame": [
         0.902052556893744,
         3.6112382720342717
        ],
        "median_px_per_frame": 2.2704752167809796
       },
       "apd_ms": {
        "apd50": {
         "iqr": [
          7.1647901740020465,
          9.211873080859775
         ],
         "median": 8.18833162743091
        },
        "apd90": {
         "iqr": [
          8.18833162743091,
          23.541453428863868
         ],
         "median": 10.235414534288639
        }
       },
       "window": [
        1510,
        1547
       ],
       "apd_frames": {
        "apd50": {
         "iqr": [
          7.0,
          9.0
         ],
         "median": 8.0,
         "defined_frac": 0.4730700179533214
        },
        "apd90": {
         "iqr": [
          8.0,
          23.0
         ],
         "median": 10.0,
         "defined_frac": 0.11220825852782765
        }
       },
       "upstroke_frame": 1540,
       "activation_coverage": 0.1114,
       "activation_spread_ms": 24.56499488229273,
       "activation_spread_frames": 24.0
      }
     ],
     "cv_cm_s_median": null,
     "apd50_ms_median": 22.517911975435005,
     "apd90_ms_median": 58.341862845445235,
     "representative_beat": 0,
     "cv_px_per_frame_median": 1.5867346869992143,
     "global_amplitude_ratio": 0.7534515895747264
    },
    "frames": [
     500,
     1547
    ],
    "dominant_freq": 6.531996179560649,
    "persistent_rotors": 0,
    "singularity_count_max": 13,
    "singularity_count_mean": 1.4001910219675262,
    "singularity_frames_frac": 0.48519579751671443,
    "persistent_rotor_count_max": 0,
    "persistent_rotor_durations": [],
    "persistent_rotor_frames_frac": 0.0
   }
  },
  "computed_on": {
   "amplitude_p99": "baseline-corrected",
   "dominant_freq": "baseline-corrected, median of per-pixel spectral peaks",
   "activation_apd_cv": "baseline-corrected display signal, per global beat",
   "singularities_and_rotors": "phase of spatially filtered signal"
  },
  "amplitude_p99": 147.62158203125,
  "dominant_freq": 6.531996179560649,
  "mask_coverage": 0.1114,
  "pixel_size_um": null,
  "tissue_pixels": 1114,
  "min_rotor_frames": 150,
  "persistence_rule": "own_rotation",
  "dominant_freq_iqr": [
   6.531996179560649,
   6.531996179560649
  ],
  "persistent_rotors": 0,
  "dominant_freq_unit": "Hz",
  "singularity_count_max": 13,
  "singularity_count_mean": 1.4001910219675262,
  "paired_singularity_frac": 0.6098226466575716,
  "persistent_rotor_tracks": 0,
  "singularity_frames_frac": 0.48519579751671443,
  "dominant_freq_tissue_mean": 6.531996179560649,
  "persistent_rotor_count_max": 0,
  "persistent_rotor_durations": [],
  "persistent_rotor_lifetimes": [],
  "persistent_rotor_frames_frac": 0.0
 },
 "reportable": {
  "persistent_rotor_tracks": {
   "unit": "count",
   "status": "unstable, not reportable",
   "settings": "sensitivity grid + trackers",
   "range_across_settings": [
    0.0,
    3.0
   ]
  },
  "whole_recording.dominant_freq_hz": {
   "unit": "Hz",
   "value": 6.532,
   "checked": "no_cited_range"
  },
  "whole_recording.persistent_rotors": {
   "unit": "count",
   "status": "unstable, not reportable",
   "settings": "sensitivity grid + trackers",
   "range_across_settings": [
    0.0,
    3.0
   ]
  },
  "whole_recording.singularity_frames_frac": {
   "unit": "fraction of frames",
   "status": "unstable, not reportable",
   "settings": "sensitivity grid + trackers",
   "range_across_settings": [
    0.18242597898758356,
    0.7459407831900668
   ]
  },
  "whole_recording.persistent_rotor_count_max": {
   "unit": "count",
   "status": "unstable, not reportable",
   "settings": "sensitivity grid + trackers",
   "range_across_settings": [
    0.0,
    1.0
   ]
  }
 },
 "physiology_ok": null,
 "sensitivity": {
  "grid": [
   {
    "sigma": "light",
    "baseline": "6x_cycle",
    "findings": null,
    "segments": {
     "whole_recording": {
      "beats": null,
      "frames": [
       500,
       1547
      ],
      "dominant_freq": null,
      "persistent_rotors": 0,
      "singularity_count_max": 28,
      "singularity_count_mean": 4.2683858643744035,
      "singularity_frames_frac": 0.7449856733524355,
      "persistent_rotor_count_max": 0,
      "persistent_rotor_durations": [],
      "persistent_rotor_frames_frac": 0.0
     }
    },
    "spatial_sigma": 0.5,
    "is_run_setting": false,
    "baseline_frames": 900,
    "persistent_rotor_tracks": 0
   },
   {
    "sigma": "default",
    "baseline": "6x_cycle",
    "findings": null,
    "segments": {
     "whole_recording": {
      "beats": null,
      "frames": [
       500,
       1547
      ],
      "dominant_freq": null,
      "persistent_rotors": 0,
      "singularity_count_max": 13,
      "singularity_count_mean": 1.4030563514804202,
      "singularity_frames_frac": 0.48519579751671443,
      "persistent_rotor_count_max": 0,
      "persistent_rotor_durations": [],
      "persistent_rotor_frames_frac": 0.0
     }
    },
    "spatial_sigma": 1.0,
    "is_run_setting": false,
    "baseline_frames": 900,
    "persistent_rotor_tracks": 0
   },
   {
    "sigma": "heavier",
    "baseline": "6x_cycle",
    "findings": null,
    "segments": {
     "whole_recording": {
      "beats": null,
      "frames": [
       500,
       1547
      ],
      "dominant_freq": null,
      "persistent_rotors": 0,
      "singularity_count_max": 7,
      "singularity_count_mean": 0.34765998089780326,
      "singularity_frames_frac": 0.20248328557784145,
      "persistent_rotor_count_max": 0,
      "persistent_rotor_durations": [],
      "persistent_rotor_frames_frac": 0.0
     }
    },
    "spatial_sigma": 2.0,
    "is_run_setting": false,
    "baseline_frames": 900,
    "persistent_rotor_tracks": 0
   },
   {
    "sigma": "light",
    "baseline": "3x_cycle",
    "findings": null,
    "segments": {
     "whole_recording": {
      "beats": null,
      "frames": [
       500,
       1547
      ],
      "dominant_freq": null,
      "persistent_rotors": 0,
      "singularity_count_max": 24,
      "singularity_count_mean": 4.255969436485196,
      "singularity_frames_frac": 0.7402101241642789,
      "persistent_rotor_count_max": 0,
      "persistent_rotor_durations": [],
      "persistent_rotor_frames_frac": 0.0
     }
    },
    "spatial_sigma": 0.5,
    "is_run_setting": false,
    "baseline_frames": 450,
    "persistent_rotor_tracks": 0
   },
   {
    "sigma": "default",
    "baseline": "3x_cycle",
    "findings": null,
    "segments": {
     "whole_recording": {
      "beats": null,
      "frames": [
       500,
       1547
      ],
      "dominant_freq": null,
      "persistent_rotors": 0,
      "singularity_count_max": 11,
      "singularity_count_mean": 1.3524355300859598,
      "singularity_frames_frac": 0.47277936962750716,
      "persistent_rotor_count_max": 0,
      "persistent_rotor_durations": [],
      "persistent_rotor_frames_frac": 0.0
     }
    },
    "spatial_sigma": 1.0,
    "is_run_setting": false,
    "baseline_frames": 450,
    "persistent_rotor_tracks": 0
   },
   {
    "sigma": "heavier",
    "baseline": "3x_cycle",
    "findings": null,
    "segments": {
     "whole_recording": {
      "beats": null,
      "frames": [
       500,
       1547
      ],
      "dominant_freq": null,
      "persistent_rotors": 1,
      "singularity_count_max": 7,
      "singularity_count_mean": 0.335243553008596,
      "singularity_frames_frac": 0.2072588347659981,
      "persistent_rotor_count_max": 1,
      "persistent_rotor_durations": [
       {
        "end": 1010,
        "core": [
         31.12,
         42.41
        ],
        "start": 967,
        "charge": 1,
        "rotations": 1.046,
        "lifetime_cycles": 0.29,
        "lifetime_frames": 44,
        "frames_in_segment": 44,
        "rotation_period_frames": 42.05
       }
      ],
      "persistent_rotor_frames_frac": 0.04202483285577841
     }
    },
    "spatial_sigma": 2.0,
    "is_run_setting": false,
    "baseline_frames": 450,
    "persistent_rotor_tracks": 1
   },
   {
    "sigma": "light",
    "baseline": "1.5x_cycle",
    "findings": null,
    "segments": {
     "whole_recording": {
      "beats": null,
      "frames": [
       500,
       1547
      ],
      "dominant_freq": null,
      "persistent_rotors": 0,
      "singularity_count_max": 23,
      "singularity_count_mean": 3.659025787965616,
      "singularity_frames_frac": 0.7058261700095511,
      "persistent_rotor_count_max": 0,
      "persistent_rotor_durations": [],
      "persistent_rotor_frames_frac": 0.0
     }
    },
    "spatial_sigma": 0.5,
    "is_run_setting": false,
    "baseline_frames": 225,
    "persistent_rotor_tracks": 0
   },
   {
    "sigma": "default",
    "baseline": "1.5x_cycle",
    "findings": null,
    "segments": {
     "whole_recording": {
      "beats": null,
      "frames": [
       500,
       1547
      ],
      "dominant_freq": null,
      "persistent_rotors": 0,
      "singularity_count_max": 9,
      "singularity_count_mean": 1.146131805157593,
      "singularity_frames_frac": 0.4469914040114613,
      "persistent_rotor_count_max": 0,
      "persistent_rotor_durations": [],
      "persistent_rotor_frames_frac": 0.0
     }
    },
    "spatial_sigma": 1.0,
    "is_run_setting": false,
    "baseline_frames": 225,
    "persistent_rotor_tracks": 0
   },
   {
    "sigma": "heavier",
    "baseline": "1.5x_cycle",
    "findings": null,
    "segments": {
     "whole_recording": {
      "beats": null,
      "frames": [
       500,
       1547
      ],
      "dominant_freq": null,
      "persistent_rotors": 0,
      "singularity_count_max": 5,
      "singularity_count_mean": 0.282712511938873,
      "singularity_frames_frac": 0.18242597898758356,
      "persistent_rotor_count_max": 0,
      "persistent_rotor_durations": [],
      "persistent_rotor_frames_frac": 0.0
     }
    },
    "spatial_sigma": 2.0,
    "is_run_setting": false,
    "baseline_frames": 225,
    "persistent_rotor_tracks": 0
   },
   {
    "sigma": "light",
    "baseline": "run",
    "findings": null,
    "segments": {
     "whole_recording": {
      "beats": null,
      "frames": [
       500,
       1547
      ],
      "dominant_freq": null,
      "persistent_rotors": 1,
      "singularity_count_max": 28,
      "singularity_count_mean": 4.260744985673353,
      "singularity_frames_frac": 0.7459407831900668,
      "persistent_rotor_count_max": 1,
      "persistent_rotor_durations": [
       {
        "end": 1272,
        "core": [
         33.33,
         37.22
        ],
        "start": 1245,
        "charge": -1,
        "rotations": 1.035,
        "lifetime_cycles": 0.19,
        "lifetime_frames": 28,
        "frames_in_segment": 28,
        "rotation_period_frames": 27.05
       }
      ],
      "persistent_rotor_frames_frac": 0.026743075453677174
     }
    },
    "spatial_sigma": 0.5,
    "is_run_setting": false,
    "baseline_frames": 901,
    "persistent_rotor_tracks": 1
   },
   {
    "sigma": "default",
    "baseline": "run",
    "findings": null,
    "segments": {
     "whole_recording": {
      "beats": null,
      "frames": [
       500,
       1547
      ],
      "dominant_freq": null,
      "persistent_rotors": 0,
      "singularity_count_max": 13,
      "singularity_count_mean": 1.4001910219675262,
      "singularity_frames_frac": 0.48519579751671443,
      "persistent_rotor_count_max": 0,
      "persistent_rotor_durations": [],
      "persistent_rotor_frames_frac": 0.0
     }
    },
    "spatial_sigma": 1.0,
    "is_run_setting": true,
    "baseline_frames": 901,
    "persistent_rotor_tracks": 0
   },
   {
    "sigma": "heavier",
    "baseline": "run",
    "findings": null,
    "segments": {
     "whole_recording": {
      "beats": null,
      "frames": [
       500,
       1547
      ],
      "dominant_freq": null,
      "persistent_rotors": 0,
      "singularity_count_max": 7,
      "singularity_count_mean": 0.35052531041069723,
      "singularity_frames_frac": 0.2034383954154728,
      "persistent_rotor_count_max": 0,
      "persistent_rotor_durations": [],
      "persistent_rotor_frames_frac": 0.0
     }
    },
    "spatial_sigma": 2.0,
    "is_run_setting": false,
    "baseline_frames": 901,
    "persistent_rotor_tracks": 0
   }
  ],
  "fixed": {
   "expect": null,
   "window": [
    500,
    1547
   ],
   "polarity": 1,
   "segments": {
    "whole_recording": [
     500,
     1547
    ]
   },
   "rotor_erode_px": 3,
   "rotor_threshold": 0.9,
   "min_rotor_frames": 150
  },
  "holds": null,
  "status": "provisional",
  "varied": {
   "spatial_sigma": {
    "light": 0.5,
    "default": 1.0,
    "heavier": 2.0
   },
   "baseline_frames": {
    "run": 901,
    "3x_cycle": 450,
    "6x_cycle": 900,
    "1.5x_cycle": 225
   },
   "baseline_scaling": {
    "multiples": {
     "3x_cycle": 3.0,
     "6x_cycle": 6.0,
     "1.5x_cycle": 1.5
    },
    "reference_segment": "whole_recording",
    "segment_cycles_frames": {
     "whole_recording": 150
    },
    "reference_cycle_frames": 150,
    "window_over_cycle_per_segment": {
     "run": {
      "whole_recording": 6.01
     },
     "3x_cycle": {
      "whole_recording": 3.0
     },
     "6x_cycle": {
      "whole_recording": 6.0
     },
     "1.5x_cycle": {
      "whole_recording": 1.5
     }
    }
   },
   "tracker(link_px, max_gap)": {
    "loose": [
     6.0,
     10
    ],
    "strict": [
     2.0,
     1
    ],
    "default": [
     4.0,
     5
    ]
   }
  },
  "findings": null,
  "trackers": [
   {
    "link_px": 2.0,
    "max_gap": 1,
    "tracker": "strict",
    "findings": null,
    "segments": {
     "whole_recording": {
      "beats": null,
      "frames": [
       500,
       1547
      ],
      "dominant_freq": null,
      "persistent_rotors": 0,
      "singularity_count_max": 13,
      "singularity_count_mean": 1.4001910219675262,
      "singularity_frames_frac": 0.48519579751671443,
      "persistent_rotor_count_max": 0,
      "persistent_rotor_durations": [],
      "persistent_rotor_frames_frac": 0.0
     }
    },
    "is_run_setting": false,
    "persistent_rotor_tracks": 0
   },
   {
    "link_px": 4.0,
    "max_gap": 5,
    "tracker": "default",
    "findings": null,
    "segments": {
     "whole_recording": {
      "beats": null,
      "frames": [
       500,
       1547
      ],
      "dominant_freq": null,
      "persistent_rotors": 0,
      "singularity_count_max": 13,
      "singularity_count_mean": 1.4001910219675262,
      "singularity_frames_frac": 0.48519579751671443,
      "persistent_rotor_count_max": 0,
      "persistent_rotor_durations": [],
      "persistent_rotor_frames_frac": 0.0
     }
    },
    "is_run_setting": true,
    "persistent_rotor_tracks": 0
   },
   {
    "link_px": 6.0,
    "max_gap": 10,
    "tracker": "loose",
    "findings": null,
    "segments": {
     "whole_recording": {
      "beats": null,
      "frames": [
       500,
       1547
      ],
      "dominant_freq": null,
      "persistent_rotors": 3,
      "singularity_count_max": 13,
      "singularity_count_mean": 1.4001910219675262,
      "singularity_frames_frac": 0.48519579751671443,
      "persistent_rotor_count_max": 1,
      "persistent_rotor_durations": [
       {
        "end": 1023,
        "core": [
         30.67,
         45.41
        ],
        "start": 968,
        "charge": 1,
        "rotations": 1.191,
        "lifetime_cycles": 0.37,
        "lifetime_frames": 56,
        "frames_in_segment": 56,
        "rotation_period_frames": 47.02
       },
       {
        "end": 1117,
        "core": [
         31.78,
         41.67
        ],
        "start": 1075,
        "charge": 1,
        "rotations": 1.443,
        "lifetime_cycles": 0.29,
        "lifetime_frames": 43,
        "frames_in_segment": 43,
        "rotation_period_frames": 29.8
       },
       {
        "end": 1210,
        "core": [
         33.91,
         51.21
        ],
        "start": 1156,
        "charge": 1,
        "rotations": 2.623,
        "lifetime_cycles": 0.37,
        "lifetime_frames": 55,
        "frames_in_segment": 55,
        "rotation_period_frames": 20.97
       }
      ],
      "persistent_rotor_frames_frac": 0.14708691499522444
     }
    },
    "is_run_setting": false,
    "persistent_rotor_tracks": 3
   }
  ]
 },
 "critic": {
  "code": {
   "dirty": true,
   "git_commit": "0aee29346248785f557664cd859ddeb50fecd3d5"
  },
  "agent": "critic",
  "model": "openai:gpt-5.5",
  "checks": {
   "checks": {
    "persistent_rotor_tracks": {
     "unit": "count",
     "range": null,
     "metric": "persistent_rotor_tracks",
     "stable": false,
     "status": "unstable_not_reportable",
     "segment": null,
     "spread_frac": null,
     "value_at_run_setting": 0,
     "range_across_settings": [
      0.0,
      3.0
     ]
    },
    "whole_recording.dominant_freq_hz": {
     "unit": "Hz",
     "range": null,
     "metric": "dominant_freq_hz",
     "stable": true,
     "status": "no_cited_range",
     "segment": "whole_recording",
     "spread_frac": 0.0,
     "value_at_run_setting": 6.532,
     "range_across_settings": [
      6.532,
      6.532
     ]
    },
    "whole_recording.persistent_rotors": {
     "unit": "count",
     "range": null,
     "metric": "persistent_rotors",
     "stable": false,
     "status": "unstable_not_reportable",
     "segment": "whole_recording",
     "spread_frac": null,
     "value_at_run_setting": 0,
     "range_across_settings": [
      0.0,
      3.0
     ]
    },
    "whole_recording.singularity_frames_frac": {
     "unit": "fraction of frames",
     "range": null,
     "metric": "singularity_frames_frac",
     "stable": false,
     "status": "unstable_not_reportable",
     "segment": "whole_recording",
     "spread_frac": 1.176,
     "value_at_run_setting": 0.48519579751671443,
     "range_across_settings": [
      0.18242597898758356,
      0.7459407831900668
     ]
    },
    "whole_recording.persistent_rotor_count_max": {
     "unit": "count",
     "range": null,
     "metric": "persistent_rotor_count_max",
     "stable": false,
     "status": "unstable_not_reportable",
     "segment": "whole_recording",
     "spread_frac": null,
     "value_at_run_setting": 0,
     "range_across_settings": [
      0.0,
      1.0
     ]
    }
   },
   "unstable": [
    "whole_recording.singularity_frames_frac",
    "whole_recording.persistent_rotors",
    "whole_recording.persistent_rotor_count_max",
    "persistent_rotor_tracks"
   ],
   "physiology_ok": null,
   "ranged_checks": []
  },
  "ranges": [
   {
    "id": "mouse_spiral_rotation_hz",
    "low": 18.75,
    "high": 20.0,
    "unit": "Hz",
    "scope": "one optical mapping recording in the same study (spiral wave before and during illumination); not a population range",
    "metric": "dominant_freq_hz",
    "source": {
     "ref": "10.1371/journal.pcbi.1011660",
     "quotes": [
      "rotational frequency of \u2248 20 Hz before illumination",
      "the frequency of the arrhythmia decreases to \u2248 18\\.75 Hz"
     ],
     "passages": [
      " is shown in Fig 3B. It shows that the arrhythmia consists of a single spiral wave with a stationary core dynamic and a rotational frequency of \u2248 20 Hz before illumination. During a single global optical pulse with a PL of 5000 ms and an LI of 3.21 \u03bcW/mm2, the frequency of the arrhythmia de",
      "ncy of \u2248 20 Hz before illumination. During a single global optical pulse with a PL of 5000 ms and an LI of 3.21 \u03bcW/mm2, the frequency of the arrhythmia decreases to \u2248 18.75 Hz. It is important to note that the frequency reverses its original value of \u2248 20 Hz when the light is turned off. Fig 3C"
     ]
    },
    "status": "provisional",
    "tissue": "whole_heart",
    "species": "mouse",
    "applies_to": {
     "segment_expected_persistent_rotors": "present"
    },
    "checked_low": 14.0625,
    "checked_high": 25.0,
    "tolerance_frac": 0.25
   }
  ],
  "run_id": "2aec1b88-1bc3-430f-9d57-a9ddcf39928c",
  "status": "provisional",
  "verdict": {
   "send_back": true,
   "critic_notes": "Send back this signature as not reportable as it stands: the whole_recording singularity-frame fraction is unstable across 0.18242597898758356 to 0.7459407831900668, persistent_rotors across 0.0 to 3.0, persistent_rotor_count_max across 0.0 to 1.0, and persistent_rotor_tracks across 0.0 to 3.0, all under the provisional stability threshold of (max - min) <= 0.25 x median and provisional criteria; the only stable metric is dominant_freq_hz at 6.532 Hz across baseline-window settings, but it has no cited acceptance range for this paced control context, and the available mouse spiral-wave context instead describes approximately 18.75 to 20.0 Hz rotation in another study (DOI 10.1371/journal.pcbi.1011660). Persistent-rotor threshold tests are not applicable because there are no segment expectations, while tracker sensitivity needs review because strict/default tracking is at the lower end of the unstable rotor range and loose tracking is at the upper end; also review the frame-rate provenance for the MiCAM-labelled file using the 977.0 Hz admission value, possible pre-deposit sign or conditioning, all-negative integer values, the unsuitable rhythm-detector short-cycle result relative to the expected pacing period, and the non-biological mask; all ranges, the stability threshold, and criteria are provisional.",
   "review_items": [
    {
     "topic": "unstable:whole_recording.singularity_frames_frac",
     "detail": "The singularity-frame fraction is unstable across the filter grid, ranging from 0.18242597898758356 to 0.7459407831900668; do not report a definitive value without resolving parameter sensitivity.",
     "severity": "block",
     "reviewer_type": "analysis_qc"
    },
    {
     "topic": "unstable:whole_recording.persistent_rotors",
     "detail": "Across sensitivity settings the range is 0.0 to 3.0; do not report persistent_rotors as a definitive result without resolving tracking and filtering sensitivity.",
     "severity": "block",
     "reviewer_type": "analysis_qc"
    },
    {
     "topic": "unstable:whole_recording.persistent_rotor_count_max",
     "detail": "Across sensitivity settings the range is 0.0 to 1.0; do not report persistent_rotor_count_max as a definitive result without sensitivity review.",
     "severity": "block",
     "reviewer_type": "analysis_qc"
    },
    {
     "topic": "unstable:persistent_rotor_tracks",
     "detail": "Across sensitivity settings the range is 0.0 to 3.0; track-level persistence is not reportable as a definitive result.",
     "severity": "block",
     "reviewer_type": "analysis_qc"
    },
    {
     "topic": "tracker_variant_count_disagreement",
     "detail": "Strict/default tracking sits at the lower end of the unstable rotor range, while loose tracking sits at the upper end; review this as tracker sensitivity, not as proof that rotors are absent or present.",
     "severity": "warn",
     "reviewer_type": "analysis_qc"
    },
    {
     "topic": "Frame-rate provenance for a MiCAM file",
     "detail": "Use the admission value of 977.0 Hz as the working frame rate, but review provenance because the cited paper quote aligns with the custom iDS system while this deposited file is labelled MiCAM, and the Zenodo metadata does not state the MiCAM frame rate.",
     "severity": "warn",
     "reviewer_type": "data_provenance"
    },
    {
     "topic": "Pre-deposit sign/conditioning",
     "detail": "The signal is consistently non-inverted even though Di-4-ANEPPS usually dims on depolarization, suggesting sign flip or other transformation before deposit/export; downstream orientation from the measurement makes this a warning rather than a block.",
     "severity": "warn",
     "reviewer_type": "data_provenance"
    },
    {
     "topic": "Unexplained all-negative data values",
     "detail": "All values are negative integers and are flagged as processed_before_deposit; the linked paper documents possible filtering/averaging workflows, but no deposit README explains this file-level transformation.",
     "severity": "warn",
     "reviewer_type": "data_provenance"
    },
    {
     "topic": "Rhythm detector not suitable for the expected paced period here",
     "detail": "Do not use the rhythm detector's short-cycle result to infer physiology or frame rate here, because the expected pacing period lies beyond the rhythm tool's baseline-correction window.",
     "severity": "info",
     "reviewer_type": "analysis_qc"
    },
    {
     "topic": "Mask is not a heart segmentation",
     "detail": "The current analysis mask is based on nonzero temporal standard deviation, not a biological tissue segmentation; spatial map interpretation needs a tissue-only mask.",
     "severity": "warn",
     "reviewer_type": "analysis_qc"
    }
   ],
   "tracker_note": "Tracker variants are sensitive: strict and default are at the lower end of the persistent-rotor range, while loose is at the upper end; this mismatch should be reviewed as tracker sensitivity rather than proof that the finding is false.",
   "physiology_ok": null,
   "metric_judgments": [
    {
     "note": "This fraction varies across the filter grid from 0.18242597898758356 to 0.7459407831900668, so it is unstable under the provisional stability rule and should not be reported as a definitive signature value.",
     "metric": "whole_recording.singularity_frames_frac",
     "status": "unstable_not_reportable"
    },
    {
     "note": "Across sensitivity settings the reportable range is 0.0 to 3.0; because the range changes with filtering and tracker choices, persistent_rotors is unstable and not reportable as a definitive result.",
     "metric": "whole_recording.persistent_rotors",
     "status": "unstable_not_reportable"
    },
    {
     "note": "Across sensitivity settings the reportable range is 0.0 to 1.0; because the range changes with filtering and tracker choices, persistent_rotor_count_max is unstable and not reportable as a definitive result.",
     "metric": "whole_recording.persistent_rotor_count_max",
     "status": "unstable_not_reportable"
    },
    {
     "note": "The dominant frequency is stable across the baseline-window sensitivity settings at 6.532 Hz, but no cited range was available for this recording context; the available mouse spiral context is from another optical-mapping study and describes approximately 18.75 to 20.0 Hz spiral-wave rotation, not a population acceptance range for this paced control file (DOI 10.1371/journal.pcbi.1011660).",
     "metric": "whole_recording.dominant_freq_hz",
     "status": "no_cited_range"
    },
    {
     "note": "Across sensitivity settings the reportable range is 0.0 to 3.0; because the range changes with filtering and tracker choices, persistent_rotor_tracks is unstable and not reportable as a definitive result.",
     "metric": "persistent_rotor_tracks",
     "status": "unstable_not_reportable"
    }
   ],
   "send_back_reason": "The core signature metrics for singularity burden and persistent rotors are unstable across sensitivity settings, so the signature should not be reported as it stands; only the stable dominant frequency can be described, and it has no cited acceptance range for this context.",
   "persistence_threshold_note": "Persistent-rotor threshold comparison is not applicable at both the measured-cycle threshold and the paper-rotation threshold, because there are no segment expectations for this recording; the two variants therefore have no agreement verdict."
  },
  "passages": {
   "mouse_spiral_rotation_period": {
    "ref": "10.1371/journal.pcbi.1011660",
    "note": "At 1000 frames/s, 20 Hz is a 50-frame rotation; the illuminated value of 18.75 Hz would be 53 frames.",
    "quotes": [
     "rotational frequency of \u2248 20 Hz before illumination"
    ],
    "status": "provisional",
    "passages": [
     " is shown in Fig 3B. It shows that the arrhythmia consists of a single spiral wave with a stationary core dynamic and a rotational frequency of \u2248 20 Hz before illumination. During a single global optical pulse with a PL of 5000 ms and an LI of 3.21 \u03bcW/mm2, the frequency of the arrhythmia de"
    ],
    "applies_to": {
     "species": "mouse"
    },
    "rotation_hz": 20.0
   }
  },
  "trackers": {
   "note": "disagreement is reported as a review item, not folded into the pass/fail",
   "agree": true,
   "trackers": [
    {
     "link_px": 2.0,
     "max_gap": 1,
     "tracker": "strict",
     "is_run_setting": false,
     "persistent_rotors_by_segment": {
      "whole_recording": 0
     }
    },
    {
     "link_px": 4.0,
     "max_gap": 5,
     "tracker": "default",
     "is_run_setting": true,
     "persistent_rotors_by_segment": {
      "whole_recording": 0
     }
    },
    {
     "link_px": 6.0,
     "max_gap": 10,
     "tracker": "loose",
     "is_run_setting": false,
     "persistent_rotors_by_segment": {
      "whole_recording": 3
     }
    }
   ]
  },
  "stability": {
   "persistent_rotor_tracks": {
    "max": 3.0,
    "min": 0.0,
    "median": 0.0,
    "stable": false,
    "settings": 15,
    "spread_frac": null,
    "values_grid": [
     0,
     0,
     0,
     0,
     0,
     1,
     0,
     0,
     0,
     1,
     0,
     0
    ],
    "varied_over": "filter grid + trackers",
    "values_trackers": [
     0,
     0,
     3
    ]
   },
   "whole_recording.dominant_freq_hz": {
    "max": 6.532,
    "min": 6.532,
    "median": 6.532,
    "stable": true,
    "settings": 4,
    "spread_frac": 0.0,
    "varied_over": "baseline windows",
    "values_by_baseline": {
     "225": 6.532,
     "450": 6.532,
     "900": 6.532,
     "901": 6.532
    }
   },
   "whole_recording.persistent_rotors": {
    "max": 3.0,
    "min": 0.0,
    "median": 0.0,
    "stable": false,
    "settings": 15,
    "spread_frac": null,
    "values_grid": [
     0,
     0,
     0,
     0,
     0,
     1,
     0,
     0,
     0,
     1,
     0,
     0
    ],
    "varied_over": "filter grid + trackers",
    "values_trackers": [
     0,
     0,
     3
    ]
   },
   "whole_recording.singularity_frames_frac": {
    "max": 0.7459407831900668,
    "min": 0.18242597898758356,
    "median": 0.4789875835721108,
    "stable": false,
    "settings": 12,
    "spread_frac": 1.176,
    "values_grid": [
     0.7449856733524355,
     0.48519579751671443,
     0.20248328557784145,
     0.7402101241642789,
     0.47277936962750716,
     0.2072588347659981,
     0.7058261700095511,
     0.4469914040114613,
     0.18242597898758356,
     0.7459407831900668,
     0.48519579751671443,
     0.2034383954154728
    ],
    "varied_over": "filter grid"
   },
   "whole_recording.persistent_rotor_present": {
    "stable": false,
    "values_grid": [
     false,
     false,
     false,
     false,
     false,
     true,
     false,
     false,
     false,
     true,
     false,
     false
    ],
    "varied_over": "filter grid + trackers",
    "values_trackers": [
     false,
     false,
     true
    ],
    "stable_across_filters": false,
    "stable_across_trackers": false
   },
   "whole_recording.persistent_rotor_count_max": {
    "max": 1.0,
    "min": 0.0,
    "median": 0.0,
    "stable": false,
    "settings": 15,
    "spread_frac": null,
    "values_grid": [
     0,
     0,
     0,
     0,
     0,
     1,
     0,
     0,
     0,
     1,
     0,
     0
    ],
    "varied_over": "filter grid + trackers",
    "values_trackers": [
     0,
     0,
     1
    ]
   }
  },
  "reviewed_at": "2026-10-28T19:01:50.716293+00:00",
  "recording_id": "ae77081e-a125-471f-8805-27dad0688848",
  "signature_id": "0187eb93-2c8b-4500-b11c-9d0062c96d4a",
  "prompt_version": "critic-v1",
  "criteria_status": {
   "note": null,
   "rules": [
    {
     "id": "physiology_reference_rates",
     "expert": "cardiac electrophysiologist per species",
     "status": "provisional",
     "values": {
      "ranges": [
       "mouse_spiral_rotation_hz"
      ],
      "tolerance_frac": 0.25,
      "segment_rhythm_rule": "expected persistent rotors 'present' -> spiral arrhythmia"
     },
     "decision": null,
     "location": "worker/voltage/physiology.py (RANGES, TOLERANCE_FRAC)",
     "reviewed": false,
     "reviewer": null,
     "description": "Cited physiological ranges (single-study values widened by a 25% tolerance), applied to segments by their expected rhythm; used by the critic and for frame-rate sanity checks",
     "reviewed_at": null
    },
    {
     "id": "stability_rule",
     "expert": "biostatistician + optical mapping analyst",
     "status": "provisional",
     "values": {
      "unstable": [
       "whole_recording.singularity_frames_frac",
       "whole_recording.persistent_rotors",
       "whole_recording.persistent_rotor_count_max",
       "persistent_rotor_tracks"
      ],
      "stable_frac": 0.25
     },
     "decision": null,
     "location": "worker/agents/critic.py (STABLE_FRAC, stability)",
     "reviewed": false,
     "reviewer": null,
     "description": "A metric is reportable only if its spread across all sensitivity settings is <= 25% of its median (zero spread when all values are 0); otherwise 'unstable, not reportable'",
     "reviewed_at": null
    },
    {
     "id": "persistence_threshold_variants",
     "expert": "computational cardiac electrophysiologist (phase mapping)",
     "status": "provisional",
     "values": {
      "measured_cycle": 150,
      "paper_rotation": null
     },
     "decision": null,
     "location": "worker/agents/critic.py (persistence_variants)",
     "reviewed": false,
     "reviewer": null,
     "description": "The persistent-rotor rule is run at two lifetimes, one measured cycle of the fastest segment and the paper's cited rotation period; both verdicts stored, disagreement flagged",
     "reviewed_at": null
    },
    {
     "id": "persistent_rotor_criterion",
     "expert": "cardiac electrophysiologist",
     "status": "provisional",
     "values": {
      "max_absent": 0,
      "min_present": 1
     },
     "decision": null,
     "location": "worker/voltage/sensitivity.py (MIN_ROTORS_PRESENT, MAX_ROTORS_ABSENT)",
     "reviewed": false,
     "reviewer": null,
     "description": "Persistent-rotor finding holds if every 'present' segment has >= 1 persistent rotor and every 'absent' segment has none, at every setting",
     "reviewed_at": null
    },
    {
     "id": "sensitivity_grid",
     "expert": "optical mapping analyst",
     "status": "provisional",
     "values": {
      "spatial_sigma": {
       "light": 0.5,
       "default": 1.0,
       "heavier": 2.0
      },
      "baseline_frames": {
       "run": 901,
       "3x_cycle": 450,
       "6x_cycle": 900,
       "1.5x_cycle": 225
      },
      "baseline_scaling": {
       "multiples": {
        "3x_cycle": 3.0,
        "6x_cycle": 6.0,
        "1.5x_cycle": 1.5
       },
       "reference_segment": "whole_recording",
       "segment_cycles_frames": {
        "whole_recording": 150
       },
       "reference_cycle_frames": 150,
       "window_over_cycle_per_segment": {
        "run": {
         "whole_recording": 6.01
        },
        "3x_cycle": {
         "whole_recording": 3.0
        },
        "6x_cycle": {
         "whole_recording": 6.0
        },
        "1.5x_cycle": {
         "whole_recording": 1.5
        }
       }
      },
      "tracker(link_px, max_gap)": {
       "loose": [
        6.0,
        10
       ],
       "strict": [
        2.0,
        1
       ],
       "default": [
        4.0,
        5
       ]
      }
     },
     "decision": null,
     "location": "worker/voltage/sensitivity.py (SIGMAS, BASELINE_MULTIPLES, baseline_levels)",
     "reviewed": false,
     "reviewer": null,
     "description": "Filter levels tested: spatial sigma and baseline window values",
     "reviewed_at": null
    }
   ],
   "status": "provisional",
   "all_reviewed": false,
   "superseded_by_run": null
  },
  "persistence_variants": {
   "agree": null,
   "measured_cycle": {
    "basis": "one dominant cycle of the fastest segment at the run setting",
    "reason": "no segment expectations, so the rule has nothing to test",
    "applicable": false,
    "min_frames": 150
   },
   "paper_rotation": {
    "reason": "no segment expectations",
    "applicable": false
   }
  },
  "required_review_topics": [
   "unstable:whole_recording.singularity_frames_frac",
   "unstable:whole_recording.persistent_rotors",
   "unstable:whole_recording.persistent_rotor_count_max",
   "unstable:persistent_rotor_tracks"
  ]
 },
 "criteria": [
  {
   "criterion": "Design expectations",
   "rule": "none stated for this recording's segments",
   "result": "no criterion to test; counts are descriptive",
   "provisional": true
  }
 ],
 "report": {
  "methods": "Using provisional parameter set version 3 for protocol f65d786f-f194-4be2-88b8-10d3dd25d674, the provisional fixed criteria use baseline_frames=901, spatial_sigma=1.0, spatial_truncate=4.0, pad_frames=500, rotor_threshold=0.9, rotor_erode_px=3, link_px=4.0, max_gap=5, min_cycles=1.0, pair_dist_px=3.0, paired_frac=0.5, and render_step=4. The recording has 2047 frames of size 100x100; the frame rate used is 977.0 Hz from the recording-row admission source citing 10.1371/journal.pone.0259174, and the pixel size is not provided. The analysed frames are 500 to 1547 for the whole-recording analysis window, and the provisional segment definition is whole_recording from frame 0 to frame 2047, defined at admission with no detected or logged events.",
  "rules": [
   {
    "id": "protocol_parameter_set",
    "description": "Each protocol's fixed, versioned analysis parameters (version 1 = developer defaults); no run or agent may deviate",
    "expert": "optical mapping analyst",
    "status": "provisional",
    "location": "worker/voltage/protocol_params.py (developer_defaults, set_params)",
    "values": {
     "set_by": "developer (not a domain scientist)",
     "protocol": "Mouse whole heart optical mapping (Luther lab)",
     "protocol_id": "f65d786f-f194-4be2-88b8-10d3dd25d674",
     "params_version": 3
    }
   },
   {
    "id": "baseline_window_rule",
    "description": "A run proceeds only if the protocol's baseline window is >= 2x the slowest segment's cycle, the cycle from the MAP channel when a DAQ log exists, else from per-pixel dominant frequency on linearly detrended pixels; otherwise the run is held by code",
    "expert": "optical mapping analyst",
    "status": "provisional",
    "location": "worker/voltage/baseline_rule.py (FACTOR, evaluate)",
    "values": {
     "ok": true,
     "factor": 2.0,
     "source": "per-pixel dominant frequency (images)",
     "required_min_frames": 44,
     "slowest_cycle_frames": 22
    }
   },
   {
    "id": "filter_defaults",
    "description": "Default baseline window (frames) and spatial Gaussian sigma/truncate for phase",
    "expert": "optical mapping analyst (cardiac electrophysiology)",
    "status": "provisional",
    "location": "worker/voltage/preprocess.py (Params)",
    "values": {
     "lowpass": null,
     "spatial_sigma": 1.0,
     "baseline_frames": 901,
     "spatial_truncate": 4.0
    }
   },
   {
    "id": "tissue_mask",
    "description": "Tissue mask from, in order: (1) NaN in frame 0 when the recording has any NaN; (2) a mask or background-image variable shipped in the file whose shape matches the frame (binary as is, an intensity image thresholded with Otsu); (3) Otsu's threshold on the mean image, the class with more temporal signal as tissue, largest connected component kept; source, coverage and threshold recorded",
    "expert": "optical mapping analyst",
    "status": "provisional",
    "location": "worker/voltage/io.py (tissue_mask_info, otsu_threshold, largest_component)",
    "values": {
     "rule": "intensity variable 'bgimage' in the file, Otsu threshold 2165, class above with more temporal signal, largest connected component",
     "side": "above",
     "source": "file_variable",
     "coverage": 0.1114,
     "variable": "bgimage",
     "threshold": 2165.203125,
     "tissue_pixels": 1114
    }
   },
   {
    "id": "polarity",
    "description": "Dye polarity from sign of median per-pixel skew of dV/dt",
    "expert": "optical mapping analyst / voltage dye chemist",
    "status": "provisional",
    "location": "worker/voltage/preprocess.py (polarity)",
    "values": {
     "method": "median skew of dV/dt",
     "result": 1
    }
   },
   {
    "id": "singularity_detection",
    "description": "Phase singularity = |winding| > threshold turns, >= erode px from tissue edge",
    "expert": "computational cardiac electrophysiologist (phase mapping)",
    "status": "provisional",
    "location": "worker/voltage/preprocess.py (Params.rotor_threshold, rotor_erode_px)",
    "values": {
     "rotor_erode_px": 3,
     "rotor_threshold": 0.9
    }
   },
   {
    "id": "rotor_persistence",
    "description": "Track linking distance/gap and minimum lifetime for a persistent rotor",
    "expert": "computational cardiac electrophysiologist (phase mapping)",
    "status": "provisional",
    "location": "worker/voltage/rotors.py (TrackParams)",
    "values": {
     "link_px": 4.0,
     "max_gap": 5,
     "min_cycles": 1.0,
     "min_frames": 150
    }
   },
   {
    "id": "chirality_pairing",
    "description": "Opposite-charge singularities within pair distance are a pair; tracks paired most of their life are excluded from rotors",
    "expert": "computational cardiac electrophysiologist (phase mapping)",
    "status": "provisional",
    "location": "worker/voltage/rotors.py (TrackParams.pair_dist_px, paired_frac)",
    "values": {
     "paired_frac": 0.5,
     "pair_dist_px": 3.0
    }
   },
   {
    "id": "sensitivity_grid",
    "description": "Filter levels tested: spatial sigma and baseline window values",
    "expert": "optical mapping analyst",
    "status": "provisional",
    "location": "worker/voltage/sensitivity.py (SIGMAS, BASELINE_MULTIPLES, baseline_levels)",
    "values": {
     "sigmas": {
      "light": 0.5,
      "default": 1.0,
      "heavier": 2.0
     },
     "trackers": {
      "loose": [
       6.0,
       10
      ],
      "strict": [
       2.0,
       1
      ],
      "default": [
       4.0,
       5
      ]
     },
     "baselines": {
      "run": 901,
      "3x_cycle": 450,
      "6x_cycle": 900,
      "1.5x_cycle": 225
     }
    }
   },
   {
    "id": "analysis_window",
    "description": "Frames analysed: whole recording minus one filter pad at each end (unless the plan narrows it)",
    "expert": "cardiac electrophysiologist familiar with the dataset",
    "status": "provisional",
    "location": "worker/voltage/runs.py (default_window)",
    "values": {
     "f0": 500,
     "f1": 1547
    }
   },
   {
    "id": "prior_processing_flags",
    "description": "Thresholds for flagging depositor processing (normalization, masking, temporal/spatial smoothing)",
    "expert": "imaging scientist (camera acquisition and noise)",
    "status": "provisional",
    "location": "worker/voltage/inspect.py (prior_processing)",
    "values": {
     "flags": [
      "negative_values"
     ],
     "thresholds": {
      "int_frac": 0.5,
      "neg_frac": 0.01,
      "dv_autocorr": 0.5,
      "neighbour_corr": 0.8
     }
    }
   },
   {
    "id": "pipeline_check",
    "description": "The pipeline agent's hold/proceed decision from protocol mismatches and inspector anomalies; it chooses no parameter",
    "expert": "optical mapping analyst",
    "status": "provisional",
    "location": "worker/agents/pipeline.py (INSTRUCTIONS, validator)",
    "values": {
     "model": "openai:gpt-5.5",
     "proceed": true,
     "anomalies": [
      "Frame-rate provenance for a MiCAM file",
      "Pre-deposit sign/conditioning",
      "Unexplained all-negative data values",
      "Mask is not a heart segmentation",
      "baseline-window rule",
      "Rhythm detector not suitable for the expected paced period here"
     ],
     "mismatches": []
    }
   },
   {
    "id": "physiology_reference_rates",
    "description": "Cited physiological ranges (single-study values widened by a 25% tolerance), applied to segments by their expected rhythm; used by the critic and for frame-rate sanity checks",
    "expert": "cardiac electrophysiologist per species",
    "status": "provisional",
    "location": "worker/voltage/physiology.py (RANGES, TOLERANCE_FRAC)",
    "values": {
     "ranges": [
      "mouse_spiral_rotation_hz"
     ],
     "tolerance_frac": 0.25,
     "segment_rhythm_rule": "expected persistent rotors 'present' -> spiral arrhythmia"
    }
   },
   {
    "id": "stability_rule",
    "description": "A metric is reportable only if its spread across all sensitivity settings is <= 25% of its median (zero spread when all values are 0); otherwise 'unstable, not reportable'",
    "expert": "biostatistician + optical mapping analyst",
    "status": "provisional",
    "location": "worker/agents/critic.py (STABLE_FRAC, stability)",
    "values": {
     "unstable": [
      "whole_recording.singularity_frames_frac",
      "whole_recording.persistent_rotors",
      "whole_recording.persistent_rotor_count_max",
      "persistent_rotor_tracks"
     ],
     "stable_frac": 0.25
    }
   },
   {
    "id": "persistence_threshold_variants",
    "description": "The persistent-rotor rule is run at two lifetimes, one measured cycle of the fastest segment and the paper's cited rotation period; both verdicts stored, disagreement flagged",
    "expert": "computational cardiac electrophysiologist (phase mapping)",
    "status": "provisional",
    "location": "worker/agents/critic.py (persistence_variants)",
    "values": {
     "measured_cycle": 150,
     "paper_rotation": null
    }
   },
   {
    "id": "persistent_rotor_criterion",
    "description": "Persistent-rotor finding holds if every 'present' segment has >= 1 persistent rotor and every 'absent' segment has none, at every setting",
    "expert": "cardiac electrophysiologist",
    "status": "provisional",
    "location": "worker/voltage/sensitivity.py (MIN_ROTORS_PRESENT, MAX_ROTORS_ABSENT)",
    "values": {
     "max_absent": 0,
     "min_present": 1
    }
   }
  ],
  "review_items": [
   {
    "topic": "unstable:whole_recording.singularity_frames_frac",
    "detail": "The singularity-frame fraction is unstable across the filter grid, ranging from 0.18242597898758356 to 0.7459407831900668; do not report a definitive value without resolving parameter sensitivity.",
    "severity": "block",
    "reviewer": "analysis_qc"
   },
   {
    "topic": "unstable:whole_recording.persistent_rotors",
    "detail": "Across sensitivity settings the range is 0.0 to 3.0; do not report persistent_rotors as a definitive result without resolving tracking and filtering sensitivity.",
    "severity": "block",
    "reviewer": "analysis_qc"
   },
   {
    "topic": "unstable:whole_recording.persistent_rotor_count_max",
    "detail": "Across sensitivity settings the range is 0.0 to 1.0; do not report persistent_rotor_count_max as a definitive result without sensitivity review.",
    "severity": "block",
    "reviewer": "analysis_qc"
   },
   {
    "topic": "unstable:persistent_rotor_tracks",
    "detail": "Across sensitivity settings the range is 0.0 to 3.0; track-level persistence is not reportable as a definitive result.",
    "severity": "block",
    "reviewer": "analysis_qc"
   },
   {
    "topic": "tracker_variant_count_disagreement",
    "detail": "Strict/default tracking sits at the lower end of the unstable rotor range, while loose tracking sits at the upper end; review this as tracker sensitivity, not as proof that rotors are absent or present.",
    "severity": "warn",
    "reviewer": "analysis_qc"
   },
   {
    "topic": "Frame-rate provenance for a MiCAM file",
    "detail": "Use the admission value of 977.0 Hz as the working frame rate, but review provenance because the cited paper quote aligns with the custom iDS system while this deposited file is labelled MiCAM, and the Zenodo metadata does not state the MiCAM frame rate.",
    "severity": "warn",
    "reviewer": "data_provenance"
   },
   {
    "topic": "Pre-deposit sign/conditioning",
    "detail": "The signal is consistently non-inverted even though Di-4-ANEPPS usually dims on depolarization, suggesting sign flip or other transformation before deposit/export; downstream orientation from the measurement makes this a warning rather than a block.",
    "severity": "warn",
    "reviewer": "data_provenance"
   },
   {
    "topic": "Unexplained all-negative data values",
    "detail": "All values are negative integers and are flagged as processed_before_deposit; the linked paper documents possible filtering/averaging workflows, but no deposit README explains this file-level transformation.",
    "severity": "warn",
    "reviewer": "data_provenance"
   },
   {
    "topic": "Rhythm detector not suitable for the expected paced period here",
    "detail": "Do not use the rhythm detector's short-cycle result to infer physiology or frame rate here, because the expected pacing period lies beyond the rhythm tool's baseline-correction window.",
    "severity": "info",
    "reviewer": "analysis_qc"
   },
   {
    "topic": "Mask is not a heart segmentation",
    "detail": "The current analysis mask is based on nonzero temporal standard deviation, not a biological tissue segmentation; spatial map interpretation needs a tissue-only mask.",
    "severity": "warn",
    "reviewer": "analysis_qc"
   }
  ],
  "reportable": [
   {
    "metric": "persistent rotor tracks",
    "segment": "all",
    "value": "0\u20133",
    "unit": "count",
    "status": "unstable, not reportable"
   },
   {
    "metric": "dominant freq (Hz)",
    "segment": "whole recording",
    "value": "6.532",
    "unit": "Hz",
    "status": "no cited range"
   },
   {
    "metric": "persistent rotors",
    "segment": "whole recording",
    "value": "0\u20133",
    "unit": "count",
    "status": "unstable, not reportable"
   },
   {
    "metric": "singularity frames fraction",
    "segment": "whole recording",
    "value": "0.182\u20130.746",
    "unit": "fraction of frames",
    "status": "unstable, not reportable"
   },
   {
    "metric": "persistent rotor count max",
    "segment": "whole recording",
    "value": "0\u20131",
    "unit": "count",
    "status": "unstable, not reportable"
   }
  ],
  "verdict": {
   "physiology_ok": null,
   "send_back": true,
   "notes": "Send back this signature as not reportable as it stands: the whole_recording singularity-frame fraction is unstable across 0.18242597898758356 to 0.7459407831900668, persistent_rotors across 0.0 to 3.0, persistent_rotor_count_max across 0.0 to 1.0, and persistent_rotor_tracks across 0.0 to 3.0, all under the provisional stability threshold of (max - min) <= 0.25 x median and provisional criteria; the only stable metric is dominant_freq_hz at 6.532 Hz across baseline-window settings, but it has no cited acceptance range for this paced control context, and the available mouse spiral-wave context instead describes approximately 18.75 to 20.0 Hz rotation in another study (DOI 10.1371/journal.pcbi.1011660). Persistent-rotor threshold tests are not applicable because there are no segment expectations, while tracker sensitivity needs review because strict/default tracking is at the lower end of the unstable rotor range and loose tracking is at the upper end; also review the frame-rate provenance for the MiCAM-labelled file using the 977.0 Hz admission value, possible pre-deposit sign or conditioning, all-negative integer values, the unsuitable rhythm-detector short-cycle result relative to the expected pacing period, and the non-biological mask; all ranges, the stability threshold, and criteria are provisional."
  },
  "provenance": {
   "recording": {
    "id": "ae77081e-a125-471f-8805-27dad0688848",
    "label": "Open-Source Low-Cost Cardiac Optical Mapping System: mouse_2609_150ms_control_MiCAM",
    "source": "admission",
    "source_ref": "10.5281/zenodo.5557829",
    "publication_ref": "10.1371/journal.pone.0259174",
    "storage_path": "uploads/public/7764050e/mouse_2609_150ms_control_MiCAM.mat",
    "format": "mat",
    "sha256": "6f7fd1ea3f1f2610645c5d235dd4bc189bcdf58c1a038c8f8e68e2233948253e",
    "size_bytes": 30452226,
    "license": "cc-by-4.0",
    "attribution": "Rybashlykov Dmitry",
    "rights_source": {
     "ref": "10.5281/zenodo.5557829",
     "kind": "deposit_metadata",
     "admitted_by": "project lead",
     "license_as_stated": "cc-by-4.0"
    },
    "frame_rate_hz": 977.0,
    "frame_rate_source": {
     "by": "project lead",
     "ref": "10.1371/journal.pone.0259174",
     "kind": "admission",
     "quote": "The custom software was designed to make recordings with a resolution of 200x200 pixels and a framerate of 977 frames per second (FPS).",
     "source": "paper_methods"
    },
    "pixel_size_um": null,
    "pixel_size_source": null,
    "frames": 2047,
    "height": 100,
    "width": 100,
    "inverted": false
   },
   "protocol": {
    "id": "f65d786f-f194-4be2-88b8-10d3dd25d674",
    "name": "Mouse whole heart optical mapping (Luther lab)",
    "species": "mouse",
    "tissue": "whole_heart",
    "params_version": 3,
    "params_set_by": "developer (not a domain scientist)",
    "params_note": "version 3: baseline 901 frames = 2.1 x the 433-frame (2.31 Hz) post-termination cycle resolved under v2; v2's 641 frames was 1.48 cycles, on the 1.5-cycle line, and the pipeline check held one run and passed another on the same inputs. pad 500 >= half the window. Provisional (REVIEW_NEEDED item 16)."
   },
   "run": {
    "id": "2aec1b88-1bc3-430f-9d57-a9ddcf39928c",
    "status": "done",
    "started_at": "2026-10-28T18:59:24.298079+00:00",
    "finished_at": "2026-10-28T19:01:51.31345+00:00",
    "code": {
     "dirty": true,
     "git_commit": "0aee29346248785f557664cd859ddeb50fecd3d5"
    },
    "workers": 4,
    "steps": [
     "load",
     "deposit_checks",
     "baseline_correct",
     "polarity",
     "spatial_filter(phase only)",
     "hilbert_phase",
     "phase_singularities",
     "track_and_pair",
     "beats_apd_cv",
     "sensitivity",
     "render"
    ],
    "protocol_params": {
     "params": {
      "link_px": 4.0,
      "max_gap": 5,
      "min_cycles": 1.0,
      "pad_frames": 500,
      "paired_frac": 0.5,
      "render_step": 4,
      "pair_dist_px": 3.0,
      "spatial_sigma": 1.0,
      "rotor_erode_px": 3,
      "baseline_frames": 901,
      "rotor_threshold": 0.9,
      "spatial_truncate": 4.0
     },
     "version": 3,
     "protocol_id": "f65d786f-f194-4be2-88b8-10d3dd25d674"
    },
    "baseline_rule": {
     "ok": true,
     "ratio": 40.955,
     "cycles": {
      "whole_recording": {
       "n_frames": 2047,
       "cycle_frames": 22,
       "pixels_agreeing_frac": 0.09964093357271095,
       "pixels_with_rhythm_frac": 1.0,
       "interval_quartiles_frames": [
        12.0,
        22.25,
        54.0
       ]
      }
     },
     "factor": 2.0,
     "reason": null,
     "source": "per-pixel dominant frequency (images)",
     "status": "provisional",
     "baseline_frames": 901,
     "slowest_segment": "whole_recording",
     "required_min_frames": 44,
     "slowest_cycle_frames": 22
    },
    "deposit_checks": {
     "flags": [
      {
       "flag": "negative_values",
       "value": 1.0,
       "suggests": "baseline-subtracted or normalized; raw fluorescence counts are non-negative",
       "threshold": 0.01
      }
     ],
     "status": "provisional",
     "measures": {
      "max": -25.0,
      "min": -13413.0,
      "frames_used": 2000,
      "integer_frac": 1.0,
      "negative_frac": 1.0,
      "frames_with_nan": 0,
      "dv_lag1_autocorr_median": -0.022236137855436912,
      "neighbour_dv_corr_median": 0.4009710844063593
     },
     "processed_before_deposit": true
    },
    "pipeline_check": {
     "model": "openai:gpt-5.5",
     "proceed": true,
     "anomalies": [
      {
       "topic": "Frame-rate provenance for a MiCAM file",
       "severity": "warn",
       "effect_on_analysis": "The run should use 977.0 Hz from the recording-row admission source, but the cited paper text refers to the custom/iDS system and 200x200 acquisition while this deposited file is labelled MiCAM and is 100x100. Frame-based protocol parameters are unchanged; any time conversion or rate interpretation should note the medium-confidence provenance."
      },
      {
       "topic": "Pre-deposit sign/conditioning",
       "severity": "warn",
       "effect_on_analysis": "The measured polarity is consistently non-inverted although Di-4-ANEPPS normally dims on depolarization, implying a sign flip or other transformation before deposit/export. The fixed pipeline orients from the measurement, so this does not by itself invalidate the run, but polarity-dependent interpretation should be cautious."
      },
      {
       "topic": "Unexplained all-negative data values",
       "severity": "warn",
       "effect_on_analysis": "All sampled values are negative integers, suggesting baseline subtraction, normalization, or other processing before deposit. The protocol can still run, but amplitudes, noise estimates, and comparisons to raw fluorescence are affected by undocumented prior processing."
      },
      {
       "topic": "Mask is not a heart segmentation",
       "severity": "warn",
       "effect_on_analysis": "The analysis mask is based only on nonzero temporal standard deviation and covers 9999/10000 pixels, so spatial maps may include non-tissue/background pixels. Analyses that require tissue-only pixels need a biological mask before interpretation."
      },
      {
       "topic": "baseline-window rule",
       "severity": "info",
       "effect_on_analysis": "The coded baseline rule passed: baseline_frames 901 is at least 2.0 times the slowest segment cycle reported by the rule, with ratio 40.955. This rule is provisional and is reported as informational only."
      },
      {
       "topic": "Rhythm detector not suitable for the expected paced period here",
       "severity": "info",
       "effect_on_analysis": "The inspector cautions that the short-cycle rhythm result used in one detector should not be used to infer physiology or frame rate for this recording. The segment rhythm report for the protocol baseline gives the analysed window and dominant cycle separately; no expected outcome is inferred."
      }
     ],
     "rationale": "The fixed protocol is appropriate to run as-is because the recording is a mouse-labelled public reference recording under the Luther lab mouse whole-heart optical-mapping protocol, and there are no recording facts that directly conflict with specified protocol fields. The protocol does not specify a required indicator, pixel size, frame rate, or image size, so the available recording facts do not create a blocking mismatch. The main limitations are provenance and preprocessing warnings: the working frame rate is admitted as 977.0 Hz but is supported by paper text for a different named camera/resolution, and the deposited data appear transformed before deposit. These issues affect interpretation and reporting rather than requiring parameter changes under the fixed version-3 protocol.",
     "mismatches": [],
     "hold_reason": null,
     "protocol_id": "f65d786f-f194-4be2-88b8-10d3dd25d674",
     "methods_text": "Using provisional parameter set version 3 for protocol f65d786f-f194-4be2-88b8-10d3dd25d674, the provisional fixed criteria use baseline_frames=901, spatial_sigma=1.0, spatial_truncate=4.0, pad_frames=500, rotor_threshold=0.9, rotor_erode_px=3, link_px=4.0, max_gap=5, min_cycles=1.0, pair_dist_px=3.0, paired_frac=0.5, and render_step=4. The recording has 2047 frames of size 100x100; the frame rate used is 977.0 Hz from the recording-row admission source citing 10.1371/journal.pone.0259174, and the pixel size is not provided. The analysed frames are 500 to 1547 for the whole-recording analysis window, and the provisional segment definition is whole_recording from frame 0 to frame 2047, defined at admission with no detected or logged events.",
     "recording_id": "ae77081e-a125-471f-8805-27dad0688848",
     "params_version": 3,
     "prompt_version": "pipeline-v2"
    }
   },
   "signature": {
    "id": "0187eb93-2c8b-4500-b11c-9d0062c96d4a",
    "created_at": "2026-10-28T19:00:32.083292+00:00",
    "movie_path": "runs/2aec1b88-1bc3-430f-9d57-a9ddcf39928c/movie.mp4",
    "frames": {
     "f0": 500,
     "f1": 1547,
     "maps": "runs/2aec1b88-1bc3-430f-9d57-a9ddcf39928c/frames/maps.npz",
     "dtype": "<f4",
     "phase": "runs/2aec1b88-1bc3-430f-9d57-a9ddcf39928c/frames/phase.npy",
     "shape": [
      1047,
      100,
      100
     ],
     "sha256": {
      "maps": "2faef5c48ac4bab2f8de7dc112bf0252495f745f2d48993e212f6d9febbe658c",
      "phase": "bbc12dc0da055e9e26dcf0f45e469f936654933dfc41fcd6c7db6814cde05a56",
      "voltage": "833b285fc616c753bdfa0e47f8c5e1baf3cdf0f3aab8d8147dbbb5767e2ba471"
     },
     "voltage": "runs/2aec1b88-1bc3-430f-9d57-a9ddcf39928c/frames/voltage.npy",
     "map_keys": [
      "activation:whole_recording",
      "dominant_frequency:whole_recording",
      "dominant_frequency:window",
      "mask"
     ],
     "map_units": {
      "mask": "tissue mask, source file_variable",
      "dominant_frequency:window": "Hz",
      "activation:whole_recording": "ms",
      "dominant_frequency:whole_recording": "Hz"
     }
    },
    "filter_params": {
     "mask": "not NaN in frame 0 and nonzero temporal std",
     "render": {
      "step": 4,
      "palettes": {
       "phase": "twilight",
       "camera": "gray",
       "voltage": "gray"
      },
      "interpolation": "nearest"
     },
     "window": {
      "f0": 500,
      "f1": 1547,
      "segments": [
       {
        "name": "whole_recording",
        "label": "whole recording",
        "defined": [
         0,
         2047
        ],
        "analysed": [
         500,
         1547
        ],
        "citation": null,
        "defined_by": "admission (project lead); no comparison defined",
        "segment_id": "f43dd23d-fc9d-4a02-a299-3c478800b938",
        "end_event_id": null,
        "start_event_id": null,
        "expected_persistent_rotors": null
       }
      ],
      "illumination": null,
      "frame_rate_hz": 977.0,
      "frame_rate_source": {
       "by": "project lead",
       "ref": "10.1371/journal.pone.0259174",
       "kind": "admission",
       "quote": "The custom software was designed to make recordings with a resolution of 200x200 pixels and a framerate of 977 frames per second (FPS).",
       "source": "paper_methods"
      },
      "segment_cycles_frames": {
       "whole_recording": 150
      }
     },
     "lowpass": null,
     "polarity": 1,
     "tracking": {
      "link_px": 4.0,
      "max_gap": 5,
      "min_cycles": 1.0,
      "min_frames": 150,
      "paired_frac": 0.5,
      "pair_dist_px": 3.0
     },
     "pad_frames": 500,
     "phase_method": "angle of scipy.signal.hilbert along time, on spatially filtered signal",
     "spatial_sigma": 1.0,
     "rotor_erode_px": 3,
     "spatial_method": "scipy.ndimage.gaussian_filter per frame, mode=reflect; NaN set to 0 before filtering, non-tissue zeroed after",
     "baseline_frames": 901,
     "baseline_method": "scipy.ndimage.uniform_filter1d, mode=reflect, subtracted per pixel",
     "polarity_method": "sign of median per-pixel skew of dV/dt on baseline-corrected signal",
     "rotor_threshold": 0.9,
     "spatial_truncate": 4.0,
     "spatial_applies_to": "phase/activation only; displayed voltage is baseline-corrected only"
    },
    "criteria_status": {
     "note": null,
     "rules": [
      {
       "id": "protocol_parameter_set",
       "expert": "optical mapping analyst",
       "status": "provisional",
       "values": {
        "set_by": "developer (not a domain scientist)",
        "protocol": "Mouse whole heart optical mapping (Luther lab)",
        "protocol_id": "f65d786f-f194-4be2-88b8-10d3dd25d674",
        "params_version": 3
       },
       "decision": null,
       "location": "worker/voltage/protocol_params.py (developer_defaults, set_params)",
       "reviewed": false,
       "reviewer": null,
       "description": "Each protocol's fixed, versioned analysis parameters (version 1 = developer defaults); no run or agent may deviate",
       "reviewed_at": null
      },
      {
       "id": "baseline_window_rule",
       "expert": "optical mapping analyst",
       "status": "provisional",
       "values": {
        "ok": true,
        "factor": 2.0,
        "source": "per-pixel dominant frequency (images)",
        "required_min_frames": 44,
        "slowest_cycle_frames": 22
       },
       "decision": null,
       "location": "worker/voltage/baseline_rule.py (FACTOR, evaluate)",
       "reviewed": false,
       "reviewer": null,
       "description": "A run proceeds only if the protocol's baseline window is >= 2x the slowest segment's cycle, the cycle from the MAP channel when a DAQ log exists, else from per-pixel dominant frequency on linearly detrended pixels; otherwise the run is held by code",
       "reviewed_at": null
      },
      {
       "id": "filter_defaults",
       "expert": "optical mapping analyst (cardiac electrophysiology)",
       "status": "provisional",
       "values": {
        "lowpass": null,
        "spatial_sigma": 1.0,
        "baseline_frames": 901,
        "spatial_truncate": 4.0
       },
       "decision": null,
       "location": "worker/voltage/preprocess.py (Params)",
       "reviewed": false,
       "reviewer": null,
       "description": "Default baseline window (frames) and spatial Gaussian sigma/truncate for phase",
       "reviewed_at": null
      },
      {
       "id": "tissue_mask",
       "expert": "optical mapping analyst",
       "status": "provisional",
       "values": {
        "rule": "intensity variable 'bgimage' in the file, Otsu threshold 2165, class above with more temporal signal, largest connected component",
        "side": "above",
        "source": "file_variable",
        "coverage": 0.1114,
        "variable": "bgimage",
        "threshold": 2165.203125,
        "tissue_pixels": 1114
       },
       "decision": null,
       "location": "worker/voltage/io.py (tissue_mask_info, otsu_threshold, largest_component)",
       "reviewed": false,
       "reviewer": null,
       "description": "Tissue mask from, in order: (1) NaN in frame 0 when the recording has any NaN; (2) a mask or background-image variable shipped in the file whose shape matches the frame (binary as is, an intensity image thresholded with Otsu); (3) Otsu's threshold on the mean image, the class with more temporal signal as tissue, largest connected component kept; source, coverage and threshold recorded",
       "reviewed_at": null
      },
      {
       "id": "polarity",
       "expert": "optical mapping analyst / voltage dye chemist",
       "status": "provisional",
       "values": {
        "method": "median skew of dV/dt",
        "result": 1
       },
       "decision": null,
       "location": "worker/voltage/preprocess.py (polarity)",
       "reviewed": false,
       "reviewer": null,
       "description": "Dye polarity from sign of median per-pixel skew of dV/dt",
       "reviewed_at": null
      },
      {
       "id": "singularity_detection",
       "expert": "computational cardiac electrophysiologist (phase mapping)",
       "status": "provisional",
       "values": {
        "rotor_erode_px": 3,
        "rotor_threshold": 0.9
       },
       "decision": null,
       "location": "worker/voltage/preprocess.py (Params.rotor_threshold, rotor_erode_px)",
       "reviewed": false,
       "reviewer": null,
       "description": "Phase singularity = |winding| > threshold turns, >= erode px from tissue edge",
       "reviewed_at": null
      },
      {
       "id": "rotor_persistence",
       "expert": "computational cardiac electrophysiologist (phase mapping)",
       "status": "provisional",
       "values": {
        "link_px": 4.0,
        "max_gap": 5,
        "min_cycles": 1.0,
        "min_frames": 150
       },
       "decision": null,
       "location": "worker/voltage/rotors.py (TrackParams)",
       "reviewed": false,
       "reviewer": null,
       "description": "Track linking distance/gap and minimum lifetime for a persistent rotor",
       "reviewed_at": null
      },
      {
       "id": "chirality_pairing",
       "expert": "computational cardiac electrophysiologist (phase mapping)",
       "status": "provisional",
       "values": {
        "paired_frac": 0.5,
        "pair_dist_px": 3.0
       },
       "decision": null,
       "location": "worker/voltage/rotors.py (TrackParams.pair_dist_px, paired_frac)",
       "reviewed": false,
       "reviewer": null,
       "description": "Opposite-charge singularities within pair distance are a pair; tracks paired most of their life are excluded from rotors",
       "reviewed_at": null
      },
      {
       "id": "sensitivity_grid",
       "expert": "optical mapping analyst",
       "status": "provisional",
       "values": {
        "sigmas": {
         "light": 0.5,
         "default": 1.0,
         "heavier": 2.0
        },
        "trackers": {
         "loose": [
          6.0,
          10
         ],
         "strict": [
          2.0,
          1
         ],
         "default": [
          4.0,
          5
         ]
        },
        "baselines": {
         "run": 901,
         "3x_cycle": 450,
         "6x_cycle": 900,
         "1.5x_cycle": 225
        }
       },
       "decision": null,
       "location": "worker/voltage/sensitivity.py (SIGMAS, BASELINE_MULTIPLES, baseline_levels)",
       "reviewed": false,
       "reviewer": null,
       "description": "Filter levels tested: spatial sigma and baseline window values",
       "reviewed_at": null
      },
      {
       "id": "analysis_window",
       "expert": "cardiac electrophysiologist familiar with the dataset",
       "status": "provisional",
       "values": {
        "f0": 500,
        "f1": 1547
       },
       "decision": null,
       "location": "worker/voltage/runs.py (default_window)",
       "reviewed": false,
       "reviewer": null,
       "description": "Frames analysed: whole recording minus one filter pad at each end (unless the plan narrows it)",
       "reviewed_at": null
      },
      {
       "id": "prior_processing_flags",
       "expert": "imaging scientist (camera acquisition and noise)",
       "status": "provisional",
       "values": {
        "flags": [
         "negative_values"
        ],
        "thresholds": {
         "int_frac": 0.5,
         "neg_frac": 0.01,
         "dv_autocorr": 0.5,
         "neighbour_corr": 0.8
        }
       },
       "decision": null,
       "location": "worker/voltage/inspect.py (prior_processing)",
       "reviewed": false,
       "reviewer": null,
       "description": "Thresholds for flagging depositor processing (normalization, masking, temporal/spatial smoothing)",
       "reviewed_at": null
      },
      {
       "id": "pipeline_check",
       "expert": "optical mapping analyst",
       "status": "provisional",
       "values": {
        "model": "openai:gpt-5.5",
        "proceed": true,
        "anomalies": [
         "Frame-rate provenance for a MiCAM file",
         "Pre-deposit sign/conditioning",
         "Unexplained all-negative data values",
         "Mask is not a heart segmentation",
         "baseline-window rule",
         "Rhythm detector not suitable for the expected paced period here"
        ],
        "mismatches": []
       },
       "decision": null,
       "location": "worker/agents/pipeline.py (INSTRUCTIONS, validator)",
       "reviewed": false,
       "reviewer": null,
       "description": "The pipeline agent's hold/proceed decision from protocol mismatches and inspector anomalies; it chooses no parameter",
       "reviewed_at": null
      },
      {
       "id": "physiology_reference_rates",
       "expert": "cardiac electrophysiologist per species",
       "status": "provisional",
       "values": {
        "ranges": [
         "mouse_spiral_rotation_hz"
        ],
        "tolerance_frac": 0.25,
        "segment_rhythm_rule": "expected persistent rotors 'present' -> spiral arrhythmia"
       },
       "decision": null,
       "location": "worker/voltage/physiology.py (RANGES, TOLERANCE_FRAC)",
       "reviewed": false,
       "reviewer": null,
       "description": "Cited physiological ranges (single-study values widened by a 25% tolerance), applied to segments by their expected rhythm; used by the critic and for frame-rate sanity checks",
       "reviewed_at": null
      },
      {
       "id": "stability_rule",
       "expert": "biostatistician + optical mapping analyst",
       "status": "provisional",
       "values": {
        "unstable": [
         "whole_recording.singularity_frames_frac",
         "whole_recording.persistent_rotors",
         "whole_recording.persistent_rotor_count_max",
         "persistent_rotor_tracks"
        ],
        "stable_frac": 0.25
       },
       "decision": null,
       "location": "worker/agents/critic.py (STABLE_FRAC, stability)",
       "reviewed": false,
       "reviewer": null,
       "description": "A metric is reportable only if its spread across all sensitivity settings is <= 25% of its median (zero spread when all values are 0); otherwise 'unstable, not reportable'",
       "reviewed_at": null
      },
      {
       "id": "persistence_threshold_variants",
       "expert": "computational cardiac electrophysiologist (phase mapping)",
       "status": "provisional",
       "values": {
        "measured_cycle": 150,
        "paper_rotation": null
       },
       "decision": null,
       "location": "worker/agents/critic.py (persistence_variants)",
       "reviewed": false,
       "reviewer": null,
       "description": "The persistent-rotor rule is run at two lifetimes, one measured cycle of the fastest segment and the paper's cited rotation period; both verdicts stored, disagreement flagged",
       "reviewed_at": null
      },
      {
       "id": "persistent_rotor_criterion",
       "expert": "cardiac electrophysiologist",
       "status": "provisional",
       "values": {
        "max_absent": 0,
        "min_present": 1
       },
       "decision": null,
       "location": "worker/voltage/sensitivity.py (MIN_ROTORS_PRESENT, MAX_ROTORS_ABSENT)",
       "reviewed": false,
       "reviewer": null,
       "description": "Persistent-rotor finding holds if every 'present' segment has >= 1 persistent rotor and every 'absent' segment has none, at every setting",
       "reviewed_at": null
      }
     ],
     "status": "provisional",
     "all_reviewed": false,
     "superseded_by_run": null
    }
   },
   "segments": [
    {
     "id": "f43dd23d-fc9d-4a02-a299-3c478800b938",
     "position": 1,
     "name": "whole_recording",
     "label": "whole recording",
     "start_frame": 0,
     "end_frame": 2047,
     "expected_persistent_rotors": null,
     "definition": "whole recording; no events detected or logged at admission",
     "defined_by": "admission (project lead); no comparison defined",
     "citation": null,
     "evidence": {},
     "provisional": true
    }
   ],
   "events": []
  }
 },
 "provenance": {
  "recording": {
   "id": "ae77081e-a125-471f-8805-27dad0688848",
   "label": "Open-Source Low-Cost Cardiac Optical Mapping System: mouse_2609_150ms_control_MiCAM",
   "source": "admission",
   "source_ref": "10.5281/zenodo.5557829",
   "publication_ref": "10.1371/journal.pone.0259174",
   "storage_path": "uploads/public/7764050e/mouse_2609_150ms_control_MiCAM.mat",
   "format": "mat",
   "sha256": "6f7fd1ea3f1f2610645c5d235dd4bc189bcdf58c1a038c8f8e68e2233948253e",
   "size_bytes": 30452226,
   "license": "cc-by-4.0",
   "attribution": "Rybashlykov Dmitry",
   "rights_source": {
    "ref": "10.5281/zenodo.5557829",
    "kind": "deposit_metadata",
    "admitted_by": "project lead",
    "license_as_stated": "cc-by-4.0"
   },
   "frame_rate_hz": 977.0,
   "frame_rate_source": {
    "by": "project lead",
    "ref": "10.1371/journal.pone.0259174",
    "kind": "admission",
    "quote": "The custom software was designed to make recordings with a resolution of 200x200 pixels and a framerate of 977 frames per second (FPS).",
    "source": "paper_methods"
   },
   "pixel_size_um": null,
   "pixel_size_source": null,
   "frames": 2047,
   "height": 100,
   "width": 100,
   "inverted": false
  },
  "protocol": {
   "id": "f65d786f-f194-4be2-88b8-10d3dd25d674",
   "name": "Mouse whole heart optical mapping (Luther lab)",
   "species": "mouse",
   "tissue": "whole_heart",
   "params_version": 3,
   "params_set_by": "developer (not a domain scientist)",
   "params_note": "version 3: baseline 901 frames = 2.1 x the 433-frame (2.31 Hz) post-termination cycle resolved under v2; v2's 641 frames was 1.48 cycles, on the 1.5-cycle line, and the pipeline check held one run and passed another on the same inputs. pad 500 >= half the window. Provisional (REVIEW_NEEDED item 16)."
  },
  "run": {
   "id": "2aec1b88-1bc3-430f-9d57-a9ddcf39928c",
   "status": "done",
   "started_at": "2026-10-28T18:59:24.298079+00:00",
   "finished_at": "2026-10-28T19:01:51.31345+00:00",
   "code": {
    "dirty": true,
    "git_commit": "0aee29346248785f557664cd859ddeb50fecd3d5"
   },
   "workers": 4,
   "steps": [
    "load",
    "deposit_checks",
    "baseline_correct",
    "polarity",
    "spatial_filter(phase only)",
    "hilbert_phase",
    "phase_singularities",
    "track_and_pair",
    "beats_apd_cv",
    "sensitivity",
    "render"
   ],
   "protocol_params": {
    "params": {
     "link_px": 4.0,
     "max_gap": 5,
     "min_cycles": 1.0,
     "pad_frames": 500,
     "paired_frac": 0.5,
     "render_step": 4,
     "pair_dist_px": 3.0,
     "spatial_sigma": 1.0,
     "rotor_erode_px": 3,
     "baseline_frames": 901,
     "rotor_threshold": 0.9,
     "spatial_truncate": 4.0
    },
    "version": 3,
    "protocol_id": "f65d786f-f194-4be2-88b8-10d3dd25d674"
   },
   "baseline_rule": {
    "ok": true,
    "ratio": 40.955,
    "cycles": {
     "whole_recording": {
      "n_frames": 2047,
      "cycle_frames": 22,
      "pixels_agreeing_frac": 0.09964093357271095,
      "pixels_with_rhythm_frac": 1.0,
      "interval_quartiles_frames": [
       12.0,
       22.25,
       54.0
      ]
     }
    },
    "factor": 2.0,
    "reason": null,
    "source": "per-pixel dominant frequency (images)",
    "status": "provisional",
    "baseline_frames": 901,
    "slowest_segment": "whole_recording",
    "required_min_frames": 44,
    "slowest_cycle_frames": 22
   },
   "deposit_checks": {
    "flags": [
     {
      "flag": "negative_values",
      "value": 1.0,
      "suggests": "baseline-subtracted or normalized; raw fluorescence counts are non-negative",
      "threshold": 0.01
     }
    ],
    "status": "provisional",
    "measures": {
     "max": -25.0,
     "min": -13413.0,
     "frames_used": 2000,
     "integer_frac": 1.0,
     "negative_frac": 1.0,
     "frames_with_nan": 0,
     "dv_lag1_autocorr_median": -0.022236137855436912,
     "neighbour_dv_corr_median": 0.4009710844063593
    },
    "processed_before_deposit": true
   },
   "pipeline_check": {
    "model": "openai:gpt-5.5",
    "proceed": true,
    "anomalies": [
     {
      "topic": "Frame-rate provenance for a MiCAM file",
      "severity": "warn",
      "effect_on_analysis": "The run should use 977.0 Hz from the recording-row admission source, but the cited paper text refers to the custom/iDS system and 200x200 acquisition while this deposited file is labelled MiCAM and is 100x100. Frame-based protocol parameters are unchanged; any time conversion or rate interpretation should note the medium-confidence provenance."
     },
     {
      "topic": "Pre-deposit sign/conditioning",
      "severity": "warn",
      "effect_on_analysis": "The measured polarity is consistently non-inverted although Di-4-ANEPPS normally dims on depolarization, implying a sign flip or other transformation before deposit/export. The fixed pipeline orients from the measurement, so this does not by itself invalidate the run, but polarity-dependent interpretation should be cautious."
     },
     {
      "topic": "Unexplained all-negative data values",
      "severity": "warn",
      "effect_on_analysis": "All sampled values are negative integers, suggesting baseline subtraction, normalization, or other processing before deposit. The protocol can still run, but amplitudes, noise estimates, and comparisons to raw fluorescence are affected by undocumented prior processing."
     },
     {
      "topic": "Mask is not a heart segmentation",
      "severity": "warn",
      "effect_on_analysis": "The analysis mask is based only on nonzero temporal standard deviation and covers 9999/10000 pixels, so spatial maps may include non-tissue/background pixels. Analyses that require tissue-only pixels need a biological mask before interpretation."
     },
     {
      "topic": "baseline-window rule",
      "severity": "info",
      "effect_on_analysis": "The coded baseline rule passed: baseline_frames 901 is at least 2.0 times the slowest segment cycle reported by the rule, with ratio 40.955. This rule is provisional and is reported as informational only."
     },
     {
      "topic": "Rhythm detector not suitable for the expected paced period here",
      "severity": "info",
      "effect_on_analysis": "The inspector cautions that the short-cycle rhythm result used in one detector should not be used to infer physiology or frame rate for this recording. The segment rhythm report for the protocol baseline gives the analysed window and dominant cycle separately; no expected outcome is inferred."
     }
    ],
    "rationale": "The fixed protocol is appropriate to run as-is because the recording is a mouse-labelled public reference recording under the Luther lab mouse whole-heart optical-mapping protocol, and there are no recording facts that directly conflict with specified protocol fields. The protocol does not specify a required indicator, pixel size, frame rate, or image size, so the available recording facts do not create a blocking mismatch. The main limitations are provenance and preprocessing warnings: the working frame rate is admitted as 977.0 Hz but is supported by paper text for a different named camera/resolution, and the deposited data appear transformed before deposit. These issues affect interpretation and reporting rather than requiring parameter changes under the fixed version-3 protocol.",
    "mismatches": [],
    "hold_reason": null,
    "protocol_id": "f65d786f-f194-4be2-88b8-10d3dd25d674",
    "methods_text": "Using provisional parameter set version 3 for protocol f65d786f-f194-4be2-88b8-10d3dd25d674, the provisional fixed criteria use baseline_frames=901, spatial_sigma=1.0, spatial_truncate=4.0, pad_frames=500, rotor_threshold=0.9, rotor_erode_px=3, link_px=4.0, max_gap=5, min_cycles=1.0, pair_dist_px=3.0, paired_frac=0.5, and render_step=4. The recording has 2047 frames of size 100x100; the frame rate used is 977.0 Hz from the recording-row admission source citing 10.1371/journal.pone.0259174, and the pixel size is not provided. The analysed frames are 500 to 1547 for the whole-recording analysis window, and the provisional segment definition is whole_recording from frame 0 to frame 2047, defined at admission with no detected or logged events.",
    "recording_id": "ae77081e-a125-471f-8805-27dad0688848",
    "params_version": 3,
    "prompt_version": "pipeline-v2"
   }
  },
  "signature": {
   "id": "0187eb93-2c8b-4500-b11c-9d0062c96d4a",
   "created_at": "2026-10-28T19:00:32.083292+00:00",
   "movie_path": "runs/2aec1b88-1bc3-430f-9d57-a9ddcf39928c/movie.mp4",
   "frames": {
    "f0": 500,
    "f1": 1547,
    "maps": "runs/2aec1b88-1bc3-430f-9d57-a9ddcf39928c/frames/maps.npz",
    "dtype": "<f4",
    "phase": "runs/2aec1b88-1bc3-430f-9d57-a9ddcf39928c/frames/phase.npy",
    "shape": [
     1047,
     100,
     100
    ],
    "sha256": {
     "maps": "2faef5c48ac4bab2f8de7dc112bf0252495f745f2d48993e212f6d9febbe658c",
     "phase": "bbc12dc0da055e9e26dcf0f45e469f936654933dfc41fcd6c7db6814cde05a56",
     "voltage": "833b285fc616c753bdfa0e47f8c5e1baf3cdf0f3aab8d8147dbbb5767e2ba471"
    },
    "voltage": "runs/2aec1b88-1bc3-430f-9d57-a9ddcf39928c/frames/voltage.npy",
    "map_keys": [
     "activation:whole_recording",
     "dominant_frequency:whole_recording",
     "dominant_frequency:window",
     "mask"
    ],
    "map_units": {
     "mask": "tissue mask, source file_variable",
     "dominant_frequency:window": "Hz",
     "activation:whole_recording": "ms",
     "dominant_frequency:whole_recording": "Hz"
    }
   },
   "filter_params": {
    "mask": "not NaN in frame 0 and nonzero temporal std",
    "render": {
     "step": 4,
     "palettes": {
      "phase": "twilight",
      "camera": "gray",
      "voltage": "gray"
     },
     "interpolation": "nearest"
    },
    "window": {
     "f0": 500,
     "f1": 1547,
     "segments": [
      {
       "name": "whole_recording",
       "label": "whole recording",
       "defined": [
        0,
        2047
       ],
       "analysed": [
        500,
        1547
       ],
       "citation": null,
       "defined_by": "admission (project lead); no comparison defined",
       "segment_id": "f43dd23d-fc9d-4a02-a299-3c478800b938",
       "end_event_id": null,
       "start_event_id": null,
       "expected_persistent_rotors": null
      }
     ],
     "illumination": null,
     "frame_rate_hz": 977.0,
     "frame_rate_source": {
      "by": "project lead",
      "ref": "10.1371/journal.pone.0259174",
      "kind": "admission",
      "quote": "The custom software was designed to make recordings with a resolution of 200x200 pixels and a framerate of 977 frames per second (FPS).",
      "source": "paper_methods"
     },
     "segment_cycles_frames": {
      "whole_recording": 150
     }
    },
    "lowpass": null,
    "polarity": 1,
    "tracking": {
     "link_px": 4.0,
     "max_gap": 5,
     "min_cycles": 1.0,
     "min_frames": 150,
     "paired_frac": 0.5,
     "pair_dist_px": 3.0
    },
    "pad_frames": 500,
    "phase_method": "angle of scipy.signal.hilbert along time, on spatially filtered signal",
    "spatial_sigma": 1.0,
    "rotor_erode_px": 3,
    "spatial_method": "scipy.ndimage.gaussian_filter per frame, mode=reflect; NaN set to 0 before filtering, non-tissue zeroed after",
    "baseline_frames": 901,
    "baseline_method": "scipy.ndimage.uniform_filter1d, mode=reflect, subtracted per pixel",
    "polarity_method": "sign of median per-pixel skew of dV/dt on baseline-corrected signal",
    "rotor_threshold": 0.9,
    "spatial_truncate": 4.0,
    "spatial_applies_to": "phase/activation only; displayed voltage is baseline-corrected only"
   },
   "criteria_status": {
    "note": null,
    "rules": [
     {
      "id": "protocol_parameter_set",
      "expert": "optical mapping analyst",
      "status": "provisional",
      "values": {
       "set_by": "developer (not a domain scientist)",
       "protocol": "Mouse whole heart optical mapping (Luther lab)",
       "protocol_id": "f65d786f-f194-4be2-88b8-10d3dd25d674",
       "params_version": 3
      },
      "decision": null,
      "location": "worker/voltage/protocol_params.py (developer_defaults, set_params)",
      "reviewed": false,
      "reviewer": null,
      "description": "Each protocol's fixed, versioned analysis parameters (version 1 = developer defaults); no run or agent may deviate",
      "reviewed_at": null
     },
     {
      "id": "baseline_window_rule",
      "expert": "optical mapping analyst",
      "status": "provisional",
      "values": {
       "ok": true,
       "factor": 2.0,
       "source": "per-pixel dominant frequency (images)",
       "required_min_frames": 44,
       "slowest_cycle_frames": 22
      },
      "decision": null,
      "location": "worker/voltage/baseline_rule.py (FACTOR, evaluate)",
      "reviewed": false,
      "reviewer": null,
      "description": "A run proceeds only if the protocol's baseline window is >= 2x the slowest segment's cycle, the cycle from the MAP channel when a DAQ log exists, else from per-pixel dominant frequency on linearly detrended pixels; otherwise the run is held by code",
      "reviewed_at": null
     },
     {
      "id": "filter_defaults",
      "expert": "optical mapping analyst (cardiac electrophysiology)",
      "status": "provisional",
      "values": {
       "lowpass": null,
       "spatial_sigma": 1.0,
       "baseline_frames": 901,
       "spatial_truncate": 4.0
      },
      "decision": null,
      "location": "worker/voltage/preprocess.py (Params)",
      "reviewed": false,
      "reviewer": null,
      "description": "Default baseline window (frames) and spatial Gaussian sigma/truncate for phase",
      "reviewed_at": null
     },
     {
      "id": "tissue_mask",
      "expert": "optical mapping analyst",
      "status": "provisional",
      "values": {
       "rule": "intensity variable 'bgimage' in the file, Otsu threshold 2165, class above with more temporal signal, largest connected component",
       "side": "above",
       "source": "file_variable",
       "coverage": 0.1114,
       "variable": "bgimage",
       "threshold": 2165.203125,
       "tissue_pixels": 1114
      },
      "decision": null,
      "location": "worker/voltage/io.py (tissue_mask_info, otsu_threshold, largest_component)",
      "reviewed": false,
      "reviewer": null,
      "description": "Tissue mask from, in order: (1) NaN in frame 0 when the recording has any NaN; (2) a mask or background-image variable shipped in the file whose shape matches the frame (binary as is, an intensity image thresholded with Otsu); (3) Otsu's threshold on the mean image, the class with more temporal signal as tissue, largest connected component kept; source, coverage and threshold recorded",
      "reviewed_at": null
     },
     {
      "id": "polarity",
      "expert": "optical mapping analyst / voltage dye chemist",
      "status": "provisional",
      "values": {
       "method": "median skew of dV/dt",
       "result": 1
      },
      "decision": null,
      "location": "worker/voltage/preprocess.py (polarity)",
      "reviewed": false,
      "reviewer": null,
      "description": "Dye polarity from sign of median per-pixel skew of dV/dt",
      "reviewed_at": null
     },
     {
      "id": "singularity_detection",
      "expert": "computational cardiac electrophysiologist (phase mapping)",
      "status": "provisional",
      "values": {
       "rotor_erode_px": 3,
       "rotor_threshold": 0.9
      },
      "decision": null,
      "location": "worker/voltage/preprocess.py (Params.rotor_threshold, rotor_erode_px)",
      "reviewed": false,
      "reviewer": null,
      "description": "Phase singularity = |winding| > threshold turns, >= erode px from tissue edge",
      "reviewed_at": null
     },
     {
      "id": "rotor_persistence",
      "expert": "computational cardiac electrophysiologist (phase mapping)",
      "status": "provisional",
      "values": {
       "link_px": 4.0,
       "max_gap": 5,
       "min_cycles": 1.0,
       "min_frames": 150
      },
      "decision": null,
      "location": "worker/voltage/rotors.py (TrackParams)",
      "reviewed": false,
      "reviewer": null,
      "description": "Track linking distance/gap and minimum lifetime for a persistent rotor",
      "reviewed_at": null
     },
     {
      "id": "chirality_pairing",
      "expert": "computational cardiac electrophysiologist (phase mapping)",
      "status": "provisional",
      "values": {
       "paired_frac": 0.5,
       "pair_dist_px": 3.0
      },
      "decision": null,
      "location": "worker/voltage/rotors.py (TrackParams.pair_dist_px, paired_frac)",
      "reviewed": false,
      "reviewer": null,
      "description": "Opposite-charge singularities within pair distance are a pair; tracks paired most of their life are excluded from rotors",
      "reviewed_at": null
     },
     {
      "id": "sensitivity_grid",
      "expert": "optical mapping analyst",
      "status": "provisional",
      "values": {
       "sigmas": {
        "light": 0.5,
        "default": 1.0,
        "heavier": 2.0
       },
       "trackers": {
        "loose": [
         6.0,
         10
        ],
        "strict": [
         2.0,
         1
        ],
        "default": [
         4.0,
         5
        ]
       },
       "baselines": {
        "run": 901,
        "3x_cycle": 450,
        "6x_cycle": 900,
        "1.5x_cycle": 225
       }
      },
      "decision": null,
      "location": "worker/voltage/sensitivity.py (SIGMAS, BASELINE_MULTIPLES, baseline_levels)",
      "reviewed": false,
      "reviewer": null,
      "description": "Filter levels tested: spatial sigma and baseline window values",
      "reviewed_at": null
     },
     {
      "id": "analysis_window",
      "expert": "cardiac electrophysiologist familiar with the dataset",
      "status": "provisional",
      "values": {
       "f0": 500,
       "f1": 1547
      },
      "decision": null,
      "location": "worker/voltage/runs.py (default_window)",
      "reviewed": false,
      "reviewer": null,
      "description": "Frames analysed: whole recording minus one filter pad at each end (unless the plan narrows it)",
      "reviewed_at": null
     },
     {
      "id": "prior_processing_flags",
      "expert": "imaging scientist (camera acquisition and noise)",
      "status": "provisional",
      "values": {
       "flags": [
        "negative_values"
       ],
       "thresholds": {
        "int_frac": 0.5,
        "neg_frac": 0.01,
        "dv_autocorr": 0.5,
        "neighbour_corr": 0.8
       }
      },
      "decision": null,
      "location": "worker/voltage/inspect.py (prior_processing)",
      "reviewed": false,
      "reviewer": null,
      "description": "Thresholds for flagging depositor processing (normalization, masking, temporal/spatial smoothing)",
      "reviewed_at": null
     },
     {
      "id": "pipeline_check",
      "expert": "optical mapping analyst",
      "status": "provisional",
      "values": {
       "model": "openai:gpt-5.5",
       "proceed": true,
       "anomalies": [
        "Frame-rate provenance for a MiCAM file",
        "Pre-deposit sign/conditioning",
        "Unexplained all-negative data values",
        "Mask is not a heart segmentation",
        "baseline-window rule",
        "Rhythm detector not suitable for the expected paced period here"
       ],
       "mismatches": []
      },
      "decision": null,
      "location": "worker/agents/pipeline.py (INSTRUCTIONS, validator)",
      "reviewed": false,
      "reviewer": null,
      "description": "The pipeline agent's hold/proceed decision from protocol mismatches and inspector anomalies; it chooses no parameter",
      "reviewed_at": null
     },
     {
      "id": "physiology_reference_rates",
      "expert": "cardiac electrophysiologist per species",
      "status": "provisional",
      "values": {
       "ranges": [
        "mouse_spiral_rotation_hz"
       ],
       "tolerance_frac": 0.25,
       "segment_rhythm_rule": "expected persistent rotors 'present' -> spiral arrhythmia"
      },
      "decision": null,
      "location": "worker/voltage/physiology.py (RANGES, TOLERANCE_FRAC)",
      "reviewed": false,
      "reviewer": null,
      "description": "Cited physiological ranges (single-study values widened by a 25% tolerance), applied to segments by their expected rhythm; used by the critic and for frame-rate sanity checks",
      "reviewed_at": null
     },
     {
      "id": "stability_rule",
      "expert": "biostatistician + optical mapping analyst",
      "status": "provisional",
      "values": {
       "unstable": [
        "whole_recording.singularity_frames_frac",
        "whole_recording.persistent_rotors",
        "whole_recording.persistent_rotor_count_max",
        "persistent_rotor_tracks"
       ],
       "stable_frac": 0.25
      },
      "decision": null,
      "location": "worker/agents/critic.py (STABLE_FRAC, stability)",
      "reviewed": false,
      "reviewer": null,
      "description": "A metric is reportable only if its spread across all sensitivity settings is <= 25% of its median (zero spread when all values are 0); otherwise 'unstable, not reportable'",
      "reviewed_at": null
     },
     {
      "id": "persistence_threshold_variants",
      "expert": "computational cardiac electrophysiologist (phase mapping)",
      "status": "provisional",
      "values": {
       "measured_cycle": 150,
       "paper_rotation": null
      },
      "decision": null,
      "location": "worker/agents/critic.py (persistence_variants)",
      "reviewed": false,
      "reviewer": null,
      "description": "The persistent-rotor rule is run at two lifetimes, one measured cycle of the fastest segment and the paper's cited rotation period; both verdicts stored, disagreement flagged",
      "reviewed_at": null
     },
     {
      "id": "persistent_rotor_criterion",
      "expert": "cardiac electrophysiologist",
      "status": "provisional",
      "values": {
       "max_absent": 0,
       "min_present": 1
      },
      "decision": null,
      "location": "worker/voltage/sensitivity.py (MIN_ROTORS_PRESENT, MAX_ROTORS_ABSENT)",
      "reviewed": false,
      "reviewer": null,
      "description": "Persistent-rotor finding holds if every 'present' segment has >= 1 persistent rotor and every 'absent' segment has none, at every setting",
      "reviewed_at": null
     }
    ],
    "status": "provisional",
    "all_reviewed": false,
    "superseded_by_run": null
   }
  },
  "segments": [
   {
    "id": "f43dd23d-fc9d-4a02-a299-3c478800b938",
    "position": 1,
    "name": "whole_recording",
    "label": "whole recording",
    "start_frame": 0,
    "end_frame": 2047,
    "expected_persistent_rotors": null,
    "definition": "whole recording; no events detected or logged at admission",
    "defined_by": "admission (project lead); no comparison defined",
    "citation": null,
    "evidence": {},
    "provisional": true
   }
  ],
  "events": []
 }
}