[{"data":1,"prerenderedAt":6529},["ShallowReactive",2],{"navigation":3,"api-navigation":126,"docyard:\u002Fapi\u002Fstates\u002FProcess":328,"api-content:\u002Fapi\u002Fstates\u002FProcess":6527,"docyard:crossref-index":6528},[4,8,38,44,48,122],{"title":5,"path":6,"stem":7},"Getting Started","\u002Fgetting-started","1.getting-started",{"title":9,"path":10,"stem":11,"children":12,"page":37},"Recipes","\u002Frecipes","2.recipes",[13,17,21,25,29,33],{"title":14,"path":15,"stem":16},"Recipe: two-stage cascade tracker","\u002Frecipes\u002Fcascade_tracker","2.recipes\u002Fcascade_tracker",{"title":18,"path":19,"stem":20},"Recipe: cosine appearance tracker","\u002Frecipes\u002Fcosine_tracker","2.recipes\u002Fcosine_tracker",{"title":22,"path":23,"stem":24},"Recipe: Kalman motion tracker","\u002Frecipes\u002Fkalman_motion_tracker","2.recipes\u002Fkalman_motion_tracker",{"title":26,"path":27,"stem":28},"Recipe: learned MOTR-style appearance tracker","\u002Frecipes\u002Flearned_motr_tracker","2.recipes\u002Flearned_motr_tracker",{"title":30,"path":31,"stem":32},"Recipe: overlap-IoU tracker (port of 1.x models.overlap)","\u002Frecipes\u002Foverlap_tracker","2.recipes\u002Foverlap_tracker",{"title":34,"path":35,"stem":36},"Recipe: SORT-style tracker on unitrack 2.0","\u002Frecipes\u002Fsort","2.recipes\u002Fsort",false,{"title":39,"path":40,"stem":41,"children":42},"API reference","\u002Fapi","3.api\u002Findex",[43],{"title":39,"path":40,"stem":41},{"title":45,"path":46,"stem":47},"Migrating from 1.x to 2.0","\u002Fmigration","4.migration",{"title":49,"path":50,"stem":51,"children":52,"page":37},"Notebooks","\u002Fnotebooks","5.notebooks",[53,84,88],{"title":54,"path":55,"stem":56,"children":57},"Embedding \u002F appearance filters","\u002Fnotebooks\u002Fembedding_filters","5.notebooks\u002Fembedding_filters\u002Findex",[58,59,64,68,72,76,80],{"title":54,"path":55,"stem":56},{"title":60,"path":61,"stem":62,"icon":63},"Embedding filters 1 — Exponential moving average (EMA)","\u002Fnotebooks\u002Fembedding_filters\u002Fema","5.notebooks\u002Fembedding_filters\u002F1.ema","i-lucide-notebook",{"title":65,"path":66,"stem":67,"icon":63},"Embedding filters 2 — Diagonal Kalman","\u002Fnotebooks\u002Fembedding_filters\u002Fkalman_diagonal","5.notebooks\u002Fembedding_filters\u002F2.kalman_diagonal",{"title":69,"path":70,"stem":71,"icon":63},"Embedding filters 3 — von Mises-Fisher (directional)","\u002Fnotebooks\u002Fembedding_filters\u002Fvmf_directional","5.notebooks\u002Fembedding_filters\u002F3.vmf_directional",{"title":73,"path":74,"stem":75,"icon":63},"Embedding filters 4 — Ensemble Kalman & information filters","\u002Fnotebooks\u002Fembedding_filters\u002Fenkf_information","5.notebooks\u002Fembedding_filters\u002F4.enkf_information",{"title":77,"path":78,"stem":79,"icon":63},"Embedding filters 5 — Memory bank & learned propagation","\u002Fnotebooks\u002Fembedding_filters\u002Fgallery_and_learned","5.notebooks\u002Fembedding_filters\u002F5.gallery_and_learned",{"title":81,"path":82,"stem":83,"icon":63},"Embedding filters 6 — summary & benchmark","\u002Fnotebooks\u002Fembedding_filters\u002Fsummary_benchmark","5.notebooks\u002Fembedding_filters\u002F6.summary_benchmark",{"title":85,"path":86,"stem":87,"icon":63},"Kalman filters for motion prediction in tracking","\u002Fnotebooks\u002Fkalman","5.notebooks\u002Fkalman",{"title":89,"path":90,"stem":91,"children":92},"Tutorial notebooks","\u002Fnotebooks\u002Ftutorials","5.notebooks\u002Ftutorials\u002Findex",[93,94,98,102,106,110,114,118],{"title":89,"path":90,"stem":91},{"title":95,"path":96,"stem":97,"icon":63},"1. Quickstart — your first tracker","\u002Fnotebooks\u002Ftutorials\u002Fquickstart","5.notebooks\u002Ftutorials\u002F1.quickstart",{"title":99,"path":100,"stem":101,"icon":63},"2. The data model — typed records that flow through a tracker","\u002Fnotebooks\u002Ftutorials\u002Fdata_model","5.notebooks\u002Ftutorials\u002F2.data_model",{"title":103,"path":104,"stem":105,"icon":63},"3. The cost & gate zoos","\u002Fnotebooks\u002Ftutorials\u002Fcosts_and_gates","5.notebooks\u002Ftutorials\u002F3.costs_and_gates",{"title":107,"path":108,"stem":109,"icon":63},"4. The composable pipeline tree","\u002Fnotebooks\u002Ftutorials\u002Fpipeline_tree","5.notebooks\u002Ftutorials\u002F4.pipeline_tree",{"title":111,"path":112,"stem":113,"icon":63},"5. State evolution and lifecycle","\u002Fnotebooks\u002Ftutorials\u002Fstates_and_lifecycle","5.notebooks\u002Ftutorials\u002F5.states_and_lifecycle",{"title":115,"path":116,"stem":117,"icon":63},"6. End-to-end: K=2 cascaded and parallel fusion","\u002Fnotebooks\u002Ftutorials\u002Fcascaded_and_parallel","5.notebooks\u002Ftutorials\u002F6.cascaded_and_parallel",{"title":119,"path":120,"stem":121,"icon":63},"7. Migration & new possibilities — driven by a real detector","\u002Fnotebooks\u002Ftutorials\u002Fmigration","5.notebooks\u002Ftutorials\u002F7.migration",{"title":123,"path":124,"stem":125},"Unitrack","\u002F","index",[127,130,133,136,139,142,145,148,151,154,157,160,163,166,169,172,175,178,181,184,187,190,193,196,199,202,205,208,211,214,217,220,223,226,229,232,235,238,241,244,247,249,252,255,258,261,263,266,269,272,274,277,280,282,285,288,290,293,296,299,302,305,308,311,313,315,318,320,323,326],{"title":128,"path":129},"assignment","\u002Fapi\u002Fassignment",{"title":131,"path":132},"associate","\u002Fapi\u002Fassignment\u002Fassociate",{"title":134,"path":135},"clip_associate","\u002Fapi\u002Fassignment\u002Fclip_associate",{"title":137,"path":138},"lap","\u002Fapi\u002Fassignment\u002Flap",{"title":140,"path":141},"lapjv","\u002Fapi\u002Fassignment\u002Flapjv",{"title":143,"path":144},"benchmarks","\u002Fapi\u002Fbenchmarks",{"title":146,"path":147},"hota","\u002Fapi\u002Fbenchmarks\u002Fhota",{"title":149,"path":150},"datasets","\u002Fapi\u002Fbenchmarks\u002Fhota\u002Fdatasets",{"title":152,"path":153},"learned_modules","\u002Fapi\u002Fbenchmarks\u002Fhota\u002Flearned_modules",{"title":155,"path":156},"metric","\u002Fapi\u002Fbenchmarks\u002Fhota\u002Fmetric",{"title":158,"path":159},"models","\u002Fapi\u002Fbenchmarks\u002Fhota\u002Fmodels",{"title":161,"path":162},"protocols","\u002Fapi\u002Fbenchmarks\u002Fhota\u002Fprotocols",{"title":164,"path":165},"render","\u002Fapi\u002Fbenchmarks\u002Fhota\u002Frender",{"title":167,"path":168},"report","\u002Fapi\u002Fbenchmarks\u002Fhota\u002Freport",{"title":170,"path":171},"runner","\u002Fapi\u002Fbenchmarks\u002Fhota\u002Frunner",{"title":173,"path":174},"tracker","\u002Fapi\u002Fbenchmarks\u002Fhota\u002Ftracker",{"title":176,"path":177},"train_learned","\u002Fapi\u002Fbenchmarks\u002Fhota\u002Ftrain_learned",{"title":179,"path":180},"types","\u002Fapi\u002Fbenchmarks\u002Fhota\u002Ftypes",{"title":182,"path":183},"costs","\u002Fapi\u002Fcosts",{"title":185,"path":186},"combinators","\u002Fapi\u002Fcosts\u002Fcombinators",{"title":188,"path":189},"distance","\u002Fapi\u002Fcosts\u002Fdistance",{"title":191,"path":192},"gallery","\u002Fapi\u002Fcosts\u002Fgallery",{"title":194,"path":195},"overlap","\u002Fapi\u002Fcosts\u002Foverlap",{"title":197,"path":198},"data","\u002Fapi\u002Fdata",{"title":200,"path":201},"clip","\u002Fapi\u002Fdata\u002Fclip",{"title":203,"path":204},"cost","\u002Fapi\u002Fdata\u002Fcost",{"title":206,"path":207},"detections","\u002Fapi\u002Fdata\u002Fdetections",{"title":209,"path":210},"frame","\u002Fapi\u002Fdata\u002Fframe",{"title":212,"path":213},"gate","\u002Fapi\u002Fdata\u002Fgate",{"title":215,"path":216},"match","\u002Fapi\u002Fdata\u002Fmatch",{"title":218,"path":219},"tensor_spec","\u002Fapi\u002Fdata\u002Ftensor_spec",{"title":221,"path":222},"tracklets","\u002Fapi\u002Fdata\u002Ftracklets",{"title":224,"path":225},"gates","\u002Fapi\u002Fgates",{"title":227,"path":228},"motion","\u002Fapi\u002Fgates\u002Fmotion",{"title":230,"path":231},"simple","\u002Fapi\u002Fgates\u002Fsimple",{"title":233,"path":234},"soft","\u002Fapi\u002Fgates\u002Fsoft",{"title":236,"path":237},"spatial","\u002Fapi\u002Fgates\u002Fspatial",{"title":239,"path":240},"lifecycle","\u002Fapi\u002Flifecycle",{"title":242,"path":243},"filters","\u002Fapi\u002Flifecycle\u002Ffilters",{"title":245,"path":246},"policies","\u002Fapi\u002Flifecycle\u002Fpolicies",{"title":233,"path":248},"\u002Fapi\u002Flifecycle\u002Fsoft",{"title":250,"path":251},"status","\u002Fapi\u002Flifecycle\u002Fstatus",{"title":253,"path":254},"visibility","\u002Fapi\u002Flifecycle\u002Fvisibility",{"title":256,"path":257},"pipeline","\u002Fapi\u002Fpipeline",{"title":259,"path":260},"base","\u002Fapi\u002Fpipeline\u002Fbase",{"title":185,"path":262},"\u002Fapi\u002Fpipeline\u002Fcombinators",{"title":264,"path":265},"diff","\u002Fapi\u002Fpipeline\u002Fdiff",{"title":267,"path":268},"merge","\u002Fapi\u002Fpipeline\u002Fmerge",{"title":270,"path":271},"states","\u002Fapi\u002Fstates",{"title":259,"path":273},"\u002Fapi\u002Fstates\u002Fbase",{"title":275,"path":276},"directional","\u002Fapi\u002Fstates\u002Fdirectional",{"title":278,"path":279},"ema","\u002Fapi\u002Fstates\u002Fema",{"title":191,"path":281},"\u002Fapi\u002Fstates\u002Fgallery",{"title":283,"path":284},"identity","\u002Fapi\u002Fstates\u002Fidentity",{"title":286,"path":287},"kalman","\u002Fapi\u002Fstates\u002Fkalman",{"title":259,"path":289},"\u002Fapi\u002Fstates\u002Fkalman\u002Fbase",{"title":291,"path":292},"bbox","\u002Fapi\u002Fstates\u002Fkalman\u002Fbbox",{"title":294,"path":295},"centroid","\u002Fapi\u002Fstates\u002Fkalman\u002Fcentroid",{"title":297,"path":298},"ensemble","\u002Fapi\u002Fstates\u002Fkalman\u002Fensemble",{"title":300,"path":301},"information","\u002Fapi\u002Fstates\u002Fkalman\u002Finformation",{"title":303,"path":304},"project","\u002Fapi\u002Fstates\u002Fkalman\u002Fproject",{"title":306,"path":307},"update","\u002Fapi\u002Fstates\u002Fkalman\u002Fupdate",{"title":309,"path":310},"learned","\u002Fapi\u002Fstates\u002Flearned",{"title":233,"path":312},"\u002Fapi\u002Fstates\u002Fsoft",{"title":173,"path":314},"\u002Fapi\u002Ftracker",{"title":316,"path":317},"batch","\u002Fapi\u002Ftracker\u002Fbatch",{"title":200,"path":319},"\u002Fapi\u002Ftracker\u002Fclip",{"title":321,"path":322},"memory","\u002Fapi\u002Ftracker\u002Fmemory",{"title":324,"path":325},"multistream","\u002Fapi\u002Ftracker\u002Fmultistream",{"title":173,"path":327},"\u002Fapi\u002Ftracker\u002Ftracker",{"docyard":329,"language":330,"name":331,"version":332,"items":333},"1","python","unitrack","unknown",[334,342,353,361,370,378,386,402,408,416,423,430,435,441,446,459,492,497,505,511,516,522,528,539,544,553,559,564,570,575,588,593,603,610,617,624,631,638,664,674,683,689,696,709,717,724,731,737,743,765,775,782,789,796,803,821,830,836,843,849,856,863,875,885,892,899,914,923,928,935,942,949,957,965,973,981,997,1006,1013,1018,1026,1032,1036,1043,1049,1053,1062,1069,1073,1082,1089,1096,1103,1109,1115,1120,1129,1136,1143,1150,1157,1167,1189,1197,1212,1222,1229,1236,1243,1258,1263,1272,1278,1283,1298,1303,1310,1322,1330,1337,1344,1359,1364,1372,1379,1385,1398,1403,1412,1418,1424,1439,1444,1452,1458,1465,1482,1499,1506,1512,1529,1535,1544,1551,1558,1562,1572,1578,1584,1592,1605,1620,1641,1662,1667,1677,1682,1689,1695,1701,1723,1728,1735,1740,1747,1764,1771,1777,1782,1790,1798,1814,1822,1838,1853,1861,1870,1875,1880,1888,1894,1900,1907,1914,1919,1947,1952,1958,1963,1969,1975,1987,2001,2017,2027,2036,2041,2046,2052,2059,2070,2077,2085,2097,2106,2122,2131,2143,2166,2172,2177,2183,2189,2194,2218,2224,2230,2236,2243,2248,2253,2271,2275,2281,2287,2291,2296,2301,2329,2352,2357,2362,2367,2380,2385,2399,2403,2408,2413,2418,2430,2435,2440,2445,2458,2462,2468,2473,2478,2492,2497,2502,2510,2518,2523,2528,2545,2550,2555,2560,2565,2570,2588,2604,2609,2615,2621,2626,2641,2646,2651,2656,2661,2672,2676,2681,2685,2696,2700,2706,2710,2719,2725,2729,2738,2742,2746,2761,2766,2772,2778,2783,2801,2806,2812,2818,2823,2833,2838,2843,2847,2860,2864,2870,2876,2881,2890,2894,2900,2905,2927,2932,2937,2942,2948,2954,2960,2965,2980,2984,2989,2996,3001,3006,3023,3028,3033,3038,3042,3047,3052,3066,3070,3074,3081,3088,3093,3097,3109,3113,3117,3121,3125,3129,3134,3138,3161,3166,3170,3174,3179,3186,3193,3199,3206,3222,3227,3242,3247,3251,3255,3259,3264,3270,3282,3287,3299,3303,3308,3313,3317,3321,3327,3337,3341,3372,3376,3382,3387,3393,3399,3405,3409,3414,3419,3441,3445,3449,3453,3457,3462,3467,3493,3514,3529,3533,3537,3542,3547,3552,3564,3568,3572,3577,3582,3596,3600,3605,3622,3627,3633,3640,3647,3653,3660,3666,3672,3679,3685,3692,3698,3704,3711,3718,3741,3762,3785,3792,3798,3806,3815,3819,3824,3840,3845,3852,3858,3864,3870,3876,3884,3890,3897,3904,3917,3922,3929,3933,3939,3950,3955,3964,3969,3976,3988,3993,4001,4005,4016,4020,4027,4031,4037,4047,4052,4060,4065,4076,4080,4087,4091,4096,4106,4111,4119,4123,4128,4141,4146,4172,4176,4180,4184,4189,4193,4198,4203,4212,4216,4227,4231,4238,4242,4253,4257,4264,4269,4279,4283,4290,4294,4298,4308,4312,4318,4324,4330,4337,4343,4350,4368,4373,4377,4382,4387,4392,4401,4405,4410,4414,4421,4426,4430,4437,4441,4447,4452,4457,4465,4469,4473,4479,4484,4489,4497,4501,4507,4512,4517,4524,4528,4532,4537,4541,4547,4553,4559,4565,4573,4580,4594,4600,4612,4620,4626,4641,4655,4660,4678,4695,4704,4712,4716,4723,4731,4735,4743,4755,4762,4769,4773,4780,4787,4794,4801,4806,4813,4819,4832,4837,4844,4851,4858,4864,4870,4883,4902,4910,4916,4923,4929,4935,4941,4949,4958,4964,4982,4998,5015,5020,5025,5032,5039,5046,5053,5070,5088,5101,5106,5111,5123,5132,5144,5153,5168,5177,5191,5200,5205,5211,5228,5239,5264,5278,5292,5304,5309,5326,5331,5340,5355,5365,5373,5385,5397,5408,5419,5425,5431,5439,5456,5461,5466,5474,5481,5488,5495,5510,5524,5532,5539,5547,5554,5561,5566,5572,5578,5583,5589,5595,5601,5608,5618,5623,5630,5636,5643,5650,5658,5665,5671,5677,5683,5688,5694,5700,5707,5715,5720,5725,5730,5735,5742,5746,5751,5756,5763,5769,5779,5784,5791,5799,5807,5812,5817,5823,5829,5834,5840,5846,5854,5863,5871,5880,5888,5894,5900,5906,5912,5919,5926,5931,5938,5944,5950,5956,5962,5968,5975,5982,5989,5994,6002,6008,6014,6019,6024,6030,6036,6044,6051,6057,6063,6069,6076,6081,6086,6092,6098,6104,6111,6118,6125,6131,6139,6145,6151,6157,6164,6170,6193,6200,6208,6214,6220,6226,6230,6237,6245,6253,6260,6264,6270,6276,6284,6292,6300,6308,6314,6321,6329,6336,6340,6344,6348,6355,6360,6366,6372,6378,6384,6390,6396,6402,6408,6415,6423,6427,6433,6438,6445,6451,6457,6462,6471,6475,6479,6483,6487,6492,6496,6502,6509,6515,6521],{"id":331,"kind":335,"path":336,"signature":337,"summary":338,"source":339},"module",[331],"module unitrack","Unitrack — image-trained video tracking primitives.",{"file":340,"line":341},"unitrack\u002F__init__.py",1,{"id":343,"kind":344,"path":345,"signature":347,"summary":348,"description":349,"source":350,"parent":331},"unitrack.ClipDetections","type",[331,346],"ClipDetections","class ClipDetections:","K frames' worth of :class:`~unitrack.data.Detections`.","Per-frame detection counts vary in MOT, so the canonical\nrepresentation is a Python list of per-frame :class:`~unitrack.data.Detections`.\n:meth:`frame_lengths` and :meth:`frame_ranges` expose the per-frame\nindex ranges; :meth:`stacked` produces a flat tensordict with a\nsingle leading batch axis equal to ``sum(frame_lengths)`` and a\nparallel ``frame_idx`` column for callers that want the clip as one\ntensor.",{"file":351,"line":352},"unitrack\u002Fdata\u002Fclip.py",56,{"id":354,"kind":355,"path":356,"signature":358,"source":359,"parent":343},"unitrack.ClipDetections.frames","property",[331,346,357],"frames","frames: list[Detections]",{"file":351,"line":360},76,{"id":362,"kind":363,"path":364,"signature":366,"summary":367,"source":368,"parent":343},"unitrack.ClipDetections.K","constant",[331,346,365],"K","K: int","Number of frames in the clip.",{"file":351,"line":369},79,{"id":371,"kind":355,"path":372,"signature":374,"summary":375,"source":376,"parent":343},"unitrack.ClipDetections.frame_lengths",[331,346,373],"frame_lengths","frame_lengths: torch.Tensor","``(K,)`` int64 tensor of per-frame detection counts.",{"file":351,"line":377},84,{"id":379,"kind":355,"path":380,"signature":382,"summary":383,"source":384,"parent":343},"unitrack.ClipDetections.frame_ranges",[331,346,381],"frame_ranges","frame_ranges: torch.Tensor","``(K, 2)`` int64 tensor of ``[start, stop)`` ranges into :meth:`stacked`.",{"file":351,"line":385},96,{"id":387,"kind":388,"path":389,"signature":391,"summary":392,"returns":393,"raises":396,"source":400,"parent":343},"unitrack.ClipDetections.stacked","method",[331,346,390],"stacked","def stacked(self) -> Detections","Return one :class:`~unitrack.data.Detections` flattening all K frames.",{"type":394,"doc":395},"Detections","Concatenated detections with an extra ``frame_idx`` field\nmarking each row's source frame. Variable per-frame counts\nare preserved by concatenation rather than padding.",[397],{"type":398,"doc":399},"ValueError","If any per-frame :class:`~unitrack.data.Detections` already carries a user\nfield named ``frame_idx``; the stacked column would silently\noverwrite it and corrupt downstream cascade indexing.",{"file":351,"line":401},103,{"id":403,"kind":388,"path":404,"signature":406,"source":407,"parent":343},"unitrack.ClipDetections.__init__",[331,346,405],"__init__","def __init__(self, frames: list[Detections]) -> None",{"file":351,"line":341},{"id":409,"kind":344,"path":410,"signature":412,"summary":413,"source":414,"parent":331},"unitrack.ClipFrameContext",[331,411],"ClipFrameContext","class ClipFrameContext:","Per-frame contexts plus clip-level metadata.",{"file":351,"line":415},240,{"id":417,"kind":355,"path":418,"signature":420,"source":421,"parent":409},"unitrack.ClipFrameContext.frame_contexts",[331,411,419],"frame_contexts","frame_contexts: list[FrameContext]",{"file":351,"line":422},254,{"id":424,"kind":355,"path":425,"signature":427,"source":428,"parent":409},"unitrack.ClipFrameContext.clip_idx",[331,411,426],"clip_idx","clip_idx: int = 0",{"file":351,"line":429},255,{"id":431,"kind":363,"path":432,"signature":366,"summary":367,"source":433,"parent":409},"unitrack.ClipFrameContext.K",[331,411,365],{"file":351,"line":434},258,{"id":436,"kind":355,"path":437,"signature":374,"summary":438,"source":439,"parent":409},"unitrack.ClipFrameContext.frame_lengths",[331,411,373],"``(K,)`` int64 tensor — each frame contributes exactly one context.",{"file":351,"line":440},263,{"id":442,"kind":355,"path":443,"signature":382,"summary":383,"source":444,"parent":409},"unitrack.ClipFrameContext.frame_ranges",[331,411,381],{"file":351,"line":445},271,{"id":447,"kind":388,"path":448,"signature":449,"summary":450,"returns":451,"raises":454,"source":457,"parent":409},"unitrack.ClipFrameContext.stacked",[331,411,390],"def stacked(self) -> FrameContext","Return a single :class:`FrameContext` with a leading ``(K,)`` batch axis.",{"type":452,"doc":453},"FrameContext","Stacked context across all ``K`` frames.",[455],{"type":398,"doc":456},"If :attr:`frame_contexts` is empty.",{"file":351,"line":458},277,{"id":460,"kind":388,"path":461,"signature":463,"summary":464,"params":465,"returns":488,"source":490,"parent":409},"unitrack.ClipFrameContext.make",[331,411,462],"make","@classmethod\ndef make(cls, start_frame: int, K: int, fps: float = 1.0, stream_key: int = 0, clip_idx: int = 0, device: torch.types.Device | None = None) -> ClipFrameContext","Build a :class:`~unitrack.data.ClipFrameContext` from Python scalars.",[466,470,472,477,481,483],{"name":467,"type":468,"doc":469},"start_frame","int","Frame index of the first frame in the clip.",{"name":365,"type":468,"doc":471},"Number of frames.",{"name":473,"type":474,"default":475,"doc":476},"fps","float","1.0","Frame rate; sets ``delta = 1.0 \u002F fps`` for every frame.",{"name":478,"type":468,"default":479,"doc":480},"stream_key","0","Stream identifier shared by all frames.",{"name":426,"type":468,"default":479,"doc":482},"Clip-level identifier.",{"name":484,"type":485,"default":486,"doc":487},"device","torch.types.Device | None","None","Device for the packed scalar tensors.",{"type":411,"doc":489},"The packed clip context.",{"file":351,"line":491},297,{"id":493,"kind":388,"path":494,"signature":495,"source":496,"parent":409},"unitrack.ClipFrameContext.__init__",[331,411,405],"def __init__(self, frame_contexts: list[FrameContext], clip_idx: int = 0) -> None",{"file":351,"line":341},{"id":498,"kind":344,"path":499,"signature":501,"summary":502,"source":503,"parent":331},"unitrack.ClipMatchOutcome",[331,500],"ClipMatchOutcome","class ClipMatchOutcome:","Per-frame :class:`~unitrack.data.MatchOutcome` records for a clip.",{"file":351,"line":504},345,{"id":506,"kind":355,"path":507,"signature":508,"source":509,"parent":498},"unitrack.ClipMatchOutcome.frames",[331,500,357],"frames: list[MatchOutcome]",{"file":351,"line":510},357,{"id":512,"kind":363,"path":513,"signature":366,"summary":367,"source":514,"parent":498},"unitrack.ClipMatchOutcome.K",[331,500,365],{"file":351,"line":515},360,{"id":517,"kind":355,"path":518,"signature":374,"summary":519,"source":520,"parent":498},"unitrack.ClipMatchOutcome.frame_lengths",[331,500,373],"``(K,)`` int64 tensor of per-frame matched-pair counts.",{"file":351,"line":521},365,{"id":523,"kind":355,"path":524,"signature":382,"summary":525,"source":526,"parent":498},"unitrack.ClipMatchOutcome.frame_ranges",[331,500,381],"``(K, 2)`` int64 ``[start, stop)`` ranges over the matched-pair axis.",{"file":351,"line":527},377,{"id":529,"kind":388,"path":530,"signature":531,"summary":532,"description":533,"returns":534,"source":537,"parent":498},"unitrack.ClipMatchOutcome.stacked",[331,500,390],"def stacked(self) -> StackedClipMatch","Return a :class:`StackedClipMatch` view across all K frames.","Per-frame :class:`~unitrack.data.MatchOutcome` rows are concatenated along\ntheir matched-pair axis; the residual-index arrays and soft-plan\ntensors cannot share a uniform shape across frames (variable\n``N`` and ``M``), so the stacked form carries only the\nmatched-pair triple plus a per-row ``frame_idx`` annotation. Use\n:meth:`frame_ranges` to slice back into per-frame views.",{"type":535,"doc":536},"StackedClipMatch","Concatenated matched-pair view.",{"file":351,"line":538},383,{"id":540,"kind":388,"path":541,"signature":542,"source":543,"parent":498},"unitrack.ClipMatchOutcome.__init__",[331,500,405],"def __init__(self, frames: list[MatchOutcome]) -> None",{"file":351,"line":341},{"id":545,"kind":344,"path":546,"signature":548,"summary":549,"description":550,"source":551,"parent":331},"unitrack.ClipTracklets",[331,547],"ClipTracklets","class ClipTracklets:","K aligned :class:`~unitrack.data.Tracklets` snapshots, one per frame.","Row ``n`` at frame ``k`` is the same identity as row ``n`` at frame\n``k + 1``. The list-of-frames form is canonical; :meth:`stacked`\nproduces a flat tensordict view marked with ``frame_idx`` for\nkernels that want a single tensor input.",{"file":351,"line":552},150,{"id":554,"kind":355,"path":555,"signature":556,"source":557,"parent":545},"unitrack.ClipTracklets.frames",[331,547,357],"frames: list[Tracklets]",{"file":351,"line":558},168,{"id":560,"kind":363,"path":561,"signature":366,"summary":367,"source":562,"parent":545},"unitrack.ClipTracklets.K",[331,547,365],{"file":351,"line":563},171,{"id":565,"kind":355,"path":566,"signature":374,"summary":567,"source":568,"parent":545},"unitrack.ClipTracklets.frame_lengths",[331,547,373],"``(K,)`` int64 tensor of per-frame row counts.",{"file":351,"line":569},176,{"id":571,"kind":355,"path":572,"signature":382,"summary":383,"source":573,"parent":545},"unitrack.ClipTracklets.frame_ranges",[331,547,381],{"file":351,"line":574},188,{"id":576,"kind":388,"path":577,"signature":578,"summary":579,"returns":580,"raises":583,"source":586,"parent":545},"unitrack.ClipTracklets.stacked",[331,547,390],"def stacked(self) -> Tracklets","Return one :class:`~unitrack.data.Tracklets` flattening all K frames.",{"type":581,"doc":582},"Tracklets","Concatenated snapshots with an extra ``frame_idx`` field\nmarking each row's source frame.",[584],{"type":398,"doc":585},"If any per-frame :class:`~unitrack.data.Tracklets` already carries a user\nfield named ``frame_idx``; the stacked column would silently\noverwrite it.",{"file":351,"line":587},194,{"id":589,"kind":388,"path":590,"signature":591,"source":592,"parent":545},"unitrack.ClipTracklets.__init__",[331,547,405],"def __init__(self, frames: list[Tracklets]) -> None",{"file":351,"line":341},{"id":594,"kind":344,"path":595,"signature":597,"summary":598,"description":599,"source":600,"parent":331},"unitrack.CostExpression",[331,596],"CostExpression","class CostExpression:","A cost matrix plus optional un-applied gates and bias.","Gates are carried separately from the matrix so a downstream node\n(Merge, Associate) can apply them at the right moment. The upstream\ncost producer never has to materialize an ``(N, M)`` ``inf``-mask\njust to express a feasibility constraint.",{"file":601,"line":602},"unitrack\u002Fdata\u002Fcost.py",11,{"id":604,"kind":355,"path":605,"signature":607,"source":608,"parent":594},"unitrack.CostExpression.matrix",[331,596,606],"matrix","matrix: torch.Tensor",{"file":601,"line":609},39,{"id":611,"kind":355,"path":612,"signature":614,"source":615,"parent":594},"unitrack.CostExpression.gate_pair",[331,596,613],"gate_pair","gate_pair: torch.Tensor | None = None",{"file":601,"line":616},40,{"id":618,"kind":355,"path":619,"signature":621,"source":622,"parent":594},"unitrack.CostExpression.gate_cs",[331,596,620],"gate_cs","gate_cs: torch.Tensor | None = None",{"file":601,"line":623},41,{"id":625,"kind":355,"path":626,"signature":628,"source":629,"parent":594},"unitrack.CostExpression.gate_ds",[331,596,627],"gate_ds","gate_ds: torch.Tensor | None = None",{"file":601,"line":630},42,{"id":632,"kind":355,"path":633,"signature":635,"source":636,"parent":594},"unitrack.CostExpression.bias",[331,596,634],"bias","bias: torch.Tensor | None = None",{"file":601,"line":637},43,{"id":639,"kind":388,"path":640,"signature":642,"summary":643,"params":644,"returns":657,"raises":659,"source":662,"parent":594},"unitrack.CostExpression.from_matrix",[331,596,641],"from_matrix","@classmethod\ndef from_matrix(cls, matrix: torch.Tensor, gate_pair: torch.Tensor | None = None, gate_cs: torch.Tensor | None = None, gate_ds: torch.Tensor | None = None, bias: torch.Tensor | None = None) -> CostExpression","Build a :class:`~unitrack.data.CostExpression` from a matrix and optional gates.",[645,648,651,653,655],{"name":606,"type":646,"doc":647},"torch.Tensor","Float ``(N, M)`` cost matrix.",{"name":613,"type":649,"default":486,"doc":650},"torch.Tensor | None","Optional bool ``(N, M)`` per-pair feasibility mask.",{"name":620,"type":649,"default":486,"doc":652},"Optional bool ``(N,)`` per-tracklet feasibility mask.",{"name":627,"type":649,"default":486,"doc":654},"Optional bool ``(M,)`` per-detection feasibility mask.",{"name":634,"type":649,"default":486,"doc":656},"Optional float ``(N, M)`` additive bias.",{"type":596,"doc":658},"The packed cost expression.",[660],{"type":398,"doc":661},"If ``matrix`` is not 2-D or if any gate\u002Fbias shape disagrees\nwith ``matrix``.",{"file":601,"line":663},45,{"id":665,"kind":388,"path":666,"signature":668,"summary":669,"returns":670,"source":672,"parent":594},"unitrack.CostExpression.materialize",[331,596,667],"materialize","def materialize(self) -> torch.Tensor","Return the cost matrix with all attached gates and bias applied.",{"type":646,"doc":671},"Float ``(N, M)`` materialised cost. Blocked pairs become\n``+inf``; ``bias`` is added to the surviving entries.",{"file":601,"line":673},125,{"id":675,"kind":344,"path":676,"signature":677,"summary":678,"description":679,"source":680,"parent":331},"unitrack.Detections",[331,394],"class Detections(TensorDict):","Record of one frame's detections.","User fields match the :class:`~unitrack.data.Tracklets` schema of the same Tracker.\nThe ``index`` field carries the caller's per-detection ordering and\nis threaded through to :class:`~unitrack.data.MatchOutcome` so the caller can\nrecover it after assignment.\n\nConstruction via ``Detections(...)`` validates the reserved-field\nschema: ``index`` must be present, ``int64``, and shape ``(M,)``.",{"file":681,"line":682},"unitrack\u002Fdata\u002Fdetections.py",58,{"id":684,"kind":388,"path":685,"signature":686,"source":687,"parent":675},"unitrack.Detections.__init__",[331,394,405],"def __init__(self, **kwargs: object = {}) -> None",{"file":681,"line":688},77,{"id":690,"kind":355,"path":691,"signature":692,"summary":693,"source":694,"parent":675},"unitrack.Detections.index",[331,394,125],"index: torch.Tensor","``int64`` shape ``(M,)`` caller-assigned detection index.",{"file":681,"line":695},88,{"id":697,"kind":388,"path":698,"signature":700,"summary":701,"params":702,"returns":705,"source":707,"parent":675},"unitrack.Detections.empty",[331,394,699],"empty","@classmethod\ndef empty(cls, device: torch.types.Device | None = None) -> Detections","Construct a zero-row Detections record.",[703],{"name":484,"type":485,"default":486,"doc":704},"Device for the zero-row ``index`` tensor. ``None`` selects\nthe default device.",{"type":394,"doc":706},"A :class:`~unitrack.data.Detections` with ``batch_size=[0]`` and an empty\n``index`` field.",{"file":681,"line":708},102,{"id":710,"kind":344,"path":711,"signature":712,"summary":713,"description":714,"source":715,"parent":331},"unitrack.FrameContext",[331,452],"class FrameContext:","Per-frame context threaded through the entire stage tree.","Carries timing (frame index, delta, fps) and stream identity. Stages\nthat need frame-level information (e.g. time-aware covariance\nscaling, annealed thresholds) read it from the third argument of\ntheir ``__call__``.",{"file":716,"line":602},"unitrack\u002Fdata\u002Fframe.py",{"id":718,"kind":355,"path":719,"signature":721,"source":722,"parent":710},"unitrack.FrameContext.frame_idx",[331,452,720],"frame_idx","frame_idx: torch.Tensor",{"file":716,"line":723},34,{"id":725,"kind":355,"path":726,"signature":728,"source":729,"parent":710},"unitrack.FrameContext.delta",[331,452,727],"delta","delta: torch.Tensor",{"file":716,"line":730},35,{"id":732,"kind":355,"path":733,"signature":734,"source":735,"parent":710},"unitrack.FrameContext.fps",[331,452,473],"fps: torch.Tensor",{"file":716,"line":736},36,{"id":738,"kind":355,"path":739,"signature":740,"source":741,"parent":710},"unitrack.FrameContext.stream_key",[331,452,478],"stream_key: torch.Tensor",{"file":716,"line":742},37,{"id":744,"kind":388,"path":745,"signature":746,"summary":747,"params":748,"returns":759,"raises":761,"source":764,"parent":710},"unitrack.FrameContext.make",[331,452,462],"@classmethod\ndef make(cls, frame_idx: int, delta: float | None = None, fps: float = 1.0, stream_key: int = 0, device: torch.types.Device | None = None) -> FrameContext","Build a :class:`FrameContext` from Python scalars.",[749,751,754,756,758],{"name":720,"type":468,"doc":750},"Frame index.",{"name":727,"type":752,"default":486,"doc":753},"float | None","Seconds since the previous frame. Defaults to ``1.0 \u002F fps``,\nthe natural step for a real frame stream. Pass ``0.0`` to\nfreeze a Kalman predict step explicitly.",{"name":473,"type":474,"default":475,"doc":755},"Frame rate. Must be positive when ``delta`` is omitted.",{"name":478,"type":468,"default":479,"doc":757},"Stream identifier; relevant for multi-stream wrappers.",{"name":484,"type":485,"default":486,"doc":487},{"type":452,"doc":760},"The packed scalar context.",[762],{"type":398,"doc":763},"If ``delta`` is omitted and ``fps`` is non-positive.",{"file":716,"line":609},{"id":766,"kind":344,"path":767,"signature":769,"summary":770,"description":771,"source":772,"parent":331},"unitrack.Gate",[331,768],"Gate","class Gate:","Algebraic gate closed under conjunction via :meth:`~unitrack.data.Gate.combine`.","The four constructors are exposed as nested classes so the public\nspelling is ``Gate.PerPair(...)``, ``Gate.CostBias(...)``, and so on.",{"file":773,"line":774},"unitrack\u002Fdata\u002Fgate.py",134,{"id":776,"kind":355,"path":777,"signature":779,"source":780,"parent":766},"unitrack.Gate.PerPair",[331,768,778],"PerPair","PerPair = _PerPair",{"file":773,"line":781},142,{"id":783,"kind":355,"path":784,"signature":786,"source":787,"parent":766},"unitrack.Gate.PerCs",[331,768,785],"PerCs","PerCs = _PerCs",{"file":773,"line":788},143,{"id":790,"kind":355,"path":791,"signature":793,"source":794,"parent":766},"unitrack.Gate.PerDs",[331,768,792],"PerDs","PerDs = _PerDs",{"file":773,"line":795},144,{"id":797,"kind":355,"path":798,"signature":800,"source":801,"parent":766},"unitrack.Gate.CostBias",[331,768,799],"CostBias","CostBias = _CostBias",{"file":773,"line":802},145,{"id":804,"kind":388,"path":805,"signature":807,"summary":808,"params":809,"returns":816,"source":819,"parent":766},"unitrack.Gate.combine",[331,768,806],"combine","@staticmethod\ndef combine(a: _GateAny, b: _GateAny) -> _GateAny","Combine two gate operands via mask AND and bias sum.",[810,814],{"name":811,"type":812,"doc":813},"a","_GateAny","Any two values drawn from ``{PerPair, PerCs, PerDs, CostBias,\n_PairAndBias}``.",{"name":815,"type":812,"doc":813},"b",{"type":817,"doc":818},"~unitrack.data.Gate","Another value of the same family. Mask-only operands stay\nmask-only with the most specific kind preserved (e.g. two\n``PerCs`` combine to a ``PerCs``); mixing a mask with a bias\nyields a ``_PairAndBias``.",{"file":773,"line":820},147,{"id":822,"kind":344,"path":823,"signature":825,"summary":826,"description":827,"source":828,"parent":331},"unitrack.MatchOutcome",[331,824],"MatchOutcome","class MatchOutcome:","Output of a stage subtree rooted at an Associator.","Each row of ``matched_pairs`` records one matched tracklet-detection\npair; the residual indices identify cs\u002Fds rows that no stage in the\nsubtree could place. The :class:`~unitrack.pipeline.Associator`\nprotocol returns one of these per call.",{"file":829,"line":602},"unitrack\u002Fdata\u002Fmatch.py",{"id":831,"kind":355,"path":832,"signature":834,"source":835,"parent":822},"unitrack.MatchOutcome.matched_pairs",[331,824,833],"matched_pairs","matched_pairs: torch.Tensor",{"file":829,"line":637},{"id":837,"kind":355,"path":838,"signature":840,"source":841,"parent":822},"unitrack.MatchOutcome.tracklets_residual_index",[331,824,839],"tracklets_residual_index","tracklets_residual_index: torch.Tensor",{"file":829,"line":842},44,{"id":844,"kind":355,"path":845,"signature":847,"source":848,"parent":822},"unitrack.MatchOutcome.detections_residual_index",[331,824,846],"detections_residual_index","detections_residual_index: torch.Tensor",{"file":829,"line":663},{"id":850,"kind":355,"path":851,"signature":853,"source":854,"parent":822},"unitrack.MatchOutcome.per_match_cost",[331,824,852],"per_match_cost","per_match_cost: torch.Tensor",{"file":829,"line":855},46,{"id":857,"kind":355,"path":858,"signature":860,"source":861,"parent":822},"unitrack.MatchOutcome.soft_plan",[331,824,859],"soft_plan","soft_plan: torch.Tensor | None = None",{"file":829,"line":862},47,{"id":864,"kind":388,"path":865,"signature":866,"summary":867,"params":868,"returns":871,"source":873,"parent":822},"unitrack.MatchOutcome.empty",[331,824,699],"@classmethod\ndef empty(cls, device: torch.types.Device | None = None) -> MatchOutcome","Construct an empty :class:`~unitrack.data.MatchOutcome`.",[869],{"name":484,"type":485,"default":486,"doc":870},"Device for the zero-row tensors.",{"type":824,"doc":872},"All fields are zero-length tensors and ``soft_plan`` is\n``None``.",{"file":829,"line":874},49,{"id":876,"kind":344,"path":877,"signature":879,"summary":880,"description":881,"source":882,"parent":331},"unitrack.TensorSpec",[331,878],"TensorSpec","class TensorSpec(typing.NamedTuple):","Per-tracklet shape and dtype declaration.","The slot dimension (number of tracklets) is implicit; :attr:`shape`\ndescribes the trailing dimensions of one tracklet's value of this\nfield.",{"file":883,"line":884},"unitrack\u002Fdata\u002Ftensor_spec.py",12,{"id":886,"kind":355,"path":887,"signature":889,"source":890,"parent":876},"unitrack.TensorSpec.shape",[331,878,888],"shape","shape: tuple[int, ...]",{"file":883,"line":891},29,{"id":893,"kind":355,"path":894,"signature":896,"source":897,"parent":876},"unitrack.TensorSpec.dtype",[331,878,895],"dtype","dtype: torch.dtype",{"file":883,"line":898},30,{"id":900,"kind":388,"path":901,"signature":902,"summary":903,"params":904,"returns":910,"source":912,"parent":876},"unitrack.TensorSpec.empty",[331,878,699],"def empty(self, slots: int, device: torch.types.Device | None = None) -> torch.Tensor","Allocate a zero buffer matching this spec.",[905,908],{"name":906,"type":468,"doc":907},"slots","Leading slot dimension (number of tracklets).",{"name":484,"type":485,"default":486,"doc":909},"Device for the allocation.",{"type":646,"doc":911},"Zero tensor of shape ``(slots, *self.shape)`` and dtype\n:attr:`dtype`.",{"file":883,"line":913},32,{"id":915,"kind":344,"path":916,"signature":917,"summary":918,"description":919,"source":920,"parent":331},"unitrack.Tracklets",[331,581],"class Tracklets(TensorDict):","Snapshot of all live tracklets at one frame.","Reserved fields are common to every Tracker; user fields are added by\nTracker construction (one per declared :class:`~unitrack.states.State`) and live\nalongside the reserved set in a flat namespace.\n\nConstruction via ``Tracklets(...)`` validates the reserved-field\nschema: all reserved names must be present with the documented dtype\nand a leading dim matching ``batch_size[0]``. :meth:`empty` is the\ncanonical way to build a fresh snapshot without re-typing every\nreserved field.",{"file":921,"line":922},"unitrack\u002Fdata\u002Ftracklets.py",78,{"id":924,"kind":388,"path":925,"signature":686,"source":926,"parent":915},"unitrack.Tracklets.__init__",[331,581,405],{"file":921,"line":927},122,{"id":929,"kind":355,"path":930,"signature":932,"summary":933,"source":934,"parent":915},"unitrack.Tracklets.id",[331,581,931],"id","id: torch.Tensor","``int64`` shape ``(N,)`` tracklet IDs.",{"file":921,"line":774},{"id":936,"kind":355,"path":937,"signature":938,"summary":939,"source":940,"parent":915},"unitrack.Tracklets.status",[331,581,250],"status: torch.Tensor","``int8`` shape ``(N,)`` lifecycle status codes.",{"file":921,"line":941},139,{"id":943,"kind":355,"path":944,"signature":946,"summary":947,"source":948,"parent":915},"unitrack.Tracklets.hits",[331,581,945],"hits","hits: torch.Tensor","``int32`` shape ``(N,)`` cumulative match counts.",{"file":921,"line":795},{"id":950,"kind":355,"path":951,"signature":953,"summary":954,"source":955,"parent":915},"unitrack.Tracklets.time_since_update",[331,581,952],"time_since_update","time_since_update: torch.Tensor","``int32`` shape ``(N,)`` frames since the last match.",{"file":921,"line":956},149,{"id":958,"kind":355,"path":959,"signature":961,"summary":962,"source":963,"parent":915},"unitrack.Tracklets.age",[331,581,960],"age","age: torch.Tensor","``int32`` shape ``(N,)`` total ages in frames.",{"file":921,"line":964},154,{"id":966,"kind":355,"path":967,"signature":969,"summary":970,"source":971,"parent":915},"unitrack.Tracklets.frame_started",[331,581,968],"frame_started","frame_started: torch.Tensor","``int32`` shape ``(N,)`` frame indices at creation.",{"file":921,"line":972},159,{"id":974,"kind":355,"path":975,"signature":977,"summary":978,"source":979,"parent":915},"unitrack.Tracklets.frame_last_seen",[331,581,976],"frame_last_seen","frame_last_seen: torch.Tensor","``int32`` shape ``(N,)`` frame indices of the last match.",{"file":921,"line":980},164,{"id":982,"kind":388,"path":983,"signature":984,"summary":985,"params":986,"returns":993,"source":995,"parent":915},"unitrack.Tracklets.empty",[331,581,699],"@classmethod\ndef empty(cls, device: torch.types.Device | None = None, user_fields: dict[str, torch.Tensor] | None = None) -> Tracklets","Construct a zero-row Tracklets snapshot.",[987,989],{"name":484,"type":485,"default":486,"doc":988},"Device for the zero-row reserved tensors. ``None`` selects\nthe default device.",{"name":990,"type":991,"default":486,"doc":992},"user_fields","dict[str, torch.Tensor] | None","Mapping from user-field name to a zero-row tensor template.\nEach value supplies the dtype and trailing shape for that\nfield.",{"type":581,"doc":994},"A :class:`~unitrack.data.Tracklets` with ``batch_size=[0]``, all reserved\nfields zero-initialised, and the supplied user fields\nattached.",{"file":921,"line":996},179,{"id":998,"kind":344,"path":999,"signature":1001,"summary":1002,"source":1003,"parent":331},"unitrack.ConfirmedOnly",[331,1000],"ConfirmedOnly","class ConfirmedOnly:","Return IDs for Active tracklets that were matched this frame.",{"file":1004,"line":1005},"unitrack\u002Flifecycle\u002Fvisibility.py",33,{"id":1007,"kind":388,"path":1008,"signature":1010,"summary":1011,"source":1012,"parent":998},"unitrack.ConfirmedOnly.__call__",[331,1000,1009],"__call__","def __call__(self, cs: Tracklets, match: MatchOutcome) -> torch.Tensor","Return IDs of Active, matched tracklets.",{"file":1004,"line":742},{"id":1014,"kind":388,"path":1015,"signature":1016,"source":1017,"parent":998},"unitrack.ConfirmedOnly.__init__",[331,1000,405],"def __init__(self) -> None",{"file":1004,"line":341},{"id":1019,"kind":344,"path":1020,"signature":1022,"summary":1023,"source":1024,"parent":331},"unitrack.IncludeAll",[331,1021],"IncludeAll","class IncludeAll:","Return every live tracklet's ID.",{"file":1004,"line":1025},23,{"id":1027,"kind":388,"path":1028,"signature":1010,"summary":1029,"source":1030,"parent":1019},"unitrack.IncludeAll.__call__",[331,1021,1009],"Return the IDs of all tracklets.",{"file":1004,"line":1031},27,{"id":1033,"kind":388,"path":1034,"signature":1016,"source":1035,"parent":1019},"unitrack.IncludeAll.__init__",[331,1021,405],{"file":1004,"line":341},{"id":1037,"kind":344,"path":1038,"signature":1040,"summary":1041,"source":1042,"parent":331},"unitrack.IncludeTentative",[331,1039],"IncludeTentative","class IncludeTentative:","Return IDs for Active or Tentative tracklets matched this frame.",{"file":1004,"line":842},{"id":1044,"kind":388,"path":1045,"signature":1010,"summary":1046,"source":1047,"parent":1037},"unitrack.IncludeTentative.__call__",[331,1039,1009],"Return IDs of Active or Tentative matched tracklets.",{"file":1004,"line":1048},48,{"id":1050,"kind":388,"path":1051,"signature":1016,"source":1052,"parent":1037},"unitrack.IncludeTentative.__init__",[331,1039,405],{"file":1004,"line":341},{"id":1054,"kind":344,"path":1055,"signature":1057,"summary":1058,"source":1059,"parent":331},"unitrack.NoLifecycle",[331,1056],"NoLifecycle","class NoLifecycle:","No-op policy. Tracklets stay in whatever status they entered with.",{"file":1060,"line":1061},"unitrack\u002Flifecycle\u002Fpolicies.py",117,{"id":1063,"kind":388,"path":1064,"signature":1065,"summary":1066,"source":1067,"parent":1054},"unitrack.NoLifecycle.__call__",[331,1056,1009],"def __call__(self, cs: Tracklets, match: MatchOutcome, ctx: FrameContext) -> Tracklets","Stamp frame_last_seen on matched rows; otherwise unchanged.",{"file":1060,"line":1068},121,{"id":1070,"kind":388,"path":1071,"signature":1016,"source":1072,"parent":1054},"unitrack.NoLifecycle.__init__",[331,1056,405],{"file":1060,"line":341},{"id":1074,"kind":344,"path":1075,"signature":1077,"summary":1078,"description":1079,"source":1080,"parent":331},"unitrack.StandardLifecycle",[331,1076],"StandardLifecycle","class StandardLifecycle:","Standard tracklet lifecycle policy.","Transitions per frame (in order):\n\n- Tentative + match → Active when ``hits >= min_hits``.\n- Tentative + miss → Removed when ``age >= grace_period`` (default 0:\n  immediate removal). With ``grace_period > 0`` a fresh Tentative that\n  misses on its first few frames stays Tentative until the grace window\n  expires, which gives the matcher a chance to recover a flickering\n  detection.\n- Lost + match within ``allow_reid`` → Active (re-id promotion).\n- Active + ``tsu > max_age`` → Lost.\n- Lost beyond ``max_age + allow_reid`` → Removed.\n\nAll transitions take effect before the Removed rows are filtered out.",{"file":1060,"line":1081},131,{"id":1083,"kind":355,"path":1084,"signature":1086,"source":1087,"parent":1074},"unitrack.StandardLifecycle.min_hits",[331,1076,1085],"min_hits","min_hits: int",{"file":1060,"line":1088},151,{"id":1090,"kind":355,"path":1091,"signature":1093,"source":1094,"parent":1074},"unitrack.StandardLifecycle.max_age",[331,1076,1092],"max_age","max_age: int",{"file":1060,"line":1095},152,{"id":1097,"kind":355,"path":1098,"signature":1100,"source":1101,"parent":1074},"unitrack.StandardLifecycle.grace_period",[331,1076,1099],"grace_period","grace_period: int = 0",{"file":1060,"line":1102},153,{"id":1104,"kind":355,"path":1105,"signature":1107,"source":1108,"parent":1074},"unitrack.StandardLifecycle.allow_reid",[331,1076,1106],"allow_reid","allow_reid: int = 0",{"file":1060,"line":964},{"id":1110,"kind":388,"path":1111,"signature":1065,"summary":1112,"source":1113,"parent":1074},"unitrack.StandardLifecycle.__call__",[331,1076,1009],"Apply lifecycle transitions and filter out Removed tracklets.",{"file":1060,"line":1114},156,{"id":1116,"kind":388,"path":1117,"signature":1118,"source":1119,"parent":1074},"unitrack.StandardLifecycle.__init__",[331,1076,405],"def __init__(self, min_hits: int, max_age: int, grace_period: int = 0, allow_reid: int = 0) -> None",{"file":1060,"line":341},{"id":1121,"kind":344,"path":1122,"signature":1124,"summary":1125,"source":1126,"parent":331},"unitrack.TrackletStatus",[331,1123],"TrackletStatus","class TrackletStatus(enum.IntEnum):","Lifecycle state of a tracklet.",{"file":1127,"line":1128},"unitrack\u002Flifecycle\u002Fstatus.py",14,{"id":1130,"kind":355,"path":1131,"signature":1133,"source":1134,"parent":1121},"unitrack.TrackletStatus.Tentative",[331,1123,1132],"Tentative","Tentative = 0",{"file":1127,"line":1135},17,{"id":1137,"kind":355,"path":1138,"signature":1140,"source":1141,"parent":1121},"unitrack.TrackletStatus.Active",[331,1123,1139],"Active","Active = 1",{"file":1127,"line":1142},18,{"id":1144,"kind":355,"path":1145,"signature":1147,"source":1148,"parent":1121},"unitrack.TrackletStatus.Lost",[331,1123,1146],"Lost","Lost = 2",{"file":1127,"line":1149},19,{"id":1151,"kind":355,"path":1152,"signature":1154,"source":1155,"parent":1121},"unitrack.TrackletStatus.Removed",[331,1123,1153],"Removed","Removed = 3",{"file":1127,"line":1156},20,{"id":1158,"kind":344,"path":1159,"signature":1161,"summary":1162,"description":1163,"source":1164,"parent":331},"unitrack.Associator",[331,1160],"Associator","class Associator(typing.Protocol):","Stage that emits a :class:`~unitrack.data.MatchOutcome`.","``ctx`` is threaded through every associator call site by the\nTracker and forwarded by combinators (:class:`Pipe`,\n:class:`Sequential`, :class:`Iterate`, :class:`Filter`,\n:class:`Gated`) so nested cost \u002F gate producers can read it (e.g.\nfor time-aware covariance scaling in\n:class:`~unitrack.costs.Mahalanobis` or\n:class:`~unitrack.gates.MotionGate`). Leaf associators that do not\nneed frame context may ignore the argument; the parameter exists\nfor forward extensibility (annealed thresholds, per-frame\ntelemetry) and to keep stage-tree composition uniform.",{"file":1165,"line":1166},"unitrack\u002Fpipeline\u002Fbase.py",92,{"id":1168,"kind":388,"path":1169,"signature":1170,"summary":1171,"params":1172,"returns":1185,"source":1187,"parent":1158},"unitrack.Associator.__call__",[331,1160,1009],"def __call__(self, cs: Tracklets, ds: Detections, ctx: FrameContext, cost: CostExpression | None = None) -> MatchOutcome","Run the assignment.",[1173,1176,1179,1182],{"name":1174,"type":581,"doc":1175},"cs","Tracklet snapshot with ``N`` rows.",{"name":1177,"type":394,"doc":1178},"ds","Detection record with ``M`` rows.",{"name":1180,"type":452,"doc":1181},"ctx","Frame context.",{"name":203,"type":1183,"default":486,"doc":1184},"CostExpression | None","Optional pre-computed cost expression from an enclosing\nstage. Leaf associators that produce their own cost ignore\nthis argument.",{"type":824,"doc":1186},"Matched pairs and residual indices into ``cs`` \u002F ``ds``.",{"file":1165,"line":1188},109,{"id":1190,"kind":344,"path":1191,"signature":1193,"summary":1194,"source":1195,"parent":331},"unitrack.CostProducer",[331,1192],"CostProducer","class CostProducer(typing.Protocol):","Leaf stage that emits a :class:`~unitrack.data.CostExpression`.",{"file":1165,"line":1196},60,{"id":1198,"kind":388,"path":1199,"signature":1200,"summary":1201,"params":1202,"returns":1208,"source":1210,"parent":1190},"unitrack.CostProducer.__call__",[331,1192,1009],"def __call__(self, cs: Tracklets, ds: Detections, ctx: FrameContext) -> CostExpression","Compute the cost expression.",[1203,1205,1207],{"name":1174,"type":581,"doc":1204},"Tracklet snapshot.",{"name":1177,"type":394,"doc":1206},"Detection record.",{"name":1180,"type":452,"doc":1181},{"type":596,"doc":1209},"``(N, M)`` cost matrix with optional un-applied gates and\nbias.",{"file":1165,"line":1211},64,{"id":1213,"kind":344,"path":1214,"signature":1216,"summary":1217,"description":1218,"source":1219,"parent":331},"unitrack.Filter",[331,1215],"Filter","class Filter:","Drop rows from ``cs`` and\u002For ``ds`` before a wrapped child runs.","The wrapped child's :class:`~unitrack.data.MatchOutcome` indices are lifted back to\nthe original (unfiltered) row space and the filtered-out rows are\nappended to the residual list, so the caller sees them as simply\nunmatched.",{"file":1220,"line":1221},"unitrack\u002Fpipeline\u002Fcombinators.py",392,{"id":1223,"kind":355,"path":1224,"signature":1226,"source":1227,"parent":1213},"unitrack.Filter.predicate",[331,1215,1225],"predicate","predicate: typing.Any",{"file":1220,"line":1228},416,{"id":1230,"kind":355,"path":1231,"signature":1233,"source":1234,"parent":1213},"unitrack.Filter.then",[331,1215,1232],"then","then: typing.Any",{"file":1220,"line":1235},417,{"id":1237,"kind":355,"path":1238,"signature":1240,"source":1241,"parent":1213},"unitrack.Filter.on",[331,1215,1239],"on","on: typing.Literal['cs', 'ds', 'both'] = 'cs'",{"file":1220,"line":1242},418,{"id":1244,"kind":388,"path":1245,"signature":1170,"summary":1246,"params":1247,"returns":1254,"source":1256,"parent":1213},"unitrack.Filter.__call__",[331,1215,1009],"Run the predicate, the child, and lift indices back.",[1248,1250,1251,1252],{"name":1174,"type":581,"doc":1249},"Forwarded to the child after filtering.",{"name":1177,"type":581,"doc":1249},{"name":1180,"type":581,"doc":1249},{"name":203,"type":1183,"default":486,"doc":1253},"Optional upstream cost; forwarded to the child unchanged\nwhen present.",{"type":824,"doc":1255},"The child's outcome with indices remapped into the\nunfiltered row space and filtered-out rows appended as\nresiduals.",{"file":1220,"line":1257},441,{"id":1259,"kind":388,"path":1260,"signature":1261,"source":1262,"parent":1213},"unitrack.Filter.__init__",[331,1215,405],"def __init__(self, predicate: typing.Any, then: typing.Any, on: typing.Literal['cs', 'ds', 'both'] = 'cs') -> None",{"file":1220,"line":341},{"id":1264,"kind":344,"path":1265,"signature":1267,"summary":1268,"description":1269,"source":1270,"parent":331},"unitrack.Gated",[331,1266],"Gated","class Gated:","Wrap a stage with a gate that projects the input or biases the cost.","Per-side gates (``PerCs``, ``PerDs``) drop rows of ``cs`` \u002F ``ds``\nbefore the child runs; pair and cost-bias gates attach to the\ndownstream :class:`~unitrack.data.CostExpression`.",{"file":1220,"line":1271},620,{"id":1273,"kind":355,"path":1274,"signature":1275,"source":1276,"parent":1264},"unitrack.Gated.gate",[331,1266,212],"gate: typing.Any",{"file":1220,"line":1277},639,{"id":1279,"kind":355,"path":1280,"signature":1233,"source":1281,"parent":1264},"unitrack.Gated.then",[331,1266,1232],{"file":1220,"line":1282},640,{"id":1284,"kind":388,"path":1285,"signature":1170,"summary":1286,"params":1287,"returns":1294,"source":1296,"parent":1264},"unitrack.Gated.__call__",[331,1266,1009],"Evaluate the gate and dispatch on its variant.",[1288,1290,1291,1292],{"name":1174,"type":581,"doc":1289},"Forwarded to the gate and to :attr:`then`.",{"name":1177,"type":581,"doc":1289},{"name":1180,"type":581,"doc":1289},{"name":203,"type":1183,"default":486,"doc":1293},"Optional upstream cost. For per-pair \u002F cost-bias gates with\na non-Pipe body, the cost is gated and forwarded to the\nbody.",{"type":824,"doc":1295},"The body's outcome with indices lifted back to the original\nrow space when a per-side gate dropped rows.",{"file":1220,"line":1297},656,{"id":1299,"kind":388,"path":1300,"signature":1301,"source":1302,"parent":1264},"unitrack.Gated.__init__",[331,1266,405],"def __init__(self, gate: typing.Any, then: typing.Any) -> None",{"file":1220,"line":341},{"id":1304,"kind":344,"path":1305,"signature":1307,"summary":1308,"source":1309,"parent":331},"unitrack.GateProducer",[331,1306],"GateProducer","class GateProducer(typing.Protocol):","Leaf stage that emits a :class:`~unitrack.data.Gate`.",{"file":1165,"line":891},{"id":1311,"kind":388,"path":1312,"signature":1313,"summary":1314,"params":1315,"returns":1319,"source":1321,"parent":1304},"unitrack.GateProducer.__call__",[331,1306,1009],"def __call__(self, cs: Tracklets, ds: Detections, ctx: FrameContext) -> Gate","Compute the gate.",[1316,1317,1318],{"name":1174,"type":581,"doc":1204},{"name":1177,"type":394,"doc":1206},{"name":1180,"type":452,"doc":1181},{"type":768,"doc":1320},"Per-pair, per-tracklet, per-detection, or cost-bias gate.",{"file":1165,"line":1005},{"id":1323,"kind":344,"path":1324,"signature":1326,"summary":1327,"source":1328,"parent":331},"unitrack.Iterate",[331,1325],"Iterate","class Iterate:","Repeat a body stage ``n`` times against accumulating residuals.",{"file":1220,"line":1329},500,{"id":1331,"kind":355,"path":1332,"signature":1334,"source":1335,"parent":1323},"unitrack.Iterate.n",[331,1325,1333],"n","n: int",{"file":1220,"line":1336},514,{"id":1338,"kind":355,"path":1339,"signature":1341,"source":1342,"parent":1323},"unitrack.Iterate.body",[331,1325,1340],"body","body: typing.Any",{"file":1220,"line":1343},515,{"id":1345,"kind":388,"path":1346,"signature":1170,"summary":1347,"params":1348,"returns":1355,"source":1357,"parent":1323},"unitrack.Iterate.__call__",[331,1325,1009],"Run :attr:`body` ``n`` times, cascading residuals across iterations.",[1349,1351,1352,1353],{"name":1174,"type":581,"doc":1350},"Forwarded to the body each iteration.",{"name":1177,"type":581,"doc":1350},{"name":1180,"type":581,"doc":1350},{"name":203,"type":1183,"default":486,"doc":1354},"Optional upstream cost (e.g. a gate-attached cost from a\nwrapping :class:`Gated`). Forwarded to the first iteration\nonly; subsequent iterations operate on residuals and build\ntheir own cost expressions because the original full-size\ncost would shape-mismatch.",{"type":824,"doc":1356},"Aggregated matched pairs and remaining residuals, lifted\nback to the original ``cs`` \u002F ``ds`` row space.",{"file":1220,"line":1358},536,{"id":1360,"kind":388,"path":1361,"signature":1362,"source":1363,"parent":1323},"unitrack.Iterate.__init__",[331,1325,405],"def __init__(self, n: int, body: typing.Any) -> None",{"file":1220,"line":341},{"id":1365,"kind":344,"path":1366,"signature":1368,"summary":1369,"source":1370,"parent":331},"unitrack.Parallel",[331,1367],"Parallel","class Parallel:","Cost-level merge of ``K`` branches into one :class:`~unitrack.data.CostExpression`.",{"file":1220,"line":1371},808,{"id":1373,"kind":355,"path":1374,"signature":1376,"source":1377,"parent":1365},"unitrack.Parallel.children",[331,1367,1375],"children","children: list",{"file":1220,"line":1378},824,{"id":1380,"kind":355,"path":1381,"signature":1382,"source":1383,"parent":1365},"unitrack.Parallel.merge",[331,1367,267],"merge: typing.Any",{"file":1220,"line":1384},825,{"id":1386,"kind":388,"path":1387,"signature":1200,"summary":1388,"params":1389,"returns":1394,"source":1396,"parent":1365},"unitrack.Parallel.__call__",[331,1367,1009],"Run every child and reduce their cost expressions.",[1390,1392,1393],{"name":1174,"type":581,"doc":1391},"Forwarded to every child.",{"name":1177,"type":581,"doc":1391},{"name":1180,"type":581,"doc":1391},{"type":596,"doc":1395},"The merged ``(N, M)`` cost expression.",{"file":1220,"line":1397},843,{"id":1399,"kind":388,"path":1400,"signature":1401,"source":1402,"parent":1365},"unitrack.Parallel.__init__",[331,1367,405],"def __init__(self, children: list, merge: typing.Any) -> None",{"file":1220,"line":341},{"id":1404,"kind":344,"path":1405,"signature":1407,"summary":1408,"description":1409,"source":1410,"parent":331},"unitrack.Pipe",[331,1406],"Pipe","class Pipe:","Feed a :class:`~unitrack.pipeline.CostProducer` into an associator as one stage.","The cost producer builds a :class:`~unitrack.data.CostExpression`,\nwhich is handed to the associator alongside the original\n``(cs, ds, ctx)``.",{"file":1220,"line":1411},57,{"id":1413,"kind":355,"path":1414,"signature":1415,"source":1416,"parent":1404},"unitrack.Pipe.cost",[331,1406,203],"cost: CostProducer",{"file":1220,"line":1417},75,{"id":1419,"kind":355,"path":1420,"signature":1422,"source":1423,"parent":1404},"unitrack.Pipe.assoc",[331,1406,1421],"assoc","assoc: Associator",{"file":1220,"line":360},{"id":1425,"kind":388,"path":1426,"signature":1170,"summary":1427,"params":1428,"returns":1435,"source":1437,"parent":1404},"unitrack.Pipe.__call__",[331,1406,1009],"Run the cost producer then the associator.",[1429,1431,1432,1433],{"name":1174,"type":581,"doc":1430},"Forwarded to both children.",{"name":1177,"type":581,"doc":1430},{"name":1180,"type":581,"doc":1430},{"name":203,"type":1183,"default":486,"doc":1434},"Ignored: a :class:`Pipe` owns its cost stage. The parameter\nexists so :class:`Pipe` satisfies the :class:`~unitrack.pipeline.Associator`\nsignature.",{"type":824,"doc":1436},"The associator's output.",{"file":1220,"line":1438},95,{"id":1440,"kind":388,"path":1441,"signature":1442,"source":1443,"parent":1404},"unitrack.Pipe.__init__",[331,1406,405],"def __init__(self, cost: CostProducer, assoc: Associator) -> None",{"file":1220,"line":341},{"id":1445,"kind":344,"path":1446,"signature":1448,"summary":1449,"source":1450,"parent":331},"unitrack.PipelineTypeError",[331,1447],"PipelineTypeError","class PipelineTypeError(TypeError):","Raised at stage-tree construction when the typed-tree contract is violated.",{"file":1165,"line":1451},218,{"id":1453,"kind":388,"path":1454,"signature":1455,"source":1456,"parent":1445},"unitrack.PipelineTypeError.__init__",[331,1447,405],"def __init__(self, message: str, path: list[str] | None = None)",{"file":1165,"line":1457},230,{"id":1459,"kind":355,"path":1460,"signature":1462,"source":1463,"parent":1445},"unitrack.PipelineTypeError.path",[331,1447,1461],"path","path = list(path) if path else []",{"file":1165,"line":1464},231,{"id":1466,"kind":344,"path":1467,"signature":1469,"summary":1470,"description":1471,"params":1472,"source":1480,"parent":331},"unitrack.Sequential",[331,1468],"Sequential","class Sequential:","Chain stages of the same output type.","For ``T = MatchOutcome`` (the cascade), each child consumes the\nprevious child's residuals. For ``T = Gate``, children are folded\npointwise via :meth:`~unitrack.data.Gate.combine`.\n``Sequential[CostExpression]`` is rejected; use :class:`Parallel`\nfor cost-level merge.",[1473,1476],{"name":1375,"type":1474,"doc":1475},"list","Stages of one output kind.",{"name":1477,"type":1478,"default":486,"doc":1479},"expected_kind","str | None","Internal flag bound by the subscript. ``None`` when\n:class:`Sequential` is constructed without a subscript; classified\nfrom the children in that case.",{"file":1220,"line":1481},174,{"id":1483,"kind":388,"path":1484,"signature":1485,"summary":1486,"params":1487,"raises":1492,"source":1497,"parent":1466},"unitrack.Sequential.__init__",[331,1468,405],"def __init__(self, children: list, expected_kind: str | None = None) -> None","Validate that ``children`` share one output kind.",[1488,1490],{"name":1375,"type":1474,"doc":1489},"Child stages; must be non-empty.",{"name":1477,"type":1478,"default":486,"doc":1491},"Optional pre-bound kind (``\"match\"`` or ``\"gate\"``) from the\nclass subscript.",[1493,1495],{"type":398,"doc":1494},"If ``children`` is empty.",{"type":1447,"doc":1496},"If children mix kinds or the inferred kind disagrees with\n``expected_kind``.",{"file":1220,"line":1498},224,{"id":1500,"kind":355,"path":1501,"signature":1503,"source":1504,"parent":1466},"unitrack.Sequential.kind",[331,1468,1502],"kind","kind = kind",{"file":1220,"line":1505},264,{"id":1507,"kind":355,"path":1508,"signature":1509,"source":1510,"parent":1466},"unitrack.Sequential.children",[331,1468,1375],"children = list(children)",{"file":1220,"line":1511},265,{"id":1513,"kind":388,"path":1514,"signature":1515,"summary":1516,"params":1517,"returns":1524,"source":1527,"parent":1466},"unitrack.Sequential.__call__",[331,1468,1009],"def __call__(self, cs: Tracklets, ds: Detections, ctx: FrameContext, cost: CostExpression | None = None) -> MatchOutcome | Gate","Run every child in sequence.",[1518,1520,1521,1522],{"name":1174,"type":581,"doc":1519},"Forwarded to each child.",{"name":1177,"type":581,"doc":1519},{"name":1180,"type":581,"doc":1519},{"name":203,"type":1183,"default":486,"doc":1523},"Optional upstream cost. Passed only to the first cascade\nstage (subsequent stages operate on residuals with their\nown costs). Ignored on a gate cascade.",{"type":1525,"doc":1526},"MatchOutcome or Gate","On a match cascade, a single :class:`~unitrack.data.MatchOutcome` lifted to\nthe original ``cs`` \u002F ``ds`` row space. On a gate cascade,\nthe pointwise combination of children's gates.",{"file":1220,"line":1528},267,{"id":1530,"kind":355,"path":1531,"signature":1533,"source":1534,"parent":331},"unitrack.Stage",[331,1532],"Stage","Stage = GateProducer | CostProducer | Associator",{"file":1165,"line":788},{"id":1536,"kind":344,"path":1537,"signature":1539,"summary":1540,"description":1541,"source":1542,"parent":331},"unitrack.AutoForkOnNewKey",[331,1538],"AutoForkOnNewKey","class AutoForkOnNewKey:","Lazily fork a fresh memory on first sight of a key.","Any sequence of keys, including interleaved access, is accepted.",{"file":1543,"line":913},"unitrack\u002Ftracker\u002Fmultistream.py",{"id":1545,"kind":388,"path":1546,"signature":1548,"summary":1549,"source":1550,"parent":1536},"unitrack.AutoForkOnNewKey.observe",[331,1538,1547],"observe","def observe(self, key: int | str) -> None","Accept any ``key`` without restriction.",{"file":1543,"line":616},{"id":1552,"kind":388,"path":1553,"signature":1555,"summary":1556,"source":1557,"parent":1536},"unitrack.AutoForkOnNewKey.forget",[331,1538,1554],"forget","def forget(self, key: int | str) -> None","No-op: this policy holds no per-key state.",{"file":1543,"line":842},{"id":1559,"kind":388,"path":1560,"signature":1016,"source":1561,"parent":1536},"unitrack.AutoForkOnNewKey.__init__",[331,1538,405],{"file":1543,"line":341},{"id":1563,"kind":344,"path":1564,"signature":1566,"summary":1567,"description":1568,"source":1569,"parent":331},"unitrack.BatchTracker",[331,1565],"BatchTracker","class BatchTracker:","Run multiple streams' :meth:`~unitrack.tracker.Tracker.step` calls together.","Two execution paths run side by side. The default loop path makes\nper-slot calls to :meth:`~unitrack.tracker.Tracker.step`; it works for any root,\nlifecycle, and shape configuration. The fast path engages when\n:meth:`is_vmap_safe` holds and the tracker root is a single\n:class:`~unitrack.pipeline.Pipe` wrapping an\n:class:`~unitrack.assignment.Associate`: per-slot cost matrices are\ndispatched together to\n:func:`~unitrack.assignment.auto_batch_assignment`. Cost\ncomputation, observation, and merge still run per slot; only the\nLAP solve — the expensive part for typical ``N`` — is batched. The\nfast path is a strict optimisation and produces identical\n:class:`StepResult` values to the loop path; the conformance test\n``tests\u002Funitrack\u002Ftracker\u002Ftest_batch_lifecycle.py`` locks this in.",{"file":1570,"line":1571},"unitrack\u002Ftracker\u002Fbatch.py",31,{"id":1573,"kind":355,"path":1574,"signature":1575,"source":1576,"parent":1563},"unitrack.BatchTracker.tracker",[331,1565,173],"tracker: Tracker",{"file":1570,"line":1577},59,{"id":1579,"kind":355,"path":1580,"signature":1582,"source":1583,"parent":1563},"unitrack.BatchTracker.batch_size",[331,1565,1581],"batch_size","batch_size: int",{"file":1570,"line":1196},{"id":1585,"kind":388,"path":1586,"signature":1588,"summary":1589,"source":1590,"parent":1563},"unitrack.BatchTracker.snapshot_of",[331,1565,1587],"snapshot_of","def snapshot_of(self, slot: int) -> Tracklets","Return the current :class:`~unitrack.data.Tracklets` for ``slot``.",{"file":1570,"line":1591},83,{"id":1593,"kind":388,"path":1594,"signature":1596,"summary":1597,"params":1598,"source":1603,"parent":1563},"unitrack.BatchTracker.reset",[331,1565,1595],"reset","def reset(self, slot: int | None = None) -> None","Reset one or all slots to their empty state.",[1599],{"name":1600,"type":1601,"default":486,"doc":1602},"slot","int | None","Slot index to reset, or ``None`` to reset every slot.",{"file":1570,"line":1604},87,{"id":1606,"kind":388,"path":1607,"signature":1609,"summary":1610,"params":1611,"returns":1616,"source":1619,"parent":1563},"unitrack.BatchTracker.is_vmap_safe",[331,1565,1608],"is_vmap_safe","def is_vmap_safe(self, detections_per_slot: list[Detections]) -> bool","Return ``True`` iff this batch can use the batched-solve fast path.",[1612],{"name":1613,"type":1614,"doc":1615},"detections_per_slot","list[Detections]","Per-slot detections for this step.",{"type":1617,"doc":1618},"bool","``True`` only when (a) lifecycle is :class:`~unitrack.lifecycle.NoLifecycle`\n(row-removal would diverge per-slot ``N``), (b) detection\ncounts match across slots, (c) tracklet counts match across\nsnapshots, and (d) the root is shaped as\n``Pipe(cost, Associate(...))`` so the cost expression can\nbe intercepted between cost-production and the LAP solve.",{"file":1570,"line":401},{"id":1621,"kind":388,"path":1622,"signature":1624,"summary":1625,"params":1626,"returns":1633,"raises":1636,"source":1639,"parent":1563},"unitrack.BatchTracker.step",[331,1565,1623],"step","def step(self, detections_per_slot: list[Detections], ctx_per_slot: list[FrameContext]) -> list[StepResult]","Advance every slot by one frame.",[1627,1629],{"name":1613,"type":1614,"doc":1628},"Per-slot detections; length must equal :attr:`batch_size`.",{"name":1630,"type":1631,"doc":1632},"ctx_per_slot","list[FrameContext]","Per-slot frame contexts; length must equal\n:attr:`batch_size`.",{"type":1634,"doc":1635},"list of StepResult","One entry per slot, in slot order. The fast path is\nselected automatically when ``_can_dispatch_batched``\nholds.",[1637],{"type":398,"doc":1638},"If the input list lengths disagree with :attr:`batch_size`.",{"file":1570,"line":1640},148,{"id":1642,"kind":388,"path":1643,"signature":1645,"summary":1646,"description":1647,"params":1648,"returns":1653,"raises":1656,"source":1660,"parent":1563},"unitrack.BatchTracker.predict_and_cost_vmap",[331,1565,1644],"predict_and_cost_vmap","def predict_and_cost_vmap(self, detections_per_slot: list[Detections], ctx_per_slot: list[FrameContext]) -> tuple[list[Tracklets], list[torch.Tensor]]","Run the predict and cost-production phase via :func:`torch.func.vmap`.","Per-slot snapshots, detections, and contexts are stacked along\na new leading slot dim with :func:`tensordict.stack`; the\npredict-plus-cost work is then traced under ``torch.func.vmap``.",[1649,1651],{"name":1613,"type":1614,"doc":1650},"Per-slot detections.",{"name":1630,"type":1631,"doc":1652},"Per-slot frame contexts.",{"type":1654,"doc":1655},"tuple","``(predicted_per_slot, materialized)`` where the first\nelement is a list of per-slot predicted :class:`~unitrack.data.Tracklets`\nand the second is a list of per-slot materialised ``(N, M)``\ncost tensors.",[1657],{"type":1658,"doc":1659},"TypeError","If the underlying root is not ``Pipe(_, Associate)`` or if\nvmap cannot trace the stage tree.",{"file":1570,"line":1661},281,{"id":1663,"kind":388,"path":1664,"signature":1665,"source":1666,"parent":1563},"unitrack.BatchTracker.__init__",[331,1565,405],"def __init__(self, tracker: Tracker, batch_size: int) -> None",{"file":1570,"line":341},{"id":1668,"kind":344,"path":1669,"signature":1671,"summary":1672,"description":1673,"source":1674,"parent":331},"unitrack.ClipTracker",[331,1670],"ClipTracker","class ClipTracker:","Wrap a :class:`~unitrack.tracker.Tracker` for clip-level inference.","In ``mode='per_frame'``, :meth:`~unitrack.tracker.Tracker.step` iterates over the\n``K`` clip frames. In ``mode='refine'``, a learned refiner module\nruns over the aligned :class:`~unitrack.data.ClipTracklets` after the per-frame\npass. The output :class:`~unitrack.data.ClipTracklets` has rows aligned by\nidentity (row ``n`` at frame ``k`` is the same tracklet as row ``n``\nat frame ``k + 1``); rows are padded with synthetic Removed\nplaceholders when a tracklet did not exist in a given frame's raw\nsnapshot, so refiners can index across frames without an ID lookup.",{"file":1675,"line":1676},"unitrack\u002Ftracker\u002Fclip.py",24,{"id":1678,"kind":355,"path":1679,"signature":1575,"source":1680,"parent":1668},"unitrack.ClipTracker.tracker",[331,1670,173],{"file":1675,"line":1681},54,{"id":1683,"kind":355,"path":1684,"signature":1686,"source":1687,"parent":1668},"unitrack.ClipTracker.mode",[331,1670,1685],"mode","mode: typing.Literal['per_frame', 'refine'] = 'per_frame'",{"file":1675,"line":1688},55,{"id":1690,"kind":355,"path":1691,"signature":1693,"source":1694,"parent":1668},"unitrack.ClipTracker.refiner",[331,1670,1692],"refiner","refiner: typing.Any | None = None",{"file":1675,"line":352},{"id":1696,"kind":355,"path":1697,"signature":1699,"source":1700,"parent":1668},"unitrack.ClipTracker.reset_per_clip",[331,1670,1698],"reset_per_clip","reset_per_clip: bool = False",{"file":1675,"line":1411},{"id":1702,"kind":388,"path":1703,"signature":1705,"summary":1706,"params":1707,"returns":1717,"raises":1719,"source":1722,"parent":1668},"unitrack.ClipTracker.process_clip",[331,1670,1704],"process_clip","def process_clip(self, snapshot: Tracklets, clip_dets: ClipDetections, clip_ctx: ClipFrameContext) -> tuple[Tracklets, ClipTracklets, ClipMatchOutcome]","Run one clip through the tracker.",[1708,1711,1714],{"name":1709,"type":581,"doc":1710},"snapshot","Initial :class:`~unitrack.data.Tracklets` snapshot. Ignored when\n:attr:`reset_per_clip` is ``True``.",{"name":1712,"type":346,"doc":1713},"clip_dets","Per-frame :class:`~unitrack.data.ClipDetections`.",{"name":1715,"type":411,"doc":1716},"clip_ctx","Per-frame :class:`~unitrack.data.ClipFrameContext`.",{"type":1654,"doc":1718},"``(final_snapshot, clip_tracklets, clip_match_outcome)``\nwhere ``final_snapshot`` is the last frame's snapshot (or\nthe refined last frame in ``refine`` mode),\n``clip_tracklets`` carries identity-aligned rows across\nframes, and ``clip_match_outcome`` collects per-frame raw\nmatches.",[1720],{"type":398,"doc":1721},"If ``mode='refine'`` but :attr:`refiner` is ``None``.",{"file":1675,"line":1577},{"id":1724,"kind":388,"path":1725,"signature":1726,"source":1727,"parent":1668},"unitrack.ClipTracker.__init__",[331,1670,405],"def __init__(self, tracker: Tracker, mode: typing.Literal['per_frame', 'refine'] = 'per_frame', refiner: typing.Any | None = None, reset_per_clip: bool = False) -> None",{"file":1675,"line":341},{"id":1729,"kind":344,"path":1730,"signature":1732,"summary":1733,"source":1734,"parent":331},"unitrack.ForkPolicy",[331,1731],"ForkPolicy","class ForkPolicy(typing.Protocol):","How a :class:`~unitrack.tracker.MultiStream` reacts to a stream key.",{"file":1543,"line":1128},{"id":1736,"kind":388,"path":1737,"signature":1548,"summary":1738,"source":1739,"parent":1729},"unitrack.ForkPolicy.observe",[331,1731,1547],"Update policy state for the given stream ``key``.",{"file":1543,"line":1142},{"id":1741,"kind":388,"path":1742,"signature":1555,"summary":1743,"description":1744,"source":1745,"parent":1729},"unitrack.ForkPolicy.forget",[331,1731,1554],"Drop any state held for ``key``.","Called by :meth:`MultiStream.end_stream`. Implementations that\nhold no per-key state may make this a no-op.",{"file":1543,"line":1746},22,{"id":1748,"kind":344,"path":1749,"signature":1751,"summary":1752,"description":1753,"params":1754,"source":1762,"parent":331},"unitrack.MultiStream",[331,1750],"MultiStream","class MultiStream:","Multi-stream wrapper around a :class:`~unitrack.tracker.Tracker`.","Holds one :class:`TrackletMemory` per stream key. The :class:`ForkPolicy`\ndecides whether a previously-seen key is allowed to be revisited.",[1755,1758],{"name":173,"type":1756,"doc":1757},"Tracker","Underlying :class:`~unitrack.tracker.Tracker`.",{"name":1759,"type":1760,"default":486,"doc":1761},"fork_policy","ForkPolicy | None","Policy for handling stream keys; defaults to\n:class:`AutoForkOnNewKey`.",{"file":1543,"line":1763},91,{"id":1765,"kind":388,"path":1766,"signature":1767,"summary":1768,"source":1769,"parent":1748},"unitrack.MultiStream.__init__",[331,1750,405],"def __init__(self, tracker: Tracker, fork_policy: ForkPolicy | None = None) -> None","See class docstring for parameter semantics.",{"file":1543,"line":1770},108,{"id":1772,"kind":355,"path":1773,"signature":1774,"source":1775,"parent":1748},"unitrack.MultiStream.tracker",[331,1750,173],"tracker = tracker",{"file":1543,"line":1776},114,{"id":1778,"kind":355,"path":1779,"signature":1780,"source":1781,"parent":1748},"unitrack.MultiStream.fork_policy",[331,1750,1759],"fork_policy = fork_policy",{"file":1543,"line":1061},{"id":1783,"kind":388,"path":1784,"signature":1786,"summary":1787,"source":1788,"parent":1748},"unitrack.MultiStream.begin_stream",[331,1750,1785],"begin_stream","def begin_stream(self, key: int | str) -> None","Eagerly create a memory slot for ``key``.",{"file":1543,"line":1789},126,{"id":1791,"kind":388,"path":1792,"signature":1794,"summary":1795,"source":1796,"parent":1748},"unitrack.MultiStream.end_stream",[331,1750,1793],"end_stream","def end_stream(self, key: int | str) -> None","Remove the memory slot for ``key`` and notify the fork policy.",{"file":1543,"line":1797},130,{"id":1799,"kind":388,"path":1800,"signature":1801,"summary":1802,"params":1803,"raises":1808,"source":1812,"parent":1748},"unitrack.MultiStream.reset",[331,1750,1595],"def reset(self, key: int | str | None = None) -> None","Reset one stream or all streams.",[1804],{"name":1805,"type":1806,"default":486,"doc":1807},"key","int | str | None","Stream key to reset, or ``None`` to reset every registered\nstream.",[1809],{"type":1810,"doc":1811},"KeyError","If ``key`` is supplied but has no memory slot.",{"file":1543,"line":1813},135,{"id":1815,"kind":388,"path":1816,"signature":1818,"summary":1819,"source":1820,"parent":1748},"unitrack.MultiStream.has_stream",[331,1750,1817],"has_stream","def has_stream(self, key: int | str) -> bool","Return ``True`` iff a memory slot already exists for ``key``.",{"file":1543,"line":1821},160,{"id":1823,"kind":388,"path":1824,"signature":1825,"summary":1826,"params":1827,"returns":1831,"raises":1834,"source":1837,"parent":1748},"unitrack.MultiStream.snapshot_of",[331,1750,1587],"def snapshot_of(self, key: int | str) -> Tracklets","Return the current snapshot for ``key`` without allocating state.",[1828],{"name":1805,"type":1829,"doc":1830},"int | str","Stream key.",{"type":1832,"doc":1833},"~unitrack.data.Tracklets","Live snapshot for ``key``.",[1835],{"type":1810,"doc":1836},"If ``key`` has no memory slot. A read-only accessor must\nnot silently allocate state; use :meth:`begin_stream` (or\n:meth:`step`, which auto-allocates) to create the slot.",{"file":1543,"line":980},{"id":1839,"kind":388,"path":1840,"signature":1841,"summary":1842,"params":1843,"returns":1849,"source":1852,"parent":1748},"unitrack.MultiStream.step",[331,1750,1623],"def step(self, stream_key: int | str, detections: Detections, ctx: FrameContext) -> StepResult","Advance ``stream_key`` by one frame.",[1844,1846,1848],{"name":478,"type":1829,"doc":1845},"Stream identifier.",{"name":206,"type":394,"doc":1847},"Frame detections.",{"name":1180,"type":452,"doc":1181},{"type":1850,"doc":1851},"StepResult","The tracker's :class:`StepResult` for this frame.",{"file":1543,"line":587},{"id":1854,"kind":344,"path":1855,"signature":1857,"summary":1858,"description":1859,"source":1860,"parent":331},"unitrack.OrderedNoInterleaving",[331,1856],"OrderedNoInterleaving","class OrderedNoInterleaving:","Strict one-stream-at-a-time policy.","Only one stream key may be live at a time. Revisiting an earlier\nkey after a different one took over raises :exc:`ValueError` so\ncallers notice they should be using :class:`AutoForkOnNewKey` or\n:class:`BatchTracker` instead. A key can be revisited cleanly after\n:meth:`MultiStream.end_stream`; :meth:`forget` drops the key from\nthe seen set.",{"file":1543,"line":874},{"id":1862,"kind":388,"path":1863,"signature":1548,"summary":1864,"raises":1865,"source":1868,"parent":1854},"unitrack.OrderedNoInterleaving.observe",[331,1856,1547],"Accept ``key`` only if it is current or never been seen.",[1866],{"type":398,"doc":1867},"If ``key`` was previously seen and a different key has\nsince taken over.",{"file":1543,"line":1869},65,{"id":1871,"kind":388,"path":1872,"signature":1555,"summary":1873,"source":1874,"parent":1854},"unitrack.OrderedNoInterleaving.forget",[331,1856,1554],"Drop ``key`` so a fresh stream can re-open after ``end_stream``.",{"file":1543,"line":377},{"id":1876,"kind":388,"path":1877,"signature":1878,"source":1879,"parent":1854},"unitrack.OrderedNoInterleaving.__init__",[331,1856,405],"def __init__(self, _seen: set[int | str] = set(), _current: int | str | None = None) -> None",{"file":1543,"line":341},{"id":1881,"kind":344,"path":1882,"signature":1883,"summary":1884,"source":1885,"parent":331},"unitrack.StepResult",[331,1850],"class StepResult:","One frame's tracker output.",{"file":1886,"line":1887},"unitrack\u002Ftracker\u002Ftracker.py",180,{"id":1889,"kind":355,"path":1890,"signature":1891,"source":1892,"parent":1881},"unitrack.StepResult.snapshot",[331,1850,1709],"snapshot: Tracklets",{"file":1886,"line":1893},207,{"id":1895,"kind":355,"path":1896,"signature":1897,"source":1898,"parent":1881},"unitrack.StepResult.match",[331,1850,215],"match: MatchOutcome",{"file":1886,"line":1899},208,{"id":1901,"kind":355,"path":1902,"signature":1904,"source":1905,"parent":1881},"unitrack.StepResult.ids",[331,1850,1903],"ids","ids: torch.Tensor",{"file":1886,"line":1906},209,{"id":1908,"kind":355,"path":1909,"signature":1911,"source":1912,"parent":1881},"unitrack.StepResult.next_id",[331,1850,1910],"next_id","next_id: int",{"file":1886,"line":1913},210,{"id":1915,"kind":388,"path":1916,"signature":1917,"source":1918,"parent":1881},"unitrack.StepResult.__init__",[331,1850,405],"def __init__(self, snapshot: Tracklets, match: MatchOutcome, ids: torch.Tensor, next_id: int) -> None",{"file":1886,"line":341},{"id":1920,"kind":344,"path":1921,"signature":1922,"summary":1923,"description":1924,"params":1925,"raises":1942,"source":1945,"parent":331},"unitrack.Tracker",[331,1756],"class Tracker:","Stateless tracker driven by a stage tree.","The tracker is a pure step function over :class:`~unitrack.data.Tracklets`\nsnapshots: it owns no per-stream state. Wrap it in\n:class:`~unitrack.tracker.MultiStream` (per-key state) or :class:`BatchTracker`\n(per-slot state) for stateful inference.",[1926,1929,1932,1935,1938],{"name":1927,"type":1160,"doc":1928},"root","Root :class:`~unitrack.pipeline.Associator`.",{"name":270,"type":1930,"doc":1931},"dict[str, State]","Mapping of state name to :class:`~unitrack.states.State`. Each\ncontributes one user field to the tracker's\n:class:`~unitrack.data.Tracklets` schema; state names must not collide with\nreserved Tracklets columns.",{"name":239,"type":1933,"doc":1934},"Lifecycle",":class:`~unitrack.pipeline.Lifecycle` callable.",{"name":253,"type":1936,"doc":1937},"Visibility",":class:`~unitrack.pipeline.Visibility` callable.",{"name":1939,"type":1617,"default":1940,"doc":1941},"differentiable","False","When ``True``, swap hard nodes in ``root`` \u002F ``states`` \u002F\n``lifecycle`` for their soft replacements before validating the\ntree.",[1943],{"type":1447,"doc":1944},"If ``root`` is not an associator, ``lifecycle`` \u002F\n``visibility`` are not callable, or any state name shadows a\nreserved Tracklets column.",{"file":1886,"line":1946},213,{"id":1948,"kind":388,"path":1949,"signature":1950,"summary":1768,"source":1951,"parent":1920},"unitrack.Tracker.__init__",[331,1756,405],"def __init__(self, root: Associator, states: dict[str, State], lifecycle: Lifecycle, visibility: Visibility, differentiable: bool = False) -> None",{"file":1886,"line":434},{"id":1953,"kind":355,"path":1954,"signature":1955,"source":1956,"parent":1920},"unitrack.Tracker.root",[331,1756,1927],"root = root",{"file":1886,"line":1957},296,{"id":1959,"kind":355,"path":1960,"signature":1961,"source":1962,"parent":1920},"unitrack.Tracker.states",[331,1756,270],"states = dict(states)",{"file":1886,"line":491},{"id":1964,"kind":355,"path":1965,"signature":1966,"source":1967,"parent":1920},"unitrack.Tracker.lifecycle",[331,1756,239],"lifecycle = lifecycle",{"file":1886,"line":1968},298,{"id":1970,"kind":355,"path":1971,"signature":1972,"source":1973,"parent":1920},"unitrack.Tracker.visibility",[331,1756,253],"visibility = visibility",{"file":1886,"line":1974},299,{"id":1976,"kind":388,"path":1977,"signature":1979,"summary":1980,"params":1981,"returns":1983,"source":1985,"parent":1920},"unitrack.Tracker.empty_snapshot",[331,1756,1978],"empty_snapshot","def empty_snapshot(self, device: torch.types.Device | None = None) -> Tracklets","Construct a zero-row :class:`~unitrack.data.Tracklets` matching the schema.",[1982],{"name":484,"type":485,"default":486,"doc":870},{"type":1832,"doc":1984},"A :class:`~unitrack.data.Tracklets` with ``batch_size=[0]`` whose user\nfields are zero-initialised templates drawn from each\nstate's :attr:`~unitrack.states.State.schema`.",{"file":1886,"line":1986},301,{"id":1988,"kind":388,"path":1989,"signature":1991,"summary":1992,"params":1993,"returns":1997,"source":1999,"parent":1920},"unitrack.Tracker.predict_only",[331,1756,1990],"predict_only","def predict_only(self, snapshot: Tracklets, ctx: FrameContext) -> Tracklets","Run each state's :class:`~unitrack.states.Process` and return predictions.",[1994,1996],{"name":1709,"type":581,"doc":1995},"Current tracklet snapshot.",{"name":1180,"type":452,"doc":1181},{"type":1832,"doc":1998},"Snapshot with every state's predict step applied in turn.",{"file":1886,"line":2000},335,{"id":2002,"kind":388,"path":2003,"signature":2004,"summary":2005,"params":2006,"returns":2014,"source":2016,"parent":1920},"unitrack.Tracker.step",[331,1756,1623],"def step(self, snapshot: Tracklets, detections: Detections, ctx: FrameContext, next_id: int) -> StepResult","Advance the tracker by one frame.",[2007,2009,2011,2012],{"name":1709,"type":581,"doc":2008},"Current :class:`~unitrack.data.Tracklets` snapshot.",{"name":206,"type":394,"doc":2010},"New :class:`~unitrack.data.Detections` for this frame.",{"name":1180,"type":452,"doc":1181},{"name":1910,"type":468,"doc":2013},"First available tracklet ID; used for any spawns.",{"type":1850,"doc":2015},"Post-lifecycle snapshot, raw pre-lifecycle match, visible\nIDs, and the next available ID counter.",{"file":1886,"line":510},{"id":2018,"kind":344,"path":2019,"signature":2021,"summary":2022,"description":2023,"source":2024,"parent":331},"unitrack.TrackletMemory",[331,2020],"TrackletMemory","class TrackletMemory:","Hold one stream's :class:`~unitrack.data.Tracklets` and its next-ID counter.","Carries no knowledge of the :class:`~unitrack.tracker.Tracker`, its policies, or its\nschema. The snapshot supplied to :meth:`__init__` serves as the\nschema template for :meth:`reset`.",{"file":2025,"line":2026},"unitrack\u002Ftracker\u002Fmemory.py",10,{"id":2028,"kind":388,"path":2029,"signature":2030,"summary":2031,"params":2032,"source":2035,"parent":2018},"unitrack.TrackletMemory.__init__",[331,2020,405],"def __init__(self, empty: Tracklets) -> None","Initialise from a zero-row :class:`~unitrack.data.Tracklets` template.",[2033],{"name":699,"type":581,"doc":2034},"Zero-row schema template used both as the initial snapshot\nand as the :meth:`reset` template.",{"file":2025,"line":1031},{"id":2037,"kind":355,"path":2038,"signature":2039,"source":2040,"parent":2018},"unitrack.TrackletMemory.snapshot",[331,2020,1709],"snapshot = empty",{"file":2025,"line":609},{"id":2042,"kind":355,"path":2043,"signature":2044,"source":2045,"parent":2018},"unitrack.TrackletMemory.next_id",[331,2020,1910],"next_id = 1",{"file":2025,"line":616},{"id":2047,"kind":388,"path":2048,"signature":2049,"summary":2050,"source":2051,"parent":2018},"unitrack.TrackletMemory.reset",[331,2020,1595],"def reset(self) -> None","Restore the initial empty snapshot and reset ``next_id`` to ``1``.",{"file":2025,"line":630},{"id":2053,"kind":388,"path":2054,"signature":2056,"summary":2057,"source":2058,"parent":2018},"unitrack.TrackletMemory.load",[331,2020,2055],"load","def load(self, snapshot: Tracklets, next_id: int) -> None","Replace ``snapshot`` and ``next_id`` with external values.",{"file":2025,"line":862},{"id":2060,"kind":388,"path":2061,"signature":2063,"summary":2064,"description":2065,"returns":2066,"source":2068,"parent":2018},"unitrack.TrackletMemory.fork",[331,2020,2062],"fork","def fork(self) -> TrackletMemory","Return an independent copy of this memory.","The fork carries the current ``snapshot`` and ``next_id``\nso callers can branch from the live state (multi-stream \u002F vmap).\nThe new memory has its own snapshot reference but shares the\nempty schema template for :meth:`reset`.",{"type":2020,"doc":2067},"Fresh instance pointing at the same schema template.",{"file":2025,"line":2069},52,{"id":2071,"kind":335,"path":2072,"signature":2073,"summary":2074,"source":2075,"parent":331},"unitrack.states",[331,270],"module unitrack.states","State protocols and :class:`~unitrack.states.State` recipes for tracklet fields.",{"file":2076,"line":341},"unitrack\u002Fstates\u002F__init__.py",{"id":2078,"kind":344,"path":2079,"signature":2081,"summary":2082,"source":2083,"parent":2071},"unitrack.states.Initializer",[331,270,2080],"Initializer","class Initializer(typing.Protocol):","Produce field-shaped initial values for newly-promoted tracklets.",{"file":2084,"line":1763},"unitrack\u002Fstates\u002Fbase.py",{"id":2086,"kind":388,"path":2087,"signature":2088,"summary":2089,"params":2090,"returns":2094,"source":2096,"parent":2078},"unitrack.states.Initializer.__call__",[331,270,2080,1009],"def __call__(self, ds: Detections, ctx: FrameContext) -> torch.Tensor","Return initial tensor values for new tracklets.",[2091,2093],{"name":1177,"type":394,"doc":2092},"Detections promoted to new tracklets this frame.",{"name":1180,"type":452,"doc":1181},{"type":646,"doc":2095},"Field-shaped initial values, one row per new tracklet.",{"file":2084,"line":1438},{"id":2098,"kind":344,"path":2099,"signature":2101,"summary":2102,"description":2103,"source":2104,"parent":2071},"unitrack.states.Observation",[331,270,2100],"Observation","class Observation(typing.Protocol):","Update-step protocol: fuse detection measurements into tracklets.","Implementations are pure functions of ``(cs, ds, match, ctx)``; they\nconsume the matched-pair index from ``match`` and produce a new\nsnapshot with the corresponding field updated.",{"file":2084,"line":2105},51,{"id":2107,"kind":388,"path":2108,"signature":2109,"summary":2110,"params":2111,"returns":2118,"source":2120,"parent":2098},"unitrack.states.Observation.__call__",[331,270,2100,1009],"def __call__(self, cs: Tracklets, ds: Detections, match: MatchOutcome, ctx: FrameContext) -> Tracklets","Fuse matched-detection measurements into tracklets.",[2112,2113,2115,2117],{"name":1174,"type":581,"doc":1995},{"name":1177,"type":394,"doc":2114},"Current-frame detections.",{"name":215,"type":824,"doc":2116},"Matched pairs and residuals.",{"name":1180,"type":452,"doc":1181},{"type":581,"doc":2119},"New snapshot with the field updated for matched tracklets.",{"file":2084,"line":2121},61,{"id":2123,"kind":344,"path":2124,"signature":2126,"summary":2127,"description":2128,"source":2129,"parent":2071},"unitrack.states.Process",[331,270,2125],"Process","class Process(typing.Protocol):","Predict-step protocol: advance a tracklet field by one time step.","Implementations are pure functions of ``(cs, ctx)``; they read the\nnamed field on the tracklet snapshot and return a new snapshot with\nthe field updated by ``ctx.delta``.",{"file":2084,"line":2130},21,{"id":2132,"kind":388,"path":2133,"signature":2134,"summary":2135,"params":2136,"returns":2140,"source":2142,"parent":2123},"unitrack.states.Process.__call__",[331,270,2125,1009],"def __call__(self, cs: Tracklets, ctx: FrameContext) -> Tracklets","Advance the named field by ``ctx.delta``.",[2137,2138],{"name":1174,"type":581,"doc":1995},{"name":1180,"type":452,"doc":2139},"Frame context; ``ctx.delta`` carries the elapsed time.",{"type":581,"doc":2141},"New snapshot with the field advanced.",{"file":2084,"line":1571},{"id":2144,"kind":344,"path":2145,"signature":2147,"summary":2148,"description":2149,"params":2150,"source":2164,"parent":2071},"unitrack.states.State",[331,270,2146],"State","class State:","A named field on the tracklet snapshot with predict\u002Fupdate\u002Finit logic.","The field name is set by the :class:`~unitrack.tracker.Tracker`'s\n``states={...}`` dict key and is therefore not stored on the\n:class:`~unitrack.states.State` itself, so the same\n:class:`~unitrack.states.State` instance can be reused under different keys.",[2151,2155,2158,2161],{"name":2152,"type":2153,"doc":2154},"schema","~unitrack.data.TensorSpec","Per-tracklet tensor shape and dtype for the field.",{"name":2156,"type":2125,"doc":2157},"process","Predict-step implementation.",{"name":2159,"type":2100,"doc":2160},"observation","Update-step implementation.",{"name":2162,"type":2080,"doc":2163},"init","Factory for new-tracklet initial values.",{"file":2084,"line":2165},115,{"id":2167,"kind":355,"path":2168,"signature":2169,"source":2170,"parent":2144},"unitrack.states.State.schema",[331,270,2146,2152],"schema: TensorSpec",{"file":2084,"line":2171},138,{"id":2173,"kind":355,"path":2174,"signature":2175,"source":2176,"parent":2144},"unitrack.states.State.process",[331,270,2146,2156],"process: Process",{"file":2084,"line":941},{"id":2178,"kind":355,"path":2179,"signature":2180,"source":2181,"parent":2144},"unitrack.states.State.observation",[331,270,2146,2159],"observation: Observation",{"file":2084,"line":2182},140,{"id":2184,"kind":355,"path":2185,"signature":2186,"source":2187,"parent":2144},"unitrack.states.State.init",[331,270,2146,2162],"init: Initializer",{"file":2084,"line":2188},141,{"id":2190,"kind":388,"path":2191,"signature":2192,"source":2193,"parent":2144},"unitrack.states.State.__init__",[331,270,2146,405],"def __init__(self, schema: TensorSpec, process: Process, observation: Observation, init: Initializer) -> None",{"file":2084,"line":341},{"id":2195,"kind":344,"path":2196,"signature":2198,"summary":2199,"description":2200,"params":2201,"raises":2213,"source":2216,"parent":2071},"unitrack.states.VonMisesFisherDecay",[331,270,2197],"VonMisesFisherDecay","class VonMisesFisherDecay:","Predict step for a von Mises-Fisher embedding state.","The mean direction is left unchanged (no appearance motion model); the\nconcentration decays multiplicatively toward :attr:`kappa_min` with a\ntime constant :attr:`tau`, so a tracklet that has not been observed\nrecently becomes less certain of its appearance.",[2202,2206,2210],{"name":2203,"type":2204,"doc":2205},"field","str","Tracklet field holding the mean direction. The concentration lives\nin ``f\"{field}_kappa\"``.",{"name":2207,"type":474,"default":2208,"doc":2209},"tau","10.0","Decay time constant. Each call multiplies ``kappa`` by\n``exp(-dt \u002F tau)``. Must be strictly positive.",{"name":2211,"type":474,"default":475,"doc":2212},"kappa_min","Floor on the concentration after decay.",[2214],{"type":398,"doc":2215},"If ``tau`` is non-positive.",{"file":2217,"line":2069},"unitrack\u002Fstates\u002Fdirectional.py",{"id":2219,"kind":355,"path":2220,"signature":2221,"source":2222,"parent":2195},"unitrack.states.VonMisesFisherDecay.field",[331,270,2197,2203],"field: str",{"file":2217,"line":2223},80,{"id":2225,"kind":355,"path":2226,"signature":2227,"source":2228,"parent":2195},"unitrack.states.VonMisesFisherDecay.tau",[331,270,2197,2207],"tau: float = 10.0",{"file":2217,"line":2229},81,{"id":2231,"kind":355,"path":2232,"signature":2233,"source":2234,"parent":2195},"unitrack.states.VonMisesFisherDecay.kappa_min",[331,270,2197,2211],"kappa_min: float = 1.0",{"file":2217,"line":2235},82,{"id":2237,"kind":355,"path":2238,"signature":2240,"summary":2241,"source":2242,"parent":2195},"unitrack.states.VonMisesFisherDecay.kappa_field",[331,270,2197,2239],"kappa_field","kappa_field: str","Return the auxiliary concentration field name.",{"file":2217,"line":1763},{"id":2244,"kind":388,"path":2245,"signature":2134,"summary":2246,"source":2247,"parent":2195},"unitrack.states.VonMisesFisherDecay.__call__",[331,270,2197,1009],"Decay the concentration by one time step; leave the direction.",{"file":2217,"line":1438},{"id":2249,"kind":388,"path":2250,"signature":2251,"source":2252,"parent":2195},"unitrack.states.VonMisesFisherDecay.__init__",[331,270,2197,405],"def __init__(self, field: str, tau: float = 10.0, kappa_min: float = 1.0) -> None",{"file":2217,"line":341},{"id":2254,"kind":344,"path":2255,"signature":2257,"summary":2258,"description":2259,"params":2260,"source":2270,"parent":2071},"unitrack.states.VonMisesFisherUpdate",[331,270,2256],"VonMisesFisherUpdate","class VonMisesFisherUpdate:","Conjugate von Mises-Fisher update for matched tracklet-detection pairs.","For each matched pair the posterior is the resultant of the prior\ndirection (weighted by its concentration) and the L2-normalised\ndetection embedding (weighted by :attr:`kappa_obs`). The new direction\nis the normalised resultant and the new concentration is its length, so\nconfident agreement sharpens the belief while disagreement broadens it.\nUnmatched tracklets keep their predicted state.",[2261,2263,2266],{"name":2203,"type":2204,"doc":2262},"Tracklet field holding the mean direction.",{"name":2264,"type":2204,"doc":2265},"meas_field","Detection field holding the measured embedding.",{"name":2267,"type":474,"default":2268,"doc":2269},"kappa_obs","20.0","Observation concentration (how much one detection is trusted).",{"file":2217,"line":401},{"id":2272,"kind":355,"path":2273,"signature":2221,"source":2274,"parent":2254},"unitrack.states.VonMisesFisherUpdate.field",[331,270,2256,2203],{"file":2217,"line":1789},{"id":2276,"kind":355,"path":2277,"signature":2278,"source":2279,"parent":2254},"unitrack.states.VonMisesFisherUpdate.meas_field",[331,270,2256,2264],"meas_field: str",{"file":2217,"line":2280},127,{"id":2282,"kind":355,"path":2283,"signature":2284,"source":2285,"parent":2254},"unitrack.states.VonMisesFisherUpdate.kappa_obs",[331,270,2256,2267],"kappa_obs: float = 20.0",{"file":2217,"line":2286},128,{"id":2288,"kind":355,"path":2289,"signature":2240,"summary":2241,"source":2290,"parent":2254},"unitrack.states.VonMisesFisherUpdate.kappa_field",[331,270,2256,2239],{"file":2217,"line":1081},{"id":2292,"kind":388,"path":2293,"signature":2109,"summary":2294,"source":2295,"parent":2254},"unitrack.states.VonMisesFisherUpdate.__call__",[331,270,2256,1009],"Fuse matched detections via the conjugate vMF resultant update.",{"file":2217,"line":1813},{"id":2297,"kind":388,"path":2298,"signature":2299,"source":2300,"parent":2254},"unitrack.states.VonMisesFisherUpdate.__init__",[331,270,2256,405],"def __init__(self, field: str, meas_field: str, kappa_obs: float = 20.0) -> None",{"file":2217,"line":341},{"id":2302,"kind":2303,"path":2304,"signature":2306,"summary":2307,"description":2308,"params":2309,"returns":2325,"source":2328,"parent":2071},"unitrack.states.vmf_state_entries","function",[331,270,2305],"vmf_state_entries","def vmf_state_entries(field: str, dim: int, meas_field: str | None = None, init_kappa: float = 20.0, kappa_obs: float = 20.0, tau: float = 10.0, kappa_min: float = 1.0) -> dict[str, State]","Build the ``(direction, concentration)`` state entries for a vMF filter.","The direction entry holds a unit ``(dim,)`` mean — match it with the\nexisting :class:`~unitrack.costs.Cosine` cost. The concentration entry\nholds a scalar, no-op'd through predict\u002Fupdate because the direction\nentry's :class:`VonMisesFisherDecay` \u002F :class:`VonMisesFisherUpdate`\nwrite it as a side effect.",[2310,2312,2315,2317,2320,2322,2324],{"name":2203,"type":2204,"doc":2311},"Name of the direction field (and prefix for ``f\"{field}_kappa\"``).",{"name":2313,"type":468,"doc":2314},"dim","Embedding dimensionality.",{"name":2264,"type":2204,"default":486,"doc":2316},"Detection field supplying the measured embedding. Defaults to\n:paramref:`field`.",{"name":2318,"type":474,"default":2268,"doc":2319},"init_kappa","Concentration assigned to a freshly spawned tracklet.",{"name":2267,"type":474,"default":2268,"doc":2321},"Per-observation concentration used by the update.",{"name":2207,"type":474,"default":2208,"doc":2323},"Concentration decay time constant used by the predict step.",{"name":2211,"type":474,"default":475,"doc":2212},{"type":2326,"doc":2327},"dict","Two :class:`~unitrack.states.State` entries keyed by ``field`` and\n``f\"{field}_kappa\"``.",{"file":2217,"line":972},{"id":2330,"kind":344,"path":2331,"signature":2333,"summary":2334,"description":2335,"params":2336,"raises":2346,"source":2349,"parent":2071},"unitrack.states.EMADecay",[331,270,2332],"EMADecay","class EMADecay:","Exponential decay of a tracklet field toward ``anchor``.","Each call multiplies the deviation from ``anchor`` by\n``exp(-ln 2 * dt \u002F half_life)``, so the field's distance to\n``anchor`` halves every ``half_life`` time units.",[2337,2339,2342],{"name":2203,"type":2204,"doc":2338},"Tracklet field to decay.",{"name":2340,"type":474,"doc":2341},"half_life","Half-life in seconds. Must be strictly positive.",{"name":2343,"type":474,"default":2344,"doc":2345},"anchor","0.0","Decay target. Default ``0.0``.",[2347],{"type":398,"doc":2348},"If ``half_life`` is non-positive or ``anchor`` is non-finite.",{"file":2350,"line":2351},"unitrack\u002Fstates\u002Fema.py",13,{"id":2353,"kind":355,"path":2354,"signature":2221,"source":2355,"parent":2330},"unitrack.states.EMADecay.field",[331,270,2332,2203],{"file":2350,"line":2356},38,{"id":2358,"kind":355,"path":2359,"signature":2360,"source":2361,"parent":2330},"unitrack.states.EMADecay.half_life",[331,270,2332,2340],"half_life: float",{"file":2350,"line":609},{"id":2363,"kind":355,"path":2364,"signature":2365,"source":2366,"parent":2330},"unitrack.states.EMADecay.anchor",[331,270,2332,2343],"anchor: float = 0.0",{"file":2350,"line":616},{"id":2368,"kind":388,"path":2369,"signature":2134,"summary":2370,"params":2371,"returns":2374,"raises":2376,"source":2379,"parent":2330},"unitrack.states.EMADecay.__call__",[331,270,2332,1009],"Decay the field toward :attr:`anchor` by one time step.",[2372,2373],{"name":1174,"type":581,"doc":1995},{"name":1180,"type":452,"doc":2139},{"type":581,"doc":2375},"New snapshot with the field decayed.",[2377],{"type":398,"doc":2378},"If ``ctx.delta`` is negative.",{"file":2350,"line":2105},{"id":2381,"kind":388,"path":2382,"signature":2383,"source":2384,"parent":2330},"unitrack.states.EMADecay.__init__",[331,270,2332,405],"def __init__(self, field: str, half_life: float, anchor: float = 0.0) -> None",{"file":2350,"line":341},{"id":2386,"kind":344,"path":2387,"signature":2389,"summary":2390,"description":2391,"params":2392,"source":2398,"parent":2071},"unitrack.states.EMAFuse",[331,270,2388],"EMAFuse","class EMAFuse:","Exponential-moving-average update of a tracklet field.","For each matched pair the tracklet field is replaced by\n``rho * field + (1 - rho) * measurement``.",[2393,2395],{"name":2203,"type":2204,"doc":2394},"Tracklet field to blend.",{"name":2396,"type":474,"doc":2397},"rho","Smoothing factor in ``[0, 1]``. Higher values keep more of the\ntracklet history; ``rho = 0`` reduces to :class:`~unitrack.states.Replace`.",{"file":2350,"line":1188},{"id":2400,"kind":355,"path":2401,"signature":2221,"source":2402,"parent":2386},"unitrack.states.EMAFuse.field",[331,270,2388,2203],{"file":2350,"line":2280},{"id":2404,"kind":355,"path":2405,"signature":2406,"source":2407,"parent":2386},"unitrack.states.EMAFuse.rho",[331,270,2388,2396],"rho: float",{"file":2350,"line":2286},{"id":2409,"kind":388,"path":2410,"signature":2109,"summary":2411,"source":2412,"parent":2386},"unitrack.states.EMAFuse.__call__",[331,270,2388,1009],"Blend matched detections into tracklets via exponential moving average.",{"file":2350,"line":1797},{"id":2414,"kind":388,"path":2415,"signature":2416,"source":2417,"parent":2386},"unitrack.states.EMAFuse.__init__",[331,270,2388,405],"def __init__(self, field: str, rho: float) -> None",{"file":2350,"line":341},{"id":2419,"kind":344,"path":2420,"signature":2422,"summary":2423,"description":2424,"params":2425,"source":2428,"parent":2071},"unitrack.states.EMATrack",[331,270,2421],"EMATrack","class EMATrack:","Predict-step companion to :class:`EMAFuse`.","No-op: the EMA blend happens in the observation step. This class\nexists so :class:`EMAFuse` can be wired into a :class:`~unitrack.states.State` whose\n:class:`~unitrack.states.Process` slot expects a non-``None`` predict step.",[2426],{"name":2203,"type":2204,"doc":2427},"Tracklet field (unused; kept for symmetry with the observation).",{"file":2350,"line":2429},85,{"id":2431,"kind":355,"path":2432,"signature":2221,"source":2433,"parent":2419},"unitrack.states.EMATrack.field",[331,270,2421,2203],{"file":2350,"line":2434},101,{"id":2436,"kind":388,"path":2437,"signature":2134,"summary":2438,"source":2439,"parent":2419},"unitrack.states.EMATrack.__call__",[331,270,2421,1009],"Return tracklets unchanged; the EMA blend happens in :class:`EMAFuse`.",{"file":2350,"line":401},{"id":2441,"kind":388,"path":2442,"signature":2443,"source":2444,"parent":2419},"unitrack.states.EMATrack.__init__",[331,270,2421,405],"def __init__(self, field: str) -> None",{"file":2350,"line":341},{"id":2446,"kind":344,"path":2447,"signature":2449,"summary":2450,"description":2451,"params":2452,"source":2457,"parent":2071},"unitrack.states.WeightedFuse",[331,270,2448],"WeightedFuse","class WeightedFuse:","Score-aware blend that uses a per-detection score as the blend weight.","Each tracklet field is blended as ``(1 - w) * field + w * detection``,\nwhere ``w`` is the detection's ``weight_field`` clamped to ``[0, 1]``.",[2453,2454],{"name":2203,"type":2204,"doc":2394},{"name":2455,"type":2204,"doc":2456},"weight_field","Detection field holding the per-detection blend weight (e.g. a\nscore in ``[0, 1]``).",{"file":2350,"line":552},{"id":2459,"kind":355,"path":2460,"signature":2221,"source":2461,"parent":2446},"unitrack.states.WeightedFuse.field",[331,270,2448,2203],{"file":2350,"line":558},{"id":2463,"kind":355,"path":2464,"signature":2465,"source":2466,"parent":2446},"unitrack.states.WeightedFuse.weight_field",[331,270,2448,2455],"weight_field: str",{"file":2350,"line":2467},169,{"id":2469,"kind":388,"path":2470,"signature":2109,"summary":2471,"source":2472,"parent":2446},"unitrack.states.WeightedFuse.__call__",[331,270,2448,1009],"Blend matched detections using per-detection score as blend weight.",{"file":2350,"line":563},{"id":2474,"kind":388,"path":2475,"signature":2476,"source":2477,"parent":2446},"unitrack.states.WeightedFuse.__init__",[331,270,2448,405],"def __init__(self, field: str, weight_field: str) -> None",{"file":2350,"line":341},{"id":2479,"kind":344,"path":2480,"signature":2482,"summary":2483,"description":2484,"params":2485,"source":2490,"parent":2071},"unitrack.states.GalleryAppend",[331,270,2481],"GalleryAppend","class GalleryAppend:","Update step: push each matched detection's embedding into the ring buffer.","For each matched pair the detection embedding overwrites the oldest\nslot (``count mod K``), the fill count is incremented, and the primary\nfield is set to the new embedding (the most-recent view). Unmatched\ntracklets keep their gallery.",[2486,2488],{"name":2203,"type":2204,"doc":2487},"Primary tracklet field (most recent embedding). The gallery lives\nin ``f\"{field}_gallery\"`` and the count in ``f\"{field}_count\"``.",{"name":2264,"type":2204,"doc":2489},"Detection field holding the embedding to append.",{"file":2491,"line":630},"unitrack\u002Fstates\u002Fgallery.py",{"id":2493,"kind":355,"path":2494,"signature":2221,"source":2495,"parent":2479},"unitrack.states.GalleryAppend.field",[331,270,2481,2203],{"file":2491,"line":2496},62,{"id":2498,"kind":355,"path":2499,"signature":2278,"source":2500,"parent":2479},"unitrack.states.GalleryAppend.meas_field",[331,270,2481,2264],{"file":2491,"line":2501},63,{"id":2503,"kind":355,"path":2504,"signature":2506,"summary":2507,"source":2508,"parent":2479},"unitrack.states.GalleryAppend.gallery_field",[331,270,2481,2505],"gallery_field","gallery_field: str","Return the gallery-buffer field name.",{"file":2491,"line":2509},66,{"id":2511,"kind":355,"path":2512,"signature":2514,"summary":2515,"source":2516,"parent":2479},"unitrack.states.GalleryAppend.count_field",[331,270,2481,2513],"count_field","count_field: str","Return the fill-count field name.",{"file":2491,"line":2517},71,{"id":2519,"kind":388,"path":2520,"signature":2109,"summary":2521,"source":2522,"parent":2479},"unitrack.states.GalleryAppend.__call__",[331,270,2481,1009],"Append matched detection embeddings to their tracklet galleries.",{"file":2491,"line":1417},{"id":2524,"kind":388,"path":2525,"signature":2526,"source":2527,"parent":2479},"unitrack.states.GalleryAppend.__init__",[331,270,2481,405],"def __init__(self, field: str, meas_field: str) -> None",{"file":2491,"line":341},{"id":2529,"kind":344,"path":2530,"signature":2532,"summary":2533,"description":2534,"params":2535,"source":2543,"parent":2071},"unitrack.states.GalleryInitializer",[331,270,2531],"GalleryInitializer","class GalleryInitializer:",":class:`~unitrack.states.Initializer` seeding a gallery with one embedding.","The new tracklet's gallery has its first slot set to the detection\nembedding and the rest zeroed; the paired count initialiser starts at 1.",[2536,2538,2541],{"name":2203,"type":2204,"doc":2537},"Detection field supplying the seed embedding.",{"name":2539,"type":468,"doc":2540},"capacity","Number of gallery slots ``K``.",{"name":2313,"type":468,"doc":2542},"Embedding dimensionality ``D``.",{"file":2491,"line":2544},105,{"id":2546,"kind":355,"path":2547,"signature":2221,"source":2548,"parent":2529},"unitrack.states.GalleryInitializer.field",[331,270,2531,2203],{"file":2491,"line":2549},124,{"id":2551,"kind":355,"path":2552,"signature":2553,"source":2554,"parent":2529},"unitrack.states.GalleryInitializer.capacity",[331,270,2531,2539],"capacity: int",{"file":2491,"line":673},{"id":2556,"kind":355,"path":2557,"signature":2558,"source":2559,"parent":2529},"unitrack.states.GalleryInitializer.dim",[331,270,2531,2313],"dim: int",{"file":2491,"line":1789},{"id":2561,"kind":388,"path":2562,"signature":2088,"summary":2563,"source":2564,"parent":2529},"unitrack.states.GalleryInitializer.__call__",[331,270,2531,1009],"Return a ``(N, K, D)`` gallery with slot 0 seeded from the detection.",{"file":2491,"line":2286},{"id":2566,"kind":388,"path":2567,"signature":2568,"source":2569,"parent":2529},"unitrack.states.GalleryInitializer.__init__",[331,270,2531,405],"def __init__(self, field: str, capacity: int, dim: int) -> None",{"file":2491,"line":341},{"id":2571,"kind":2303,"path":2572,"signature":2574,"summary":2575,"description":2576,"params":2577,"returns":2585,"source":2587,"parent":2071},"unitrack.states.gallery_state_entries",[331,270,2573],"gallery_state_entries","def gallery_state_entries(field: str, dim: int, capacity: int = 8, meas_field: str | None = None) -> dict[str, State]","Build the ``(recent, gallery, count)`` state entries for a feature bank.","Pair the gallery with :class:`~unitrack.costs.GalleryCost` (reading\n``f\"{field}_gallery\"`` and ``f\"{field}_count\"``) for memory-bank\nmatching, or match the primary ``field`` with plain\n:class:`~unitrack.costs.Cosine` for last-embedding matching.",[2578,2580,2581,2583],{"name":2203,"type":2204,"doc":2579},"Name of the primary (most-recent) field and prefix for the\n``f\"{field}_gallery\"`` \u002F ``f\"{field}_count\"`` auxiliaries.",{"name":2313,"type":468,"doc":2314},{"name":2539,"type":468,"default":2582,"doc":2540},"8",{"name":2264,"type":2204,"default":486,"doc":2584},"Detection field supplying the embedding. Defaults to\n:paramref:`field`.",{"type":2326,"doc":2586},"Three :class:`~unitrack.states.State` entries keyed by ``field``,\n``f\"{field}_gallery\"`` and ``f\"{field}_count\"``.",{"file":2491,"line":941},{"id":2589,"kind":344,"path":2590,"signature":2592,"summary":2593,"description":2594,"params":2595,"source":2601,"parent":2071},"unitrack.states.ConstantInitializer",[331,270,2591],"ConstantInitializer","class ConstantInitializer:",":class:`Initializer` that fills the schema-shaped buffer with a constant.","Used to seed scalar auxiliary fields such as a von Mises-Fisher\nconcentration or a gallery fill-count. The fill value is cast to the\nschema dtype.",[2596,2598],{"name":2152,"type":2153,"doc":2597},"Per-tracklet shape and dtype.",{"name":2599,"type":474,"doc":2600},"value","Constant fill value.",{"file":2602,"line":2603},"unitrack\u002Fstates\u002Fidentity.py",204,{"id":2605,"kind":355,"path":2606,"signature":2169,"source":2607,"parent":2589},"unitrack.states.ConstantInitializer.schema",[331,270,2591,2152],{"file":2602,"line":2608},222,{"id":2610,"kind":355,"path":2611,"signature":2612,"source":2613,"parent":2589},"unitrack.states.ConstantInitializer.value",[331,270,2591,2599],"value: float",{"file":2602,"line":2614},223,{"id":2616,"kind":388,"path":2617,"signature":2088,"summary":2618,"source":2619,"parent":2589},"unitrack.states.ConstantInitializer.__call__",[331,270,2591,1009],"Return a constant-filled buffer shaped for the given detections batch.",{"file":2602,"line":2620},225,{"id":2622,"kind":388,"path":2623,"signature":2624,"source":2625,"parent":2589},"unitrack.states.ConstantInitializer.__init__",[331,270,2591,405],"def __init__(self, schema: TensorSpec, value: float) -> None",{"file":2602,"line":341},{"id":2627,"kind":344,"path":2628,"signature":2630,"summary":2631,"description":2632,"params":2633,"source":2639,"parent":2071},"unitrack.states.EyeInitializer",[331,270,2629],"EyeInitializer","class EyeInitializer:",":class:`Initializer` that emits a per-tracklet scaled identity matrix.","Used to initialise Kalman covariances. Each new tracklet receives\n``scale * I_dim``.",[2634,2636],{"name":2313,"type":468,"doc":2635},"Side length of the identity matrix.",{"name":2637,"type":474,"default":475,"doc":2638},"scale","Multiplier applied to ``I_dim``. Default ``1.0``.",{"file":2602,"line":2640},129,{"id":2642,"kind":355,"path":2643,"signature":2558,"source":2644,"parent":2627},"unitrack.states.EyeInitializer.dim",[331,270,2629,2313],{"file":2602,"line":2645},146,{"id":2647,"kind":355,"path":2648,"signature":2649,"source":2650,"parent":2627},"unitrack.states.EyeInitializer.scale",[331,270,2629,2637],"scale: float = 1.0",{"file":2602,"line":820},{"id":2652,"kind":388,"path":2653,"signature":2088,"summary":2654,"source":2655,"parent":2627},"unitrack.states.EyeInitializer.__call__",[331,270,2629,1009],"Return ``(N, dim, dim)`` per-tracklet scaled identity matrices.",{"file":2602,"line":956},{"id":2657,"kind":388,"path":2658,"signature":2659,"source":2660,"parent":2627},"unitrack.states.EyeInitializer.__init__",[331,270,2629,405],"def __init__(self, dim: int, scale: float = 1.0) -> None",{"file":2602,"line":341},{"id":2662,"kind":344,"path":2663,"signature":2665,"summary":2666,"params":2667,"source":2670,"parent":2071},"unitrack.states.FromDetectionField",[331,270,2664],"FromDetectionField","class FromDetectionField:",":class:`Initializer` that copies a named field from new detections.",[2668],{"name":2203,"type":2204,"doc":2669},"Detection field whose tensor seeds the new tracklets.",{"file":2602,"line":2671},89,{"id":2673,"kind":355,"path":2674,"signature":2221,"source":2675,"parent":2662},"unitrack.states.FromDetectionField.field",[331,270,2664,2203],{"file":2602,"line":2434},{"id":2677,"kind":388,"path":2678,"signature":2088,"summary":2679,"source":2680,"parent":2662},"unitrack.states.FromDetectionField.__call__",[331,270,2664,1009],"Return the detection field tensor.",{"file":2602,"line":401},{"id":2682,"kind":388,"path":2683,"signature":2443,"source":2684,"parent":2662},"unitrack.states.FromDetectionField.__init__",[331,270,2664,405],{"file":2602,"line":341},{"id":2686,"kind":344,"path":2687,"signature":2689,"summary":2690,"description":2691,"params":2692,"source":2695,"parent":2071},"unitrack.states.Identity",[331,270,2688],"Identity","class Identity:","No-op :class:`~unitrack.states.Process` for fields that need no prediction step.","Useful for embeddings, one-hot class labels, scores, and any other\nfield whose value does not evolve under the motion model.",[2693],{"name":2203,"type":2204,"doc":2694},"Tracklet field name (unused; kept for symmetry with the matching\nobservation).",{"file":2602,"line":913},{"id":2697,"kind":355,"path":2698,"signature":2221,"source":2699,"parent":2686},"unitrack.states.Identity.field",[331,270,2688,2203],{"file":2602,"line":1048},{"id":2701,"kind":388,"path":2702,"signature":2134,"summary":2703,"source":2704,"parent":2686},"unitrack.states.Identity.__call__",[331,270,2688,1009],"Return tracklets unchanged.",{"file":2602,"line":2705},50,{"id":2707,"kind":388,"path":2708,"signature":2443,"source":2709,"parent":2686},"unitrack.states.Identity.__init__",[331,270,2688,405],{"file":2602,"line":341},{"id":2711,"kind":344,"path":2712,"signature":2714,"summary":2715,"description":2716,"source":2717,"parent":2071},"unitrack.states.NoopObservation",[331,270,2713],"NoopObservation","class NoopObservation:",":class:`Observation` that leaves the snapshot unchanged.","The dual of :class:`NoopProcess` for the update step.",{"file":2602,"line":2718},302,{"id":2720,"kind":388,"path":2721,"signature":2109,"summary":2722,"source":2723,"parent":2711},"unitrack.states.NoopObservation.__call__",[331,270,2713,1009],"Return the snapshot unchanged.",{"file":2602,"line":2724},310,{"id":2726,"kind":388,"path":2727,"signature":1016,"source":2728,"parent":2711},"unitrack.states.NoopObservation.__init__",[331,270,2713,405],{"file":2602,"line":341},{"id":2730,"kind":344,"path":2731,"signature":2733,"summary":2734,"description":2735,"source":2736,"parent":2071},"unitrack.states.NoopProcess",[331,270,2732],"NoopProcess","class NoopProcess:",":class:`~unitrack.states.Process` that leaves the snapshot unchanged.","Useful for the auxiliary covariance entry of a Kalman state, where\nthe paired mean entry's :class:`KalmanLinear` predict already writes\nthe new covariance — running another predict here would double-step.",{"file":2602,"line":2737},286,{"id":2739,"kind":388,"path":2740,"signature":2134,"summary":2722,"source":2741,"parent":2730},"unitrack.states.NoopProcess.__call__",[331,270,2732,1009],{"file":2602,"line":1957},{"id":2743,"kind":388,"path":2744,"signature":1016,"source":2745,"parent":2730},"unitrack.states.NoopProcess.__init__",[331,270,2732,405],{"file":2602,"line":341},{"id":2747,"kind":344,"path":2748,"signature":2750,"summary":2751,"description":2752,"params":2753,"source":2759,"parent":2071},"unitrack.states.NormalizedFromDetectionField",[331,270,2749],"NormalizedFromDetectionField","class NormalizedFromDetectionField:",":class:`Initializer` copying a detection field, L2-normalised along the last axis.","Seeds a unit-vector field (e.g. a von Mises-Fisher mean direction) from\na possibly unnormalised detection embedding.",[2754,2755],{"name":2203,"type":2204,"doc":2669},{"name":2756,"type":474,"default":2757,"doc":2758},"eps","1e-12","Lower bound on the norm used for normalisation. Default ``1e-12``.",{"file":2602,"line":2760},232,{"id":2762,"kind":355,"path":2763,"signature":2221,"source":2764,"parent":2747},"unitrack.states.NormalizedFromDetectionField.field",[331,270,2749,2203],{"file":2602,"line":2765},249,{"id":2767,"kind":355,"path":2768,"signature":2769,"source":2770,"parent":2747},"unitrack.states.NormalizedFromDetectionField.eps",[331,270,2749,2756],"eps: float = 1e-12",{"file":2602,"line":2771},250,{"id":2773,"kind":388,"path":2774,"signature":2088,"summary":2775,"source":2776,"parent":2747},"unitrack.states.NormalizedFromDetectionField.__call__",[331,270,2749,1009],"Return the L2-normalised detection field tensor.",{"file":2602,"line":2777},252,{"id":2779,"kind":388,"path":2780,"signature":2781,"source":2782,"parent":2747},"unitrack.states.NormalizedFromDetectionField.__init__",[331,270,2749,405],"def __init__(self, field: str, eps: float = 1e-12) -> None",{"file":2602,"line":341},{"id":2784,"kind":344,"path":2785,"signature":2787,"summary":2788,"description":2789,"params":2790,"raises":2796,"source":2799,"parent":2071},"unitrack.states.PadZerosInitializer",[331,270,2786],"PadZerosInitializer","class PadZerosInitializer:",":class:`Initializer` that copies a detection field and zero-pads to ``full_dim``.","Used to spawn a Kalman state from a measurement-only detection: the\ndetection's measurement vector becomes the leading slice of the full\nstate, with zeros for the unobserved velocity (or higher-order)\ncomponents. ``ds.{field}`` must have shape ``(N, meas_dim)`` and\n``meas_dim \u003C= full_dim``.",[2791,2793],{"name":2203,"type":2204,"doc":2792},"Detection field that supplies the leading measurement slice.",{"name":2794,"type":468,"doc":2795},"full_dim","Final state dimensionality.",[2797],{"type":398,"doc":2798},"If the detection field is wider than ``full_dim``.",{"file":2602,"line":2800},157,{"id":2802,"kind":355,"path":2803,"signature":2221,"source":2804,"parent":2784},"unitrack.states.PadZerosInitializer.field",[331,270,2786,2203],{"file":2602,"line":2805},182,{"id":2807,"kind":355,"path":2808,"signature":2809,"source":2810,"parent":2784},"unitrack.states.PadZerosInitializer.full_dim",[331,270,2786,2794],"full_dim: int",{"file":2602,"line":2811},183,{"id":2813,"kind":388,"path":2814,"signature":2088,"summary":2815,"source":2816,"parent":2784},"unitrack.states.PadZerosInitializer.__call__",[331,270,2786,1009],"Return a ``(N, full_dim)`` tensor with detection data padded with zeros.",{"file":2602,"line":2817},185,{"id":2819,"kind":388,"path":2820,"signature":2821,"source":2822,"parent":2784},"unitrack.states.PadZerosInitializer.__init__",[331,270,2786,405],"def __init__(self, field: str, full_dim: int) -> None",{"file":2602,"line":341},{"id":2824,"kind":344,"path":2825,"signature":2827,"summary":2828,"params":2829,"source":2832,"parent":2071},"unitrack.states.Replace",[331,270,2826],"Replace","class Replace:","Hard-replace :class:`Observation`: matched tracklets adopt the detection value.",[2830],{"name":2203,"type":2204,"doc":2831},"Tracklet field to overwrite from the matched detection's field of\nthe same name.",{"file":2602,"line":352},{"id":2834,"kind":355,"path":2835,"signature":2221,"source":2836,"parent":2824},"unitrack.states.Replace.field",[331,270,2826,2203],{"file":2602,"line":2837},69,{"id":2839,"kind":388,"path":2840,"signature":2109,"summary":2841,"source":2842,"parent":2824},"unitrack.states.Replace.__call__",[331,270,2826,1009],"Replace matched tracklet field values with detection values.",{"file":2602,"line":2517},{"id":2844,"kind":388,"path":2845,"signature":2443,"source":2846,"parent":2824},"unitrack.states.Replace.__init__",[331,270,2826,405],{"file":2602,"line":341},{"id":2848,"kind":344,"path":2849,"signature":2851,"summary":2852,"description":2853,"params":2854,"source":2858,"parent":2071},"unitrack.states.ScaledFromDetectionField",[331,270,2850],"ScaledFromDetectionField","class ScaledFromDetectionField:",":class:`Initializer` copying a detection field scaled by a constant.","Used to seed an information-vector field ``y = z \u002F init_var`` from a\nmeasurement ``z``.",[2855,2856],{"name":2203,"type":2204,"doc":2669},{"name":2637,"type":474,"doc":2857},"Multiplier applied to the field.",{"file":2602,"line":2859},260,{"id":2861,"kind":355,"path":2862,"signature":2221,"source":2863,"parent":2848},"unitrack.states.ScaledFromDetectionField.field",[331,270,2850,2203],{"file":2602,"line":458},{"id":2865,"kind":355,"path":2866,"signature":2867,"source":2868,"parent":2848},"unitrack.states.ScaledFromDetectionField.scale",[331,270,2850,2637],"scale: float",{"file":2602,"line":2869},278,{"id":2871,"kind":388,"path":2872,"signature":2088,"summary":2873,"source":2874,"parent":2848},"unitrack.states.ScaledFromDetectionField.__call__",[331,270,2850,1009],"Return the scaled detection field tensor.",{"file":2602,"line":2875},280,{"id":2877,"kind":388,"path":2878,"signature":2879,"source":2880,"parent":2848},"unitrack.states.ScaledFromDetectionField.__init__",[331,270,2850,405],"def __init__(self, field: str, scale: float) -> None",{"file":2602,"line":341},{"id":2882,"kind":344,"path":2883,"signature":2885,"summary":2886,"params":2887,"source":2889,"parent":2071},"unitrack.states.ZerosInitializer",[331,270,2884],"ZerosInitializer","class ZerosInitializer:",":class:`Initializer` that fills the schema-shaped buffer with zeros.",[2888],{"name":2152,"type":2153,"doc":2597},{"file":2602,"line":1188},{"id":2891,"kind":355,"path":2892,"signature":2169,"source":2893,"parent":2882},"unitrack.states.ZerosInitializer.schema",[331,270,2884,2152],{"file":2602,"line":1068},{"id":2895,"kind":388,"path":2896,"signature":2088,"summary":2897,"source":2898,"parent":2882},"unitrack.states.ZerosInitializer.__call__",[331,270,2884,1009],"Return a zeros buffer shaped for the given detections batch.",{"file":2602,"line":2899},123,{"id":2901,"kind":388,"path":2902,"signature":2903,"source":2904,"parent":2882},"unitrack.states.ZerosInitializer.__init__",[331,270,2884,405],"def __init__(self, schema: TensorSpec) -> None",{"file":2602,"line":341},{"id":2906,"kind":344,"path":2907,"signature":2909,"summary":2910,"description":2911,"params":2912,"source":2925,"parent":2071},"unitrack.states.EnsembleInitializer",[331,270,2908],"EnsembleInitializer","class EnsembleInitializer:",":class:`~unitrack.states.Initializer` spawning an ensemble around a measurement.","Members are ``z + init_std * noise`` with the noise drawn once from a\nfixed-seed generator and mean-centred so the ensemble mean equals ``z``\nexactly. Only this spawn is randomised; predict and update are\ndeterministic.",[2913,2915,2918,2919,2922],{"name":2203,"type":2204,"doc":2914},"Detection field supplying the measurement.",{"name":2916,"type":468,"doc":2917},"ensemble_size","Number of members ``E``.",{"name":2313,"type":468,"doc":2542},{"name":2920,"type":474,"doc":2921},"init_std","Standard deviation of the initial ensemble spread.",{"name":2923,"type":468,"doc":2924},"seed","Seed for the spawn generator.",{"file":2926,"line":558},"unitrack\u002Fstates\u002Fkalman\u002Fensemble.py",{"id":2928,"kind":355,"path":2929,"signature":2221,"source":2930,"parent":2906},"unitrack.states.EnsembleInitializer.field",[331,270,2908,2203],{"file":2926,"line":2931},193,{"id":2933,"kind":355,"path":2934,"signature":2935,"source":2936,"parent":2906},"unitrack.states.EnsembleInitializer.ensemble_size",[331,270,2908,2916],"ensemble_size: int",{"file":2926,"line":587},{"id":2938,"kind":355,"path":2939,"signature":2558,"source":2940,"parent":2906},"unitrack.states.EnsembleInitializer.dim",[331,270,2908,2313],{"file":2926,"line":2941},195,{"id":2943,"kind":355,"path":2944,"signature":2945,"source":2946,"parent":2906},"unitrack.states.EnsembleInitializer.init_std",[331,270,2908,2920],"init_std: float",{"file":2926,"line":2947},196,{"id":2949,"kind":355,"path":2950,"signature":2951,"source":2952,"parent":2906},"unitrack.states.EnsembleInitializer.seed",[331,270,2908,2923],"seed: int",{"file":2926,"line":2953},197,{"id":2955,"kind":388,"path":2956,"signature":2088,"summary":2957,"source":2958,"parent":2906},"unitrack.states.EnsembleInitializer.__call__",[331,270,2908,1009],"Return ``(N, E, D)`` ensemble members centred on the measurement.",{"file":2926,"line":2959},199,{"id":2961,"kind":388,"path":2962,"signature":2963,"source":2964,"parent":2906},"unitrack.states.EnsembleInitializer.__init__",[331,270,2908,405],"def __init__(self, field: str, ensemble_size: int, dim: int, init_std: float, seed: int) -> None",{"file":2926,"line":341},{"id":2966,"kind":344,"path":2967,"signature":2969,"summary":2970,"description":2971,"params":2972,"source":2979,"parent":2071},"unitrack.states.EnsembleProcess",[331,270,2968],"EnsembleProcess","class EnsembleProcess:","Random-walk predict step: multiplicative covariance inflation.","Adds process uncertainty by inflating the ensemble's spread about its\nmean by ``sqrt(1 + q * dt)``. This is the standard EnKF treatment of\nadditive process noise for a random-walk state and leaves the ensemble\nmean (the matched estimate) unchanged.",[2973,2975],{"name":2203,"type":2204,"doc":2974},"Primary mean field. The ensemble members live in\n``f\"{field}_ensemble\"`` with shape ``(N, E, D)``.",{"name":2976,"type":474,"default":2977,"doc":2978},"q","0.01","Per-unit-time process-noise (inflation) scale.",{"file":2926,"line":352},{"id":2981,"kind":355,"path":2982,"signature":2221,"source":2983,"parent":2966},"unitrack.states.EnsembleProcess.field",[331,270,2968,2203],{"file":2926,"line":360},{"id":2985,"kind":355,"path":2986,"signature":2987,"source":2988,"parent":2966},"unitrack.states.EnsembleProcess.q",[331,270,2968,2976],"q: float = 0.01",{"file":2926,"line":688},{"id":2990,"kind":355,"path":2991,"signature":2993,"summary":2994,"source":2995,"parent":2966},"unitrack.states.EnsembleProcess.ensemble_field",[331,270,2968,2992],"ensemble_field","ensemble_field: str","Return the ensemble-members field name.",{"file":2926,"line":2223},{"id":2997,"kind":388,"path":2998,"signature":2134,"summary":2999,"source":3000,"parent":2966},"unitrack.states.EnsembleProcess.__call__",[331,270,2968,1009],"Inflate the ensemble spread about its per-tracklet mean.",{"file":2926,"line":377},{"id":3002,"kind":388,"path":3003,"signature":3004,"source":3005,"parent":2966},"unitrack.states.EnsembleProcess.__init__",[331,270,2968,405],"def __init__(self, field: str, q: float = 0.01) -> None",{"file":2926,"line":341},{"id":3007,"kind":344,"path":3008,"signature":3010,"summary":3011,"description":3012,"params":3013,"source":3022,"parent":2071},"unitrack.states.EnsembleUpdate",[331,270,3009],"EnsembleUpdate","class EnsembleUpdate:","Deterministic ETKF measurement update for matched tracklet-detection pairs.","Works entirely in the ``E``-dimensional ensemble space (``H = I``,\n``R = r I``): forms the analysis-error covariance\n``Pa = [(E-1) I + r^{-1} A A^T]^{-1}``, the mean weights\n``Pa r^{-1} A (z - x̄)``, and a symmetric-square-root transform of the\nperturbations, then maps back to state space. No random perturbed\nobservations. Unmatched tracklets keep their predicted ensemble.",[3014,3016,3018],{"name":2203,"type":2204,"doc":3015},"Primary mean field.",{"name":2264,"type":2204,"doc":3017},"Detection field holding the measurement.",{"name":3019,"type":474,"default":3020,"doc":3021},"r","0.1","Measurement-noise scale.",{"file":2926,"line":385},{"id":3024,"kind":355,"path":3025,"signature":2221,"source":3026,"parent":3007},"unitrack.states.EnsembleUpdate.field",[331,270,3009,2203],{"file":2926,"line":3027},119,{"id":3029,"kind":355,"path":3030,"signature":2278,"source":3031,"parent":3007},"unitrack.states.EnsembleUpdate.meas_field",[331,270,3009,2264],{"file":2926,"line":3032},120,{"id":3034,"kind":355,"path":3035,"signature":3036,"source":3037,"parent":3007},"unitrack.states.EnsembleUpdate.r",[331,270,3009,3019],"r: float = 0.1",{"file":2926,"line":1068},{"id":3039,"kind":355,"path":3040,"signature":2993,"summary":2994,"source":3041,"parent":3007},"unitrack.states.EnsembleUpdate.ensemble_field",[331,270,3009,2992],{"file":2926,"line":2549},{"id":3043,"kind":388,"path":3044,"signature":2109,"summary":3045,"source":3046,"parent":3007},"unitrack.states.EnsembleUpdate.__call__",[331,270,3009,1009],"Transform matched ensembles by the deterministic ETKF analysis.",{"file":2926,"line":2286},{"id":3048,"kind":388,"path":3049,"signature":3050,"source":3051,"parent":3007},"unitrack.states.EnsembleUpdate.__init__",[331,270,3009,405],"def __init__(self, field: str, meas_field: str, r: float = 0.1) -> None",{"file":2926,"line":341},{"id":3053,"kind":344,"path":3054,"signature":3056,"summary":3057,"description":3058,"params":3059,"source":3064,"parent":2071},"unitrack.states.InformationProcess",[331,270,3055],"InformationProcess","class InformationProcess:","Random-walk predict step in information form.","Adds isotropic process noise ``Q = q * dt * I`` to the covariance,\nexpressed on the information matrix via the Woodbury identity\n\n.. math::\n\n    Y' = (Y^{-1} + cI)^{-1} = Y - Y (Y + c^{-1} I)^{-1} Y,\n    \\quad c = q\\,dt,\n\nthen rescales the information vector to preserve the mean\n(``F = I`` leaves ``mu`` unchanged, so ``y' = Y' mu``). A non-positive\n``dt`` is a no-op.",[3060,3062],{"name":2203,"type":2204,"doc":3061},"Primary mean field. The information matrix lives in\n``f\"{field}_infomat\"`` and the information vector in\n``f\"{field}_infovec\"``.",{"name":2976,"type":474,"default":2977,"doc":3063},"Per-unit-time process-noise scale.",{"file":3065,"line":2705},"unitrack\u002Fstates\u002Fkalman\u002Finformation.py",{"id":3067,"kind":355,"path":3068,"signature":2221,"source":3069,"parent":3053},"unitrack.states.InformationProcess.field",[331,270,3055,2203],{"file":3065,"line":922},{"id":3071,"kind":355,"path":3072,"signature":2987,"source":3073,"parent":3053},"unitrack.states.InformationProcess.q",[331,270,3055,2976],{"file":3065,"line":369},{"id":3075,"kind":355,"path":3076,"signature":3078,"summary":3079,"source":3080,"parent":3053},"unitrack.states.InformationProcess.infomat_field",[331,270,3055,3077],"infomat_field","infomat_field: str","Return the information-matrix field name.",{"file":3065,"line":2235},{"id":3082,"kind":355,"path":3083,"signature":3085,"summary":3086,"source":3087,"parent":3053},"unitrack.states.InformationProcess.infovec_field",[331,270,3055,3084],"infovec_field","infovec_field: str","Return the information-vector field name.",{"file":3065,"line":1604},{"id":3089,"kind":388,"path":3090,"signature":2134,"summary":3091,"source":3092,"parent":3053},"unitrack.states.InformationProcess.__call__",[331,270,3055,1009],"Inflate the covariance by ``q * dt`` in information form.",{"file":3065,"line":1763},{"id":3094,"kind":388,"path":3095,"signature":3004,"source":3096,"parent":3053},"unitrack.states.InformationProcess.__init__",[331,270,3055,405],{"file":3065,"line":341},{"id":3098,"kind":344,"path":3099,"signature":3101,"summary":3102,"description":3103,"params":3104,"source":3108,"parent":2071},"unitrack.states.InformationUpdate",[331,270,3100],"InformationUpdate","class InformationUpdate:","Additive measurement update in information form.","For each matched pair (``H = I``, ``R = r I``) the fusion is a plain\nsum, ``Y' = Y + r^{-1} I`` and ``y' = y + r^{-1} z``, after which the\nfiltered mean is recovered as ``mu = Y'^{-1} y'``. Unmatched tracklets\nkeep their predicted state.",[3105,3106,3107],{"name":2203,"type":2204,"doc":3015},{"name":2264,"type":2204,"doc":3017},{"name":3019,"type":474,"default":3020,"doc":3021},{"file":3065,"line":1770},{"id":3110,"kind":355,"path":3111,"signature":2221,"source":3112,"parent":3098},"unitrack.states.InformationUpdate.field",[331,270,3100,2203],{"file":3065,"line":2640},{"id":3114,"kind":355,"path":3115,"signature":2278,"source":3116,"parent":3098},"unitrack.states.InformationUpdate.meas_field",[331,270,3100,2264],{"file":3065,"line":1797},{"id":3118,"kind":355,"path":3119,"signature":3036,"source":3120,"parent":3098},"unitrack.states.InformationUpdate.r",[331,270,3100,3019],{"file":3065,"line":1081},{"id":3122,"kind":355,"path":3123,"signature":3078,"summary":3079,"source":3124,"parent":3098},"unitrack.states.InformationUpdate.infomat_field",[331,270,3100,3077],{"file":3065,"line":774},{"id":3126,"kind":355,"path":3127,"signature":3085,"summary":3086,"source":3128,"parent":3098},"unitrack.states.InformationUpdate.infovec_field",[331,270,3100,3084],{"file":3065,"line":941},{"id":3130,"kind":388,"path":3131,"signature":2109,"summary":3132,"source":3133,"parent":3098},"unitrack.states.InformationUpdate.__call__",[331,270,3100,1009],"Fuse matched detections by adding measurement information.",{"file":3065,"line":788},{"id":3135,"kind":388,"path":3136,"signature":3050,"source":3137,"parent":3098},"unitrack.states.InformationUpdate.__init__",[331,270,3100,405],{"file":3065,"line":341},{"id":3139,"kind":344,"path":3140,"signature":3142,"summary":3143,"description":3144,"params":3145,"raises":3156,"source":3159,"parent":2071},"unitrack.states.KalmanBBox",[331,270,3141],"KalmanBBox","class KalmanBBox:","Constant-velocity bounding-box Kalman process.","Builds the state-transition matrix ``F``, measurement matrix ``H``, and\nisotropic noise covariances ``Q``, ``R`` for one of two bbox models:\n\n- ``\"sort\"`` — 7-D state ``[x, y, a, h, vx, vy, va]``, 4-D measurement\n  ``[x, y, a, h]``. Height carries no velocity, matching the original\n  SORT formulation.\n- ``\"deepsort\"`` — 8-D state ``[x, y, a, h, vx, vy, va, vh]`` with an\n  added height velocity, matching the canonical Kalman-bbox convention.\n\n``Q`` is parameterised as ``q * I_D`` and treated as per-unit-time\nprocess noise: each call accumulates ``q * dt`` along the diagonal of\nthe propagated covariance (see :class:`KalmanLinear` for the exact\nintegration rule). ``R`` is parameterised as ``r * I_4``.",[3146,3149,3150,3151],{"name":2203,"type":2204,"default":3147,"doc":3148},"'bbox'","Field name for the bbox mean. The matching covariance lives in\n``f\"{field}_cov\"``.",{"name":2976,"type":474,"default":2977,"doc":3063},{"name":3019,"type":474,"default":3020,"doc":3021},{"name":3152,"type":3153,"default":3154,"doc":3155},"model","('sort', 'deepsort')","\"sort\"","Bbox motion model. Default ``\"sort\"``.",[3157],{"type":398,"doc":3158},"If ``model`` is not one of ``\"sort\"`` or ``\"deepsort\"``.",{"file":3160,"line":708},"unitrack\u002Fstates\u002Fkalman\u002Fbbox.py",{"id":3162,"kind":355,"path":3163,"signature":3164,"source":3165,"parent":3139},"unitrack.states.KalmanBBox.field",[331,270,3141,2203],"field: str = 'bbox'",{"file":3160,"line":2182},{"id":3167,"kind":355,"path":3168,"signature":2987,"source":3169,"parent":3139},"unitrack.states.KalmanBBox.q",[331,270,3141,2976],{"file":3160,"line":2188},{"id":3171,"kind":355,"path":3172,"signature":3036,"source":3173,"parent":3139},"unitrack.states.KalmanBBox.r",[331,270,3141,3019],{"file":3160,"line":781},{"id":3175,"kind":355,"path":3176,"signature":3177,"source":3178,"parent":3139},"unitrack.states.KalmanBBox.model",[331,270,3141,3152],"model: BBoxModel = 'sort'",{"file":3160,"line":788},{"id":3180,"kind":355,"path":3181,"signature":3183,"summary":3184,"source":3185,"parent":3139},"unitrack.states.KalmanBBox.cov_field",[331,270,3141,3182],"cov_field","cov_field: str","Return auxiliary covariance field name.",{"file":3160,"line":1095},{"id":3187,"kind":355,"path":3188,"signature":3190,"summary":3191,"source":3192,"parent":3139},"unitrack.states.KalmanBBox.state_dim",[331,270,3141,3189],"state_dim","state_dim: int","Return the state dimensionality (7 for SORT, 8 for DeepSORT).",{"file":3160,"line":2800},{"id":3194,"kind":388,"path":3195,"signature":2134,"summary":3196,"source":3197,"parent":3139},"unitrack.states.KalmanBBox.__call__",[331,270,3141,1009],"Advance bbox mean and covariance by one predict step.",{"file":3160,"line":3198},161,{"id":3200,"kind":388,"path":3201,"signature":3203,"summary":3204,"source":3205,"parent":3139},"unitrack.states.KalmanBBox.make_update",[331,270,3141,3202],"make_update","def make_update(self) -> KalmanUpdate","Construct a matching KalmanUpdate for the bbox observation.",{"file":3160,"line":1481},{"id":3207,"kind":388,"path":3208,"signature":3210,"summary":3211,"description":3212,"params":3213,"returns":3219,"source":3221,"parent":3139},"unitrack.states.KalmanBBox.state_entries",[331,270,3141,3209],"state_entries","def state_entries(self, meas_field: str | None = None, init_cov_scale: float = 1.0) -> dict[str, State]","Return ``(mean, cov)`` :class:`~unitrack.states.State` entries.","Mean is a 7-D ``[x, y, a, h, vx, vy, va]`` (SORT) or 8-D\n``[x, y, a, h, vx, vy, va, vh]`` (DeepSORT) state seeded from the\ndetection field ``meas_field``; the detection must already be in\n``[x, y, a, h]`` order — convert from xyxy upstream.",[3214,3216],{"name":2264,"type":2204,"default":486,"doc":3215},"Detection field that supplies the initial measurement. Defaults\nto :attr:`field`.",{"name":3217,"type":474,"default":475,"doc":3218},"init_cov_scale","Scale applied to the identity matrix used to initialise the\ncovariance. Default ``1.0``.",{"type":2326,"doc":3220},"Two :class:`~unitrack.states.State` entries keyed by\n``self.field`` (mean) and ``f\"{self.field}_cov\"`` (covariance).",{"file":3160,"line":2811},{"id":3223,"kind":388,"path":3224,"signature":3225,"source":3226,"parent":3139},"unitrack.states.KalmanBBox.__init__",[331,270,3141,405],"def __init__(self, field: str = 'bbox', q: float = 0.01, r: float = 0.1, model: BBoxModel = 'sort') -> None",{"file":3160,"line":341},{"id":3228,"kind":344,"path":3229,"signature":3231,"summary":3232,"description":3233,"params":3234,"source":3240,"parent":2071},"unitrack.states.KalmanCentroid2D",[331,270,3230],"KalmanCentroid2D","class KalmanCentroid2D:","Constant-velocity 2-D centroid Kalman process.","State is 4-D ``[x, y, vx, vy]``; measurement is 2-D ``[x, y]``. The\nstate-transition matrix injects ``dt`` into the position-velocity\ncross-terms, and ``H`` reads the leading two entries (position).\nProcess noise is parameterised as ``q * I_4`` and integrated as\nper-unit-time noise (see :class:`KalmanLinear`); measurement noise is\n``r * I_2``.",[3235,3238,3239],{"name":2203,"type":2204,"default":3236,"doc":3237},"'centroid'","Field name for the centroid mean. Covariance lives in\n``f\"{field}_cov\"``.",{"name":2976,"type":474,"default":2977,"doc":3063},{"name":3019,"type":474,"default":3020,"doc":3021},{"file":3241,"line":2069},"unitrack\u002Fstates\u002Fkalman\u002Fcentroid.py",{"id":3243,"kind":355,"path":3244,"signature":3245,"source":3246,"parent":3228},"unitrack.states.KalmanCentroid2D.field",[331,270,3230,2203],"field: str = 'centroid'",{"file":3241,"line":360},{"id":3248,"kind":355,"path":3249,"signature":2987,"source":3250,"parent":3228},"unitrack.states.KalmanCentroid2D.q",[331,270,3230,2976],{"file":3241,"line":688},{"id":3252,"kind":355,"path":3253,"signature":3036,"source":3254,"parent":3228},"unitrack.states.KalmanCentroid2D.r",[331,270,3230,3019],{"file":3241,"line":922},{"id":3256,"kind":355,"path":3257,"signature":3183,"summary":3184,"source":3258,"parent":3228},"unitrack.states.KalmanCentroid2D.cov_field",[331,270,3230,3182],{"file":3241,"line":2229},{"id":3260,"kind":388,"path":3261,"signature":2134,"summary":3262,"source":3263,"parent":3228},"unitrack.states.KalmanCentroid2D.__call__",[331,270,3230,1009],"Advance centroid mean and covariance by one predict step.",{"file":3241,"line":2429},{"id":3265,"kind":388,"path":3266,"signature":3203,"summary":3267,"source":3268,"parent":3228},"unitrack.states.KalmanCentroid2D.make_update",[331,270,3230,3202],"Construct a matching KalmanUpdate for the 2D centroid observation.",{"file":3241,"line":3269},97,{"id":3271,"kind":388,"path":3272,"signature":3210,"summary":3273,"description":3274,"params":3275,"returns":3278,"source":3280,"parent":3228},"unitrack.states.KalmanCentroid2D.state_entries",[331,270,3230,3209],"Return ``(mean, cov)`` :class:`~unitrack.states.State` entries for ``Tracker``.","The mean entry holds a 4-D ``[x, y, vx, vy]`` state seeded from\n``meas_field``; the cov entry holds a 4-by-4 covariance no-op'd\nthrough predict\u002Fupdate because the mean entry's\n:class:`KalmanLinear` \u002F :class:`KalmanUpdate` already write the\ncovariance as a side effect.",[3276,3277],{"name":2264,"type":2204,"default":486,"doc":3215},{"name":3217,"type":474,"default":475,"doc":3218},{"type":2326,"doc":3279},"Two :class:`~unitrack.states.State` entries keyed by\n``self.field`` and ``f\"{self.field}_cov\"``.",{"file":3241,"line":3281},106,{"id":3283,"kind":388,"path":3284,"signature":3285,"source":3286,"parent":3228},"unitrack.states.KalmanCentroid2D.__init__",[331,270,3230,405],"def __init__(self, field: str = 'centroid', q: float = 0.01, r: float = 0.1) -> None",{"file":3241,"line":341},{"id":3288,"kind":344,"path":3289,"signature":3291,"summary":3292,"description":3293,"params":3294,"source":3298,"parent":2071},"unitrack.states.KalmanCentroid3D",[331,270,3290],"KalmanCentroid3D","class KalmanCentroid3D:","Constant-velocity 3-D centroid Kalman process.","State is 6-D ``[x, y, z, vx, vy, vz]``; measurement is 3-D\n``[x, y, z]``. The state-transition matrix injects ``dt`` into each\nposition-velocity cross-term, and ``H`` reads the leading three entries\n(position). Process noise is parameterised as ``q * I_6`` and\nintegrated as per-unit-time noise; measurement noise is ``r * I_3``.",[3295,3296,3297],{"name":2203,"type":2204,"default":3236,"doc":3237},{"name":2976,"type":474,"default":2977,"doc":3063},{"name":3019,"type":474,"default":3020,"doc":3021},{"file":3241,"line":1640},{"id":3300,"kind":355,"path":3301,"signature":3245,"source":3302,"parent":3288},"unitrack.states.KalmanCentroid3D.field",[331,270,3290,2203],{"file":3241,"line":563},{"id":3304,"kind":355,"path":3305,"signature":2987,"source":3306,"parent":3288},"unitrack.states.KalmanCentroid3D.q",[331,270,3290,2976],{"file":3241,"line":3307},172,{"id":3309,"kind":355,"path":3310,"signature":3036,"source":3311,"parent":3288},"unitrack.states.KalmanCentroid3D.r",[331,270,3290,3019],{"file":3241,"line":3312},173,{"id":3314,"kind":355,"path":3315,"signature":3183,"summary":3184,"source":3316,"parent":3288},"unitrack.states.KalmanCentroid3D.cov_field",[331,270,3290,3182],{"file":3241,"line":569},{"id":3318,"kind":388,"path":3319,"signature":2134,"summary":3262,"source":3320,"parent":3288},"unitrack.states.KalmanCentroid3D.__call__",[331,270,3290,1009],{"file":3241,"line":1887},{"id":3322,"kind":388,"path":3323,"signature":3203,"summary":3324,"source":3325,"parent":3288},"unitrack.states.KalmanCentroid3D.make_update",[331,270,3290,3202],"Construct a matching KalmanUpdate for the 3D centroid observation.",{"file":3241,"line":3326},192,{"id":3328,"kind":388,"path":3329,"signature":3210,"summary":3273,"description":3330,"params":3331,"returns":3334,"source":3335,"parent":3288},"unitrack.states.KalmanCentroid3D.state_entries",[331,270,3290,3209],"The mean entry holds a 6-D ``[x, y, z, vx, vy, vz]`` state seeded\nfrom ``meas_field``; the cov entry holds a 6-by-6 covariance.",[3332,3333],{"name":2264,"type":2204,"default":486,"doc":3215},{"name":3217,"type":474,"default":475,"doc":3218},{"type":2326,"doc":3279},{"file":3241,"line":3336},201,{"id":3338,"kind":388,"path":3339,"signature":3285,"source":3340,"parent":3288},"unitrack.states.KalmanCentroid3D.__init__",[331,270,3290,405],{"file":3241,"line":341},{"id":3342,"kind":344,"path":3343,"signature":3345,"summary":3346,"description":3347,"params":3348,"raises":3367,"source":3370,"parent":2071},"unitrack.states.KalmanLinear",[331,270,3344],"KalmanLinear","class KalmanLinear:","Linear-Gaussian Kalman predict step.","Reads ``cs.{field}`` (mean, shape ``(N, D)``) and ``cs.{field}_cov``\n(covariance, shape ``(N, D, D)``) and writes both back as\n\n.. math::\n\n    x' = F x, \\qquad P' = F P F^T + Q \\cdot dt.",[3349,3351,3354,3357,3360,3363],{"name":2203,"type":2204,"doc":3350},"Field name for the mean. Covariance lives in ``f\"{field}_cov\"``.",{"name":3352,"type":646,"doc":3353},"F","``(D, D)`` state-transition matrix.",{"name":3355,"type":646,"doc":3356},"H","``(M, D)`` measurement matrix. Stored here for the paired\n:class:`KalmanUpdate` factory; not used by the predict step\nitself.",{"name":3358,"type":646,"doc":3359},"Q","``(D, D)`` process-noise covariance (per unit time when\n``dt_scale_q=True``).",{"name":3361,"type":646,"doc":3362},"R","``(M, M)`` measurement-noise covariance. Stored for the paired\nupdate; not used by the predict step itself.",{"name":3364,"type":1617,"default":3365,"doc":3366},"dt_scale_q","True","Multiply ``Q`` by ``ctx.delta`` before adding to the predicted\ncovariance. Default ``True``.",[3368],{"type":398,"doc":3369},"If ``F``, ``H``, ``Q``, and ``R`` do not all share the same dtype\n(would force silent per-call casting).",{"file":3371,"line":1128},"unitrack\u002Fstates\u002Fkalman\u002Fbase.py",{"id":3373,"kind":355,"path":3374,"signature":2221,"source":3375,"parent":3342},"unitrack.states.KalmanLinear.field",[331,270,3344,2203],{"file":3371,"line":2837},{"id":3377,"kind":363,"path":3378,"signature":3379,"source":3380,"parent":3342},"unitrack.states.KalmanLinear.F",[331,270,3344,3352],"F: torch.Tensor",{"file":3371,"line":3381},70,{"id":3383,"kind":363,"path":3384,"signature":3385,"source":3386,"parent":3342},"unitrack.states.KalmanLinear.H",[331,270,3344,3355],"H: torch.Tensor",{"file":3371,"line":2517},{"id":3388,"kind":363,"path":3389,"signature":3390,"source":3391,"parent":3342},"unitrack.states.KalmanLinear.Q",[331,270,3344,3358],"Q: torch.Tensor",{"file":3371,"line":3392},72,{"id":3394,"kind":363,"path":3395,"signature":3396,"source":3397,"parent":3342},"unitrack.states.KalmanLinear.R",[331,270,3344,3361],"R: torch.Tensor",{"file":3371,"line":3398},73,{"id":3400,"kind":355,"path":3401,"signature":3402,"source":3403,"parent":3342},"unitrack.states.KalmanLinear.dt_scale_q",[331,270,3344,3364],"dt_scale_q: bool = True",{"file":3371,"line":3404},74,{"id":3406,"kind":355,"path":3407,"signature":3183,"summary":3184,"source":3408,"parent":3342},"unitrack.states.KalmanLinear.cov_field",[331,270,3344,3182],{"file":3371,"line":1604},{"id":3410,"kind":388,"path":3411,"signature":2134,"summary":3412,"source":3413,"parent":3342},"unitrack.states.KalmanLinear.__call__",[331,270,3344,1009],"Advance mean and covariance by one predict step.",{"file":3371,"line":1763},{"id":3415,"kind":388,"path":3416,"signature":3417,"source":3418,"parent":3342},"unitrack.states.KalmanLinear.__init__",[331,270,3344,405],"def __init__(self, field: str, F: torch.Tensor, H: torch.Tensor, Q: torch.Tensor, R: torch.Tensor, dt_scale_q: bool = True) -> None",{"file":3371,"line":341},{"id":3420,"kind":344,"path":3421,"signature":3423,"summary":3424,"description":3425,"params":3426,"raises":3435,"source":3438,"parent":2071},"unitrack.states.KalmanUpdate",[331,270,3422],"KalmanUpdate","class KalmanUpdate:","Kalman measurement update (Joseph form) for matched tracklet-detection pairs.","Reads predicted mean ``cs.{field}`` of shape ``(N, D)`` and covariance\n``cs.{cov_field}`` of shape ``(N, D, D)``, reads detection\nmeasurements ``ds.{field}`` of shape ``(M, M_dim)``, and writes back\nthe updated mean and covariance for matched tracklets. Unmatched\ntracklets keep their predicted state (predict-only on miss).\n\nThe update applies the standard Kalman gain\n``K = P H^T (H P H^T + R)^{-1}`` via ``solve_psd``, then\npropagates covariance through the Joseph form\n``(I - K H) P (I - K H)^T + K R K^T`` to preserve positive\nsemi-definiteness under finite-precision arithmetic. The result is\nsymmetrised to remove off-diagonal drift that accumulates over long\nsequences.\n\n``H`` shape ``(M_dim, D)`` is the measurement matrix and ``R`` shape\n``(M_dim, M_dim)`` is the measurement-noise covariance. Each\nbbox\u002Fcentroid process ships a ``make_update(...)`` factory that\nconstructs the matching :class:`KalmanUpdate`.",[3427,3429,3431,3433],{"name":2203,"type":2204,"doc":3428},"Field name for the mean.",{"name":3182,"type":2204,"doc":3430},"Field name for the covariance.",{"name":3355,"type":646,"doc":3432},"``(M_dim, D)`` measurement matrix.",{"name":3361,"type":646,"doc":3434},"``(M_dim, M_dim)`` measurement-noise covariance.",[3436],{"type":398,"doc":3437},"If ``H`` and ``R`` have different dtypes (would force silent\nper-call casting).",{"file":3439,"line":3440},"unitrack\u002Fstates\u002Fkalman\u002Fupdate.py",15,{"id":3442,"kind":355,"path":3443,"signature":2221,"source":3444,"parent":3420},"unitrack.states.KalmanUpdate.field",[331,270,3422,2203],{"file":3439,"line":682},{"id":3446,"kind":355,"path":3447,"signature":3183,"source":3448,"parent":3420},"unitrack.states.KalmanUpdate.cov_field",[331,270,3422,3182],{"file":3439,"line":1577},{"id":3450,"kind":363,"path":3451,"signature":3385,"source":3452,"parent":3420},"unitrack.states.KalmanUpdate.H",[331,270,3422,3355],{"file":3439,"line":1196},{"id":3454,"kind":363,"path":3455,"signature":3396,"source":3456,"parent":3420},"unitrack.states.KalmanUpdate.R",[331,270,3422,3361],{"file":3439,"line":2121},{"id":3458,"kind":388,"path":3459,"signature":2109,"summary":3460,"source":3461,"parent":3420},"unitrack.states.KalmanUpdate.__call__",[331,270,3422,1009],"Apply Kalman measurement update for matched tracklet-detection pairs.",{"file":3439,"line":3392},{"id":3463,"kind":388,"path":3464,"signature":3465,"source":3466,"parent":3420},"unitrack.states.KalmanUpdate.__init__",[331,270,3422,405],"def __init__(self, field: str, cov_field: str, H: torch.Tensor, R: torch.Tensor) -> None",{"file":3439,"line":341},{"id":3468,"kind":2303,"path":3469,"signature":3471,"summary":3472,"description":3473,"params":3474,"returns":3489,"source":3491,"parent":2071},"unitrack.states.enkf_state_entries",[331,270,3470],"enkf_state_entries","def enkf_state_entries(field: str, dim: int, meas_field: str | None = None, ensemble_size: int = 32, q: float = 0.01, r: float = 0.1, init_std: float = 0.3, seed: int = 0) -> dict[str, State]","Build the ``(mean, ensemble)`` state entries for an Ensemble Kalman filter.","The mean entry holds the ensemble mean ``(dim,)`` used for matching; the\nensemble entry holds the ``(ensemble_size, dim)`` members, no-op'd\nthrough predict\u002Fupdate because the mean entry's :class:`EnsembleProcess`\n\u002F :class:`EnsembleUpdate` maintain them.",[3475,3477,3478,3480,3483,3484,3485,3487],{"name":2203,"type":2204,"doc":3476},"Name of the mean field (and prefix for ``f\"{field}_ensemble\"``).",{"name":2313,"type":468,"doc":2314},{"name":2264,"type":2204,"default":486,"doc":3479},"Detection field supplying the measurement. Defaults to\n:paramref:`field`.",{"name":2916,"type":468,"default":3481,"doc":3482},"32","Number of ensemble members.",{"name":2976,"type":474,"default":2977,"doc":2978},{"name":3019,"type":474,"default":3020,"doc":3021},{"name":2920,"type":474,"default":3486,"doc":2921},"0.3",{"name":2923,"type":468,"default":479,"doc":3488},"Seed for the ensemble spawn generator.",{"type":2326,"doc":3490},"Two :class:`~unitrack.states.State` entries keyed by ``field`` and\n``f\"{field}_ensemble\"``.",{"file":2926,"line":3492},217,{"id":3494,"kind":2303,"path":3495,"signature":3497,"summary":3498,"description":3499,"params":3500,"returns":3510,"source":3512,"parent":2071},"unitrack.states.information_state_entries",[331,270,3496],"information_state_entries","def information_state_entries(field: str, dim: int, meas_field: str | None = None, q: float = 0.01, r: float = 0.1, init_var: float = 1.0) -> dict[str, State]","Build the ``(mean, infomat, infovec)`` entries for an information filter.","The mean entry holds the recovered ``(dim,)`` estimate (match it with\nany embedding cost). The information-matrix and -vector entries are\nno-op'd through predict\u002Fupdate because the mean entry's\n:class:`InformationProcess` \u002F :class:`InformationUpdate` maintain them.",[3501,3503,3504,3505,3506,3507],{"name":2203,"type":2204,"doc":3502},"Name of the mean field (and prefix for the auxiliary fields).",{"name":2313,"type":468,"doc":2314},{"name":2264,"type":2204,"default":486,"doc":3479},{"name":2976,"type":474,"default":2977,"doc":3063},{"name":3019,"type":474,"default":3020,"doc":3021},{"name":3508,"type":474,"default":475,"doc":3509},"init_var","Initial per-dimension variance; the spawned information matrix is\n``(1 \u002F init_var) I``.",{"type":2326,"doc":3511},"Three :class:`~unitrack.states.State` entries keyed by ``field``,\n``f\"{field}_infomat\"`` and ``f\"{field}_infovec\"``.",{"file":3065,"line":3513},177,{"id":3515,"kind":344,"path":3516,"signature":3518,"summary":3519,"params":3520,"source":3527,"parent":2071},"unitrack.states.LearnedObservation",[331,270,3517],"LearnedObservation","class LearnedObservation:","Update step that fuses matched detections with a learned module.",[3521,3523,3524],{"name":2203,"type":2204,"doc":3522},"Tracklet field to update.",{"name":2264,"type":2204,"doc":3017},{"name":335,"type":3525,"doc":3526},"callable","Callable ``(track: (K, D), measurement: (K, D)) -> (K, D)`` — e.g. a\n``GRUCell``-style gated update. Applied to matched pairs only.",{"file":3528,"line":1411},"unitrack\u002Fstates\u002Flearned.py",{"id":3530,"kind":355,"path":3531,"signature":2221,"source":3532,"parent":3515},"unitrack.states.LearnedObservation.field",[331,270,3517,2203],{"file":3528,"line":3404},{"id":3534,"kind":355,"path":3535,"signature":2278,"source":3536,"parent":3515},"unitrack.states.LearnedObservation.meas_field",[331,270,3517,2264],{"file":3528,"line":1417},{"id":3538,"kind":355,"path":3539,"signature":3540,"source":3541,"parent":3515},"unitrack.states.LearnedObservation.module",[331,270,3517,335],"module: typing.Callable",{"file":3528,"line":360},{"id":3543,"kind":388,"path":3544,"signature":2109,"summary":3545,"source":3546,"parent":3515},"unitrack.states.LearnedObservation.__call__",[331,270,3517,1009],"Apply the learned update module to matched tracklet-detection pairs.",{"file":3528,"line":922},{"id":3548,"kind":388,"path":3549,"signature":3550,"source":3551,"parent":3515},"unitrack.states.LearnedObservation.__init__",[331,270,3517,405],"def __init__(self, field: str, meas_field: str, module: typing.Callable) -> None",{"file":3528,"line":341},{"id":3553,"kind":344,"path":3554,"signature":3556,"summary":3557,"params":3558,"source":3563,"parent":2071},"unitrack.states.LearnedProcess",[331,270,3555],"LearnedProcess","class LearnedProcess:","Predict step that applies a learned module to every tracklet's field.",[3559,3561],{"name":2203,"type":2204,"doc":3560},"Tracklet field to propagate.",{"name":335,"type":3525,"doc":3562},"Callable ``(field_tensor: (N, D), dt: float) -> (N, D)`` — e.g. a\n``torch.nn.Module`` implementing a recurrent query update. Invoked\nonce per frame on all live tracklets.",{"file":3528,"line":891},{"id":3565,"kind":355,"path":3566,"signature":2221,"source":3567,"parent":3553},"unitrack.states.LearnedProcess.field",[331,270,3555,2203],{"file":3528,"line":663},{"id":3569,"kind":355,"path":3570,"signature":3540,"source":3571,"parent":3553},"unitrack.states.LearnedProcess.module",[331,270,3555,335],{"file":3528,"line":855},{"id":3573,"kind":388,"path":3574,"signature":2134,"summary":3575,"source":3576,"parent":3553},"unitrack.states.LearnedProcess.__call__",[331,270,3555,1009],"Apply the learned propagation module to the field.",{"file":3528,"line":1048},{"id":3578,"kind":388,"path":3579,"signature":3580,"source":3581,"parent":3553},"unitrack.states.LearnedProcess.__init__",[331,270,3555,405],"def __init__(self, field: str, module: typing.Callable) -> None",{"file":3528,"line":341},{"id":3583,"kind":344,"path":3584,"signature":3586,"summary":3587,"description":3588,"params":3589,"source":3594,"parent":2071},"unitrack.states.SoftReplace",[331,270,3585],"SoftReplace","class SoftReplace:","Differentiable :class:`~unitrack.states.Replace` driven by a transport plan.","Each tracklet's field becomes ``sum_j p[i, j] * detection.field[j]``,\nwhere ``p`` is an ``(N, M)`` row-stochastic transport plan. For\n``p[i] = e_j`` (one-hot) this reduces to the hard :class:`~unitrack.states.Replace`.\n\n``soft_assignment`` may be supplied at construction when the caller\nhas already computed the plan; otherwise the plan is read at call\ntime from ``match.soft_plan`` (attribute on :class:`~unitrack.data.MatchOutcome`),\nwhich :class:`~unitrack.assignment.Associate` attaches automatically\nwhen its assignment backend is a\n:class:`~unitrack.assignment.SoftAssignment`.\n\nRows of the transport plan that sum to zero (every pair forbidden by\nan upstream gate) preserve the prior tracklet field rather than\noverwriting it with the all-zero blend that ``plan @ v`` would\nproduce — that would silently destroy re-id embeddings for\nfully-gated tracklets.",[3590,3591],{"name":2203,"type":2204,"doc":2394},{"name":3592,"type":646,"default":486,"doc":3593},"soft_assignment","Precomputed ``(N, M)`` transport plan. If ``None``, the plan is\nread from ``match.soft_plan`` at call time.",{"file":3595,"line":1128},"unitrack\u002Fstates\u002Fsoft.py",{"id":3597,"kind":355,"path":3598,"signature":2221,"source":3599,"parent":3583},"unitrack.states.SoftReplace.field",[331,270,3585,2203],{"file":3595,"line":855},{"id":3601,"kind":355,"path":3602,"signature":3603,"source":3604,"parent":3583},"unitrack.states.SoftReplace.soft_assignment",[331,270,3585,3592],"soft_assignment: torch.Tensor | None = None",{"file":3595,"line":862},{"id":3606,"kind":388,"path":3607,"signature":2109,"summary":3608,"params":3609,"returns":3615,"raises":3617,"source":3621,"parent":3583},"unitrack.states.SoftReplace.__call__",[331,270,3585,1009],"Blend each tracklet field as a weighted sum of detection values.",[3610,3611,3612,3614],{"name":1174,"type":581,"doc":1995},{"name":1177,"type":394,"doc":2114},{"name":215,"type":824,"doc":3613},"Matched pairs and (optionally) attached transport plan.",{"name":1180,"type":452,"doc":1181},{"type":581,"doc":3616},"New snapshot with the field updated.",[3618],{"type":3619,"doc":3620},"RuntimeError","If no transport plan is available — neither passed at\nconstruction nor attached to ``match``.",{"file":3595,"line":874},{"id":3623,"kind":388,"path":3624,"signature":3625,"source":3626,"parent":3583},"unitrack.states.SoftReplace.__init__",[331,270,3585,405],"def __init__(self, field: str, soft_assignment: torch.Tensor | None = None) -> None",{"file":3595,"line":341},{"id":3628,"kind":335,"path":3629,"signature":3630,"summary":3631,"source":3632,"parent":2071},"unitrack.states.soft",[331,270,233],"module unitrack.states.soft","Differentiable :class:`Observation` companions used under ``differentiable=True``.",{"file":3595,"line":341},{"id":3634,"kind":335,"path":3635,"signature":3636,"summary":3637,"description":3638,"source":3639,"parent":2071},"unitrack.states.learned",[331,270,309],"module unitrack.states.learned","Learned propagation hooks — a slot for a MOTR-style recurrent update.","DETR-based trackers (MOTR, TrackFormer, MeMOTR) do not filter the track\nembedding with a hand-written motion model; they let a *learned* module\npropagate the track query from frame to frame and fuse the new detection.\nThat is a learned recurrent filter, not a closed-form one, so unitrack\nsupports it as a pair of hooks that wrap any callable \u002F ``torch.nn.Module``:\n\n- :class:`LearnedProcess` is the predict step — ``query \u003C- module(query, dt)``.\n- :class:`LearnedObservation` is the update step —\n  ``query \u003C- module(query, measurement)`` for matched pairs.\n\nBecause the wrapped module is autograd-native, these are the differentiable\nmember of the embedding-filter family: a tracking loss can backpropagate\ninto the propagation\u002Fupdate module (and through it, the backbone).",{"file":3528,"line":341},{"id":3641,"kind":335,"path":3642,"signature":3643,"summary":3644,"description":3645,"source":3646,"parent":2071},"unitrack.states.directional",[331,270,275],"module unitrack.states.directional","von Mises-Fisher directional filter for unit-norm embedding states.","A recursive Bayesian filter for appearance\u002Fkernel embeddings that live on\nthe unit sphere (cosine geometry). The belief over a tracklet's embedding is\na von Mises-Fisher distribution with mean direction ``mu`` (a unit vector)\nand concentration ``kappa >= 0`` (larger = more certain). The vMF mean\ndirection has a conjugate vMF prior, so combining the prior with a new\nobservation is exact: the posterior parameter is the *resultant* of the two\nconcentration-weighted directions,\n\n.. math::\n\n    R = \\kappa\\,\\mu + \\kappa_{obs}\\,\\hat z,\\quad\n    \\mu' = R \u002F \\lVert R \\rVert,\\quad \\kappa' = \\lVert R \\rVert,\n\nwhich is the directional analogue of a Kalman update. The predict step has\nno motion model for appearance, so it only *decays* the concentration:\nconfidence in a stale embedding fades with time.",{"file":2217,"line":341},{"id":3648,"kind":335,"path":3649,"signature":3650,"summary":3651,"source":3652,"parent":2071},"unitrack.states.identity",[331,270,283],"module unitrack.states.identity","Identity ``Process``, ``Replace``, and simple ``Initializer`` recipes.",{"file":2602,"line":341},{"id":3654,"kind":335,"path":3655,"signature":3656,"summary":3657,"description":3658,"source":3659,"parent":2071},"unitrack.states.gallery",[331,270,191],"module unitrack.states.gallery","Gallery (feature-bank) state — keep a ring buffer of recent embeddings.","The non-parametric memory-bank approach to appearance: instead of a single\nfiltered embedding, each tracklet stores its last ``K`` matched embeddings.\nMatching then consults the whole buffer (see\n:class:`~unitrack.costs.GalleryCost`), so one good past view re-associates an\nobject whose current appearance has drifted. The primary field still holds\nthe most recent embedding, so plain :class:`~unitrack.costs.Cosine` matching\nalso works as a fallback.",{"file":2491,"line":341},{"id":3661,"kind":335,"path":3662,"signature":3663,"summary":3664,"source":3665,"parent":2071},"unitrack.states.ema",[331,270,278],"module unitrack.states.ema","EMA-family :class:`~unitrack.states.Process` and :class:`Observation` primitives.",{"file":2350,"line":341},{"id":3667,"kind":335,"path":3668,"signature":3669,"summary":3670,"source":3671,"parent":2071},"unitrack.states.base",[331,270,259],"module unitrack.states.base","State, Process, Observation, and Initializer protocols.",{"file":2084,"line":341},{"id":3673,"kind":335,"path":3674,"signature":3675,"summary":3676,"source":3677,"parent":2071},"unitrack.states.kalman",[331,270,286],"module unitrack.states.kalman","Kalman filter state family for unitrack.",{"file":3678,"line":341},"unitrack\u002Fstates\u002Fkalman\u002F__init__.py",{"id":3680,"kind":335,"path":3681,"signature":3682,"summary":3683,"source":3684,"parent":3673},"unitrack.states.kalman.update",[331,270,286,306],"module unitrack.states.kalman.update","KalmanUpdate Observation — Joseph-form update; predict-only on miss.",{"file":3439,"line":341},{"id":3686,"kind":335,"path":3687,"signature":3688,"summary":3689,"description":3690,"source":3691,"parent":3673},"unitrack.states.kalman.bbox",[331,270,286,291],"module unitrack.states.kalman.bbox","Bounding-box Kalman processes — SORT (7-D) and DeepSORT (8-D) variants.","Two models ship in-tree:\n\n- ``\"sort\"`` (default, 7-D state): ``[x, y, a, h, vx, vy, va]``. Aspect ratio\n  ``a`` carries a velocity ``va``; height ``h`` is observed but has no\n  velocity (matches the original SORT formulation, where height changes\n  are absorbed by the measurement-update step rather than predicted).\n- ``\"deepsort\"`` (8-D state): ``[x, y, a, h, vx, vy, va, vh]``. Adds a\n  height-velocity ``vh`` to match the DeepSORT \u002F canonical-Kalman-bbox\n  convention used by most modern tracking-by-detection pipelines.\n\nBoth models observe the same 4-D measurement ``[x, y, a, h]``.",{"file":3160,"line":341},{"id":3693,"kind":355,"path":3694,"signature":3696,"source":3697,"parent":3686},"unitrack.states.kalman.bbox.BBoxModel",[331,270,286,291,3695],"BBoxModel","BBoxModel = typing.Literal['sort', 'deepsort']",{"file":3160,"line":2356},{"id":3699,"kind":335,"path":3700,"signature":3701,"summary":3702,"source":3703,"parent":3673},"unitrack.states.kalman.centroid",[331,270,286,294],"module unitrack.states.kalman.centroid","Constant-velocity centroid Kalman process specializations.",{"file":3241,"line":341},{"id":3705,"kind":335,"path":3706,"signature":3707,"summary":3708,"description":3709,"source":3710,"parent":3673},"unitrack.states.kalman.ensemble",[331,270,286,297],"module unitrack.states.kalman.ensemble","Ensemble Kalman filter (deterministic ETKF) for high-dimensional states.","A Kalman filter on a D-dimensional embedding needs a D-by-D covariance,\nwhich is expensive and ill-conditioned when D is large (e.g. a 256-d DETR\nquery). The Ensemble Kalman Filter sidesteps this: it never forms the\ncovariance explicitly, representing the belief by an ensemble of ``E``\nsample states whose spread *implies* the covariance. Cost scales with the\nensemble size, not ``D``-squared, which is why EnKF is the method of choice\nfor very high-dimensional filtering (its original home is numerical weather\nprediction with millions of dimensions).\n\nThe update here is the deterministic **Ensemble Transform Kalman Filter**\n(ETKF; Bishop 2001, Hunt 2007) with ``H = I`` and ``R = r I`` and no\nlocalisation: the analysis ensemble is a closed-form linear transform of\nthe forecast ensemble computed in the ``E``-dimensional ensemble space, so\nno random perturbed observations are needed and the step is reproducible.\nThe predict step is multiplicative covariance inflation, the standard EnKF\ntreatment of process noise for a random-walk state. Only the one-time\nensemble spawn is randomised, from a fixed seed.",{"file":2926,"line":341},{"id":3712,"kind":335,"path":3713,"signature":3714,"summary":3715,"source":3716,"parent":3673},"unitrack.states.kalman.project",[331,270,286,303],"module unitrack.states.kalman.project","Measurement-projection and PSD-solve helpers used by Mahalanobis primitives.",{"file":3717,"line":341},"unitrack\u002Fstates\u002Fkalman\u002Fproject.py",{"id":3719,"kind":2303,"path":3720,"signature":3722,"summary":3723,"description":3724,"params":3725,"returns":3735,"raises":3737,"source":3740,"parent":3712},"unitrack.states.kalman.project.project_to_measurement",[331,270,286,303,3721],"project_to_measurement","def project_to_measurement(mean: torch.Tensor, cov: torch.Tensor, d_meas: int) -> tuple[torch.Tensor, torch.Tensor]","Truncate a Kalman state and covariance to the measurement subspace.","Mirrors :class:`unitrack.gates.MotionGate`: when the state has higher\ndimension than the measurement (e.g. a 6-D CV state vs a 3-D centroid\ndetection), the measurement matrix is taken as ``H = [I, 0]`` and the\nleading ``d_meas`` rows and columns are returned. When the dimensions\nalready match the inputs are returned unchanged.",[3726,3729,3732],{"name":3727,"type":646,"doc":3728},"mean","``(..., D)`` state mean.",{"name":3730,"type":646,"doc":3731},"cov","``(..., D, D)`` state covariance.",{"name":3733,"type":468,"doc":3734},"d_meas","Measurement subspace dimension. Must be ``\u003C= D``.",{"type":646,"doc":3736},"``(..., d_meas)`` truncated mean.",[3738],{"type":398,"doc":3739},"If ``d_meas`` is greater than the state dimension.",{"file":3717,"line":2026},{"id":3742,"kind":2303,"path":3743,"signature":3745,"summary":3746,"params":3747,"returns":3756,"raises":3758,"source":3761,"parent":3712},"unitrack.states.kalman.project.solve_psd",[331,270,286,303,3744],"solve_psd","def solve_psd(cov: torch.Tensor, rhs: torch.Tensor, label: str) -> torch.Tensor","Solve ``cov @ x = rhs`` for a (batch of) PSD covariance(s).",[3748,3750,3753],{"name":3730,"type":646,"doc":3749},"``(..., D, D)`` positive-semi-definite system matrix.",{"name":3751,"type":646,"doc":3752},"rhs","``(..., D, K)`` right-hand side.",{"name":3754,"type":2204,"doc":3755},"label","Identifier embedded in the error message on failure.",{"type":646,"doc":3757},"``(..., D, K)`` solution tensor.",[3759],{"type":3619,"doc":3760},"If the solve produces non-finite values, indicating a singular\ncovariance or PSD-cone drift. The caller should re-tune\nprocess\u002Fmeasurement noise or the initial covariance.",{"file":3717,"line":1411},{"id":3763,"kind":2303,"path":3764,"signature":3766,"summary":3767,"description":3768,"params":3769,"returns":3781,"source":3783,"parent":3712},"unitrack.states.kalman.project.mahalanobis_d2",[331,270,286,303,3765],"mahalanobis_d2","def mahalanobis_d2(cs_field: torch.Tensor, cs_cov: torch.Tensor, ds_field: torch.Tensor, label: str) -> torch.Tensor","Pairwise Mahalanobis chi-squared over a measurement subspace.","Truncates the state to ``ds_field``'s dimension (``H = [I, 0]``),\nthen solves :math:`\\Sigma x = (a - b)` per pair and returns\n:math:`(a - b)^T x`. Shared by :class:`Mahalanobis`,\n:class:`~unitrack.gates.MotionGate`, and\n:class:`~unitrack.gates.SoftMotionGate` so they agree on\nthe projection and PSD-guard conventions.",[3770,3773,3776,3779],{"name":3771,"type":646,"doc":3772},"cs_field","``(N, D)`` tracklet mean.",{"name":3774,"type":646,"doc":3775},"cs_cov","``(N, D, D)`` tracklet covariance.",{"name":3777,"type":646,"doc":3778},"ds_field","``(M, d_meas)`` detection field.",{"name":3754,"type":2204,"doc":3780},"Identifier embedded in :func:`solve_psd`'s error message.",{"type":646,"doc":3782},"``(N, M)`` pairwise chi-squared distances.",{"file":3717,"line":3784},98,{"id":3786,"kind":335,"path":3787,"signature":3788,"summary":3789,"description":3790,"source":3791,"parent":3673},"unitrack.states.kalman.information",[331,270,286,300],"module unitrack.states.kalman.information","Information filter — the exact dual of the Kalman filter.","The information form carries the *inverse* covariance instead of the\ncovariance: an information matrix ``Y = P^{-1}`` and information vector\n``y = P^{-1} mu``. Its appeal is the update step, which becomes a plain\n*addition* — fusing a measurement only adds ``H^T R^{-1} H`` to ``Y`` and\n``H^T R^{-1} z`` to ``y`` — so multiple independent cues combine without a\nmatrix inverse per fusion. The predict step pays for that by being the\nawkward one (it needs a Woodbury identity to add process noise). The\nfiltered mean ``mu = Y^{-1} y`` is kept in the primary field so the\nexisting cost zoo can match on it.\n\nThis implementation uses a random-walk model (``F = H = I``), which is the\nappropriate \"no motion\" assumption for appearance\u002Fkernel embeddings. Its\nposterior is the exact Gaussian posterior, identical to\n:class:`~unitrack.states.KalmanLinear` + :class:`~unitrack.states.KalmanUpdate`.",{"file":3065,"line":341},{"id":3793,"kind":335,"path":3794,"signature":3795,"summary":3796,"source":3797,"parent":3673},"unitrack.states.kalman.base",[331,270,286,259],"module unitrack.states.kalman.base","KalmanLinear backbone — generic linear-Gaussian predict step.",{"file":3371,"line":341},{"id":3799,"kind":335,"path":3800,"signature":3801,"summary":3802,"description":3803,"source":3804,"parent":331},"unitrack.costs",[331,182],"module unitrack.costs","Cost producers and cost-side combinators.","Leaves consume a :class:`~unitrack.data.Tracklets` \u002F\n:class:`~unitrack.data.Detections` pair and emit a\n:class:`~unitrack.data.CostExpression`. The lower-is-better convention\nholds throughout: a cost of ``0`` is a perfect match.",{"file":3805,"line":341},"unitrack\u002Fcosts\u002F__init__.py",{"id":3807,"kind":344,"path":3808,"signature":3810,"summary":3811,"source":3812,"parent":3799},"unitrack.costs.Reduce",[331,182,3809],"Reduce","class Reduce:","Combine multiple child cost producers via a reduction.",{"file":3813,"line":3814},"unitrack\u002Fcosts\u002Fcombinators.py",86,{"id":3816,"kind":355,"path":3817,"signature":1376,"source":3818,"parent":3807},"unitrack.costs.Reduce.children",[331,182,3809,1375],{"file":3813,"line":2434},{"id":3820,"kind":355,"path":3821,"signature":3822,"source":3823,"parent":3807},"unitrack.costs.Reduce.method",[331,182,3809,388],"method: Reduction | str",{"file":3813,"line":708},{"id":3825,"kind":388,"path":3826,"signature":1200,"summary":3827,"params":3828,"returns":3833,"raises":3835,"source":3838,"parent":3807},"unitrack.costs.Reduce.__call__",[331,182,3809,1009],"Run every child and combine their cost matrices.",[3829,3831,3832],{"name":1174,"type":581,"doc":3830},"Forwarded to each child unchanged.",{"name":1177,"type":581,"doc":3830},{"name":1180,"type":581,"doc":3830},{"type":596,"doc":3834},"``(N, M)`` reduced cost matrix. Per-child gate masks are\nAND-combined pointwise; biases sum additively.",[3836],{"type":398,"doc":3837},"If :attr:`method` is not a recognised :class:`Reduction`.",{"file":3813,"line":3839},104,{"id":3841,"kind":388,"path":3842,"signature":3843,"source":3844,"parent":3807},"unitrack.costs.Reduce.__init__",[331,182,3809,405],"def __init__(self, children: list, method: Reduction | str) -> None",{"file":3813,"line":341},{"id":3846,"kind":344,"path":3847,"signature":3849,"summary":3850,"source":3851,"parent":3799},"unitrack.costs.Reduction",[331,182,3848],"Reduction","class Reduction(enum.StrEnum):","Reduction method for combining multiple cost matrices.",{"file":3813,"line":1869},{"id":3853,"kind":363,"path":3854,"signature":3856,"source":3857,"parent":3846},"unitrack.costs.Reduction.SUM",[331,182,3848,3855],"SUM","SUM = 'sum'",{"file":3813,"line":2223},{"id":3859,"kind":363,"path":3860,"signature":3862,"source":3863,"parent":3846},"unitrack.costs.Reduction.MEAN",[331,182,3848,3861],"MEAN","MEAN = 'mean'",{"file":3813,"line":2229},{"id":3865,"kind":363,"path":3866,"signature":3868,"source":3869,"parent":3846},"unitrack.costs.Reduction.MIN",[331,182,3848,3867],"MIN","MIN = 'min'",{"file":3813,"line":2235},{"id":3871,"kind":363,"path":3872,"signature":3874,"source":3875,"parent":3846},"unitrack.costs.Reduction.MAX",[331,182,3848,3873],"MAX","MAX = 'max'",{"file":3813,"line":1591},{"id":3877,"kind":344,"path":3878,"signature":3880,"summary":3881,"description":3882,"source":3883,"parent":3799},"unitrack.costs.Sinkhorn",[331,182,3879],"Sinkhorn","class Sinkhorn:","Soft-OT renormalisation wrapper for the differentiable path.","Materialises the inner cost expression, runs ``n_iter`` Sinkhorn\niterations in log space at temperature ``epsilon``, and returns the\nnegative log transport plan as a new cost matrix. Useful as the cost\nfeed into :class:`~unitrack.assignment.SoftAssignment`.",{"file":3813,"line":1887},{"id":3885,"kind":355,"path":3886,"signature":3888,"source":3889,"parent":3877},"unitrack.costs.Sinkhorn.inner",[331,182,3879,3887],"inner","inner: typing.Any",{"file":3813,"line":3336},{"id":3891,"kind":355,"path":3892,"signature":3894,"source":3895,"parent":3877},"unitrack.costs.Sinkhorn.epsilon",[331,182,3879,3893],"epsilon","epsilon: float = 0.1",{"file":3813,"line":3896},202,{"id":3898,"kind":355,"path":3899,"signature":3901,"source":3902,"parent":3877},"unitrack.costs.Sinkhorn.n_iter",[331,182,3879,3900],"n_iter","n_iter: int = 50",{"file":3813,"line":3903},203,{"id":3905,"kind":388,"path":3906,"signature":1200,"summary":3907,"params":3908,"returns":3913,"source":3915,"parent":3877},"unitrack.costs.Sinkhorn.__call__",[331,182,3879,1009],"Run the inner producer and Sinkhorn-renormalise its cost.",[3909,3911,3912],{"name":1174,"type":581,"doc":3910},"Forwarded to :attr:`inner` unchanged.",{"name":1177,"type":581,"doc":3910},{"name":1180,"type":581,"doc":3910},{"type":596,"doc":3914},"``(N, M)`` cost matrix equal to the negative log transport\nplan. Inner gate masks are forwarded so downstream\ncombinators retain provenance; ``bias`` is consumed by\nmaterialisation and intentionally dropped.",{"file":3813,"line":3916},205,{"id":3918,"kind":388,"path":3919,"signature":3920,"source":3921,"parent":3877},"unitrack.costs.Sinkhorn.__init__",[331,182,3879,405],"def __init__(self, inner: typing.Any, epsilon: float = 0.1, n_iter: int = 50) -> None",{"file":3813,"line":341},{"id":3923,"kind":344,"path":3924,"signature":3926,"summary":3927,"source":3928,"parent":3799},"unitrack.costs.Weighted",[331,182,3925],"Weighted","class Weighted:","Scale a child cost producer's output by a scalar weight.",{"file":3813,"line":1135},{"id":3930,"kind":355,"path":3931,"signature":3888,"source":3932,"parent":3923},"unitrack.costs.Weighted.inner",[331,182,3925,3887],{"file":3813,"line":1571},{"id":3934,"kind":355,"path":3935,"signature":3937,"source":3938,"parent":3923},"unitrack.costs.Weighted.weight",[331,182,3925,3936],"weight","weight: float",{"file":3813,"line":913},{"id":3940,"kind":388,"path":3941,"signature":1200,"summary":3942,"params":3943,"returns":3947,"source":3949,"parent":3923},"unitrack.costs.Weighted.__call__",[331,182,3925,1009],"Run :attr:`inner` and scale its cost matrix.",[3944,3945,3946],{"name":1174,"type":581,"doc":3910},{"name":1177,"type":581,"doc":3910},{"name":1180,"type":581,"doc":3910},{"type":596,"doc":3948},"The inner expression with ``matrix`` multiplied by\n:attr:`weight`; attached gates and bias are preserved.",{"file":3813,"line":723},{"id":3951,"kind":388,"path":3952,"signature":3953,"source":3954,"parent":3923},"unitrack.costs.Weighted.__init__",[331,182,3925,405],"def __init__(self, inner: typing.Any, weight: float) -> None",{"file":3813,"line":341},{"id":3956,"kind":344,"path":3957,"signature":3959,"summary":3960,"source":3961,"parent":3799},"unitrack.costs.RBF",[331,182,3958],"RBF","class RBF:","RBF-kernel cost ``1 - exp(-gamma * ‖a - b‖²)``.",{"file":3962,"line":3963},"unitrack\u002Fcosts\u002Fdistance.py",175,{"id":3965,"kind":355,"path":3966,"signature":2221,"source":3967,"parent":3956},"unitrack.costs.RBF.field",[331,182,3958,2203],{"file":3962,"line":3968},189,{"id":3970,"kind":355,"path":3971,"signature":3973,"source":3974,"parent":3956},"unitrack.costs.RBF.gamma",[331,182,3958,3972],"gamma","gamma: float = 1.0",{"file":3962,"line":3975},190,{"id":3977,"kind":388,"path":3978,"signature":1200,"summary":3979,"params":3980,"returns":3985,"source":3987,"parent":3956},"unitrack.costs.RBF.__call__",[331,182,3958,1009],"Compute the RBF-kernel cost matrix.",[3981,3982,3983],{"name":1174,"type":581,"doc":1175},{"name":1177,"type":394,"doc":1178},{"name":1180,"type":452,"doc":3984},"Frame context (unused).",{"type":596,"doc":3986},"``(N, M)`` cost matrix bounded in ``[0, 1]``; lower is better.",{"file":3962,"line":3326},{"id":3989,"kind":388,"path":3990,"signature":3991,"source":3992,"parent":3956},"unitrack.costs.RBF.__init__",[331,182,3958,405],"def __init__(self, field: str, gamma: float = 1.0) -> None",{"file":3962,"line":341},{"id":3994,"kind":344,"path":3995,"signature":3997,"summary":3998,"description":3999,"source":4000,"parent":3799},"unitrack.costs.BiSoftmax",[331,182,3996],"BiSoftmax","class BiSoftmax:","Bi-directional softmax cost ``1 - 0.5 * (softmax_cs + softmax_ds)``.","The inner ``sim = a @ b.mT`` is reduced via a softmax along each\naxis; the symmetric average is then inverted into a distance.",{"file":3962,"line":673},{"id":4002,"kind":355,"path":4003,"signature":2221,"source":4004,"parent":3994},"unitrack.costs.BiSoftmax.field",[331,182,3996,2203],{"file":3962,"line":2182},{"id":4006,"kind":388,"path":4007,"signature":1200,"summary":4008,"params":4009,"returns":4013,"source":4015,"parent":3994},"unitrack.costs.BiSoftmax.__call__",[331,182,3996,1009],"Compute the bi-directional softmax cost matrix.",[4010,4011,4012],{"name":1174,"type":581,"doc":1175},{"name":1177,"type":394,"doc":1178},{"name":1180,"type":452,"doc":3984},{"type":596,"doc":4014},"``(N, M)`` cost matrix; lower is better.",{"file":3962,"line":781},{"id":4017,"kind":388,"path":4018,"signature":2443,"source":4019,"parent":3994},"unitrack.costs.BiSoftmax.__init__",[331,182,3996,405],{"file":3962,"line":341},{"id":4021,"kind":344,"path":4022,"signature":4024,"summary":4025,"source":4026,"parent":3799},"unitrack.costs.CDist",[331,182,4023],"CDist","class CDist:","``‖a - b‖_p`` distance over a named float-vector field.",{"file":3962,"line":3404},{"id":4028,"kind":355,"path":4029,"signature":2221,"source":4030,"parent":4021},"unitrack.costs.CDist.field",[331,182,4023,2203],{"file":3962,"line":695},{"id":4032,"kind":355,"path":4033,"signature":4035,"source":4036,"parent":4021},"unitrack.costs.CDist.p_norm",[331,182,4023,4034],"p_norm","p_norm: float = 2.0",{"file":3962,"line":2671},{"id":4038,"kind":388,"path":4039,"signature":1200,"summary":4040,"params":4041,"returns":4045,"source":4046,"parent":4021},"unitrack.costs.CDist.__call__",[331,182,4023,1009],"Compute the pairwise :math:`L_p` distance cost matrix.",[4042,4043,4044],{"name":1174,"type":581,"doc":1175},{"name":1177,"type":394,"doc":1178},{"name":1180,"type":452,"doc":3984},{"type":596,"doc":4014},{"file":3962,"line":1763},{"id":4048,"kind":388,"path":4049,"signature":4050,"source":4051,"parent":4021},"unitrack.costs.CDist.__init__",[331,182,4023,405],"def __init__(self, field: str, p_norm: float = 2.0) -> None",{"file":3962,"line":341},{"id":4053,"kind":344,"path":4054,"signature":4056,"summary":4057,"description":4058,"source":4059,"parent":3799},"unitrack.costs.Chamfer",[331,182,4055],"Chamfer","class Chamfer:","Symmetric chamfer distance over a fixed-size point-cloud field.","The field shape must be ``(B, K, D)`` where ``B`` is the\ntracklet\u002Fdetection batch, ``K`` is points per cloud, and ``D`` is\npoint dimensionality.",{"file":3962,"line":458},{"id":4061,"kind":355,"path":4062,"signature":2221,"source":4063,"parent":4053},"unitrack.costs.Chamfer.field",[331,182,4055,2203],{"file":3962,"line":4064},293,{"id":4066,"kind":388,"path":4067,"signature":1200,"summary":4068,"params":4069,"returns":4073,"source":4074,"parent":4053},"unitrack.costs.Chamfer.__call__",[331,182,4055,1009],"Compute the symmetric chamfer-distance cost matrix.",[4070,4071,4072],{"name":1174,"type":581,"doc":1175},{"name":1177,"type":394,"doc":1178},{"name":1180,"type":452,"doc":3984},{"type":596,"doc":4014},{"file":3962,"line":4075},295,{"id":4077,"kind":388,"path":4078,"signature":2443,"source":4079,"parent":4053},"unitrack.costs.Chamfer.__init__",[331,182,4055,405],{"file":3962,"line":341},{"id":4081,"kind":344,"path":4082,"signature":4084,"summary":4085,"source":4086,"parent":3799},"unitrack.costs.Cosine",[331,182,4083],"Cosine","class Cosine:","``1 - cosine_similarity`` cost over a named float-vector field.",{"file":3962,"line":1025},{"id":4088,"kind":355,"path":4089,"signature":2221,"source":4090,"parent":4081},"unitrack.costs.Cosine.field",[331,182,4083,2203],{"file":3962,"line":2356},{"id":4092,"kind":355,"path":4093,"signature":4094,"source":4095,"parent":4081},"unitrack.costs.Cosine.eps",[331,182,4083,2756],"eps: float = 1e-05",{"file":3962,"line":609},{"id":4097,"kind":388,"path":4098,"signature":1200,"summary":4099,"params":4100,"returns":4104,"source":4105,"parent":4081},"unitrack.costs.Cosine.__call__",[331,182,4083,1009],"Compute the cosine-distance cost matrix.",[4101,4102,4103],{"name":1174,"type":581,"doc":1175},{"name":1177,"type":394,"doc":1178},{"name":1180,"type":452,"doc":3984},{"type":596,"doc":4014},{"file":3962,"line":623},{"id":4107,"kind":388,"path":4108,"signature":4109,"source":4110,"parent":4081},"unitrack.costs.Cosine.__init__",[331,182,4083,405],"def __init__(self, field: str, eps: float = 1e-05) -> None",{"file":3962,"line":341},{"id":4112,"kind":344,"path":4113,"signature":4115,"summary":4116,"description":4117,"source":4118,"parent":3799},"unitrack.costs.Mahalanobis",[331,182,4114],"Mahalanobis","class Mahalanobis:","Mahalanobis squared distance ``(a - b)^T Σ^-1 (a - b)``.","Σ is read from a Kalman state's covariance field on ``cs``.",{"file":3962,"line":1498},{"id":4120,"kind":355,"path":4121,"signature":2221,"source":4122,"parent":4112},"unitrack.costs.Mahalanobis.field",[331,182,4114,2203],{"file":3962,"line":415},{"id":4124,"kind":355,"path":4125,"signature":3183,"source":4126,"parent":4112},"unitrack.costs.Mahalanobis.cov_field",[331,182,4114,3182],{"file":3962,"line":4127},241,{"id":4129,"kind":388,"path":4130,"signature":1200,"summary":4131,"params":4132,"returns":4138,"source":4139,"parent":4112},"unitrack.costs.Mahalanobis.__call__",[331,182,4114,1009],"Compute the Mahalanobis squared-distance cost matrix.",[4133,4135,4137],{"name":1174,"type":581,"doc":4134},"Tracklet snapshot with ``N`` rows; must carry both\n:attr:`field` and :attr:`cov_field`.",{"name":1177,"type":394,"doc":4136},"Detection record with ``M`` rows; must carry :attr:`field`.",{"name":1180,"type":452,"doc":3984},{"type":596,"doc":4014},{"file":3962,"line":4140},243,{"id":4142,"kind":388,"path":4143,"signature":4144,"source":4145,"parent":4112},"unitrack.costs.Mahalanobis.__init__",[331,182,4114,405],"def __init__(self, field: str, cov_field: str) -> None",{"file":3962,"line":341},{"id":4147,"kind":344,"path":4148,"signature":4150,"summary":4151,"description":4152,"params":4153,"raises":4167,"source":4170,"parent":3799},"unitrack.costs.GalleryCost",[331,182,4149],"GalleryCost","class GalleryCost:","Cosine cost between detections and each tracklet's embedding gallery.","For tracklet gallery ``(N, K, D)`` and detections ``(M, D)``, computes\nthe cosine similarity ``(N, K, M)``, masks gallery slots that are not\nyet filled (per the count field), reduces over the ``K`` slots, and\nreturns ``1 - similarity`` as an ``(N, M)`` cost.",[4154,4156,4158,4160,4165],{"name":2505,"type":2204,"doc":4155},"Tracklet field holding the ``(N, K, D)`` gallery buffer.",{"name":2513,"type":2204,"doc":4157},"Tracklet field holding the ``(N,)`` fill count (number of appends).",{"name":2203,"type":2204,"doc":4159},"Detection field holding the ``(M, D)`` query embedding.",{"name":4161,"type":4162,"default":4163,"doc":4164},"reduce","('max', 'mean')","\"max\"","Slot reduction. ``\"max\"`` takes the best-matching historical view\n(robust to appearance change); ``\"mean\"`` averages valid slots.",{"name":2756,"type":474,"default":2757,"doc":4166},"Lower bound on the L2 norm used for normalisation.",[4168],{"type":398,"doc":4169},"If ``reduce`` is not ``\"max\"`` or ``\"mean\"``.",{"file":4171,"line":898},"unitrack\u002Fcosts\u002Fgallery.py",{"id":4173,"kind":355,"path":4174,"signature":2506,"source":4175,"parent":4147},"unitrack.costs.GalleryCost.gallery_field",[331,182,4149,2505],{"file":4171,"line":2121},{"id":4177,"kind":355,"path":4178,"signature":2514,"source":4179,"parent":4147},"unitrack.costs.GalleryCost.count_field",[331,182,4149,2513],{"file":4171,"line":2496},{"id":4181,"kind":355,"path":4182,"signature":2221,"source":4183,"parent":4147},"unitrack.costs.GalleryCost.field",[331,182,4149,2203],{"file":4171,"line":2501},{"id":4185,"kind":355,"path":4186,"signature":4187,"source":4188,"parent":4147},"unitrack.costs.GalleryCost.reduce",[331,182,4149,4161],"reduce: GalleryReduce = 'max'",{"file":4171,"line":1211},{"id":4190,"kind":355,"path":4191,"signature":2769,"source":4192,"parent":4147},"unitrack.costs.GalleryCost.eps",[331,182,4149,2756],{"file":4171,"line":1869},{"id":4194,"kind":388,"path":4195,"signature":1200,"summary":4196,"source":4197,"parent":4147},"unitrack.costs.GalleryCost.__call__",[331,182,4149,1009],"Compute the gallery-reduced cosine cost matrix.",{"file":4171,"line":3398},{"id":4199,"kind":388,"path":4200,"signature":4201,"source":4202,"parent":4147},"unitrack.costs.GalleryCost.__init__",[331,182,4149,405],"def __init__(self, gallery_field: str, count_field: str, field: str, reduce: GalleryReduce = 'max', eps: float = 1e-12) -> None",{"file":4171,"line":341},{"id":4204,"kind":344,"path":4205,"signature":4207,"summary":4208,"source":4209,"parent":3799},"unitrack.costs.BoxCIoU",[331,182,4206],"BoxCIoU","class BoxCIoU:","``1 - CIoU`` cost over a named bounding-box field (``xyxy`` format).",{"file":4210,"line":4211},"unitrack\u002Fcosts\u002Foverlap.py",187,{"id":4213,"kind":355,"path":4214,"signature":2221,"source":4215,"parent":4204},"unitrack.costs.BoxCIoU.field",[331,182,4206,2203],{"file":4210,"line":2959},{"id":4217,"kind":388,"path":4218,"signature":1200,"summary":4219,"params":4220,"returns":4224,"source":4226,"parent":4204},"unitrack.costs.BoxCIoU.__call__",[331,182,4206,1009],"Compute the complete box-IoU cost matrix.",[4221,4222,4223],{"name":1174,"type":581,"doc":1175},{"name":1177,"type":394,"doc":1178},{"name":1180,"type":452,"doc":3984},{"type":596,"doc":4225},"``(N, M)`` cost matrix; lower is better. CIoU adds a\ncentre-distance and aspect-ratio penalty on top of GIoU.",{"file":4210,"line":3336},{"id":4228,"kind":388,"path":4229,"signature":2443,"source":4230,"parent":4204},"unitrack.costs.BoxCIoU.__init__",[331,182,4206,405],{"file":4210,"line":341},{"id":4232,"kind":344,"path":4233,"signature":4235,"summary":4236,"source":4237,"parent":3799},"unitrack.costs.BoxGIoU",[331,182,4234],"BoxGIoU","class BoxGIoU:","``1 - GIoU`` cost over a named bounding-box field (``xyxy`` format).",{"file":4210,"line":2182},{"id":4239,"kind":355,"path":4240,"signature":2221,"source":4241,"parent":4232},"unitrack.costs.BoxGIoU.field",[331,182,4234,2203],{"file":4210,"line":1095},{"id":4243,"kind":388,"path":4244,"signature":1200,"summary":4245,"params":4246,"returns":4250,"source":4252,"parent":4232},"unitrack.costs.BoxGIoU.__call__",[331,182,4234,1009],"Compute the generalised box-IoU cost matrix.",[4247,4248,4249],{"name":1174,"type":581,"doc":1175},{"name":1177,"type":394,"doc":1178},{"name":1180,"type":452,"doc":3984},{"type":596,"doc":4251},"``(N, M)`` cost matrix; lower is better. Unlike box-IoU,\nnon-overlapping pairs receive a finite positive cost rather\nthan the constant ``1``.",{"file":4210,"line":964},{"id":4254,"kind":388,"path":4255,"signature":2443,"source":4256,"parent":4232},"unitrack.costs.BoxGIoU.__init__",[331,182,4234,405],{"file":4210,"line":341},{"id":4258,"kind":344,"path":4259,"signature":4261,"summary":4262,"source":4263,"parent":3799},"unitrack.costs.BoxIoU",[331,182,4260],"BoxIoU","class BoxIoU:","``1 - IoU`` cost over a named bounding-box field (``xyxy`` format).",{"file":4210,"line":1438},{"id":4265,"kind":355,"path":4266,"signature":2221,"source":4267,"parent":4258},"unitrack.costs.BoxIoU.field",[331,182,4260,2203],{"file":4210,"line":4268},107,{"id":4270,"kind":388,"path":4271,"signature":1200,"summary":4272,"params":4273,"returns":4277,"source":4278,"parent":4258},"unitrack.costs.BoxIoU.__call__",[331,182,4260,1009],"Compute the box-IoU cost matrix.",[4274,4275,4276],{"name":1174,"type":581,"doc":1175},{"name":1177,"type":394,"doc":1178},{"name":1180,"type":452,"doc":3984},{"type":596,"doc":3986},{"file":4210,"line":1188},{"id":4280,"kind":388,"path":4281,"signature":2443,"source":4282,"parent":4258},"unitrack.costs.BoxIoU.__init__",[331,182,4260,405],{"file":4210,"line":341},{"id":4284,"kind":344,"path":4285,"signature":4287,"summary":4288,"source":4289,"parent":3799},"unitrack.costs.MaskIoU",[331,182,4286],"MaskIoU","class MaskIoU:","``1 - IoU`` cost over a named boolean mask field.",{"file":4210,"line":1149},{"id":4291,"kind":355,"path":4292,"signature":2221,"source":4293,"parent":4284},"unitrack.costs.MaskIoU.field",[331,182,4286,2203],{"file":4210,"line":723},{"id":4295,"kind":355,"path":4296,"signature":4094,"source":4297,"parent":4284},"unitrack.costs.MaskIoU.eps",[331,182,4286,2756],{"file":4210,"line":730},{"id":4299,"kind":388,"path":4300,"signature":1200,"summary":4301,"params":4302,"returns":4306,"source":4307,"parent":4284},"unitrack.costs.MaskIoU.__call__",[331,182,4286,1009],"Compute the mask-IoU cost matrix.",[4303,4304,4305],{"name":1174,"type":581,"doc":1175},{"name":1177,"type":394,"doc":1178},{"name":1180,"type":452,"doc":3984},{"type":596,"doc":3986},{"file":4210,"line":742},{"id":4309,"kind":388,"path":4310,"signature":4109,"source":4311,"parent":4284},"unitrack.costs.MaskIoU.__init__",[331,182,4286,405],{"file":4210,"line":341},{"id":4313,"kind":335,"path":4314,"signature":4315,"summary":4316,"source":4317,"parent":3799},"unitrack.costs.overlap",[331,182,194],"module unitrack.costs.overlap","IoU-family :class:`~unitrack.pipeline.CostProducer` leaves.",{"file":4210,"line":341},{"id":4319,"kind":335,"path":4320,"signature":4321,"summary":4322,"source":4323,"parent":3799},"unitrack.costs.combinators",[331,182,185],"module unitrack.costs.combinators","Cost-side combinators: :class:`Weighted`, :class:`Reduce`, :class:`Sinkhorn`.",{"file":3813,"line":341},{"id":4325,"kind":335,"path":4326,"signature":4327,"summary":4328,"source":4329,"parent":3799},"unitrack.costs.distance",[331,182,188],"module unitrack.costs.distance","Distance-based :class:`~unitrack.pipeline.CostProducer` leaves.",{"file":3962,"line":341},{"id":4331,"kind":335,"path":4332,"signature":4333,"summary":4334,"description":4335,"source":4336,"parent":3799},"unitrack.costs.gallery",[331,182,191],"module unitrack.costs.gallery","Gallery (feature-bank) cost — match a detection against a tracklet's history.","Single-embedding matching (one stored vector per tracklet) is brittle when\nan object's appearance changes: a fresh detection from a new viewpoint can\nlook unlike the last stored embedding even though it is the same identity.\nDeepSORT \u002F MeMOT-style trackers keep a small **gallery** of recent\nembeddings per tracklet and match a detection against the *best* (or mean)\nof them, so a single good historical view is enough to re-associate.\n\n:class:`GalleryCost` reads a tracklet's gallery buffer and fill count\n(maintained by :class:`~unitrack.states.GalleryAppend`) and reduces the\nper-slot cosine similarities to an ``(N, M)`` cost matrix.",{"file":4171,"line":341},{"id":4338,"kind":355,"path":4339,"signature":4341,"source":4342,"parent":4331},"unitrack.costs.gallery.GalleryReduce",[331,182,191,4340],"GalleryReduce","GalleryReduce = typing.Literal['max', 'mean']",{"file":4171,"line":1031},{"id":4344,"kind":335,"path":4345,"signature":4346,"summary":4347,"source":4348,"parent":331},"unitrack.gates",[331,224],"module unitrack.gates","Gates layer.",{"file":4349,"line":341},"unitrack\u002Fgates\u002F__init__.py",{"id":4351,"kind":344,"path":4352,"signature":4354,"summary":4355,"description":4356,"params":4357,"source":4366,"parent":4344},"unitrack.gates.MotionGate",[331,224,4353],"MotionGate","class MotionGate:","Mahalanobis chi-squared gate over a Kalman covariance field.","For each (tracklet, detection) pair, the squared Mahalanobis distance\n``d2 = (x - z)^T S^{-1} (x - z)`` is computed from the predicted\ntracklet mean ``x``, the projected covariance ``S`` on ``cov_field``,\nand the detection measurement ``z``. Pairs with ``d2 \u003C= max_chi2``\nare admitted; the rest are rejected.",[4358,4361,4363],{"name":4359,"type":2204,"doc":4360},"mean_field","Name of the field on :class:`~unitrack.data.Tracklets` and\n:class:`~unitrack.data.Detections` holding the state mean used to\nform the residual.",{"name":3182,"type":2204,"doc":4362},"Name of the field on :class:`~unitrack.data.Tracklets` holding the projected\nmeasurement covariance ``S``.",{"name":4364,"type":474,"doc":4365},"max_chi2","Chi-squared threshold on the squared Mahalanobis distance. A\ncommon choice is the 0.95 quantile of the chi-squared\ndistribution at the measurement dimensionality (e.g. ``9.4877``\nfor 4 degrees of freedom, as used by SORT\u002FDeepSORT).",{"file":4367,"line":2351},"unitrack\u002Fgates\u002Fmotion.py",{"id":4369,"kind":355,"path":4370,"signature":4371,"source":4372,"parent":4351},"unitrack.gates.MotionGate.mean_field",[331,224,4353,4359],"mean_field: str",{"file":4367,"line":623},{"id":4374,"kind":355,"path":4375,"signature":3183,"source":4376,"parent":4351},"unitrack.gates.MotionGate.cov_field",[331,224,4353,3182],{"file":4367,"line":630},{"id":4378,"kind":355,"path":4379,"signature":4380,"source":4381,"parent":4351},"unitrack.gates.MotionGate.max_chi2",[331,224,4353,4364],"max_chi2: float",{"file":4367,"line":637},{"id":4383,"kind":388,"path":4384,"signature":1313,"summary":4385,"source":4386,"parent":4351},"unitrack.gates.MotionGate.__call__",[331,224,4353,1009],"Return a PerPair gate keeping pairs with chi2 \u003C= max_chi2.",{"file":4367,"line":663},{"id":4388,"kind":388,"path":4389,"signature":4390,"source":4391,"parent":4351},"unitrack.gates.MotionGate.__init__",[331,224,4353,405],"def __init__(self, mean_field: str, cov_field: str, max_chi2: float) -> None",{"file":4367,"line":341},{"id":4393,"kind":344,"path":4394,"signature":4396,"summary":4397,"source":4398,"parent":4344},"unitrack.gates.ClassGate",[331,224,4395],"ClassGate","class ClassGate:","Outer-equal class match — Gate.PerPair.",{"file":4399,"line":4400},"unitrack\u002Fgates\u002Fsimple.py",26,{"id":4402,"kind":355,"path":4403,"signature":2221,"source":4404,"parent":4393},"unitrack.gates.ClassGate.field",[331,224,4395,2203],{"file":4399,"line":898},{"id":4406,"kind":388,"path":4407,"signature":1313,"summary":4408,"source":4409,"parent":4393},"unitrack.gates.ClassGate.__call__",[331,224,4395,1009],"Return a PerPair gate where mask[i,j] = (cs[i].field == ds[j].field).",{"file":4399,"line":913},{"id":4411,"kind":388,"path":4412,"signature":2443,"source":4413,"parent":4393},"unitrack.gates.ClassGate.__init__",[331,224,4395,405],{"file":4399,"line":341},{"id":4415,"kind":344,"path":4416,"signature":4418,"summary":4419,"source":4420,"parent":4344},"unitrack.gates.NoneGate",[331,224,4417],"NoneGate","class NoneGate:","Identity gate — always-True PerPair mask.",{"file":4399,"line":1128},{"id":4422,"kind":388,"path":4423,"signature":1313,"summary":4424,"source":4425,"parent":4415},"unitrack.gates.NoneGate.__call__",[331,224,4417,1009],"Return a PerPair gate with all-True mask of shape (N, M).",{"file":4399,"line":1142},{"id":4427,"kind":388,"path":4428,"signature":1016,"source":4429,"parent":4415},"unitrack.gates.NoneGate.__init__",[331,224,4417,405],{"file":4399,"line":341},{"id":4431,"kind":344,"path":4432,"signature":4434,"summary":4435,"source":4436,"parent":4344},"unitrack.gates.ScoreGate",[331,224,4433],"ScoreGate","class ScoreGate:","Per-detection score threshold — Gate.PerDs.",{"file":4399,"line":616},{"id":4438,"kind":355,"path":4439,"signature":2221,"source":4440,"parent":4431},"unitrack.gates.ScoreGate.field",[331,224,4433,2203],{"file":4399,"line":842},{"id":4442,"kind":355,"path":4443,"signature":4445,"source":4446,"parent":4431},"unitrack.gates.ScoreGate.threshold",[331,224,4433,4444],"threshold","threshold: float",{"file":4399,"line":663},{"id":4448,"kind":388,"path":4449,"signature":1313,"summary":4450,"source":4451,"parent":4431},"unitrack.gates.ScoreGate.__call__",[331,224,4433,1009],"Return a PerDs gate keeping detections with score >= threshold.",{"file":4399,"line":862},{"id":4453,"kind":388,"path":4454,"signature":4455,"source":4456,"parent":4431},"unitrack.gates.ScoreGate.__init__",[331,224,4433,405],"def __init__(self, field: str, threshold: float) -> None",{"file":4399,"line":341},{"id":4458,"kind":344,"path":4459,"signature":4461,"summary":4462,"source":4463,"parent":4344},"unitrack.gates.SoftMotionGate",[331,224,4460],"SoftMotionGate","class SoftMotionGate:","Smooth Mahalanobis: returns Gate.CostBias = chi2 \u002F temperature.",{"file":4464,"line":2351},"unitrack\u002Fgates\u002Fsoft.py",{"id":4466,"kind":355,"path":4467,"signature":4371,"source":4468,"parent":4458},"unitrack.gates.SoftMotionGate.mean_field",[331,224,4460,4359],{"file":4464,"line":1135},{"id":4470,"kind":355,"path":4471,"signature":3183,"source":4472,"parent":4458},"unitrack.gates.SoftMotionGate.cov_field",[331,224,4460,3182],{"file":4464,"line":1142},{"id":4474,"kind":355,"path":4475,"signature":4477,"source":4478,"parent":4458},"unitrack.gates.SoftMotionGate.temperature",[331,224,4460,4476],"temperature","temperature: float = 1.0",{"file":4464,"line":1149},{"id":4480,"kind":388,"path":4481,"signature":1313,"summary":4482,"source":4483,"parent":4458},"unitrack.gates.SoftMotionGate.__call__",[331,224,4460,1009],"Return a CostBias gate with Mahalanobis distance \u002F temperature.",{"file":4464,"line":2130},{"id":4485,"kind":388,"path":4486,"signature":4487,"source":4488,"parent":4458},"unitrack.gates.SoftMotionGate.__init__",[331,224,4460,405],"def __init__(self, mean_field: str, cov_field: str, temperature: float = 1.0) -> None",{"file":4464,"line":341},{"id":4490,"kind":344,"path":4491,"signature":4493,"summary":4494,"source":4495,"parent":4344},"unitrack.gates.SpatialGate2D",[331,224,4492],"SpatialGate2D","class SpatialGate2D:","2-D spatial gate — keep pairs within max_dist Euclidean distance.",{"file":4496,"line":1031},"unitrack\u002Fgates\u002Fspatial.py",{"id":4498,"kind":355,"path":4499,"signature":2221,"source":4500,"parent":4490},"unitrack.gates.SpatialGate2D.field",[331,224,4492,2203],{"file":4496,"line":1571},{"id":4502,"kind":355,"path":4503,"signature":4505,"source":4506,"parent":4490},"unitrack.gates.SpatialGate2D.max_dist",[331,224,4492,4504],"max_dist","max_dist: float",{"file":4496,"line":913},{"id":4508,"kind":388,"path":4509,"signature":1313,"summary":4510,"source":4511,"parent":4490},"unitrack.gates.SpatialGate2D.__call__",[331,224,4492,1009],"Return a PerPair gate based on 2-D pairwise L2 distance.",{"file":4496,"line":723},{"id":4513,"kind":388,"path":4514,"signature":4515,"source":4516,"parent":4490},"unitrack.gates.SpatialGate2D.__init__",[331,224,4492,405],"def __init__(self, field: str, max_dist: float) -> None",{"file":4496,"line":341},{"id":4518,"kind":344,"path":4519,"signature":4521,"summary":4522,"source":4523,"parent":4344},"unitrack.gates.SpatialGate3D",[331,224,4520],"SpatialGate3D","class SpatialGate3D:","3-D spatial gate — keep pairs within max_dist Euclidean distance.",{"file":4496,"line":637},{"id":4525,"kind":355,"path":4526,"signature":2221,"source":4527,"parent":4518},"unitrack.gates.SpatialGate3D.field",[331,224,4520,2203],{"file":4496,"line":862},{"id":4529,"kind":355,"path":4530,"signature":4505,"source":4531,"parent":4518},"unitrack.gates.SpatialGate3D.max_dist",[331,224,4520,4504],{"file":4496,"line":1048},{"id":4533,"kind":388,"path":4534,"signature":1313,"summary":4535,"source":4536,"parent":4518},"unitrack.gates.SpatialGate3D.__call__",[331,224,4520,1009],"Return a PerPair gate based on 3-D pairwise L2 distance.",{"file":4496,"line":2705},{"id":4538,"kind":388,"path":4539,"signature":4515,"source":4540,"parent":4518},"unitrack.gates.SpatialGate3D.__init__",[331,224,4520,405],{"file":4496,"line":341},{"id":4542,"kind":335,"path":4543,"signature":4544,"summary":4545,"source":4546,"parent":4344},"unitrack.gates.soft",[331,224,233],"module unitrack.gates.soft","Soft companions for gates.",{"file":4464,"line":341},{"id":4548,"kind":335,"path":4549,"signature":4550,"summary":4551,"source":4552,"parent":4344},"unitrack.gates.spatial",[331,224,236],"module unitrack.gates.spatial","Spatial-distance gates.",{"file":4496,"line":341},{"id":4554,"kind":335,"path":4555,"signature":4556,"summary":4557,"source":4558,"parent":4344},"unitrack.gates.motion",[331,224,227],"module unitrack.gates.motion","Mahalanobis (χ²) motion gate using Kalman state covariance.",{"file":4367,"line":341},{"id":4560,"kind":335,"path":4561,"signature":4562,"summary":4563,"source":4564,"parent":4344},"unitrack.gates.simple",[331,224,230],"module unitrack.gates.simple","Built-in gates: NoneGate, ClassGate, ScoreGate.",{"file":4399,"line":341},{"id":4566,"kind":335,"path":4567,"signature":4568,"summary":4569,"description":4570,"source":4571,"parent":331},"unitrack.pipeline",[331,256],"module unitrack.pipeline","Stage protocols, combinators, merges, and the hard-to-soft tree rewrite.","Stages compose into a tree consumed by the\n:class:`~unitrack.tracker.Tracker`. The protocols (:class:`Stage`,\n:class:`~unitrack.pipeline.CostProducer`, :class:`GateProducer`,\n:class:`~unitrack.pipeline.Associator`, :class:`~unitrack.pipeline.Lifecycle`,\n:class:`~unitrack.pipeline.Visibility`) define the contract; the\ncombinators (:class:`Pipe`, :class:`Sequential`, :class:`Parallel`,\n:class:`Gated`, :class:`Filter`, :class:`Iterate`) wire stages together.",{"file":4572,"line":341},"unitrack\u002Fpipeline\u002F__init__.py",{"id":4574,"kind":344,"path":4575,"signature":4576,"summary":4577,"description":4578,"source":4579,"parent":4566},"unitrack.pipeline.Lifecycle",[331,256,1933],"class Lifecycle(typing.Protocol):","Status machine over a merged :class:`~unitrack.data.Tracklets` snapshot.","Implementations must preserve row order: the returned snapshot must\nbe a subset of input rows in their original order (a boolean\nkeep-mask applied to ``cs``). :meth:`~unitrack.tracker.Tracker.step`\nexploits this to remap matched-pair indices into the surviving row space; reordering\nor merging rows silently breaks visibility remapping.",{"file":1165,"line":2645},{"id":4581,"kind":388,"path":4582,"signature":1065,"summary":4583,"params":4584,"returns":4590,"source":4592,"parent":4574},"unitrack.pipeline.Lifecycle.__call__",[331,256,1933,1009],"Apply per-row status transitions and return the surviving rows.",[4585,4587,4589],{"name":1174,"type":581,"doc":4586},"Merged tracklet snapshot (predicted plus newly-spawned rows).",{"name":215,"type":824,"doc":4588},"Pre-lifecycle match outcome.",{"name":1180,"type":452,"doc":1181},{"type":581,"doc":4591},"Row-preserving subset of ``cs``.",{"file":1165,"line":4593},165,{"id":4595,"kind":344,"path":4596,"signature":4597,"summary":4598,"source":4599,"parent":4566},"unitrack.pipeline.Visibility",[331,256,1936],"class Visibility(typing.Protocol):","Reduce a lifecycle output to the user-facing list of visible IDs.",{"file":1165,"line":3326},{"id":4601,"kind":388,"path":4602,"signature":1010,"summary":4603,"params":4604,"returns":4609,"source":4611,"parent":4595},"unitrack.pipeline.Visibility.__call__",[331,256,1936,1009],"Return the IDs of tracklets that should appear in the public output.",[4605,4607],{"name":1174,"type":581,"doc":4606},"Post-lifecycle snapshot (with Removed rows already dropped\nfrom the visibility view).",{"name":215,"type":824,"doc":4608},"Pre-lifecycle match outcome remapped into the visible row\nspace, optionally extended with virtual pairs for\nnewly-spawned tracklets.",{"type":646,"doc":4610},"``int64`` tensor of visible tracklet IDs.",{"file":1165,"line":2941},{"id":4613,"kind":344,"path":4614,"signature":4616,"summary":4617,"source":4618,"parent":4566},"unitrack.pipeline.SoftRegistry",[331,256,4615],"SoftRegistry","class SoftRegistry:","Registry mapping hard node types to soft-replacement factories.",{"file":4619,"line":4400},"unitrack\u002Fpipeline\u002Fdiff.py",{"id":4621,"kind":355,"path":4622,"signature":4624,"source":4625,"parent":4613},"unitrack.pipeline.SoftRegistry.table",[331,256,4615,4623],"table","table: dict[type, _Factory] = dataclasses.field(default_factory=dict)",{"file":4619,"line":2356},{"id":4627,"kind":388,"path":4628,"signature":4630,"summary":4631,"params":4632,"source":4640,"parent":4613},"unitrack.pipeline.SoftRegistry.register",[331,256,4615,4629],"register","def register(self, hard_cls: type, factory: _Factory) -> None","Register a factory for the given hard-node class.",[4633,4636],{"name":4634,"type":344,"doc":4635},"hard_cls","Class to swap on encounter.",{"name":4637,"type":4638,"doc":4639},"factory","_Factory","Callable that consumes the hard node and returns its soft\nreplacement.",{"file":4619,"line":630},{"id":4642,"kind":388,"path":4643,"signature":4645,"summary":4646,"params":4647,"returns":4652,"source":4654,"parent":4613},"unitrack.pipeline.SoftRegistry.soft_for",[331,256,4615,4644],"soft_for","def soft_for(self, node: object) -> object","Return the soft replacement for ``node``, or ``node`` unchanged.",[4648],{"name":4649,"type":4650,"doc":4651},"node","object","Candidate node.",{"type":4650,"doc":4653},"Replacement produced by the matching factory, or ``node``\nitself if no factory applies.",{"file":4619,"line":1411},{"id":4656,"kind":388,"path":4657,"signature":4658,"source":4659,"parent":4613},"unitrack.pipeline.SoftRegistry.__init__",[331,256,4615,405],"def __init__(self, table: dict[type, _Factory] = dict()) -> None",{"file":4619,"line":341},{"id":4661,"kind":2303,"path":4662,"signature":4664,"summary":4665,"params":4666,"returns":4675,"source":4677,"parent":4566},"unitrack.pipeline.default_soft_registry",[331,256,4663],"default_soft_registry","def default_soft_registry(epsilon: float = 0.1, temperature: float = 1.0, sinkhorn_iters: int = 50) -> SoftRegistry","Build the default hard-to-soft registry for differentiable mode.",[4667,4669,4671],{"name":3893,"type":474,"default":3020,"doc":4668},"Entropy regularisation for the Sinkhorn-backed\n:class:`~unitrack.assignment.SoftAssignment` swap of\n:class:`~unitrack.assignment.Associate`. Smaller is sharper\n(closer to a hard assignment); larger is smoother.",{"name":4476,"type":474,"default":475,"doc":4670},"Temperature for the\n:class:`~unitrack.gates.soft.SoftMotionGate` swap of\n:class:`~unitrack.gates.MotionGate`. The Mahalanobis\n:math:`\\\\chi^2` is divided by this before attachment as a soft\ncost bias.",{"name":4672,"type":468,"default":4673,"doc":4674},"sinkhorn_iters","50","Number of Sinkhorn iterations for the soft assignment.",{"type":4615,"doc":4676},"A registry that swaps :class:`~unitrack.assignment.Associate` →\n:class:`~unitrack.assignment.SoftAssignment`,\n:class:`~unitrack.gates.MotionGate` →\n:class:`~unitrack.gates.SoftMotionGate`,\n:class:`~unitrack.states.Replace` → :class:`~unitrack.states.SoftReplace`,\nand :class:`~unitrack.lifecycle.StandardLifecycle` →\n:class:`~unitrack.lifecycle.SoftLifecycle`.",{"file":4619,"line":369},{"id":4679,"kind":2303,"path":4680,"signature":4682,"summary":4683,"description":4684,"params":4685,"returns":4691,"source":4693,"parent":4566},"unitrack.pipeline.walk_swap",[331,256,4681],"walk_swap","def walk_swap(root: object, registry: SoftRegistry) -> object","Replace nodes in the stage tree by structural recursion.","Uses :func:`dataclasses.replace` to preserve frozen-dataclass\nimmutability.",[4686,4688],{"name":1927,"type":4650,"doc":4687},"Stage-tree root.",{"name":4689,"type":4615,"doc":4690},"registry","Hard-to-soft factory table.",{"type":4650,"doc":4692},"New root with all replaceable nodes swapped.",{"file":4619,"line":4694},191,{"id":4696,"kind":344,"path":4697,"signature":4699,"summary":4700,"description":4701,"source":4702,"parent":4566},"unitrack.pipeline.Max",[331,256,4698],"Max","class Max:","Merge by elementwise maximum of cost matrices; OR-combines gates.","See :class:`Min` for the gate rationale; :class:`Max` likewise\nrepresents a best-of-branches worst-case bound.",{"file":4703,"line":996},"unitrack\u002Fpipeline\u002Fmerge.py",{"id":4705,"kind":388,"path":4706,"signature":4707,"summary":4708,"returns":4709,"source":4711,"parent":4696},"unitrack.pipeline.Max.__call__",[331,256,4698,1009],"def __call__(self, exprs: list[CostExpression]) -> CostExpression","Return the elementwise-maximum cost expression.",{"type":596,"doc":4710},"``(N, M)`` maximum matrix with OR-combined gates.",{"file":4703,"line":574},{"id":4713,"kind":388,"path":4714,"signature":1016,"source":4715,"parent":4696},"unitrack.pipeline.Max.__init__",[331,256,4698,405],{"file":4703,"line":341},{"id":4717,"kind":344,"path":4718,"signature":4720,"summary":4721,"source":4722,"parent":4566},"unitrack.pipeline.Mean",[331,256,4719],"Mean","class Mean:","Merge by elementwise mean of cost matrices; AND-combines gates.",{"file":4703,"line":3896},{"id":4724,"kind":388,"path":4725,"signature":4707,"summary":4726,"returns":4727,"source":4729,"parent":4717},"unitrack.pipeline.Mean.__call__",[331,256,4719,1009],"Return the elementwise-mean cost expression.",{"type":596,"doc":4728},"``(N, M)`` mean matrix with AND-combined gates.",{"file":4703,"line":4730},206,{"id":4732,"kind":388,"path":4733,"signature":1016,"source":4734,"parent":4717},"unitrack.pipeline.Mean.__init__",[331,256,4719,405],{"file":4703,"line":341},{"id":4736,"kind":344,"path":4737,"signature":4739,"summary":4740,"source":4741,"parent":4566},"unitrack.pipeline.Merge",[331,256,4738],"Merge","class Merge(typing.Protocol):","Protocol for strategies that combine a list of cost expressions.",{"file":4703,"line":4742},28,{"id":4744,"kind":388,"path":4745,"signature":4707,"summary":4746,"params":4747,"returns":4752,"source":4754,"parent":4736},"unitrack.pipeline.Merge.__call__",[331,256,4738,1009],"Merge ``exprs`` into one :class:`~unitrack.data.CostExpression`.",[4748],{"name":4749,"type":4750,"doc":4751},"exprs","list[CostExpression]","Per-branch cost expressions, all of shape ``(N, M)``.",{"type":596,"doc":4753},"The reduced expression.",{"file":4703,"line":913},{"id":4756,"kind":344,"path":4757,"signature":4759,"summary":4760,"source":4761,"parent":4566},"unitrack.pipeline.Min",[331,256,4758],"Min","class Min:","Merge by elementwise minimum of cost matrices; OR-combines gates.",{"file":4703,"line":1095},{"id":4763,"kind":388,"path":4764,"signature":4707,"summary":4765,"returns":4766,"source":4768,"parent":4756},"unitrack.pipeline.Min.__call__",[331,256,4758,1009],"Return the elementwise-minimum cost expression.",{"type":596,"doc":4767},"``(N, M)`` minimum matrix with OR-combined gates.",{"file":4703,"line":4593},{"id":4770,"kind":388,"path":4771,"signature":1016,"source":4772,"parent":4756},"unitrack.pipeline.Min.__init__",[331,256,4758,405],{"file":4703,"line":341},{"id":4774,"kind":344,"path":4775,"signature":4777,"summary":4778,"source":4779,"parent":4566},"unitrack.pipeline.StackReduce",[331,256,4776],"StackReduce","class StackReduce:","Apply a user-supplied reducer to stacked cost matrices.",{"file":4703,"line":2608},{"id":4781,"kind":355,"path":4782,"signature":4784,"source":4785,"parent":4774},"unitrack.pipeline.StackReduce.reducer",[331,256,4776,4783],"reducer","reducer: typing.Callable[[torch.Tensor], torch.Tensor]",{"file":4703,"line":4786},237,{"id":4788,"kind":355,"path":4789,"signature":4791,"source":4792,"parent":4774},"unitrack.pipeline.StackReduce.gate_mode",[331,256,4776,4790],"gate_mode","gate_mode: GateCombineMode = 'and'",{"file":4703,"line":4793},238,{"id":4795,"kind":388,"path":4796,"signature":4707,"summary":4797,"returns":4798,"source":4800,"parent":4774},"unitrack.pipeline.StackReduce.__call__",[331,256,4776,1009],"Return the reducer's output as a cost expression.",{"type":596,"doc":4799},"``(N, M)`` matrix from :attr:`reducer` with gates combined\naccording to :attr:`gate_mode`.",{"file":4703,"line":415},{"id":4802,"kind":388,"path":4803,"signature":4804,"source":4805,"parent":4774},"unitrack.pipeline.StackReduce.__init__",[331,256,4776,405],"def __init__(self, reducer: typing.Callable[[torch.Tensor], torch.Tensor], gate_mode: GateCombineMode = 'and') -> None",{"file":4703,"line":341},{"id":4807,"kind":344,"path":4808,"signature":4810,"summary":4811,"source":4812,"parent":4566},"unitrack.pipeline.WeightedSum",[331,256,4809],"WeightedSum","class WeightedSum:","Merge by weighted sum of cost matrices; AND-combines gates.",{"file":4703,"line":4268},{"id":4814,"kind":355,"path":4815,"signature":4817,"source":4818,"parent":4807},"unitrack.pipeline.WeightedSum.weights",[331,256,4809,4816],"weights","weights: list[float]",{"file":4703,"line":3027},{"id":4820,"kind":388,"path":4821,"signature":4707,"summary":4822,"params":4823,"returns":4826,"raises":4828,"source":4831,"parent":4807},"unitrack.pipeline.WeightedSum.__call__",[331,256,4809,1009],"Return the weighted-sum cost expression.",[4824],{"name":4749,"type":4750,"doc":4825},"Per-branch cost expressions.",{"type":596,"doc":4827},"``(N, M)`` weighted-sum matrix with AND-combined gates.",[4829],{"type":398,"doc":4830},"If ``len(weights) != len(exprs)``.",{"file":4703,"line":1068},{"id":4833,"kind":388,"path":4834,"signature":4835,"source":4836,"parent":4807},"unitrack.pipeline.WeightedSum.__init__",[331,256,4809,405],"def __init__(self, weights: list[float]) -> None",{"file":4703,"line":341},{"id":4838,"kind":335,"path":4839,"signature":4840,"summary":4841,"description":4842,"source":4843,"parent":4566},"unitrack.pipeline.merge",[331,256,267],"module unitrack.pipeline.merge","Merge strategies for :class:`~unitrack.pipeline.combinators.Parallel`.","Each strategy declares an explicit policy for how branch gates combine.\n:class:`WeightedSum` and :class:`Mean` AND-combine (conservative): a\npair is allowed only when every branch's gate allows it. :class:`Min`\nand :class:`Max` OR-combine (permissive): a pair is allowed when any\nbranch allows it; this matches the \"best-of-branches\" reduction\nsemantics. :class:`StackReduce` defaults to AND for user-supplied\nreducers; pass ``gate_mode=\"or\"`` when the reducer is best-of-branches.\nBiases always sum additively regardless of mode.",{"file":4703,"line":341},{"id":4845,"kind":355,"path":4846,"signature":4848,"source":4849,"parent":4838},"unitrack.pipeline.merge.GateCombineMode",[331,256,267,4847],"GateCombineMode","GateCombineMode = typing.Literal['and', 'or']",{"file":4703,"line":4850},25,{"id":4852,"kind":335,"path":4853,"signature":4854,"summary":4855,"description":4856,"source":4857,"parent":4566},"unitrack.pipeline.combinators",[331,256,185],"module unitrack.pipeline.combinators","Stage-tree combinators.","Provides :class:`Pipe`, :class:`Sequential`, :class:`Parallel`,\n:class:`Gated`, :class:`Filter`, and :class:`Iterate`.",{"file":1220,"line":341},{"id":4859,"kind":335,"path":4860,"signature":4861,"summary":4862,"source":4863,"parent":4566},"unitrack.pipeline.base",[331,256,259],"module unitrack.pipeline.base","Stage protocols and the construction-time type error.",{"file":1165,"line":341},{"id":4865,"kind":335,"path":4866,"signature":4867,"summary":4868,"source":4869,"parent":4566},"unitrack.pipeline.diff",[331,256,264],"module unitrack.pipeline.diff","Hard-to-soft node-replacement registry for ``differentiable=True``.",{"file":4619,"line":341},{"id":4871,"kind":2303,"path":4872,"signature":4874,"summary":4875,"params":4876,"returns":4880,"source":4882,"parent":4865},"unitrack.pipeline.diff.walk_swap_states",[331,256,264,4873],"walk_swap_states","def walk_swap_states(states: dict[str, State], registry: SoftRegistry) -> dict[str, State]","Swap a :class:`~unitrack.states.State`'s ``process``, ``observation``, ``init``.",[4877,4879],{"name":270,"type":1930,"doc":4878},"Mapping of state name to :class:`~unitrack.states.State`.",{"name":4689,"type":4615,"doc":4690},{"type":2326,"doc":4881},"New mapping with each :class:`~unitrack.states.State` rebuilt via\n:func:`dataclasses.replace`; the input is not mutated.",{"file":4619,"line":3492},{"id":4884,"kind":2303,"path":4885,"signature":4887,"summary":4888,"description":4889,"params":4890,"raises":4897,"source":4900,"parent":4865},"unitrack.pipeline.diff.validate_soft_tree",[331,256,264,4886],"validate_soft_tree","def validate_soft_tree(root: object, states: dict[str, State], lifecycle: object) -> None","Raise if the differentiable tree still contains a hard component.","Run after :func:`walk_swap` \u002F :func:`walk_swap_states` to catch\nuser-defined containers the structural recursion missed, or hard\nAssignment subclasses tucked behind a non-default Associate. The\ncheck keeps differentiable training honest: a caller seeing a NaN\nloss can rule out a silently-retained hard node.",[4891,4893,4895],{"name":1927,"type":4650,"doc":4892},"Stage-tree root after the swap.",{"name":270,"type":1930,"doc":4894},"State mapping after the swap.",{"name":239,"type":4650,"doc":4896},"Lifecycle node after the swap.",[4898],{"type":1658,"doc":4899},"If any forbidden hard node survives.",{"file":4619,"line":4901},273,{"id":4903,"kind":335,"path":4904,"signature":4905,"summary":4906,"description":4907,"source":4908,"parent":331},"unitrack.tracker",[331,173],"module unitrack.tracker","Pure tracker, multi-stream\u002Fbatch wrappers, and clip-level inference.",":class:`~unitrack.tracker.Tracker` is the pure step function over snapshots;\n:class:`~unitrack.tracker.MultiStream` and :class:`BatchTracker` add stateful per-stream\nor per-slot wrapping, and :class:`~unitrack.tracker.ClipTracker` runs the tracker over a\nfixed-length clip.",{"file":4909,"line":341},"unitrack\u002Ftracker\u002F__init__.py",{"id":4911,"kind":335,"path":4912,"signature":4913,"summary":4914,"source":4915,"parent":4903},"unitrack.tracker.multistream",[331,173,324],"module unitrack.tracker.multistream","Per-key tracker wrapper and fork-policy primitives.",{"file":1543,"line":341},{"id":4917,"kind":335,"path":4918,"signature":4919,"summary":4920,"description":4921,"source":4922,"parent":4903},"unitrack.tracker.batch",[331,173,316],"module unitrack.tracker.batch","Multi-slot tracker wrapper with an optional batched LAP fast path.",":meth:`BatchTracker.step` runs either a per-slot fallback loop or, when\n:meth:`is_vmap_safe` holds and the root is :class:`Pipe(_, Associate)`,\na batched LAP solve via :func:`auto_batch_assignment`. The opt-in\n:meth:`BatchTracker.predict_and_cost_vmap` runs the predict and\ncost-production phase under :func:`torch.func.vmap`; end-to-end vmap\ncurrently trips a tensordict-internal unbind limitation tracked by\nxfail tests in ``tests\u002Funitrack\u002Ftracker\u002Ftest_batch_vmap.py``.",{"file":1570,"line":341},{"id":4924,"kind":335,"path":4925,"signature":4926,"summary":4927,"source":4928,"parent":4903},"unitrack.tracker.clip",[331,173,200],"module unitrack.tracker.clip","Clip-level tracker: per-frame iteration plus optional refiner mode.",{"file":1675,"line":341},{"id":4930,"kind":335,"path":4931,"signature":4932,"summary":4933,"source":4934,"parent":4903},"unitrack.tracker.tracker",[331,173,173],"module unitrack.tracker.tracker","Pure tracker — step function over :class:`~unitrack.data.Tracklets` snapshots.",{"file":1886,"line":341},{"id":4936,"kind":335,"path":4937,"signature":4938,"summary":4939,"source":4940,"parent":4903},"unitrack.tracker.memory",[331,173,321],"module unitrack.tracker.memory","Per-stream tracker state: current snapshot and the next-ID counter.",{"file":2025,"line":341},{"id":4942,"kind":335,"path":4943,"signature":4944,"summary":4945,"description":4946,"source":4947,"parent":331},"unitrack.assignment",[331,128],"module unitrack.assignment","Linear-assignment problem (LAP) solvers over a cost matrix.","For new code prefer :func:`auto_assignment` \u002F :class:`AutoLAP`. Both\nroute to the empirically-fastest backend for the given input; the CPU\nLAPJV path currently beats every CUDA solver across the benchmarked\nsize range (see ``assets\u002Fbenchmarks\u002F`` for the data).",{"file":4948,"line":341},"unitrack\u002Fassignment\u002F__init__.py",{"id":4950,"kind":344,"path":4951,"signature":4953,"summary":4954,"description":4955,"source":4956,"parent":4942},"unitrack.assignment.Auction",[331,128,4952],"Auction","class Auction(Assignment):","Bertsekas auction solver for the linear assignment problem.","Iteratively bids unassigned rows on their most-profitable columns until\nevery row holds an assignment or no further bids can be placed. Yields\nan :math:`\\epsilon`-optimal matching where ``epsilon`` scales with\n``bid_size``; smaller values approach the LAP optimum at the cost of\nmore iterations.",{"file":4957,"line":1135},"unitrack\u002Fassignment\u002F_auction.py",{"id":4959,"kind":355,"path":4960,"signature":4962,"source":4963,"parent":4950},"unitrack.assignment.Auction.bid_size",[331,128,4952,4961],"bid_size","bid_size: T.Final[float] = bid_size",{"file":4957,"line":1048},{"id":4965,"kind":388,"path":4966,"signature":4967,"summary":4968,"params":4969,"source":4981,"parent":4950},"unitrack.assignment.Auction.__init__",[331,128,4952,405],"def __init__(self, bid_size = 0.05, *args = (), **kwargs = {})","Initialize the auction solver.",[4970,4973,4977],{"name":4961,"type":474,"default":4971,"doc":4972},"0.05","Auction bid step size. Tune to the dynamic range of the cost\nmatrix; values that are large relative to typical cost gaps\nconverge faster but produce coarser matches.",{"name":4974,"default":4975,"doc":4976},"*args","()","Positional arguments forwarded to :class:`Assignment`.",{"name":4978,"default":4979,"doc":4980},"**kwargs","{}","Keyword arguments forwarded to :class:`Assignment`.",{"file":4957,"line":898},{"id":4983,"kind":2303,"path":4984,"signature":4986,"summary":4987,"description":4988,"params":4989,"returns":4995,"source":4997,"parent":4942},"unitrack.assignment.auction_assignment",[331,128,4985],"auction_assignment","def auction_assignment(cost_matrix: torch.Tensor, bid_size: float) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]","Solve a linear assignment problem using Bertsekas' auction algorithm.","Converts the cost matrix to a profit matrix, then runs synchronous\nbidding until every row (or every column, for rectangular problems) is\nassigned. Non-finite entries mark forbidden pairs and are penalised\ninternally so the solver never selects them.",[4990,4993],{"name":4991,"type":646,"doc":4992},"cost_matrix","``(N, M)`` cost matrix. ``inf`` entries mark forbidden pairs.",{"name":4961,"type":474,"doc":4994},"Auction bid step size. The internal ``epsilon`` is derived as\n``min(bid_size \u002F min(N, M), 1e-3)``.",{"type":646,"doc":4996},"``(K, 2)`` long tensor of matched ``(row, col)`` indices.",{"file":4957,"line":1411},{"id":4999,"kind":344,"path":5000,"signature":5002,"summary":5003,"description":5004,"params":5005,"source":5013,"parent":4942},"unitrack.assignment.AutoLAP",[331,128,5001],"AutoLAP","class AutoLAP(Assignment):",":class:`Assignment` wrapper around the auto-dispatched LAP solver.","Defaults to the CPU LAPJV path (see module docstring). Pass\n``prefer=\"cuda\"`` to pin to the torchmatch CUDA solver.",[5006,5007,5012],{"name":4974,"default":4975,"doc":4976},{"name":5008,"type":5009,"default":5010,"doc":5011},"prefer","Prefer or str","Prefer.AUTO","Backend preference. Default :attr:`Prefer.AUTO`.",{"name":4978,"default":4979,"doc":4980},{"file":5014,"line":1797},"unitrack\u002Fassignment\u002F_auto.py",{"id":5016,"kind":355,"path":5017,"signature":5018,"source":5019,"parent":4999},"unitrack.assignment.AutoLAP.prefer",[331,128,5001,5008],"prefer: typing.Final[Prefer] = Prefer(prefer)",{"file":5014,"line":2800},{"id":5021,"kind":388,"path":5022,"signature":5023,"source":5024,"parent":4999},"unitrack.assignment.AutoLAP.__init__",[331,128,5001,405],"def __init__(self, *args = (), prefer: Prefer | str = Prefer.AUTO, **kwargs = {}) -> None",{"file":5014,"line":552},{"id":5026,"kind":344,"path":5027,"signature":5029,"summary":5030,"source":5031,"parent":4942},"unitrack.assignment.Prefer",[331,128,5028],"Prefer","class Prefer(enum.StrEnum):","Backend preference for :func:`auto_assignment` and :class:`AutoLAP`.",{"file":5014,"line":1571},{"id":5033,"kind":363,"path":5034,"signature":5036,"summary":5037,"source":5038,"parent":5026},"unitrack.assignment.Prefer.AUTO",[331,128,5028,5035],"AUTO","AUTO = 'auto'","Pick the empirically-fastest backend. Currently always CPU LAPJV.",{"file":5014,"line":723},{"id":5040,"kind":363,"path":5041,"signature":5043,"summary":5044,"source":5045,"parent":5026},"unitrack.assignment.Prefer.CPU",[331,128,5028,5042],"CPU","CPU = 'cpu'","Force the CPU LAPJV solver. Same as ``AUTO`` for now.",{"file":5014,"line":742},{"id":5047,"kind":363,"path":5048,"signature":5050,"summary":5051,"source":5052,"parent":5026},"unitrack.assignment.Prefer.CUDA",[331,128,5028,5049],"CUDA","CUDA = 'cuda'","Force the torchmatch CUDA solver (Munkres\u002FLawler via AUTO dispatch).",{"file":5014,"line":616},{"id":5054,"kind":2303,"path":5055,"signature":5057,"summary":5058,"params":5059,"returns":5064,"raises":5066,"source":5069,"parent":4942},"unitrack.assignment.auto_assignment",[331,128,5056],"auto_assignment","def auto_assignment(cost: torch.Tensor, prefer: Prefer | str = Prefer.AUTO) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]","Solve a single LAP via the empirically-fastest backend.",[5060,5062],{"name":203,"type":646,"doc":5061},"``(N, M)`` cost matrix. May live on any device; non-CUDA paths\ncopy to host transparently.",{"name":5008,"type":5009,"default":5010,"doc":5063},"Backend preference. See :class:`Prefer`. Default\n:attr:`Prefer.AUTO`.",{"type":646,"doc":5065},"``(K, 2)`` long tensor of matched ``(row, col)`` indices on the\ninput tensor's device.",[5067],{"type":3619,"doc":5068},"If ``prefer=\"cuda\"`` is requested without a CUDA device.",{"file":5014,"line":1688},{"id":5071,"kind":2303,"path":5072,"signature":5074,"summary":5075,"params":5076,"returns":5082,"raises":5085,"source":5087,"parent":4942},"unitrack.assignment.auto_batch_assignment",[331,128,5073],"auto_batch_assignment","def auto_batch_assignment(cost_matrices: list[torch.Tensor], prefer: Prefer | str = Prefer.AUTO) -> list[tuple[torch.Tensor, torch.Tensor, torch.Tensor]]","Solve a batch of LAPs via the empirically-fastest backend.",[5077,5081],{"name":5078,"type":5079,"doc":5080},"cost_matrices","list of torch.Tensor","Per-problem cost matrices. Shapes may differ.",{"name":5008,"type":5009,"default":5010,"doc":5011},{"type":5083,"doc":5084},"list of tuple","Per-problem ``(matches, unmatched_rows, unmatched_cols)`` triples.",[5086],{"type":3619,"doc":5068},{"file":5014,"line":385},{"id":5089,"kind":344,"path":5090,"signature":5092,"summary":5093,"description":5094,"params":5095,"source":5099,"parent":4942},"unitrack.assignment.Assignment",[331,128,5091],"Assignment","class Assignment(torch.nn.Module):","Base class for linear-assignment-problem solvers.","Subclasses implement ``_assign`` over a 2-D cost matrix. The base\n:meth:`forward` masks entries above :attr:`threshold` to ``inf``\nbefore dispatching, so callers can bound match cost without each\nbackend re-implementing the guard.",[5096],{"name":4444,"type":474,"default":5097,"doc":5098},"torch.inf","Cost upper bound. Entries strictly above ``threshold`` are\nreplaced with ``inf`` and treated as forbidden by the solver.\nDefault ``inf`` (no thresholding).",{"file":5100,"line":2026},"unitrack\u002Fassignment\u002F_base.py",{"id":5102,"kind":355,"path":5103,"signature":5104,"source":5105,"parent":5089},"unitrack.assignment.Assignment.threshold",[331,128,5091,4444],"threshold: float = threshold",{"file":5100,"line":1005},{"id":5107,"kind":388,"path":5108,"signature":5109,"source":5110,"parent":5089},"unitrack.assignment.Assignment.__init__",[331,128,5091,405],"def __init__(self, threshold: float = torch.inf)",{"file":5100,"line":898},{"id":5112,"kind":388,"path":5113,"signature":5115,"summary":5116,"params":5117,"returns":5120,"source":5122,"parent":5089},"unitrack.assignment.Assignment.forward",[331,128,5091,5114],"forward","def forward(self, cost_matrix: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]","Solve the cost matrix.",[5118],{"name":4991,"type":646,"doc":5119},"``(N, M)`` cost matrix to solve.",{"type":646,"doc":5121},"``(K, 2)`` long tensor. Column 0 holds tracklet (row) indices,\ncolumn 1 holds detection (column) indices.",{"file":5100,"line":730},{"id":5124,"kind":344,"path":5125,"signature":5127,"summary":5128,"description":5129,"source":5130,"parent":4942},"unitrack.assignment.Greedy",[331,128,5126],"Greedy","class Greedy(Assignment):","Greedy nearest-neighbour linear-assignment solver.","Sorts cost entries ascending and consumes them in order, claiming each\nrow-column pair whose endpoints are still free. The result is locally\noptimal but not globally optimal; pairs whose cost exceeds the inherited\n:attr:`Assignment.threshold` are pre-masked to ``inf`` by the base class\nand never assigned. Useful as a low-cost baseline and when the cost\nmatrix is sparse enough that the optimal solution coincides with the\ngreedy one (e.g. high-confidence Re-ID after motion gating).\n\nSee :func:`.greedy_assignment` for the underlying tensor shapes and\ndtypes.",{"file":5131,"line":1128},"unitrack\u002Fassignment\u002F_greedy.py",{"id":5133,"kind":2303,"path":5134,"signature":5136,"summary":5137,"description":5138,"params":5139,"returns":5142,"source":5143,"parent":4942},"unitrack.assignment.greedy_assignment",[331,128,5135],"greedy_assignment","def greedy_assignment(cost_matrix: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]","Assign rows to columns by repeatedly picking the cheapest free pair.","Sorts the flattened cost matrix once and walks it in ascending order,\nclaiming each ``(row, col)`` whose endpoints are still free. Non-finite\nentries terminate the scan, so callers can mark forbidden pairs by\nsetting them to ``inf``.",[5140],{"name":4991,"type":646,"doc":5141},"``(N, M)`` 2-D cost matrix.",{"type":646,"doc":4996},{"file":5131,"line":736},{"id":5145,"kind":344,"path":5146,"signature":5148,"summary":5149,"source":5150,"parent":4942},"unitrack.assignment.Hungarian",[331,128,5147],"Hungarian","class Hungarian(Assignment):","Hungarian-algorithm LAP solver wrapping the SciPy implementation.",{"file":5151,"line":5152},"unitrack\u002Fassignment\u002F_hungarian.py",16,{"id":5154,"kind":2303,"path":5155,"signature":5157,"summary":5158,"description":5159,"params":5160,"returns":5163,"raises":5164,"source":5167,"parent":4942},"unitrack.assignment.hungarian_assignment",[331,128,5156],"hungarian_assignment","def hungarian_assignment(cost_matrix: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]","Solve a LAP via SciPy's Hungarian implementation.","Copies the cost matrix to host, calls\n:func:`scipy.optimize.linear_sum_assignment`, and returns the result\nas PyTorch tensors on the original device.",[5161],{"name":4991,"type":646,"doc":5162},"``(N, M)`` cost matrix. ``inf`` entries mark forbidden pairs;\n``NaN`` entries raise.",{"type":646,"doc":4996},[5165],{"type":398,"doc":5166},"If the cost matrix contains ``NaN``.",{"file":5151,"line":609},{"id":5169,"kind":344,"path":5170,"signature":5172,"summary":5173,"description":5174,"source":5175,"parent":4942},"unitrack.assignment.Jonker",[331,128,5171],"Jonker","class Jonker(Assignment):","Jonker-Volgenant LAP solver backed by the rectangular LAPJV CPU backend.","Dispatches to :func:`.lapjvx_assignment`; see that function for the\nfull shape and dtype contract.",{"file":5176,"line":1128},"unitrack\u002Fassignment\u002F_jonker.py",{"id":5178,"kind":2303,"path":5179,"signature":5181,"summary":5182,"description":5183,"params":5184,"returns":5189,"source":5190,"parent":4942},"unitrack.assignment.jonker_volgenant_assignment",[331,128,5180],"jonker_volgenant_assignment","def jonker_volgenant_assignment(cost_matrix: torch.Tensor, threshold: float) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]","Solve a LAP via the Jonker-Volgenant algorithm with a cost threshold.","Masks entries strictly above ``threshold`` to ``inf`` and dispatches\nto :func:`.lapjvx_assignment`.",[5185,5187],{"name":4991,"type":646,"doc":5186},"``(N, M)`` cost matrix.",{"name":4444,"type":474,"doc":5188},"Cost upper bound. Entries above ``threshold`` are treated as\nforbidden pairs.",{"type":646,"doc":4996},{"file":5176,"line":891},{"id":5192,"kind":344,"path":5193,"signature":5195,"summary":5196,"description":5197,"source":5198,"parent":4942},"unitrack.assignment.SoftAssignment",[331,128,5194],"SoftAssignment","class SoftAssignment(Assignment):","Differentiable linear-assignment solver using Sinkhorn iterations.","Computes an entropy-regularized optimal-transport plan for the cost\nmatrix (via log-domain Sinkhorn iterations) and extracts a discrete\nassignment by taking mutual-argmax pairs over the plan. The plan\nitself is fully differentiable; use :func:`.sinkhorn_log_plan`\ndirectly when training with a soft-assignment loss.",{"file":5199,"line":891},"unitrack\u002Fassignment\u002F_soft.py",{"id":5201,"kind":355,"path":5202,"signature":5203,"source":5204,"parent":5192},"unitrack.assignment.SoftAssignment.epsilon",[331,128,5194,3893],"epsilon: typing.Final[float] = epsilon",{"file":5199,"line":2517},{"id":5206,"kind":355,"path":5207,"signature":5209,"source":5210,"parent":5192},"unitrack.assignment.SoftAssignment.num_iter",[331,128,5194,5208],"num_iter","num_iter: typing.Final[int] = num_iter",{"file":5199,"line":3392},{"id":5212,"kind":388,"path":5213,"signature":5214,"summary":5215,"params":5216,"source":5227,"parent":5192},"unitrack.assignment.SoftAssignment.__init__",[331,128,5194,405],"def __init__(self, *args = (), epsilon: float = DEFAULT_EPSILON, num_iter: int = DEFAULT_NUM_ITER, **kwargs = {})","Initialize the soft-assignment module.",[5217,5220,5223,5225],{"name":3893,"type":474,"default":5218,"doc":5219},"DEFAULT_EPSILON","Entropy-regularization weight. Smaller values yield sharper,\nmore discrete transport plans at the cost of slower Sinkhorn\nconvergence and reduced numerical stability.",{"name":5208,"type":468,"default":5221,"doc":5222},"DEFAULT_NUM_ITER","Number of Sinkhorn iterations.",{"name":4974,"default":4975,"doc":5224},"Positional arguments passed to :class:`.Assignment`.",{"name":4978,"default":4979,"doc":5226},"Keyword arguments passed to :class:`.Assignment`.",{"file":5199,"line":637},{"id":5229,"kind":388,"path":5230,"signature":5232,"summary":5233,"description":5234,"params":5235,"returns":5237,"source":5238,"parent":5192},"unitrack.assignment.SoftAssignment.solve_with_plan",[331,128,5194,5231],"solve_with_plan","def solve_with_plan(self, cost_matrix: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor]","Solve and return matches together with the Sinkhorn log-plan.","Threads the Sinkhorn log-plan back to the caller in one solve.\nUse this when a downstream consumer (e.g. :class:`~unitrack.states.SoftReplace`)\nneeds the same plan that produced the matches — calling\n:meth:`~unitrack.assignment.Assignment.forward` and re-running\n:func:`sinkhorn_log_plan` would\ncompute the plan twice on different inputs (the threshold-masked\ncost vs the un-masked original).",[5236],{"name":4991,"type":646,"doc":5186},{"type":646,"doc":4996},{"file":5199,"line":2235},{"id":5240,"kind":2303,"path":5241,"signature":5243,"summary":5244,"description":5245,"params":5246,"returns":5258,"raises":5260,"source":5263,"parent":4942},"unitrack.assignment.sinkhorn_log_plan",[331,128,5242],"sinkhorn_log_plan","def sinkhorn_log_plan(cost_matrix: torch.Tensor, epsilon: float = DEFAULT_EPSILON, num_iter: int = DEFAULT_NUM_ITER, row_marginal: torch.Tensor | None = None, col_marginal: torch.Tensor | None = None) -> torch.Tensor","Compute a log-domain Sinkhorn transport plan for a cost matrix.","Performs ``num_iter`` iterations of log-domain Sinkhorn updates on\nthe Gibbs kernel :math:`\\log K = -C \u002F \\epsilon`, producing the log\nof the entropy-regularized optimal transport plan. The result is\nnumerically stable with respect to ``inf`` entries in ``C`` (which\nmark forbidden assignments) via ``torch.logsumexp``.",[5247,5249,5251,5252,5255],{"name":4991,"type":646,"doc":5248},"``(N, M)`` cost matrix. ``inf`` entries are treated as forbidden\nassignments and produce ``-inf`` entries in the log-plan.",{"name":3893,"type":474,"default":5218,"doc":5250},"Entropy-regularization weight.",{"name":5208,"type":468,"default":5221,"doc":5222},{"name":5253,"type":649,"default":486,"doc":5254},"row_marginal","``(N,)`` target row marginal. Uniform ``1\u002FN`` by default.",{"name":5256,"type":649,"default":486,"doc":5257},"col_marginal","``(M,)`` target column marginal. Uniform ``1\u002FM`` by default.",{"type":646,"doc":5259},"``(N, M)`` tensor of ``log P`` where ``P`` is the Sinkhorn plan.",[5261],{"type":398,"doc":5262},"If ``epsilon`` is not strictly positive.",{"file":5199,"line":2182},{"id":5265,"kind":2303,"path":5266,"signature":5267,"summary":5268,"description":5269,"params":5270,"returns":5276,"source":5277,"parent":4942},"unitrack.assignment.soft_assignment",[331,128,3592],"def soft_assignment(cost_matrix: torch.Tensor, epsilon: float = DEFAULT_EPSILON, num_iter: int = DEFAULT_NUM_ITER) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]","Derive a discrete assignment from a Sinkhorn transport plan.","Runs :func:`.sinkhorn_log_plan` on the cost matrix, then extracts a\nfull discrete assignment by running the Hungarian algorithm on\n``-log_plan`` — equivalently, maximising the plan's log-likelihood\nover a bipartite matching. Pairs whose underlying cost is non-finite\nare rejected and moved to the residual.\n\nThe hard extraction is non-differentiable. When training with a\nsoft-assignment loss, call :func:`.sinkhorn_log_plan` directly and\ncompute the loss from the returned log-plan.",[5271,5272,5274],{"name":4991,"type":646,"doc":4992},{"name":3893,"type":474,"default":5218,"doc":5273},"Entropy-regularization weight, forwarded to Sinkhorn.",{"name":5208,"type":468,"default":5221,"doc":5275},"Number of Sinkhorn iterations, forwarded to Sinkhorn.",{"type":646,"doc":4996},{"file":5199,"line":3896},{"id":5279,"kind":2303,"path":5280,"signature":5282,"summary":5283,"params":5284,"returns":5288,"source":5290,"parent":4942},"unitrack.assignment.gather_total_cost",[331,128,5281],"gather_total_cost","def gather_total_cost(cost_matrix: Tensor, assignment: Tensor) -> Tensor","Sum the cost-matrix entries selected by a row-column assignment.",[5285,5286],{"name":4991,"type":646,"doc":5186},{"name":128,"type":646,"doc":5287},"``(K, 2)`` long tensor of ``(row, col)`` index pairs.",{"type":646,"doc":5289},"Scalar tensor holding the sum of ``cost_matrix[r, c]`` over the\nassigned pairs.",{"file":5291,"line":2026},"unitrack\u002Fassignment\u002F_utils.py",{"id":5293,"kind":344,"path":5294,"signature":5296,"summary":5297,"description":5298,"params":5299,"source":5302,"parent":4942},"unitrack.assignment.Associate",[331,128,5295],"Associate","class Associate:","Materialise a :class:`~unitrack.data.CostExpression` and run an :class:`Assignment`.","Acts as the bridge between cost-construction (gates, fused costs) and\nhard matching. For :class:`~unitrack.assignment.SoftAssignment` backends\nthe Sinkhorn log-plan is solved once and reused both for hard extraction and for\ndownstream :class:`~unitrack.states.SoftReplace` blending.",[5300],{"name":128,"type":5091,"doc":5301},"Backend that produces a hard match from a materialised cost\nmatrix.",{"file":5303,"line":1746},"unitrack\u002Fassignment\u002Fassociate.py",{"id":5305,"kind":355,"path":5306,"signature":5307,"source":5308,"parent":5293},"unitrack.assignment.Associate.assignment",[331,128,5295,128],"assignment: Assignment",{"file":5303,"line":616},{"id":5310,"kind":388,"path":5311,"signature":1170,"summary":5312,"params":5313,"returns":5320,"raises":5322,"source":5325,"parent":5293},"unitrack.assignment.Associate.__call__",[331,128,5295,1009],"Materialise ``cost`` and produce a :class:`~unitrack.data.MatchOutcome`.",[5314,5315,5316,5318],{"name":1174,"type":581,"doc":1995},{"name":1177,"type":394,"doc":2114},{"name":1180,"type":452,"doc":5317},"Frame context (unused; kept for protocol parity).",{"name":203,"type":596,"default":486,"doc":5319},"Cost expression to materialise. Required; the ``None``\ndefault exists only so this method matches the broader\nassociator call signature.",{"type":824,"doc":5321},"Matched pairs, residual indices, per-match costs, and\n(for soft assignment) the transport plan.",[5323],{"type":398,"doc":5324},"If ``cost`` is ``None``.",{"file":5303,"line":630},{"id":5327,"kind":388,"path":5328,"signature":5329,"source":5330,"parent":5293},"unitrack.assignment.Associate.__init__",[331,128,5295,405],"def __init__(self, assignment: Assignment) -> None",{"file":5303,"line":341},{"id":5332,"kind":344,"path":5333,"signature":5335,"summary":5336,"description":5337,"source":5338,"parent":4942},"unitrack.assignment.ClipAssociator",[331,128,5334],"ClipAssociator","class ClipAssociator(abc.ABC):","Abstract base for clip-global matchers.","Extension point: no concrete implementation ships in-tree. Users\nprovide their own subclass and pass it to :class:`~unitrack.tracker.ClipTracker`.",{"file":5339,"line":1135},"unitrack\u002Fassignment\u002Fclip_associate.py",{"id":5341,"kind":388,"path":5342,"signature":5343,"summary":5344,"params":5345,"returns":5352,"source":5354,"parent":5332},"unitrack.assignment.ClipAssociator.__call__",[331,128,5334,1009],"def __call__(self, cs: ClipTracklets, ds: ClipDetections, ctx: ClipFrameContext) -> ClipMatchOutcome","Match clip tracklets to clip detections.",[5346,5348,5350],{"name":1174,"type":547,"doc":5347},"Tracklet snapshot spanning the clip.",{"name":1177,"type":346,"doc":5349},"Detection snapshot spanning the clip.",{"name":1180,"type":411,"doc":5351},"Per-clip frame context.",{"type":500,"doc":5353},"Per-frame match outcomes for the clip.",{"file":5339,"line":4850},{"id":5356,"kind":344,"path":5357,"signature":5359,"summary":5360,"description":5361,"source":5362,"parent":4942},"unitrack.assignment.LAPJVS",[331,128,5358],"LAPJVS","class LAPJVS(Assignment):",":class:`Assignment` wrapper for the square Jonker-Volgenant solver.","See :func:`lapjvs_assignment` for shape and dtype contract.",{"file":5363,"line":5364},"unitrack\u002Fassignment\u002Flapjv\u002F_solver.py",162,{"id":5366,"kind":344,"path":5367,"signature":5369,"summary":5370,"description":5371,"source":5372,"parent":4942},"unitrack.assignment.LAPJVX",[331,128,5368],"LAPJVX","class LAPJVX(Assignment):",":class:`Assignment` wrapper for the rectangular Jonker-Volgenant solver.","See :func:`lapjvx_assignment` for shape and dtype contract.",{"file":5363,"line":1640},{"id":5374,"kind":2303,"path":5375,"signature":5377,"summary":5378,"params":5379,"returns":5382,"source":5384,"parent":4942},"unitrack.assignment.lapjvs_assignment",[331,128,5376],"lapjvs_assignment","def lapjvs_assignment(cost: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]","Solve a single square LAP via the Jonker-Volgenant solver.",[5380],{"name":203,"type":646,"doc":5381},"``(N, N)`` square cost matrix.",{"type":646,"doc":5383},"``(N, 2)`` long tensor of matched ``(row, col)`` indices.",{"file":5363,"line":369},{"id":5386,"kind":2303,"path":5387,"signature":5389,"summary":5390,"params":5391,"returns":5394,"source":5396,"parent":4942},"unitrack.assignment.lapjvs_batch_assignment",[331,128,5388],"lapjvs_batch_assignment","def lapjvs_batch_assignment(cost_matrices: list[torch.Tensor]) -> list[tuple[torch.Tensor, torch.Tensor, torch.Tensor]]","Solve a batch of square LAPs via the Jonker-Volgenant solver.",[5392],{"name":5078,"type":5079,"doc":5393},"Per-problem square cost matrices. Shapes may differ.",{"type":5083,"doc":5395},"Per-problem ``(matches, unmatched_rows, unmatched_cols)`` triples\nfollowing the shape conventions of :func:`lapjvs_assignment`.",{"file":5363,"line":1789},{"id":5398,"kind":2303,"path":5399,"signature":5401,"summary":5402,"params":5403,"returns":5406,"source":5407,"parent":4942},"unitrack.assignment.lapjvx_assignment",[331,128,5400],"lapjvx_assignment","def lapjvx_assignment(cost: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]","Solve a single LAP via the rectangular Jonker-Volgenant solver.",[5404],{"name":203,"type":646,"doc":5405},"``(N, M)`` cost matrix. May live on any device; moves to CPU\ntransparently.",{"type":646,"doc":5065},{"file":5363,"line":723},{"id":5409,"kind":2303,"path":5410,"signature":5412,"summary":5413,"params":5414,"returns":5416,"source":5418,"parent":4942},"unitrack.assignment.lapjvx_batch_assignment",[331,128,5411],"lapjvx_batch_assignment","def lapjvx_batch_assignment(cost_matrices: list[torch.Tensor]) -> list[tuple[torch.Tensor, torch.Tensor, torch.Tensor]]","Solve a batch of LAPs via the rectangular Jonker-Volgenant solver.",[5415],{"name":5078,"type":5079,"doc":5080},{"type":5083,"doc":5417},"Per-problem ``(matches, unmatched_rows, unmatched_cols)`` triples\nfollowing the shape conventions of :func:`lapjvx_assignment`.",{"file":5363,"line":3839},{"id":5420,"kind":335,"path":5421,"signature":5422,"summary":5423,"source":5424,"parent":4942},"unitrack.assignment.associate",[331,128,131],"module unitrack.assignment.associate","Associate — bridges a CostExpression to a hard assignment.",{"file":5303,"line":341},{"id":5426,"kind":335,"path":5427,"signature":5428,"summary":5429,"source":5430,"parent":4942},"unitrack.assignment.clip_associate",[331,128,134],"module unitrack.assignment.clip_associate","ClipAssociator abstract base — extension point for clip-global solvers.",{"file":5339,"line":341},{"id":5432,"kind":335,"path":5433,"signature":5434,"summary":5435,"description":5436,"source":5437,"parent":4942},"unitrack.assignment.lap",[331,128,137],"module unitrack.assignment.lap","CUDA LAP solvers backed by :mod:`torchmatch.assignment`.","Three backends (classical\u002FMunkres, tree\u002FLawler, hybrid\u002Fdeprecated) plus\na batched entry point. Prefer\n:func:`unitrack.assignment.auto_assignment` \u002F\n:class:`unitrack.assignment.AutoLAP` for new code; reach for these\nbackends only when you need explicit CUDA solver control.",{"file":5438,"line":341},"unitrack\u002Fassignment\u002Flap\u002F__init__.py",{"id":5440,"kind":344,"path":5441,"signature":5443,"summary":5444,"description":5445,"params":5446,"source":5454,"parent":5432},"unitrack.assignment.lap.LAP",[331,128,137,5442],"LAP","class LAP(Assignment):","Solves the linear assignment problem via torchmatch CUDA solvers.","A CUDA-capable device is required.",[5447,5452],{"name":5448,"type":5449,"default":5450,"doc":5451},"backend","Backend | str","Backend.CLASSICAL","Solver backend (default :attr:`Backend.CLASSICAL`). Accepts a\n:class:`Backend` member or its string value.",{"name":4444,"doc":5453},"Cost threshold passed to :class:`.Assignment`.",{"file":5455,"line":874},"unitrack\u002Fassignment\u002Flap\u002F_solver.py",{"id":5457,"kind":355,"path":5458,"signature":5459,"source":5460,"parent":5440},"unitrack.assignment.lap.LAP.backend",[331,128,137,5442,5448],"backend: typing.Final[Backend] = Backend(backend)",{"file":5455,"line":2223},{"id":5462,"kind":388,"path":5463,"signature":5464,"source":5465,"parent":5440},"unitrack.assignment.lap.LAP.__init__",[331,128,137,5442,405],"def __init__(self, *args = (), backend: Backend | str = Backend.CLASSICAL, **kwargs = {}) -> None",{"file":5455,"line":360},{"id":5467,"kind":344,"path":5468,"signature":5470,"summary":5471,"description":5472,"source":5473,"parent":5432},"unitrack.assignment.lap.Backend",[331,128,137,5469],"Backend","class Backend(enum.StrEnum):","LAP solver backend selection.","Maps to :class:`torchmatch.assignment.Backend` at dispatch time.",{"file":5455,"line":1135},{"id":5475,"kind":363,"path":5476,"signature":5478,"summary":5479,"source":5480,"parent":5467},"unitrack.assignment.lap.Backend.CLASSICAL",[331,128,137,5469,5477],"CLASSICAL","CLASSICAL = 'classical'","Classical augmenting-path Hungarian solver (Munkres).",{"file":5455,"line":1676},{"id":5482,"kind":363,"path":5483,"signature":5485,"summary":5486,"source":5487,"parent":5467},"unitrack.assignment.lap.Backend.HYBRID",[331,128,137,5469,5484],"HYBRID","HYBRID = 'hybrid'","Deprecated. Falls back to :attr:`CLASSICAL` (Munkres).",{"file":5455,"line":1031},{"id":5489,"kind":363,"path":5490,"signature":5492,"summary":5493,"source":5494,"parent":5467},"unitrack.assignment.lap.Backend.TREE",[331,128,137,5469,5491],"TREE","TREE = 'tree'","Parallel BFS tree-augmentation Hungarian solver (Lawler).",{"file":5455,"line":898},{"id":5496,"kind":2303,"path":5497,"signature":5499,"summary":5500,"params":5501,"returns":5505,"raises":5506,"source":5509,"parent":5432},"unitrack.assignment.lap.lap_assignment",[331,128,137,5498],"lap_assignment","def lap_assignment(cost_matrix: torch.Tensor, backend: Backend | str = Backend.CLASSICAL) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]","Solve the linear assignment problem via a torchmatch CUDA solver.",[5502,5504],{"name":4991,"type":646,"doc":5503},"``(N, M)`` cost matrix. Non-finite entries (``inf``) mark\nforbidden assignments.",{"name":5448,"type":5449,"default":5450,"doc":5451},{"type":646,"doc":4996},[5507],{"type":3619,"doc":5508},"If no CUDA device is available.",{"file":5455,"line":2671},{"id":5511,"kind":2303,"path":5512,"signature":5514,"summary":5515,"params":5516,"returns":5520,"source":5522,"parent":5432},"unitrack.assignment.lap.lap_batch_assignment",[331,128,137,5513],"lap_batch_assignment","def lap_batch_assignment(cost_matrices: list[torch.Tensor]) -> list[tuple[torch.Tensor, torch.Tensor, torch.Tensor]]","Solve a batch of linear assignment problems via torchmatch CUDA solvers.",[5517],{"name":5078,"type":5518,"doc":5519},"list[torch.Tensor]","List of ``(N_i, M_i)`` cost matrices.",{"type":5083,"doc":5521},"Per-problem ``(matches, unmatched_rows, unmatched_cols)`` triples\nfollowing the shape conventions of :func:`lap_assignment`.",{"file":5455,"line":5523},158,{"id":5525,"kind":335,"path":5526,"signature":5527,"summary":5528,"description":5529,"source":5530,"parent":4942},"unitrack.assignment.lapjv",[331,128,140],"module unitrack.assignment.lapjv","CPU LAP solvers backed by :mod:`torchmatch.assignment`.","Two solver flavours:\n\n* ``lapjvx`` -- rectangular-cost JV; the empirical default in\n  :func:`unitrack.assignment.auto_assignment`.\n* ``lapjvs`` -- square-cost JV; equivalent to ``lapjvx`` (torchmatch\n  auto-selects the compact kernel for square inputs).",{"file":5531,"line":341},"unitrack\u002Fassignment\u002Flapjv\u002F__init__.py",{"id":5533,"kind":335,"path":5534,"signature":5535,"summary":5536,"source":5537,"parent":331},"unitrack.benchmarks",[331,143],"module unitrack.benchmarks","Benchmark harnesses for unitrack (not part of the core import surface).",{"file":5538,"line":341},"unitrack\u002Fbenchmarks\u002F__init__.py",{"id":5540,"kind":335,"path":5541,"signature":5542,"summary":5543,"description":5544,"source":5545,"parent":5533},"unitrack.benchmarks.hota",[331,143,146],"module unitrack.benchmarks.hota","HOTA model-benchmark harness.","Pairs open-weights HuggingFace models with the unitrack tracker and the\nevaluators HOTA metric. See ``benchmarks\u002Fhota\u002FREADME.md``.",{"file":5546,"line":341},"unitrack\u002Fbenchmarks\u002Fhota\u002F__init__.py",{"id":5548,"kind":363,"path":5549,"signature":5551,"source":5552,"parent":5540},"unitrack.benchmarks.hota.DATASET_REGISTRY",[331,143,146,5550],"DATASET_REGISTRY","DATASET_REGISTRY: dict[str, type] = {CityscapesDVPSDataset.key: CityscapesDVPSDataset}",{"file":5553,"line":1438},"unitrack\u002Fbenchmarks\u002Fhota\u002Fdatasets.py",{"id":5555,"kind":344,"path":5556,"signature":5558,"summary":5559,"source":5560,"parent":5540},"unitrack.benchmarks.hota.CityscapesDVPSDataset",[331,143,146,5557],"CityscapesDVPSDataset","class CityscapesDVPSDataset:","Reads ``cityscapes-dvps.{split}.lmdb`` (keys ``seq\u002Fframe\u002F{image,panoptic}``).",{"file":5553,"line":1025},{"id":5562,"kind":355,"path":5563,"signature":5564,"source":5565,"parent":5555},"unitrack.benchmarks.hota.CityscapesDVPSDataset.key",[331,143,146,5557,1805],"key = 'cityscapes-dvps'",{"file":5553,"line":4400},{"id":5567,"kind":355,"path":5568,"signature":5570,"source":5571,"parent":5555},"unitrack.benchmarks.hota.CityscapesDVPSDataset.thing_ids",[331,143,146,5557,5569],"thing_ids","thing_ids = _THING_IDS",{"file":5553,"line":1031},{"id":5573,"kind":355,"path":5574,"signature":5576,"source":5577,"parent":5555},"unitrack.benchmarks.hota.CityscapesDVPSDataset.offset",[331,143,146,5557,5575],"offset","offset = _OFFSET",{"file":5553,"line":4742},{"id":5579,"kind":388,"path":5580,"signature":5581,"source":5582,"parent":5555},"unitrack.benchmarks.hota.CityscapesDVPSDataset.__init__",[331,143,146,5557,405],"def __init__(self, lmdb_path: str | Path, limit_seqs: int | None = None, max_frames: int | None = None) -> None",{"file":5553,"line":898},{"id":5584,"kind":355,"path":5585,"signature":5587,"source":5588,"parent":5555},"unitrack.benchmarks.hota.CityscapesDVPSDataset.lmdb_path",[331,143,146,5557,5586],"lmdb_path","lmdb_path = Path(lmdb_path)",{"file":5553,"line":742},{"id":5590,"kind":355,"path":5591,"signature":5593,"source":5594,"parent":5555},"unitrack.benchmarks.hota.CityscapesDVPSDataset.limit_seqs",[331,143,146,5557,5592],"limit_seqs","limit_seqs = limit_seqs",{"file":5553,"line":2356},{"id":5596,"kind":355,"path":5597,"signature":5599,"source":5600,"parent":5555},"unitrack.benchmarks.hota.CityscapesDVPSDataset.max_frames",[331,143,146,5557,5598],"max_frames","max_frames = max_frames",{"file":5553,"line":609},{"id":5602,"kind":388,"path":5603,"signature":5605,"summary":5606,"source":5607,"parent":5555},"unitrack.benchmarks.hota.CityscapesDVPSDataset.sequences",[331,143,146,5557,5604],"sequences","def sequences(self) -> Iterator[SequenceSample]","Yield one :class:`SequenceSample` per sequence in id order.",{"file":5553,"line":352},{"id":5609,"kind":344,"path":5610,"signature":5612,"summary":5613,"description":5614,"source":5615,"parent":5540},"unitrack.benchmarks.hota.PanopticMetricRunner",[331,143,146,5611],"PanopticMetricRunner","class PanopticMetricRunner:","Stream (gt, pred) panoptic maps into HOTA\u002FCLEAR\u002FIdentity and aggregate.","Surfaces a flat ``{metric_name: float}`` of the headline scores: HOTA\u002FDetA\u002F\nAssA\u002FLocA (``___AUC`` aggregates) plus MOTA and IDF1.",{"file":5616,"line":5617},"unitrack\u002Fbenchmarks\u002Fhota\u002Fmetric.py",8,{"id":5619,"kind":388,"path":5620,"signature":5621,"source":5622,"parent":5609},"unitrack.benchmarks.hota.PanopticMetricRunner.__init__",[331,143,146,5611,405],"def __init__(self, offset: int, thing_ids: list[int]) -> None",{"file":5616,"line":5152},{"id":5624,"kind":388,"path":5625,"signature":5627,"summary":5628,"source":5629,"parent":5609},"unitrack.benchmarks.hota.PanopticMetricRunner.start_sequence",[331,143,146,5611,5626],"start_sequence","def start_sequence(self, length: int) -> None","Open a new sequence of ``length`` frames on every metric.",{"file":5616,"line":1025},{"id":5631,"kind":388,"path":5632,"signature":5633,"summary":5634,"source":5635,"parent":5609},"unitrack.benchmarks.hota.PanopticMetricRunner.update",[331,143,146,5611,306],"def update(self, gt_panoptic: np.ndarray, pred_panoptic: np.ndarray) -> None","Feed one frame's ground-truth and predicted panoptic maps.",{"file":5616,"line":4742},{"id":5637,"kind":388,"path":5638,"signature":5640,"summary":5641,"source":5642,"parent":5609},"unitrack.benchmarks.hota.PanopticMetricRunner.end_sequence",[331,143,146,5611,5639],"end_sequence","def end_sequence(self) -> None","Close the current sequence on every metric.",{"file":5616,"line":1005},{"id":5644,"kind":388,"path":5645,"signature":5647,"summary":5648,"source":5649,"parent":5609},"unitrack.benchmarks.hota.PanopticMetricRunner.compute",[331,143,146,5611,5646],"compute","def compute(self) -> dict[str, float]","Aggregate the streamed sequences into headline scalar scores.",{"file":5616,"line":2356},{"id":5651,"kind":363,"path":5652,"signature":5654,"source":5655,"parent":5540},"unitrack.benchmarks.hota.MODEL_REGISTRY",[331,143,146,5653],"MODEL_REGISTRY","MODEL_REGISTRY = dict(_MODEL_REPOS)",{"file":5656,"line":5657},"unitrack\u002Fbenchmarks\u002Fhota\u002Fmodels.py",215,{"id":5659,"kind":344,"path":5660,"signature":5662,"summary":5663,"source":5664,"parent":5540},"unitrack.benchmarks.hota.HFPanopticAdapter",[331,143,146,5661],"HFPanopticAdapter","class HFPanopticAdapter:","Loads a HF panoptic model and emits per-frame thing instances.",{"file":5656,"line":1821},{"id":5666,"kind":388,"path":5667,"signature":5668,"source":5669,"parent":5659},"unitrack.benchmarks.hota.HFPanopticAdapter.__init__",[331,143,146,5661,405],"def __init__(self, key: str, thing_ids: Iterable[int]) -> None",{"file":5656,"line":5670},163,{"id":5672,"kind":355,"path":5673,"signature":5674,"source":5675,"parent":5659},"unitrack.benchmarks.hota.HFPanopticAdapter.key",[331,143,146,5661,1805],"key = key",{"file":5656,"line":5676},167,{"id":5678,"kind":355,"path":5679,"signature":5681,"source":5682,"parent":5659},"unitrack.benchmarks.hota.HFPanopticAdapter.repo_id",[331,143,146,5661,5680],"repo_id","repo_id = _MODEL_REPOS[key]",{"file":5656,"line":558},{"id":5684,"kind":355,"path":5685,"signature":5686,"source":5687,"parent":5659},"unitrack.benchmarks.hota.HFPanopticAdapter.thing_ids",[331,143,146,5661,5569],"thing_ids = {(int(t)) for t in thing_ids}",{"file":5656,"line":2467},{"id":5689,"kind":388,"path":5690,"signature":5691,"summary":5692,"source":5693,"parent":5659},"unitrack.benchmarks.hota.HFPanopticAdapter.load",[331,143,146,5661,2055],"def load(self, device: torch.device) -> None","Download and instantiate the HF model + image processor on ``device``.",{"file":5656,"line":1481},{"id":5695,"kind":388,"path":5696,"signature":5697,"summary":5698,"source":5699,"parent":5659},"unitrack.benchmarks.hota.HFPanopticAdapter.__call__",[331,143,146,5661,1009],"def __call__(self, image: np.ndarray) -> FramePrediction","Run panoptic inference on one RGB frame and return thing instances.",{"file":5656,"line":3968},{"id":5701,"kind":2303,"path":5702,"signature":5704,"summary":5705,"source":5706,"parent":5540},"unitrack.benchmarks.hota.build_model",[331,143,146,5703],"build_model","def build_model(key: str, thing_ids: Iterable[int]) -> HFPanopticAdapter","Construct an :class:`HFPanopticAdapter` for a registry ``key``.",{"file":5656,"line":1913},{"id":5708,"kind":344,"path":5709,"signature":5711,"summary":5712,"source":5713,"parent":5540},"unitrack.benchmarks.hota.DatasetAdapter",[331,143,146,5710],"DatasetAdapter","class DatasetAdapter(Protocol):","A source of ground-truth sequences plus its panoptic label space.",{"file":5714,"line":913},"unitrack\u002Fbenchmarks\u002Fhota\u002Fprotocols.py",{"id":5716,"kind":355,"path":5717,"signature":5718,"source":5719,"parent":5708},"unitrack.benchmarks.hota.DatasetAdapter.key",[331,143,146,5710,1805],"key: str",{"file":5714,"line":736},{"id":5721,"kind":355,"path":5722,"signature":5723,"source":5724,"parent":5708},"unitrack.benchmarks.hota.DatasetAdapter.thing_ids",[331,143,146,5710,5569],"thing_ids: list[int]",{"file":5714,"line":742},{"id":5726,"kind":355,"path":5727,"signature":5728,"source":5729,"parent":5708},"unitrack.benchmarks.hota.DatasetAdapter.offset",[331,143,146,5710,5575],"offset: int",{"file":5714,"line":2356},{"id":5731,"kind":388,"path":5732,"signature":5605,"summary":5733,"source":5734,"parent":5708},"unitrack.benchmarks.hota.DatasetAdapter.sequences",[331,143,146,5710,5604],"Yield each ground-truth sequence in deterministic order.",{"file":5714,"line":616},{"id":5736,"kind":344,"path":5737,"signature":5739,"summary":5740,"source":5741,"parent":5540},"unitrack.benchmarks.hota.ModelAdapter",[331,143,146,5738],"ModelAdapter","class ModelAdapter(Protocol):","A HuggingFace model that emits one ``FramePrediction`` per image.",{"file":5714,"line":1135},{"id":5743,"kind":355,"path":5744,"signature":5718,"source":5745,"parent":5736},"unitrack.benchmarks.hota.ModelAdapter.key",[331,143,146,5738,1805],{"file":5714,"line":2130},{"id":5747,"kind":388,"path":5748,"signature":5691,"summary":5749,"source":5750,"parent":5736},"unitrack.benchmarks.hota.ModelAdapter.load",[331,143,146,5738,2055],"Materialize weights\u002Fprocessor on ``device`` (call once before use).",{"file":5714,"line":1025},{"id":5752,"kind":388,"path":5753,"signature":5697,"summary":5754,"source":5755,"parent":5736},"unitrack.benchmarks.hota.ModelAdapter.__call__",[331,143,146,5738,1009],"Run inference on a single ``(H, W, 3)`` uint8 RGB frame.",{"file":5714,"line":1031},{"id":5757,"kind":344,"path":5758,"signature":5760,"summary":5761,"source":5762,"parent":5540},"unitrack.benchmarks.hota.TrackerFactory",[331,143,146,5759],"TrackerFactory","class TrackerFactory(Protocol):","A factory returning a fresh ``unitrack.MultiStream`` for one sequence.",{"file":5714,"line":663},{"id":5764,"kind":388,"path":5765,"signature":5766,"summary":5767,"source":5768,"parent":5757},"unitrack.benchmarks.hota.TrackerFactory.__call__",[331,143,146,5759,1009],"def __call__(self, height: int, width: int) -> MultiStream","Build a fresh tracker sized to a sequence's frame resolution.",{"file":5714,"line":874},{"id":5770,"kind":344,"path":5771,"signature":5773,"summary":5774,"description":5775,"source":5776,"parent":5540},"unitrack.benchmarks.hota.TrackRemap",[331,143,146,5772],"TrackRemap","class TrackRemap:","Stable, per-sequence ``(semantic_class, track_id) -> 1-based instance`` map.","The panoptic encoding ``semantic * offset + instance`` requires the instance\ncomponent to be a small positive integer (index 0 is reserved for\ncrowd\u002Fvoid and is excluded by the metric). Track ids assigned by the tracker\nare arbitrary and may exceed ``offset``; this remaps them to ``1, 2, 3, …``\nin first-seen order, kept consistent across all frames of one sequence.\n\nIndexing is scoped per semantic class: two tracks of *different* classes may\nshare an instance index without colliding in the encoding because their\n``semantic`` component differs. A new index that would reach ``offset``\n(which would corrupt the encoding by carrying into the semantic component)\nraises a :class:`ValueError`.",{"file":5777,"line":5778},"unitrack\u002Fbenchmarks\u002Fhota\u002Frender.py",9,{"id":5780,"kind":388,"path":5781,"signature":5782,"source":5783,"parent":5770},"unitrack.benchmarks.hota.TrackRemap.__init__",[331,143,146,5772,405],"def __init__(self, offset: int) -> None",{"file":5777,"line":4400},{"id":5785,"kind":388,"path":5786,"signature":5788,"summary":5789,"source":5790,"parent":5770},"unitrack.benchmarks.hota.TrackRemap.index_for",[331,143,146,5772,5787],"index_for","def index_for(self, track_id: int, semantic_class: int) -> int","Return the 1-based instance index for ``track_id`` in its class.",{"file":5777,"line":898},{"id":5792,"kind":2303,"path":5793,"signature":5795,"summary":5796,"description":5797,"source":5798,"parent":5540},"unitrack.benchmarks.hota.render_pred_panoptic",[331,143,146,5794],"render_pred_panoptic","def render_pred_panoptic(masks: torch.Tensor, categories: torch.Tensor, track_ids: torch.Tensor, height: int, width: int, offset: int, remap: TrackRemap) -> np.ndarray","Paint thing instances as ``semantic * offset + dense_instance``.","Detections with ``track_id \u003C 0`` are skipped (a defensive contract; the\nrunner only renders kept, tracked instances). Later masks win on overlap\n(model panoptic output is non-overlapping in practice).",{"file":5777,"line":862},{"id":5800,"kind":344,"path":5801,"signature":5803,"summary":5804,"source":5805,"parent":5540},"unitrack.benchmarks.hota.BenchmarkRunner",[331,143,146,5802],"BenchmarkRunner","class BenchmarkRunner:","Run each model over every sequence and aggregate HOTA per model.",{"file":5806,"line":4742},"unitrack\u002Fbenchmarks\u002Fhota\u002Frunner.py",{"id":5808,"kind":388,"path":5809,"signature":5810,"source":5811,"parent":5800},"unitrack.benchmarks.hota.BenchmarkRunner.__init__",[331,143,146,5802,405],"def __init__(self, device: torch.device | None = None, cost_threshold: float = 0.5, min_score: float = 0.1, fps: float = 15.0, tracker_factory: TrackerFactory | None = None, metric_factory: Callable[[int, list[int]], PanopticMetricRunner] | None = None) -> None",{"file":5806,"line":1571},{"id":5813,"kind":355,"path":5814,"signature":5815,"source":5816,"parent":5800},"unitrack.benchmarks.hota.BenchmarkRunner.device",[331,143,146,5802,484],"device = device or torch.device('cpu')",{"file":5806,"line":623},{"id":5818,"kind":355,"path":5819,"signature":5821,"source":5822,"parent":5800},"unitrack.benchmarks.hota.BenchmarkRunner.cost_threshold",[331,143,146,5802,5820],"cost_threshold","cost_threshold = cost_threshold",{"file":5806,"line":630},{"id":5824,"kind":355,"path":5825,"signature":5827,"source":5828,"parent":5800},"unitrack.benchmarks.hota.BenchmarkRunner.min_score",[331,143,146,5802,5826],"min_score","min_score = min_score",{"file":5806,"line":637},{"id":5830,"kind":355,"path":5831,"signature":5832,"source":5833,"parent":5800},"unitrack.benchmarks.hota.BenchmarkRunner.fps",[331,143,146,5802,473],"fps = fps",{"file":5806,"line":842},{"id":5835,"kind":355,"path":5836,"signature":5838,"source":5839,"parent":5800},"unitrack.benchmarks.hota.BenchmarkRunner.tracker_factory",[331,143,146,5802,5837],"tracker_factory","tracker_factory = tracker_factory or default_tracker_factory(cost_threshold=cost_threshold)",{"file":5806,"line":663},{"id":5841,"kind":355,"path":5842,"signature":5844,"source":5845,"parent":5800},"unitrack.benchmarks.hota.BenchmarkRunner.metric_factory",[331,143,146,5802,5843],"metric_factory","metric_factory = metric_factory or (lambda offset, thing_ids: PanopticMetricRunner(offset=offset, thing_ids=thing_ids))",{"file":5806,"line":1048},{"id":5847,"kind":388,"path":5848,"signature":5850,"summary":5851,"description":5852,"source":5853,"parent":5800},"unitrack.benchmarks.hota.BenchmarkRunner.run",[331,143,146,5802,5849],"run","def run(self, models: list[ModelAdapter], dataset: DatasetAdapter, trackers: dict[str, TrackerFactory] | None = None) -> list[BenchmarkResult]","Score every ``(model, tracker)`` combo on ``dataset``, one result each.","``trackers`` maps a tracker key to its factory; when omitted it defaults\nto ``{\"maskiou\": \u003Cconstructor tracker_factory>}`` so the single-tracker\nbehavior is preserved. A combo that fails (e.g. an unsupported checkpoint,\nan out-of-memory load, or a tracker that cannot be built) is logged and\nskipped so it cannot lose the rest of the sweep; only successfully-scored\ncombos appear in the returned list.",{"file":5806,"line":1681},{"id":5855,"kind":2303,"path":5856,"signature":5858,"summary":5859,"description":5860,"source":5861,"parent":5540},"unitrack.benchmarks.hota.build_mask_tracker",[331,143,146,5857],"build_mask_tracker","def build_mask_tracker(height: int, width: int, cost_threshold: float = 0.5, class_gate: bool = True) -> unitrack.Tracker","Build a single-stage mask-IoU tracker over a fixed ``(height, width)``.","``cost_threshold`` is the maximum acceptable ``1 - IoU`` association cost,\ni.e. matches require ``IoU >= 1 - cost_threshold``. ``NoLifecycle`` keeps\nevery track (no row drops), which ``ids_per_detection`` relies on.\n\nScore filtering is not done here: low-confidence detections are dropped in\nthe runner before a ``Detections`` is built, so the tracker only ever sees\nkept instances and carries no ``score`` state.",{"file":5862,"line":874},"unitrack\u002Fbenchmarks\u002Fhota\u002Ftracker.py",{"id":5864,"kind":2303,"path":5865,"signature":5867,"summary":5868,"description":5869,"source":5870,"parent":5540},"unitrack.benchmarks.hota.default_tracker_factory",[331,143,146,5866],"default_tracker_factory","def default_tracker_factory(cost_threshold: float = 0.5)","Return a :class:`TrackerFactory` building a fresh mask-IoU ``MultiStream``.","The returned callable takes the frame ``(height, width)`` (known only once\na sequence's first frame is seen) and wraps :func:`build_mask_tracker`.",{"file":5862,"line":1438},{"id":5872,"kind":2303,"path":5873,"signature":5875,"summary":5876,"description":5877,"source":5878,"parent":5540},"unitrack.benchmarks.hota.ids_per_detection",[331,143,146,5874],"ids_per_detection","def ids_per_detection(res: StepResult, n_dets: int) -> torch.Tensor","Recover per-detection track ids in detection order (``-1`` if gated out).","Accurate under ``NoLifecycle``: ``snapshot`` is ``cat([updated, spawned])``\nwith no rows dropped, so matched detections read their id from\n``snapshot.id[matched_pairs[:, 0]]`` and unmatched (residual) detections read\nthe appended rows in residual order.",{"file":5862,"line":5879},409,{"id":5881,"kind":344,"path":5882,"signature":5884,"summary":5885,"source":5886,"parent":5540},"unitrack.benchmarks.hota.BenchmarkResult",[331,143,146,5883],"BenchmarkResult","class BenchmarkResult:","One ``(model, tracker)`` combo's aggregated metric output plus timing.",{"file":5887,"line":1763},"unitrack\u002Fbenchmarks\u002Fhota\u002Ftypes.py",{"id":5889,"kind":355,"path":5890,"signature":5892,"source":5893,"parent":5881},"unitrack.benchmarks.hota.BenchmarkResult.model_key",[331,143,146,5883,5891],"model_key","model_key: str",{"file":5887,"line":1438},{"id":5895,"kind":355,"path":5896,"signature":5898,"source":5899,"parent":5881},"unitrack.benchmarks.hota.BenchmarkResult.tracker_key",[331,143,146,5883,5897],"tracker_key","tracker_key: str",{"file":5887,"line":385},{"id":5901,"kind":355,"path":5902,"signature":5904,"source":5905,"parent":5881},"unitrack.benchmarks.hota.BenchmarkResult.metrics",[331,143,146,5883,5903],"metrics","metrics: dict[str, float]",{"file":5887,"line":3269},{"id":5907,"kind":355,"path":5908,"signature":5910,"source":5911,"parent":5881},"unitrack.benchmarks.hota.BenchmarkResult.num_sequences",[331,143,146,5883,5909],"num_sequences","num_sequences: int",{"file":5887,"line":3784},{"id":5913,"kind":355,"path":5914,"signature":5916,"source":5917,"parent":5881},"unitrack.benchmarks.hota.BenchmarkResult.num_frames",[331,143,146,5883,5915],"num_frames","num_frames: int",{"file":5887,"line":5918},99,{"id":5920,"kind":355,"path":5921,"signature":5923,"source":5924,"parent":5881},"unitrack.benchmarks.hota.BenchmarkResult.seconds",[331,143,146,5883,5922],"seconds","seconds: float",{"file":5887,"line":5925},100,{"id":5927,"kind":388,"path":5928,"signature":5929,"source":5930,"parent":5881},"unitrack.benchmarks.hota.BenchmarkResult.__init__",[331,143,146,5883,405],"def __init__(self, model_key: str, tracker_key: str, metrics: dict[str, float], num_sequences: int, num_frames: int, seconds: float) -> None",{"file":5887,"line":341},{"id":5932,"kind":344,"path":5933,"signature":5935,"summary":5936,"source":5937,"parent":5540},"unitrack.benchmarks.hota.FramePrediction",[331,143,146,5934],"FramePrediction","class FramePrediction:","One frame of model output: per-instance thing masks + semantics.",{"file":5887,"line":884},{"id":5939,"kind":355,"path":5940,"signature":5942,"source":5943,"parent":5932},"unitrack.benchmarks.hota.FramePrediction.masks",[331,143,146,5934,5941],"masks","masks: torch.Tensor",{"file":5887,"line":723},{"id":5945,"kind":355,"path":5946,"signature":5948,"source":5949,"parent":5932},"unitrack.benchmarks.hota.FramePrediction.categories",[331,143,146,5934,5947],"categories","categories: torch.Tensor",{"file":5887,"line":730},{"id":5951,"kind":355,"path":5952,"signature":5954,"source":5955,"parent":5932},"unitrack.benchmarks.hota.FramePrediction.scores",[331,143,146,5934,5953],"scores","scores: torch.Tensor",{"file":5887,"line":736},{"id":5957,"kind":355,"path":5958,"signature":5960,"source":5961,"parent":5932},"unitrack.benchmarks.hota.FramePrediction.embeddings",[331,143,146,5934,5959],"embeddings","embeddings: torch.Tensor | None = None",{"file":5887,"line":742},{"id":5963,"kind":355,"path":5964,"signature":5966,"source":5967,"parent":5932},"unitrack.benchmarks.hota.FramePrediction.centroids",[331,143,146,5934,5965],"centroids","centroids: torch.Tensor | None = None",{"file":5887,"line":2356},{"id":5969,"kind":355,"path":5970,"signature":5972,"summary":5973,"source":5974,"parent":5932},"unitrack.benchmarks.hota.FramePrediction.num_instances",[331,143,146,5934,5971],"num_instances","num_instances: int","Number of predicted instances ``M``.",{"file":5887,"line":2121},{"id":5976,"kind":355,"path":5977,"signature":5979,"summary":5980,"source":5981,"parent":5932},"unitrack.benchmarks.hota.FramePrediction.height",[331,143,146,5934,5978],"height","height: int","Mask height ``H``.",{"file":5887,"line":2509},{"id":5983,"kind":355,"path":5984,"signature":5986,"summary":5987,"source":5988,"parent":5932},"unitrack.benchmarks.hota.FramePrediction.width",[331,143,146,5934,5985],"width","width: int","Mask width ``W``.",{"file":5887,"line":2517},{"id":5990,"kind":388,"path":5991,"signature":5992,"source":5993,"parent":5932},"unitrack.benchmarks.hota.FramePrediction.__init__",[331,143,146,5934,405],"def __init__(self, masks: torch.Tensor, categories: torch.Tensor, scores: torch.Tensor, embeddings: torch.Tensor | None = None, centroids: torch.Tensor | None = None) -> None",{"file":5887,"line":341},{"id":5995,"kind":344,"path":5996,"signature":5998,"summary":5999,"description":6000,"source":6001,"parent":5540},"unitrack.benchmarks.hota.SequenceSample",[331,143,146,5997],"SequenceSample","class SequenceSample:","One ground-truth sequence: an id, length, and a frame iterator.","Each item from ``frames`` is ``(image, gt_panoptic)`` where ``image`` is\n``(H, W, 3)`` uint8 RGB and ``gt_panoptic`` is ``(H, W)`` int64 encoded as\n``semantic * offset + instance``.",{"file":5887,"line":360},{"id":6003,"kind":355,"path":6004,"signature":6006,"source":6007,"parent":5995},"unitrack.benchmarks.hota.SequenceSample.sequence_id",[331,143,146,5997,6005],"sequence_id","sequence_id: str",{"file":5887,"line":3814},{"id":6009,"kind":355,"path":6010,"signature":6012,"source":6013,"parent":5995},"unitrack.benchmarks.hota.SequenceSample.length",[331,143,146,5997,6011],"length","length: int",{"file":5887,"line":1604},{"id":6015,"kind":355,"path":6016,"signature":6017,"source":6018,"parent":5995},"unitrack.benchmarks.hota.SequenceSample.frames",[331,143,146,5997,357],"frames: Iterator[tuple[np.ndarray, np.ndarray]]",{"file":5887,"line":695},{"id":6020,"kind":388,"path":6021,"signature":6022,"source":6023,"parent":5995},"unitrack.benchmarks.hota.SequenceSample.__init__",[331,143,146,5997,405],"def __init__(self, sequence_id: str, length: int, frames: Iterator[tuple[np.ndarray, np.ndarray]]) -> None",{"file":5887,"line":341},{"id":6025,"kind":335,"path":6026,"signature":6027,"summary":6028,"source":6029,"parent":5540},"unitrack.benchmarks.hota.metric",[331,143,146,155],"module unitrack.benchmarks.hota.metric","Wrap the evaluators panoptic_tracking() preset as a streaming runner.",{"file":5616,"line":341},{"id":6031,"kind":335,"path":6032,"signature":6033,"summary":6034,"source":6035,"parent":5540},"unitrack.benchmarks.hota.types",[331,143,146,179],"module unitrack.benchmarks.hota.types","Plain data carriers exchanged between the harness plug points.",{"file":5887,"line":341},{"id":6037,"kind":335,"path":6038,"signature":6039,"summary":6040,"description":6041,"source":6042,"parent":5540},"unitrack.benchmarks.hota.learned_modules",[331,143,146,152],"module unitrack.benchmarks.hota.learned_modules","Learned MOTR-style appearance-filter modules.","The ``learned`` tracker (``build_learned_tracker`` in ``tracker.py``) replaces the\nclosed-form ``Identity``\u002F``Replace`` embedding filter with a pair of small learned\nmodules wrapped by ``LearnedProcess`` \u002F ``LearnedObservation``:\n\n- :class:`Propagator` is the predict step — a residual MLP that nudges a track\n  embedding forward in time and renormalizes it onto the unit sphere.\n- :class:`Fuser` is the update step — a gated residual fuse of a track embedding\n  with its matched detection's embedding.\n\nBoth are autograd-native, so the same cosine\u002FSinkhorn association objective used\nat inference can train them (see ``train_learned.py``).",{"file":6043,"line":341},"unitrack\u002Fbenchmarks\u002Fhota\u002Flearned_modules.py",{"id":6045,"kind":344,"path":6046,"signature":6048,"summary":6049,"source":6050,"parent":6037},"unitrack.benchmarks.hota.learned_modules.Propagator",[331,143,146,152,6047],"Propagator","class Propagator(nn.Module):","Predict step: residual MLP over a track embedding, renormalized.",{"file":6043,"line":4400},{"id":6052,"kind":388,"path":6053,"signature":6054,"summary":6055,"source":6056,"parent":6045},"unitrack.benchmarks.hota.learned_modules.Propagator.__init__",[331,143,146,152,6047,405],"def __init__(self, dim: int, hidden: int = 64) -> None","Build a ``dim -> hidden -> dim`` residual MLP.",{"file":6043,"line":891},{"id":6058,"kind":355,"path":6059,"signature":6061,"source":6062,"parent":6045},"unitrack.benchmarks.hota.learned_modules.Propagator.net",[331,143,146,152,6047,6060],"net","net = nn.Sequential(nn.Linear(dim, hidden), nn.Tanh(), nn.Linear(hidden, dim))",{"file":6043,"line":913},{"id":6064,"kind":388,"path":6065,"signature":6066,"summary":6067,"source":6068,"parent":6045},"unitrack.benchmarks.hota.learned_modules.Propagator.forward",[331,143,146,152,6047,5114],"def forward(self, x: torch.Tensor, dt: float = 1.0) -> torch.Tensor","Propagate ``x`` ``(N, D)`` one step and renormalize to unit norm.",{"file":6043,"line":736},{"id":6070,"kind":344,"path":6071,"signature":6073,"summary":6074,"source":6075,"parent":6037},"unitrack.benchmarks.hota.learned_modules.Fuser",[331,143,146,152,6072],"Fuser","class Fuser(nn.Module):","Update step: gated residual fuse of track + matched measurement.",{"file":6043,"line":630},{"id":6077,"kind":388,"path":6078,"signature":6054,"summary":6079,"source":6080,"parent":6070},"unitrack.benchmarks.hota.learned_modules.Fuser.__init__",[331,143,146,152,6072,405],"Build a gate MLP over ``[track, measurement]`` (``2*dim -> dim``).",{"file":6043,"line":663},{"id":6082,"kind":355,"path":6083,"signature":6084,"source":6085,"parent":6070},"unitrack.benchmarks.hota.learned_modules.Fuser.gate",[331,143,146,152,6072,212],"gate = nn.Sequential(nn.Linear(2 * dim, hidden), nn.Tanh(), nn.Linear(hidden, dim), nn.Sigmoid())",{"file":6043,"line":1048},{"id":6087,"kind":388,"path":6088,"signature":6089,"summary":6090,"source":6091,"parent":6070},"unitrack.benchmarks.hota.learned_modules.Fuser.forward",[331,143,146,152,6072,5114],"def forward(self, track: torch.Tensor, meas: torch.Tensor) -> torch.Tensor","Fuse matched ``track``\u002F``meas`` ``(K, D)`` pairs, renormalized.",{"file":6043,"line":1688},{"id":6093,"kind":335,"path":6094,"signature":6095,"summary":6096,"source":6097,"parent":5540},"unitrack.benchmarks.hota.runner",[331,143,146,170],"module unitrack.benchmarks.hota.runner","Sweep models x sequences, streaming predictions into the HOTA metric.",{"file":5806,"line":341},{"id":6099,"kind":355,"path":6100,"signature":6102,"source":6103,"parent":6093},"unitrack.benchmarks.hota.runner.logger",[331,143,146,170,6101],"logger","logger = logging.getLogger(__name__)",{"file":5806,"line":1156},{"id":6105,"kind":335,"path":6106,"signature":6107,"summary":6108,"source":6109,"parent":5540},"unitrack.benchmarks.hota.report",[331,143,146,167],"module unitrack.benchmarks.hota.report","Markdown + JSON writers for benchmark results.",{"file":6110,"line":341},"unitrack\u002Fbenchmarks\u002Fhota\u002Freport.py",{"id":6112,"kind":2303,"path":6113,"signature":6115,"summary":6116,"source":6117,"parent":6105},"unitrack.benchmarks.hota.report.write_markdown",[331,143,146,167,6114],"write_markdown","def write_markdown(results: list[BenchmarkResult], path: str | Path, metadata: dict) -> None","Write a markdown table of ``results`` with a metadata preamble.",{"file":6110,"line":1128},{"id":6119,"kind":2303,"path":6120,"signature":6122,"summary":6123,"source":6124,"parent":6105},"unitrack.benchmarks.hota.report.write_json",[331,143,146,167,6121],"write_json","def write_json(results: list[BenchmarkResult], path: str | Path, metadata: dict) -> None","Write ``results`` as a JSON document with a ``metadata`` block.",{"file":6110,"line":736},{"id":6126,"kind":335,"path":6127,"signature":6128,"summary":6129,"source":6130,"parent":5540},"unitrack.benchmarks.hota.datasets",[331,143,146,149],"module unitrack.benchmarks.hota.datasets","Dataset adapters. The first is cityscapes-dvps from a local LMDB.",{"file":5553,"line":341},{"id":6132,"kind":335,"path":6133,"signature":6134,"summary":6135,"description":6136,"source":6137,"parent":5540},"unitrack.benchmarks.hota.train_learned",[331,143,146,176],"module unitrack.benchmarks.hota.train_learned","Train the learned MOTR-style appearance filter and write its checkpoint.","This is a one-time script that produces the small committed checkpoint\n``benchmarks\u002Fhota\u002Fweights\u002Flearned_filter.safetensors`` consumed by\n:func:`~unitrack.benchmarks.hota.tracker.build_learned_tracker`.",{"file":6138,"line":341},"unitrack\u002Fbenchmarks\u002Fhota\u002Ftrain_learned.py",{"id":6140,"kind":363,"path":6141,"signature":6143,"source":6144,"parent":6132},"unitrack.benchmarks.hota.train_learned.EMBED_DIM",[331,143,146,176,6142],"EMBED_DIM","EMBED_DIM = 256",{"file":6138,"line":630},{"id":6146,"kind":363,"path":6147,"signature":6149,"source":6150,"parent":6132},"unitrack.benchmarks.hota.train_learned.DEFAULT_CKPT",[331,143,146,176,6148],"DEFAULT_CKPT","DEFAULT_CKPT = Path(__file__).parent \u002F 'weights' \u002F 'learned_filter.safetensors'",{"file":6138,"line":663},{"id":6152,"kind":363,"path":6153,"signature":6155,"source":6156,"parent":6132},"unitrack.benchmarks.hota.train_learned.TEMPERATURE",[331,143,146,176,6154],"TEMPERATURE","TEMPERATURE = 0.07",{"file":6138,"line":2705},{"id":6158,"kind":355,"path":6159,"signature":6161,"source":6162,"parent":6132},"unitrack.benchmarks.hota.train_learned.Frame",[331,143,146,176,6160],"Frame","Frame = tuple[torch.Tensor, torch.Tensor]",{"file":6138,"line":6163},53,{"id":6165,"kind":355,"path":6166,"signature":6168,"source":6169,"parent":6132},"unitrack.benchmarks.hota.train_learned.Clip",[331,143,146,176,6167],"Clip","Clip = list[Frame]",{"file":6138,"line":1681},{"id":6171,"kind":2303,"path":6172,"signature":6174,"summary":6175,"params":6176,"returns":6190,"source":6192,"parent":6132},"unitrack.benchmarks.hota.train_learned.train_step",[331,143,146,176,6173],"train_step","def train_step(propagator: Propagator, fuser: Fuser, clip: Clip, optimizer: torch.optim.Optimizer, temperature: float = TEMPERATURE) -> float","Run one contrastive multi-frame optimization step on a single clip.",[6177,6180,6182,6184,6188],{"name":6178,"type":6047,"doc":6179},"propagator","The learned modules being trained.",{"name":6181,"type":6047,"doc":6179},"fuser",{"name":200,"type":6167,"doc":6183},"A list of frames ``[(embeddings (n_f, D), gt_ids (n_f,)), ...]`` for one\nclip in frame order. Detection embeddings are L2-normalized internally so\ntraining matches inference (where the Fuser emits unit norm and the\ncosine cost normalizes).",{"name":6185,"type":6186,"doc":6187},"optimizer","torch.optim.Optimizer","An optimizer over both modules' parameters.",{"name":4476,"type":474,"default":6154,"doc":6189},"InfoNCE temperature; smaller demands a sharper margin.",{"type":474,"doc":6191},"The scalar loss before the gradient step (``0.0`` if the clip has no\nmulti-frame GT track to roll out).",{"file":6138,"line":377},{"id":6194,"kind":2303,"path":6195,"signature":6197,"summary":6198,"source":6199,"parent":6132},"unitrack.benchmarks.hota.train_learned.save_checkpoint",[331,143,146,176,6196],"save_checkpoint","def save_checkpoint(propagator: Propagator, fuser: Fuser, path: str | Path = DEFAULT_CKPT) -> Path","Write the flattened ``{propagator,fuser}`` state to a safetensors file.",{"file":6138,"line":5670},{"id":6201,"kind":2303,"path":6202,"signature":6204,"summary":6205,"source":6206,"parent":6132},"unitrack.benchmarks.hota.train_learned.main",[331,143,146,176,6203],"main","def main(argv: list[str] | None = None) -> None","Extract train clips, train the learned filter, and save the checkpoint.",{"file":6138,"line":6207},234,{"id":6209,"kind":335,"path":6210,"signature":6211,"summary":6212,"source":6213,"parent":5540},"unitrack.benchmarks.hota.protocols",[331,143,146,161],"module unitrack.benchmarks.hota.protocols","Structural protocols for the three harness plug points.",{"file":5714,"line":341},{"id":6215,"kind":335,"path":6216,"signature":6217,"summary":6218,"source":6219,"parent":5540},"unitrack.benchmarks.hota.render",[331,143,146,164],"module unitrack.benchmarks.hota.render","Render tracker output into an evaluators-compatible panoptic map.",{"file":5777,"line":341},{"id":6221,"kind":335,"path":6222,"signature":6223,"summary":6224,"source":6225,"parent":5540},"unitrack.benchmarks.hota.models",[331,143,146,158],"module unitrack.benchmarks.hota.models","HuggingFace panoptic-segmentation model adapters.",{"file":5656,"line":341},{"id":6227,"kind":363,"path":6228,"signature":6143,"source":6229,"parent":6221},"unitrack.benchmarks.hota.models.EMBED_DIM",[331,143,146,158,6142],{"file":5656,"line":1128},{"id":6231,"kind":2303,"path":6232,"signature":6234,"summary":6235,"source":6236,"parent":6221},"unitrack.benchmarks.hota.models.segments_to_prediction",[331,143,146,158,6233],"segments_to_prediction","def segments_to_prediction(segmentation: torch.Tensor, segments_info: list[dict], thing_ids: Iterable[int]) -> FramePrediction","Convert HF panoptic output into a thing-only ``FramePrediction``.",{"file":5656,"line":898},{"id":6238,"kind":2303,"path":6239,"signature":6241,"summary":6242,"description":6243,"source":6244,"parent":6221},"unitrack.benchmarks.hota.models.extract_segments_with_queries",[331,143,146,158,6240],"extract_segments_with_queries","def extract_segments_with_queries(outputs, target_size, threshold = 0.5, mask_threshold = 0.5, overlap = 0.8)","Reimplement Mask2Former panoptic post-processing, recording source queries.","Additionally records each segment's source decoder-query index so its\nappearance embedding can be recovered.\n\nReturns ``(segmentation (H, W) int32, segments [{id,label_id,score,q}],\nemb_keep (K_kept, D))``. Bit-identical to\n``post_process_panoptic_segmentation`` for the segmentation map and segment\nids\u002Flabels; ``emb_keep`` is the kept-query decoder hidden state, indexed by\neach segment's recorded ``q``.",{"file":5656,"line":1196},{"id":6246,"kind":2303,"path":6247,"signature":6249,"summary":6250,"description":6251,"source":6252,"parent":6221},"unitrack.benchmarks.hota.models.segments_to_prediction_with_features",[331,143,146,158,6248],"segments_to_prediction_with_features","def segments_to_prediction_with_features(segmentation: torch.Tensor, segments: list[dict], emb_keep: torch.Tensor, thing_ids: Iterable[int]) -> FramePrediction","Build a thing-only ``FramePrediction`` with embeddings and centroids.","Uses the same thing-filter logic as :func:`segments_to_prediction`.",{"file":5656,"line":1061},{"id":6254,"kind":335,"path":6255,"signature":6256,"summary":6257,"description":6258,"source":6259,"parent":5540},"unitrack.benchmarks.hota.tracker",[331,143,146,173],"module unitrack.benchmarks.hota.tracker","Tracker factories (mask-IoU, cosine, cascade, Kalman) + a registry.","Each factory builds a :class:`~unitrack.Tracker` over a fixed ``(height, width)``\nfrom existing unitrack primitives — no core-library changes. ``TRACKER_REGISTRY``\nmaps a key to a ``(height, width) -> MultiStream`` factory so the benchmark can\nsweep the tracker as a first-class variable, parallel to the model registry.",{"file":5862,"line":341},{"id":6261,"kind":363,"path":6262,"signature":6143,"source":6263,"parent":6254},"unitrack.benchmarks.hota.tracker.EMBED_DIM",[331,143,146,173,6142],{"file":5862,"line":609},{"id":6265,"kind":363,"path":6266,"signature":6268,"source":6269,"parent":6254},"unitrack.benchmarks.hota.tracker.DEFAULT_LEARNED_CKPT",[331,143,146,173,6267],"DEFAULT_LEARNED_CKPT","DEFAULT_LEARNED_CKPT = Path(__file__).parent \u002F 'weights' \u002F 'learned_filter.safetensors'",{"file":5862,"line":630},{"id":6271,"kind":363,"path":6272,"signature":6274,"source":6275,"parent":6254},"unitrack.benchmarks.hota.tracker.CHI2_GATE",[331,143,146,173,6273],"CHI2_GATE","CHI2_GATE = 5.9915",{"file":5862,"line":855},{"id":6277,"kind":2303,"path":6278,"signature":6280,"summary":6281,"description":6282,"source":6283,"parent":6254},"unitrack.benchmarks.hota.tracker.build_cosine_tracker",[331,143,146,173,6279],"build_cosine_tracker","def build_cosine_tracker(height: int, width: int, cost_threshold: float = 0.5, embed_dim: int = EMBED_DIM) -> unitrack.Tracker","Build an appearance tracker matching instances by embedding cosine distance.","Matches require ``1 - cosine_similarity \u003C= cost_threshold`` within the same\nclass. ``height`` \u002F ``width`` are accepted for a uniform factory signature\nbut unused (appearance matching needs no mask state).",{"file":5862,"line":972},{"id":6285,"kind":2303,"path":6286,"signature":6288,"summary":6289,"description":6290,"source":6291,"parent":6254},"unitrack.benchmarks.hota.tracker.build_cascade_tracker",[331,143,146,173,6287],"build_cascade_tracker","def build_cascade_tracker(height: int, width: int, hi: float = 0.9, cos_threshold: float = 0.5, iou_threshold: float = 0.5, embed_dim: int = EMBED_DIM) -> unitrack.Tracker","Build a two-stage cascade: appearance for high-score, mask-IoU for the rest.","Within a class, detections split by score. High-confidence detections\n(``score >= hi``) go only to the embedding-cosine stage; a high-score\ndetection left unmatched there spawns a new track (it is NOT re-offered to\nmask-IoU). Low-confidence detections (``score \u003C hi``) go only to the mask-IoU\nstage. ``hi`` is the cascade's internal split, independent of the runner's\n``min_score`` floor.\n\nThe default ``hi=0.9`` is tuned for panoptic-segmentation scores, which\ncluster high (Mask2Former Cityscapes thing scores have a ~0.8 floor and a\n~0.997 median): a lower split would route every detection to the appearance\nstage and the cascade would collapse to the pure-cosine tracker.",{"file":5862,"line":3975},{"id":6293,"kind":2303,"path":6294,"signature":6296,"summary":6297,"description":6298,"source":6299,"parent":6254},"unitrack.benchmarks.hota.tracker.build_kalman_tracker",[331,143,146,173,6295],"build_kalman_tracker","def build_kalman_tracker(height: int, width: int, max_chi2: float = CHI2_GATE, jonker_threshold: float | None = None, q: float = 1.0, r: float = 1.0) -> unitrack.Tracker","Build a constant-velocity centroid Kalman tracker with a motion gate.","The tracklet centroid state is 4-D ``[x, y, vx, vy]`` (predicted forward\neach frame); detections carry a 2-D ``[x, y]`` centroid. The association\ncost is the Mahalanobis chi-squared distance to the *predicted* centroid\n(projected into the 2-D measurement subspace), gated by ``MotionGate`` at\n``max_chi2`` and ``ClassGate``. A plain ``CDist(\"centroid\")`` cannot be used\nhere: the 4-D tracklet mean and 2-D detection mean have mismatched feature\ndimensions; ``Mahalanobis`` is the primitive that projects between them.\n\n``max_chi2`` bounds the ``MotionGate`` (pairs with a larger chi-squared\ndistance are masked out before assignment). ``jonker_threshold`` bounds the\nJonker assignment cost and defaults to ``max_chi2`` (so the gate and the\nassignment share one rejection radius, the standard SORT setting); passing a\nlooser ``jonker_threshold`` isolates the ``MotionGate`` as the sole cause of a\nrejection, which the gate-isolation test relies on.\n\n``height`` \u002F ``width`` are accepted for a uniform factory signature but the\nKalman state is resolution-independent (pixel centroids). ``q`` \u002F ``r`` are\nsized for pixel-space centroids (process\u002Fmeasurement noise of order one\npixel²), not the normalized-coordinate defaults of ``KalmanCentroid2D``.",{"file":5862,"line":2777},{"id":6301,"kind":2303,"path":6302,"signature":6304,"summary":6305,"description":6306,"source":6307,"parent":6254},"unitrack.benchmarks.hota.tracker.build_learned_tracker",[331,143,146,173,6303],"build_learned_tracker","def build_learned_tracker(height: int, width: int, cost_threshold: float = 0.5, embed_dim: int = EMBED_DIM, checkpoint: str | Path = DEFAULT_LEARNED_CKPT) -> unitrack.Tracker","Build a MOTR-style learned appearance tracker from a trained checkpoint.","Wires the same cosine-distance association as :func:`build_cosine_tracker`,\nbut the embedding state is filtered by learned modules: a\n:class:`~.learned_modules.Propagator` (predict, via ``LearnedProcess``) and a\n:class:`~.learned_modules.Fuser` (update on match, via\n``LearnedObservation``), loaded from ``checkpoint``. Raises\n:class:`FileNotFoundError` if the checkpoint is missing.\n\n``height`` \u002F ``width`` are accepted for a uniform factory signature but unused\n(appearance matching needs no mask state).",{"file":5862,"line":504},{"id":6309,"kind":355,"path":6310,"signature":6311,"source":6312,"parent":6254},"unitrack.benchmarks.hota.tracker.TrackerFactory",[331,143,146,173,5759],"TrackerFactory = Callable[[int, int], MultiStream]",{"file":5862,"line":6313},388,{"id":6315,"kind":363,"path":6316,"signature":6318,"source":6319,"parent":6254},"unitrack.benchmarks.hota.tracker.TRACKER_REGISTRY",[331,143,146,173,6317],"TRACKER_REGISTRY","TRACKER_REGISTRY: dict[str, TrackerFactory] = {'maskiou': _wrap(build_mask_tracker), 'cosine': _wrap(build_cosine_tracker), 'cascade': _wrap(build_cascade_tracker), 'kalman': _wrap(build_kalman_tracker), 'learned': _wrap(build_learned_tracker)}",{"file":5862,"line":6320},400,{"id":6322,"kind":335,"path":6323,"signature":6324,"summary":6325,"description":6326,"source":6327,"parent":331},"unitrack.data",[331,197],"module unitrack.data","Typed records carried by the stage tree.","The data layer defines :class:`~unitrack.data.Tracklets`,\n:class:`~unitrack.data.Detections`, :class:`FrameContext`,\n:class:`~unitrack.data.CostExpression`, :class:`Gate`, and\n:class:`~unitrack.data.MatchOutcome`, together with clip-aware wrappers for sequence\ninference.",{"file":6328,"line":341},"unitrack\u002Fdata\u002F__init__.py",{"id":6330,"kind":344,"path":6331,"signature":6332,"summary":6333,"description":6334,"source":6335,"parent":6322},"unitrack.data.StackedClipMatch",[331,197,535],"class StackedClipMatch:","Stacked view of a :class:`ClipMatchOutcome` along its matched-pair axis.","Per-frame :class:`~unitrack.data.MatchOutcome` residual-index and soft-plan tensors\nhave variable per-frame shapes (they depend on per-frame ``N`` and\n``M``), so the stacked form carries only the matched-pair triple\nplus a per-row ``frame_idx`` annotation. Use\n:meth:`ClipMatchOutcome.frame_ranges` to slice back into per-frame\nviews.",{"file":351,"line":1025},{"id":6337,"kind":355,"path":6338,"signature":834,"source":6339,"parent":6330},"unitrack.data.StackedClipMatch.matched_pairs",[331,197,535,833],{"file":351,"line":855},{"id":6341,"kind":355,"path":6342,"signature":853,"source":6343,"parent":6330},"unitrack.data.StackedClipMatch.per_match_cost",[331,197,535,852],{"file":351,"line":862},{"id":6345,"kind":355,"path":6346,"signature":721,"source":6347,"parent":6330},"unitrack.data.StackedClipMatch.frame_idx",[331,197,535,720],{"file":351,"line":1048},{"id":6349,"kind":355,"path":6350,"signature":6352,"summary":6353,"source":6354,"parent":6330},"unitrack.data.StackedClipMatch.K_total",[331,197,535,6351],"K_total","K_total: int","Total number of matched pairs across all frames.",{"file":351,"line":2105},{"id":6356,"kind":388,"path":6357,"signature":6358,"source":6359,"parent":6330},"unitrack.data.StackedClipMatch.__init__",[331,197,535,405],"def __init__(self, matched_pairs: torch.Tensor, per_match_cost: torch.Tensor, frame_idx: torch.Tensor) -> None",{"file":351,"line":341},{"id":6361,"kind":335,"path":6362,"signature":6363,"summary":6364,"source":6365,"parent":6322},"unitrack.data.tensor_spec",[331,197,218],"module unitrack.data.tensor_spec","Typed tensor shape and dtype declaration used by State schemas.",{"file":883,"line":341},{"id":6367,"kind":335,"path":6368,"signature":6369,"summary":6370,"source":6371,"parent":6322},"unitrack.data.frame",[331,197,209],"module unitrack.data.frame","Per-frame timing and stream metadata.",{"file":716,"line":341},{"id":6373,"kind":335,"path":6374,"signature":6375,"summary":6376,"source":6377,"parent":6322},"unitrack.data.gate",[331,197,212],"module unitrack.data.gate","Algebraic ``Gate`` variant: ``PerPair``, ``PerCs``, ``PerDs``, ``CostBias``.",{"file":773,"line":341},{"id":6379,"kind":335,"path":6380,"signature":6381,"summary":6382,"source":6383,"parent":6322},"unitrack.data.cost",[331,197,203],"module unitrack.data.cost","Cost matrix with un-applied gate attachments.",{"file":601,"line":341},{"id":6385,"kind":335,"path":6386,"signature":6387,"summary":6388,"source":6389,"parent":6322},"unitrack.data.tracklets",[331,197,221],"module unitrack.data.tracklets","Typed snapshot of all tracked identities at a frame.",{"file":921,"line":341},{"id":6391,"kind":335,"path":6392,"signature":6393,"summary":6394,"source":6395,"parent":6322},"unitrack.data.detections",[331,197,206],"module unitrack.data.detections","Typed record of one frame's new detections.",{"file":681,"line":341},{"id":6397,"kind":335,"path":6398,"signature":6399,"summary":6400,"source":6401,"parent":6322},"unitrack.data.clip",[331,197,200],"module unitrack.data.clip","Clip-aware records: sequences of per-frame detections and tracklets.",{"file":351,"line":341},{"id":6403,"kind":335,"path":6404,"signature":6405,"summary":6406,"source":6407,"parent":6322},"unitrack.data.match",[331,197,215],"module unitrack.data.match","Result of running a stage tree to assignment.",{"file":829,"line":341},{"id":6409,"kind":335,"path":6410,"signature":6411,"summary":6412,"source":6413,"parent":331},"unitrack.lifecycle",[331,239],"module unitrack.lifecycle","Lifecycle management layer.",{"file":6414,"line":341},"unitrack\u002Flifecycle\u002F__init__.py",{"id":6416,"kind":344,"path":6417,"signature":6419,"summary":6420,"source":6421,"parent":6409},"unitrack.lifecycle.MaxAgeFilter",[331,239,6418],"MaxAgeFilter","class MaxAgeFilter:","Keep tracklets whose ``time_since_update`` is ``\u003C= max_age``.",{"file":6422,"line":5152},"unitrack\u002Flifecycle\u002Ffilters.py",{"id":6424,"kind":355,"path":6425,"signature":1093,"source":6426,"parent":6416},"unitrack.lifecycle.MaxAgeFilter.max_age",[331,239,6418,1092],{"file":6422,"line":1156},{"id":6428,"kind":388,"path":6429,"signature":6430,"summary":6431,"source":6432,"parent":6416},"unitrack.lifecycle.MaxAgeFilter.__call__",[331,239,6418,1009],"def __call__(self, cs: Tracklets) -> torch.Tensor","Return a bool mask, True where ``time_since_update \u003C= max_age``.",{"file":6422,"line":1746},{"id":6434,"kind":388,"path":6435,"signature":6436,"source":6437,"parent":6416},"unitrack.lifecycle.MaxAgeFilter.__init__",[331,239,6418,405],"def __init__(self, max_age: int) -> None",{"file":6422,"line":341},{"id":6439,"kind":344,"path":6440,"signature":6442,"summary":6443,"source":6444,"parent":6409},"unitrack.lifecycle.StatusFilter",[331,239,6441],"StatusFilter","class StatusFilter:","Keep tracklets whose ``status`` is in ``allowed``.",{"file":6422,"line":1031},{"id":6446,"kind":355,"path":6447,"signature":6449,"source":6450,"parent":6439},"unitrack.lifecycle.StatusFilter.allowed",[331,239,6441,6448],"allowed","allowed: tuple[TrackletStatus, ...]",{"file":6422,"line":1571},{"id":6452,"kind":388,"path":6453,"signature":6454,"summary":6455,"source":6456,"parent":6439},"unitrack.lifecycle.StatusFilter.__init__",[331,239,6441,405],"def __init__(self, *allowed: TrackletStatus = ()) -> None","Accept one or more allowed TrackletStatus values.",{"file":6422,"line":1005},{"id":6458,"kind":388,"path":6459,"signature":6430,"summary":6460,"source":6461,"parent":6439},"unitrack.lifecycle.StatusFilter.__call__",[331,239,6441,1009],"Return a bool mask, True where ``status`` is in ``allowed``.",{"file":6422,"line":630},{"id":6463,"kind":344,"path":6464,"signature":6466,"summary":6467,"description":6468,"source":6469,"parent":6409},"unitrack.lifecycle.SoftLifecycle",[331,239,6465],"SoftLifecycle","class SoftLifecycle:","Shape-stable :class:`~unitrack.lifecycle.StandardLifecycle` for differentiable mode.","Applies the same status \u002F counter transitions as the hard policy but\nkeeps the row count of the snapshot constant: Removed rows stay in\nplace rather than being filtered out, so gradients flow through\nevery tracklet across frames without index reshuffling. Consumers\nthat want only live rows can still filter via the returned status\nfield; the soft path itself is shape-stable.\n\nStatus transitions remain discrete — the lifecycle state machine is\nintrinsically non-differentiable. SoftLifecycle's job is purely to\navoid the autograd-unfriendly row-removal step. End-to-end soft\nlearning rides on the upstream :class:`~unitrack.assignment.SoftAssignment` plan and\nsoft observations (e.g. :class:`~unitrack.states.SoftReplace`), not on this policy.",{"file":6470,"line":1128},"unitrack\u002Flifecycle\u002Fsoft.py",{"id":6472,"kind":355,"path":6473,"signature":1086,"source":6474,"parent":6463},"unitrack.lifecycle.SoftLifecycle.min_hits",[331,239,6465,1085],{"file":6470,"line":1005},{"id":6476,"kind":355,"path":6477,"signature":1093,"source":6478,"parent":6463},"unitrack.lifecycle.SoftLifecycle.max_age",[331,239,6465,1092],{"file":6470,"line":723},{"id":6480,"kind":355,"path":6481,"signature":1100,"source":6482,"parent":6463},"unitrack.lifecycle.SoftLifecycle.grace_period",[331,239,6465,1099],{"file":6470,"line":730},{"id":6484,"kind":355,"path":6485,"signature":1107,"source":6486,"parent":6463},"unitrack.lifecycle.SoftLifecycle.allow_reid",[331,239,6465,1106],{"file":6470,"line":736},{"id":6488,"kind":388,"path":6489,"signature":1065,"summary":6490,"source":6491,"parent":6463},"unitrack.lifecycle.SoftLifecycle.__call__",[331,239,6465,1009],"Apply lifecycle transitions without dropping rows.",{"file":6470,"line":2356},{"id":6493,"kind":388,"path":6494,"signature":1118,"source":6495,"parent":6463},"unitrack.lifecycle.SoftLifecycle.__init__",[331,239,6465,405],{"file":6470,"line":341},{"id":6497,"kind":335,"path":6498,"signature":6499,"summary":6500,"source":6501,"parent":6409},"unitrack.lifecycle.soft",[331,239,233],"module unitrack.lifecycle.soft","Differentiable companion to :class:`~unitrack.lifecycle.StandardLifecycle`.",{"file":6470,"line":341},{"id":6503,"kind":335,"path":6504,"signature":6505,"summary":6506,"description":6507,"source":6508,"parent":6409},"unitrack.lifecycle.status",[331,239,250],"module unitrack.lifecycle.status","Tracklet lifecycle status enum.","Integer values are persisted into snapshot fields; do not renumber casually.",{"file":1127,"line":341},{"id":6510,"kind":335,"path":6511,"signature":6512,"summary":6513,"source":6514,"parent":6409},"unitrack.lifecycle.filters",[331,239,242],"module unitrack.lifecycle.filters","Predicate functions used by the pipeline.Filter combinator.",{"file":6422,"line":341},{"id":6516,"kind":335,"path":6517,"signature":6518,"summary":6519,"source":6520,"parent":6409},"unitrack.lifecycle.policies",[331,239,245],"module unitrack.lifecycle.policies","Lifecycle policies.",{"file":1060,"line":341},{"id":6522,"kind":335,"path":6523,"signature":6524,"summary":6525,"source":6526,"parent":6409},"unitrack.lifecycle.visibility",[331,239,253],"module unitrack.lifecycle.visibility","Visibility policies.",{"file":1004,"line":341},null,{},1785139897595]