spine 0.10.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (359) hide show
  1. spine-0.10.0/CONTRIBUTING.md +32 -0
  2. spine-0.10.0/LICENSE +21 -0
  3. spine-0.10.0/MANIFEST.in +12 -0
  4. spine-0.10.0/PKG-INFO +372 -0
  5. spine-0.10.0/README.md +314 -0
  6. spine-0.10.0/config/test_io.cfg +57 -0
  7. spine-0.10.0/config/test_loader.cfg +52 -0
  8. spine-0.10.0/config/train_graph_spice.cfg +103 -0
  9. spine-0.10.0/config/train_grappa_inter.cfg +151 -0
  10. spine-0.10.0/config/train_grappa_shower.cfg +122 -0
  11. spine-0.10.0/config/train_grappa_track.cfg +117 -0
  12. spine-0.10.0/config/train_image_class.cfg +68 -0
  13. spine-0.10.0/config/train_uresnet.cfg +65 -0
  14. spine-0.10.0/config/train_uresnet_ppn.cfg +78 -0
  15. spine-0.10.0/pyproject.toml +163 -0
  16. spine-0.10.0/setup.cfg +4 -0
  17. spine-0.10.0/src/spine/__init__.py +5 -0
  18. spine-0.10.0/src/spine/ana/__init__.py +81 -0
  19. spine-0.10.0/src/spine/ana/base.py +395 -0
  20. spine-0.10.0/src/spine/ana/calib/__init__.py +10 -0
  21. spine-0.10.0/src/spine/ana/calib/mcs.py +175 -0
  22. spine-0.10.0/src/spine/ana/diag/__init__.py +11 -0
  23. spine-0.10.0/src/spine/ana/diag/shower.py +53 -0
  24. spine-0.10.0/src/spine/ana/diag/track.py +224 -0
  25. spine-0.10.0/src/spine/ana/factories.py +47 -0
  26. spine-0.10.0/src/spine/ana/manager.py +119 -0
  27. spine-0.10.0/src/spine/ana/metric/__init__.py +13 -0
  28. spine-0.10.0/src/spine/ana/metric/cluster.py +217 -0
  29. spine-0.10.0/src/spine/ana/metric/optical.py +167 -0
  30. spine-0.10.0/src/spine/ana/metric/point.py +139 -0
  31. spine-0.10.0/src/spine/ana/metric/segment.py +185 -0
  32. spine-0.10.0/src/spine/ana/script/__init__.py +3 -0
  33. spine-0.10.0/src/spine/ana/script/save.py +184 -0
  34. spine-0.10.0/src/spine/ana/template.py +85 -0
  35. spine-0.10.0/src/spine/banner.py +7 -0
  36. spine-0.10.0/src/spine/bin/__init__.py +48 -0
  37. spine-0.10.0/src/spine/bin/cli.py +357 -0
  38. spine-0.10.0/src/spine/config/__init__.py +44 -0
  39. spine-0.10.0/src/spine/config/api.py +30 -0
  40. spine-0.10.0/src/spine/config/download.py +242 -0
  41. spine-0.10.0/src/spine/config/errors.py +47 -0
  42. spine-0.10.0/src/spine/config/load.py +416 -0
  43. spine-0.10.0/src/spine/config/loader.py +254 -0
  44. spine-0.10.0/src/spine/config/meta.py +312 -0
  45. spine-0.10.0/src/spine/config/operations.py +401 -0
  46. spine-0.10.0/src/spine/construct/__init__.py +115 -0
  47. spine-0.10.0/src/spine/construct/base.py +228 -0
  48. spine-0.10.0/src/spine/construct/fragment.py +424 -0
  49. spine-0.10.0/src/spine/construct/interaction.py +277 -0
  50. spine-0.10.0/src/spine/construct/manager.py +291 -0
  51. spine-0.10.0/src/spine/construct/particle.py +503 -0
  52. spine-0.10.0/src/spine/data/__init__.py +70 -0
  53. spine-0.10.0/src/spine/data/base.py +385 -0
  54. spine-0.10.0/src/spine/data/batch/__init__.py +5 -0
  55. spine-0.10.0/src/spine/data/batch/base.py +252 -0
  56. spine-0.10.0/src/spine/data/batch/edge_index.py +253 -0
  57. spine-0.10.0/src/spine/data/batch/index.py +384 -0
  58. spine-0.10.0/src/spine/data/batch/tensor.py +287 -0
  59. spine-0.10.0/src/spine/data/crt.py +141 -0
  60. spine-0.10.0/src/spine/data/list.py +29 -0
  61. spine-0.10.0/src/spine/data/meta.py +163 -0
  62. spine-0.10.0/src/spine/data/neutrino.py +211 -0
  63. spine-0.10.0/src/spine/data/optical.py +186 -0
  64. spine-0.10.0/src/spine/data/out/__init__.py +5 -0
  65. spine-0.10.0/src/spine/data/out/base.py +363 -0
  66. spine-0.10.0/src/spine/data/out/fragment.py +240 -0
  67. spine-0.10.0/src/spine/data/out/interaction.py +505 -0
  68. spine-0.10.0/src/spine/data/out/particle.py +705 -0
  69. spine-0.10.0/src/spine/data/particle.py +322 -0
  70. spine-0.10.0/src/spine/data/run_info.py +50 -0
  71. spine-0.10.0/src/spine/data/trigger.py +59 -0
  72. spine-0.10.0/src/spine/driver.py +945 -0
  73. spine-0.10.0/src/spine/geo/__init__.py +4 -0
  74. spine-0.10.0/src/spine/geo/base.py +822 -0
  75. spine-0.10.0/src/spine/geo/config/2x2/2x2_mr4-5_geometry.yaml +44 -0
  76. spine-0.10.0/src/spine/geo/config/2x2/2x2_mr5-0_geometry.yaml +44 -0
  77. spine-0.10.0/src/spine/geo/config/2x2/2x2_mr6-0_geometry.yaml +44 -0
  78. spine-0.10.0/src/spine/geo/config/2x2/2x2_mr6-1_geometry.yaml +44 -0
  79. spine-0.10.0/src/spine/geo/config/2x2/2x2_mr6-2_geometry.yaml +45 -0
  80. spine-0.10.0/src/spine/geo/config/2x2/2x2_mr6-3_geometry.yaml +45 -0
  81. spine-0.10.0/src/spine/geo/config/2x2/2x2_mr6-4_geometry.yaml +45 -0
  82. spine-0.10.0/src/spine/geo/config/2x2/2x2_mr6-5_geometry.yaml +45 -0
  83. spine-0.10.0/src/spine/geo/config/2x2-single/2x2-single_mr5-0_geometry.yaml +38 -0
  84. spine-0.10.0/src/spine/geo/config/2x2-single/2x2-single_mr6-5_geometry.yaml +39 -0
  85. spine-0.10.0/src/spine/geo/config/dune10kt-1x2x6/dune10kt-1x2x6_geometry.yaml +497 -0
  86. spine-0.10.0/src/spine/geo/config/fsd/fsd_cr1_geometry.yaml +67 -0
  87. spine-0.10.0/src/spine/geo/config/fsd/fsd_cr3_geometry.yaml +67 -0
  88. spine-0.10.0/src/spine/geo/config/icarus/icarus_crt_mapping.yaml +14 -0
  89. spine-0.10.0/src/spine/geo/config/icarus/icarus_v4_geometry.yaml +243 -0
  90. spine-0.10.0/src/spine/geo/config/nd-lar/nd-lar_mp1-2_geometry.yaml +81 -0
  91. spine-0.10.0/src/spine/geo/config/nd-lar/nd-lar_mp5-1_geometry.yaml +138 -0
  92. spine-0.10.0/src/spine/geo/config/nd-lar/nd-lar_up3-2_geometry.yaml +138 -0
  93. spine-0.10.0/src/spine/geo/config/nd-lar/nd-lar_up4-1_geometry.yaml +138 -0
  94. spine-0.10.0/src/spine/geo/config/protodune-hd/protodune-hd_v6_geometry.yaml +202 -0
  95. spine-0.10.0/src/spine/geo/config/protodune-sp/protodune-sp_v7_geometry.yaml +138 -0
  96. spine-0.10.0/src/spine/geo/config/protodune-vd/protodune-vd_v5_geometry.yaml +72 -0
  97. spine-0.10.0/src/spine/geo/config/sbnd/sbnd_v2-4_geometry.yaml +361 -0
  98. spine-0.10.0/src/spine/geo/config/sbnd/sbnd_v2-6_geometry.yaml +361 -0
  99. spine-0.10.0/src/spine/geo/detector/__init__.py +12 -0
  100. spine-0.10.0/src/spine/geo/detector/base.py +203 -0
  101. spine-0.10.0/src/spine/geo/detector/crt.py +216 -0
  102. spine-0.10.0/src/spine/geo/detector/optical.py +439 -0
  103. spine-0.10.0/src/spine/geo/detector/tpc.py +465 -0
  104. spine-0.10.0/src/spine/geo/factories.py +123 -0
  105. spine-0.10.0/src/spine/geo/manager.py +132 -0
  106. spine-0.10.0/src/spine/io/__init__.py +60 -0
  107. spine-0.10.0/src/spine/io/core/__init__.py +3 -0
  108. spine-0.10.0/src/spine/io/core/factories.py +62 -0
  109. spine-0.10.0/src/spine/io/core/parse/__init__.py +86 -0
  110. spine-0.10.0/src/spine/io/core/parse/base.py +124 -0
  111. spine-0.10.0/src/spine/io/core/parse/clean_data.py +267 -0
  112. spine-0.10.0/src/spine/io/core/parse/cluster.py +674 -0
  113. spine-0.10.0/src/spine/io/core/parse/data.py +138 -0
  114. spine-0.10.0/src/spine/io/core/parse/misc.py +396 -0
  115. spine-0.10.0/src/spine/io/core/parse/particle.py +815 -0
  116. spine-0.10.0/src/spine/io/core/parse/sparse.py +583 -0
  117. spine-0.10.0/src/spine/io/core/read/__init__.py +4 -0
  118. spine-0.10.0/src/spine/io/core/read/base.py +485 -0
  119. spine-0.10.0/src/spine/io/core/read/hdf5.py +348 -0
  120. spine-0.10.0/src/spine/io/core/read/larcv.py +240 -0
  121. spine-0.10.0/src/spine/io/core/write/__init__.py +4 -0
  122. spine-0.10.0/src/spine/io/core/write/csv.py +145 -0
  123. spine-0.10.0/src/spine/io/core/write/hdf5.py +698 -0
  124. spine-0.10.0/src/spine/io/torch/__init__.py +3 -0
  125. spine-0.10.0/src/spine/io/torch/augment.py +164 -0
  126. spine-0.10.0/src/spine/io/torch/collate.py +274 -0
  127. spine-0.10.0/src/spine/io/torch/dataset.py +184 -0
  128. spine-0.10.0/src/spine/io/torch/factories.py +215 -0
  129. spine-0.10.0/src/spine/io/torch/overlay.py +371 -0
  130. spine-0.10.0/src/spine/io/torch/sample.py +236 -0
  131. spine-0.10.0/src/spine/main.py +191 -0
  132. spine-0.10.0/src/spine/math/__init__.py +16 -0
  133. spine-0.10.0/src/spine/math/base.py +354 -0
  134. spine-0.10.0/src/spine/math/cluster.py +126 -0
  135. spine-0.10.0/src/spine/math/decomposition.py +95 -0
  136. spine-0.10.0/src/spine/math/distance.py +532 -0
  137. spine-0.10.0/src/spine/math/graph.py +443 -0
  138. spine-0.10.0/src/spine/math/linalg.py +170 -0
  139. spine-0.10.0/src/spine/math/metrics.py +265 -0
  140. spine-0.10.0/src/spine/math/neighbors.py +239 -0
  141. spine-0.10.0/src/spine/model/__init__.py +57 -0
  142. spine-0.10.0/src/spine/model/bayes_uresnet.py +411 -0
  143. spine-0.10.0/src/spine/model/experimental/bayes/__init__.py +0 -0
  144. spine-0.10.0/src/spine/model/experimental/bayes/calibration.py +137 -0
  145. spine-0.10.0/src/spine/model/experimental/bayes/decoder.py +119 -0
  146. spine-0.10.0/src/spine/model/experimental/bayes/encoder.py +200 -0
  147. spine-0.10.0/src/spine/model/experimental/bayes/evidential.py +271 -0
  148. spine-0.10.0/src/spine/model/experimental/bayes/factories.py +23 -0
  149. spine-0.10.0/src/spine/model/experimental/cluster/criterion.py +249 -0
  150. spine-0.10.0/src/spine/model/experimental/cluster/transformer_spice.py +385 -0
  151. spine-0.10.0/src/spine/model/experimental/hyperopt/__init__.py +0 -0
  152. spine-0.10.0/src/spine/model/experimental/hyperopt/factories.py +13 -0
  153. spine-0.10.0/src/spine/model/experimental/hyperopt/search.py +333 -0
  154. spine-0.10.0/src/spine/model/experimental/hyperopt/utils.py +42 -0
  155. spine-0.10.0/src/spine/model/experimental/layer/__init__.py +0 -0
  156. spine-0.10.0/src/spine/model/experimental/layer/pointnet.py +119 -0
  157. spine-0.10.0/src/spine/model/experimental/transformers/positional_encodings.py +62 -0
  158. spine-0.10.0/src/spine/model/experimental/transformers/transformer.py +525 -0
  159. spine-0.10.0/src/spine/model/experimental/xai/__init__.py +0 -0
  160. spine-0.10.0/src/spine/model/experimental/xai/gnnexplainer.py +173 -0
  161. spine-0.10.0/src/spine/model/experimental/xai/lrp.py +0 -0
  162. spine-0.10.0/src/spine/model/experimental/xai/shapley.py +2 -0
  163. spine-0.10.0/src/spine/model/experimental/xai/simple_cnn.py +15 -0
  164. spine-0.10.0/src/spine/model/experimental/xai/subgraphx.py +48 -0
  165. spine-0.10.0/src/spine/model/factories.py +78 -0
  166. spine-0.10.0/src/spine/model/full_chain.py +1651 -0
  167. spine-0.10.0/src/spine/model/graph_spice.py +407 -0
  168. spine-0.10.0/src/spine/model/grappa.py +648 -0
  169. spine-0.10.0/src/spine/model/image.py +229 -0
  170. spine-0.10.0/src/spine/model/layer/__init__.py +7 -0
  171. spine-0.10.0/src/spine/model/layer/cluster/__init__.py +3 -0
  172. spine-0.10.0/src/spine/model/layer/cluster/embeddings.py +137 -0
  173. spine-0.10.0/src/spine/model/layer/cluster/factories.py +73 -0
  174. spine-0.10.0/src/spine/model/layer/cluster/graph_spice_embedder.py +210 -0
  175. spine-0.10.0/src/spine/model/layer/cluster/kernel.py +362 -0
  176. spine-0.10.0/src/spine/model/layer/cluster/loss/__init__.py +6 -0
  177. spine-0.10.0/src/spine/model/layer/cluster/loss/gs_embeddings.py +527 -0
  178. spine-0.10.0/src/spine/model/layer/cluster/loss/lovasz.py +292 -0
  179. spine-0.10.0/src/spine/model/layer/cluster/loss/misc.py +236 -0
  180. spine-0.10.0/src/spine/model/layer/cluster/loss/single_layers.py +298 -0
  181. spine-0.10.0/src/spine/model/layer/cluster/loss/spatial_embeddings.py +806 -0
  182. spine-0.10.0/src/spine/model/layer/cluster/loss/spatial_embeddings_fast.py +492 -0
  183. spine-0.10.0/src/spine/model/layer/cnn/__init__.py +0 -0
  184. spine-0.10.0/src/spine/model/layer/cnn/act_norm.py +85 -0
  185. spine-0.10.0/src/spine/model/layer/cnn/blocks.py +1203 -0
  186. spine-0.10.0/src/spine/model/layer/cnn/configuration.py +70 -0
  187. spine-0.10.0/src/spine/model/layer/cnn/encoder.py +116 -0
  188. spine-0.10.0/src/spine/model/layer/cnn/fpn.py +182 -0
  189. spine-0.10.0/src/spine/model/layer/cnn/mobilenet.py +303 -0
  190. spine-0.10.0/src/spine/model/layer/cnn/nonlinearities.py +36 -0
  191. spine-0.10.0/src/spine/model/layer/cnn/normalizations.py +148 -0
  192. spine-0.10.0/src/spine/model/layer/cnn/ppn.py +1051 -0
  193. spine-0.10.0/src/spine/model/layer/cnn/senet.py +181 -0
  194. spine-0.10.0/src/spine/model/layer/cnn/sparse_generator.py +280 -0
  195. spine-0.10.0/src/spine/model/layer/cnn/uresnet_layers.py +261 -0
  196. spine-0.10.0/src/spine/model/layer/cnn/uresnext.py +183 -0
  197. spine-0.10.0/src/spine/model/layer/cnn/vertex_ppn.py +359 -0
  198. spine-0.10.0/src/spine/model/layer/common/__init__.py +0 -0
  199. spine-0.10.0/src/spine/model/layer/common/act_norm.py +80 -0
  200. spine-0.10.0/src/spine/model/layer/common/dbscan.py +259 -0
  201. spine-0.10.0/src/spine/model/layer/common/evidential.py +72 -0
  202. spine-0.10.0/src/spine/model/layer/common/final.py +146 -0
  203. spine-0.10.0/src/spine/model/layer/common/losses.py +477 -0
  204. spine-0.10.0/src/spine/model/layer/common/metric.py +36 -0
  205. spine-0.10.0/src/spine/model/layer/common/mlp.py +82 -0
  206. spine-0.10.0/src/spine/model/layer/factories.py +125 -0
  207. spine-0.10.0/src/spine/model/layer/gnn/__init__.py +3 -0
  208. spine-0.10.0/src/spine/model/layer/gnn/encode/__init__.py +6 -0
  209. spine-0.10.0/src/spine/model/layer/gnn/encode/cnn.py +197 -0
  210. spine-0.10.0/src/spine/model/layer/gnn/encode/empty.py +101 -0
  211. spine-0.10.0/src/spine/model/layer/gnn/encode/geometric.py +442 -0
  212. spine-0.10.0/src/spine/model/layer/gnn/encode/mixed.py +146 -0
  213. spine-0.10.0/src/spine/model/layer/gnn/factories.py +166 -0
  214. spine-0.10.0/src/spine/model/layer/gnn/graph/__init__.py +8 -0
  215. spine-0.10.0/src/spine/model/layer/gnn/graph/base.py +252 -0
  216. spine-0.10.0/src/spine/model/layer/gnn/graph/bipartite.py +89 -0
  217. spine-0.10.0/src/spine/model/layer/gnn/graph/complete.py +61 -0
  218. spine-0.10.0/src/spine/model/layer/gnn/graph/delaunay.py +107 -0
  219. spine-0.10.0/src/spine/model/layer/gnn/graph/knn.py +88 -0
  220. spine-0.10.0/src/spine/model/layer/gnn/graph/loop.py +46 -0
  221. spine-0.10.0/src/spine/model/layer/gnn/graph/mst.py +68 -0
  222. spine-0.10.0/src/spine/model/layer/gnn/loss/__init__.py +6 -0
  223. spine-0.10.0/src/spine/model/layer/gnn/loss/edge_channel.py +179 -0
  224. spine-0.10.0/src/spine/model/layer/gnn/loss/node_class.py +195 -0
  225. spine-0.10.0/src/spine/model/layer/gnn/loss/node_orient.py +143 -0
  226. spine-0.10.0/src/spine/model/layer/gnn/loss/node_reg.py +109 -0
  227. spine-0.10.0/src/spine/model/layer/gnn/loss/node_shower_primary.py +174 -0
  228. spine-0.10.0/src/spine/model/layer/gnn/loss/node_vertex.py +262 -0
  229. spine-0.10.0/src/spine/model/layer/gnn/model/__init__.py +1 -0
  230. spine-0.10.0/src/spine/model/layer/gnn/model/factories.py +78 -0
  231. spine-0.10.0/src/spine/model/layer/gnn/model/layer/__init__.py +5 -0
  232. spine-0.10.0/src/spine/model/layer/gnn/model/layer/agnnconv.py +72 -0
  233. spine-0.10.0/src/spine/model/layer/gnn/model/layer/econv.py +72 -0
  234. spine-0.10.0/src/spine/model/layer/gnn/model/layer/gatconv.py +83 -0
  235. spine-0.10.0/src/spine/model/layer/gnn/model/layer/mlp.py +273 -0
  236. spine-0.10.0/src/spine/model/layer/gnn/model/layer/nnconv.py +81 -0
  237. spine-0.10.0/src/spine/model/layer/gnn/model/meta.py +165 -0
  238. spine-0.10.0/src/spine/model/manager.py +582 -0
  239. spine-0.10.0/src/spine/model/singlep.py +566 -0
  240. spine-0.10.0/src/spine/model/spice.py +54 -0
  241. spine-0.10.0/src/spine/model/transformer.py +209 -0
  242. spine-0.10.0/src/spine/model/uresnet.py +499 -0
  243. spine-0.10.0/src/spine/model/uresnet_ppn.py +193 -0
  244. spine-0.10.0/src/spine/model/vertex.py +173 -0
  245. spine-0.10.0/src/spine/post/__init__.py +96 -0
  246. spine-0.10.0/src/spine/post/base.py +429 -0
  247. spine-0.10.0/src/spine/post/crt/__init__.py +3 -0
  248. spine-0.10.0/src/spine/post/crt/crt_matching.py +96 -0
  249. spine-0.10.0/src/spine/post/crt/match.py +238 -0
  250. spine-0.10.0/src/spine/post/factories.py +37 -0
  251. spine-0.10.0/src/spine/post/manager.py +98 -0
  252. spine-0.10.0/src/spine/post/optical/__init__.py +3 -0
  253. spine-0.10.0/src/spine/post/optical/barycenter.py +154 -0
  254. spine-0.10.0/src/spine/post/optical/flash_matching.py +282 -0
  255. spine-0.10.0/src/spine/post/optical/likelihood.py +422 -0
  256. spine-0.10.0/src/spine/post/reco/__init__.py +17 -0
  257. spine-0.10.0/src/spine/post/reco/calo.py +202 -0
  258. spine-0.10.0/src/spine/post/reco/cathode_cross.py +585 -0
  259. spine-0.10.0/src/spine/post/reco/cluster.py +228 -0
  260. spine-0.10.0/src/spine/post/reco/direction.py +106 -0
  261. spine-0.10.0/src/spine/post/reco/geometry.py +319 -0
  262. spine-0.10.0/src/spine/post/reco/kinematics.py +370 -0
  263. spine-0.10.0/src/spine/post/reco/mcs.py +177 -0
  264. spine-0.10.0/src/spine/post/reco/pid.py +85 -0
  265. spine-0.10.0/src/spine/post/reco/points.py +91 -0
  266. spine-0.10.0/src/spine/post/reco/ppn.py +113 -0
  267. spine-0.10.0/src/spine/post/reco/shower.py +408 -0
  268. spine-0.10.0/src/spine/post/reco/source.py +89 -0
  269. spine-0.10.0/src/spine/post/reco/topology.py +399 -0
  270. spine-0.10.0/src/spine/post/reco/tracking.py +109 -0
  271. spine-0.10.0/src/spine/post/reco/vertex.py +157 -0
  272. spine-0.10.0/src/spine/post/template.py +90 -0
  273. spine-0.10.0/src/spine/post/trigger/__init__.py +3 -0
  274. spine-0.10.0/src/spine/post/trigger/trigger.py +116 -0
  275. spine-0.10.0/src/spine/post/truth/__init__.py +4 -0
  276. spine-0.10.0/src/spine/post/truth/label.py +83 -0
  277. spine-0.10.0/src/spine/post/truth/match.py +295 -0
  278. spine-0.10.0/src/spine/utils/__init__.py +50 -0
  279. spine-0.10.0/src/spine/utils/calib/__init__.py +3 -0
  280. spine-0.10.0/src/spine/utils/calib/constant.py +112 -0
  281. spine-0.10.0/src/spine/utils/calib/database.py +275 -0
  282. spine-0.10.0/src/spine/utils/calib/factories.py +34 -0
  283. spine-0.10.0/src/spine/utils/calib/field.py +29 -0
  284. spine-0.10.0/src/spine/utils/calib/gain.py +59 -0
  285. spine-0.10.0/src/spine/utils/calib/lifetime.py +103 -0
  286. spine-0.10.0/src/spine/utils/calib/manager.py +158 -0
  287. spine-0.10.0/src/spine/utils/calib/recombination.py +293 -0
  288. spine-0.10.0/src/spine/utils/calib/transparency.py +85 -0
  289. spine-0.10.0/src/spine/utils/cluster/ccc.py +208 -0
  290. spine-0.10.0/src/spine/utils/cluster/dense_cluster.py +677 -0
  291. spine-0.10.0/src/spine/utils/cluster/fragmenter.py +82 -0
  292. spine-0.10.0/src/spine/utils/cluster/graph.py +425 -0
  293. spine-0.10.0/src/spine/utils/cluster/label.py +329 -0
  294. spine-0.10.0/src/spine/utils/cluster/orphan.py +97 -0
  295. spine-0.10.0/src/spine/utils/conditional.py +85 -0
  296. spine-0.10.0/src/spine/utils/csda_tables/kaE_liquid_argon_bethe.table +78 -0
  297. spine-0.10.0/src/spine/utils/csda_tables/muE_liquid_argon.table +146 -0
  298. spine-0.10.0/src/spine/utils/csda_tables/pE_liquid_argon.table +133 -0
  299. spine-0.10.0/src/spine/utils/csda_tables/pE_liquid_argon_bethe.table +78 -0
  300. spine-0.10.0/src/spine/utils/csda_tables/piE_liquid_argon_bethe.table +78 -0
  301. spine-0.10.0/src/spine/utils/docstring.py +46 -0
  302. spine-0.10.0/src/spine/utils/energy_loss.py +403 -0
  303. spine-0.10.0/src/spine/utils/enums.py +90 -0
  304. spine-0.10.0/src/spine/utils/factory.py +183 -0
  305. spine-0.10.0/src/spine/utils/ghost.py +105 -0
  306. spine-0.10.0/src/spine/utils/globals.py +249 -0
  307. spine-0.10.0/src/spine/utils/gnn/cluster.py +1479 -0
  308. spine-0.10.0/src/spine/utils/gnn/evaluation.py +872 -0
  309. spine-0.10.0/src/spine/utils/gnn/network.py +544 -0
  310. spine-0.10.0/src/spine/utils/gnn/voxels.py +127 -0
  311. spine-0.10.0/src/spine/utils/inference.py +83 -0
  312. spine-0.10.0/src/spine/utils/jit.py +94 -0
  313. spine-0.10.0/src/spine/utils/logger.py +24 -0
  314. spine-0.10.0/src/spine/utils/match.py +243 -0
  315. spine-0.10.0/src/spine/utils/mcs.py +354 -0
  316. spine-0.10.0/src/spine/utils/metrics.py +295 -0
  317. spine-0.10.0/src/spine/utils/optical.py +121 -0
  318. spine-0.10.0/src/spine/utils/particles.py +565 -0
  319. spine-0.10.0/src/spine/utils/pid.py +228 -0
  320. spine-0.10.0/src/spine/utils/point_break_clustering.py +229 -0
  321. spine-0.10.0/src/spine/utils/ppn.py +936 -0
  322. spine-0.10.0/src/spine/utils/shower.py +290 -0
  323. spine-0.10.0/src/spine/utils/stopwatch.py +398 -0
  324. spine-0.10.0/src/spine/utils/torch/__init__.py +17 -0
  325. spine-0.10.0/src/spine/utils/torch/adabound.py +309 -0
  326. spine-0.10.0/src/spine/utils/torch/devices.py +71 -0
  327. spine-0.10.0/src/spine/utils/torch/runtime.py +62 -0
  328. spine-0.10.0/src/spine/utils/torch/scripts.py +47 -0
  329. spine-0.10.0/src/spine/utils/torch/training.py +87 -0
  330. spine-0.10.0/src/spine/utils/tracking.py +579 -0
  331. spine-0.10.0/src/spine/utils/unwrap.py +221 -0
  332. spine-0.10.0/src/spine/utils/vertex.py +315 -0
  333. spine-0.10.0/src/spine/utils/weighting.py +60 -0
  334. spine-0.10.0/src/spine/version.py +3 -0
  335. spine-0.10.0/src/spine/vis/__init__.py +60 -0
  336. spine-0.10.0/src/spine/vis/arrow.py +123 -0
  337. spine-0.10.0/src/spine/vis/box.py +360 -0
  338. spine-0.10.0/src/spine/vis/cluster.py +290 -0
  339. spine-0.10.0/src/spine/vis/cone.py +123 -0
  340. spine-0.10.0/src/spine/vis/cylinder.py +240 -0
  341. spine-0.10.0/src/spine/vis/ellipsoid.py +237 -0
  342. spine-0.10.0/src/spine/vis/evaluation.py +138 -0
  343. spine-0.10.0/src/spine/vis/geo.py +498 -0
  344. spine-0.10.0/src/spine/vis/hull.py +67 -0
  345. spine-0.10.0/src/spine/vis/layout.py +414 -0
  346. spine-0.10.0/src/spine/vis/lite.py +498 -0
  347. spine-0.10.0/src/spine/vis/metric/__init__.py +3 -0
  348. spine-0.10.0/src/spine/vis/metric/confmat.py +179 -0
  349. spine-0.10.0/src/spine/vis/network.py +241 -0
  350. spine-0.10.0/src/spine/vis/out.py +1128 -0
  351. spine-0.10.0/src/spine/vis/particle.py +94 -0
  352. spine-0.10.0/src/spine/vis/point.py +155 -0
  353. spine-0.10.0/src/spine/vis/train.py +575 -0
  354. spine-0.10.0/src/spine.egg-info/PKG-INFO +372 -0
  355. spine-0.10.0/src/spine.egg-info/SOURCES.txt +357 -0
  356. spine-0.10.0/src/spine.egg-info/dependency_links.txt +1 -0
  357. spine-0.10.0/src/spine.egg-info/entry_points.txt +2 -0
  358. spine-0.10.0/src/spine.egg-info/requires.txt +35 -0
  359. spine-0.10.0/src/spine.egg-info/top_level.txt +1 -0
@@ -0,0 +1,32 @@
1
+ # Contribution Guidelines
2
+
3
+ Thanks for your interest in contributing to this repository!
4
+
5
+ This repository contains a framework to define, train, run, and evaluate machine learning models for LArTPC data. Goals are to
6
+ 1) Provide the basic framework needed for I/O, batching, and parallelization for models
7
+ 2) Make it easy to try out new models
8
+ 3) Make it easy to customize different parts of a LArTPC reconstruction pipeline
9
+
10
+ ## Basics
11
+
12
+ 1) Code should definitely run with Python 3. Please include imports to make your code Python 2 compatible.
13
+ 2) Please use the appropriate directories
14
+
15
+ ## Tests
16
+
17
+ Obviously, you should test your code. Ideally, we would have a unit testing framework that would make it easy for you to prove to others that you at least didn't break something.
18
+
19
+ Use the command `CUDA_VISBLE_DEVICES='' pytest -rxXs` to run all the tests that are currently available (still work in progress).
20
+
21
+ ## Documentation
22
+
23
+ If you are contributing code, please remember that other people use this repository as well, and that they may want (or need) to understand how to use what you have done. You may also need to understand what you do today 6 months from now. This means that documentation is important. There are three steps to making sure that others (and future you) can easily use and understand your code.
24
+
25
+ 1) Write a [docstring](https://www.python.org/dev/peps/pep-0257/) for every function you write, no matter how simple.
26
+ 2) Comment your code. If you're writing more than a few lines in a function, a docstring will not suffice. Let any reader know what you're doing, especially when you get to a loop or if statement.
27
+ 3) If appropriate, update a README with your contribution.
28
+
29
+
30
+ ### Docstring Template
31
+
32
+ We use the [numpy](https://numpydoc.readthedocs.io/en/latest/format.html) style for docstrings. Several example docstrings can be viewed [here](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_numpy.html).
spine-0.10.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 DeepLearnPhysics Collaboration
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,12 @@
1
+ include README.md
2
+ include CONTRIBUTING.md
3
+ recursive-include src *.py
4
+ recursive-include src *.yaml *.table
5
+ recursive-include config *.cfg
6
+ recursive-exclude test *
7
+ recursive-exclude docs *
8
+ global-exclude __pycache__
9
+ global-exclude *.py[co]
10
+ global-exclude .DS_Store
11
+ global-exclude *.so
12
+ global-exclude .git*
spine-0.10.0/PKG-INFO ADDED
@@ -0,0 +1,372 @@
1
+ Metadata-Version: 2.1
2
+ Name: spine
3
+ Version: 0.10.0
4
+ Summary: SPINE: Scalable Particle Imaging with Neural Embeddings for 3D high energy physics data analysis
5
+ Author-email: DeepLearnPhysics Collaboration <drielsma@stanford.edu>
6
+ Maintainer-email: Francois Drielsma <drielsma@stanford.edu>
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/DeepLearnPhysics/spine
9
+ Project-URL: Repository, https://github.com/DeepLearnPhysics/spine.git
10
+ Project-URL: Documentation, https://spine.readthedocs.io/
11
+ Project-URL: Bug Tracker, https://github.com/DeepLearnPhysics/spine/issues
12
+ Keywords: machine learning,physics,neutrino,sparse convolution,graph neural network
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Topic :: Scientific/Engineering :: Physics
23
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
24
+ Requires-Python: >=3.8
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: numexpr>=2.8.0
28
+ Requires-Dist: numpy>=1.19.0
29
+ Requires-Dist: scipy>=1.7.0
30
+ Requires-Dist: pandas>=1.3.0
31
+ Requires-Dist: PyYAML>=5.4.0
32
+ Requires-Dist: h5py>=3.1.0
33
+ Requires-Dist: numba>=0.56.0
34
+ Requires-Dist: psutil>=5.8.0
35
+ Requires-Dist: tqdm>=4.60.0
36
+ Provides-Extra: viz
37
+ Requires-Dist: matplotlib>=3.3.0; extra == "viz"
38
+ Requires-Dist: plotly>=4.14.0; extra == "viz"
39
+ Requires-Dist: seaborn>=0.11.0; extra == "viz"
40
+ Provides-Extra: dev
41
+ Requires-Dist: pytest>=6.0.0; extra == "dev"
42
+ Requires-Dist: pytest-cov>=2.10.0; extra == "dev"
43
+ Requires-Dist: black>=23.0.0; extra == "dev"
44
+ Requires-Dist: flake8>=6.0.0; extra == "dev"
45
+ Requires-Dist: isort>=5.12.0; extra == "dev"
46
+ Requires-Dist: pre-commit>=3.0.0; extra == "dev"
47
+ Requires-Dist: build>=0.8.0; extra == "dev"
48
+ Requires-Dist: twine>=4.0.0; extra == "dev"
49
+ Requires-Dist: wheel>=0.38.0; extra == "dev"
50
+ Requires-Dist: sphinx>=4.0.0; extra == "dev"
51
+ Requires-Dist: sphinx-rtd-theme>=1.0.0; extra == "dev"
52
+ Requires-Dist: sphinx-copybutton>=0.5.0; extra == "dev"
53
+ Requires-Dist: numpydoc>=1.4.0; extra == "dev"
54
+ Provides-Extra: all
55
+ Requires-Dist: spine[viz]; extra == "all"
56
+ Requires-Dist: spine[dev]; extra == "all"
57
+ Provides-Extra: core
58
+
59
+ <h1 align="center">
60
+ <img src="https://raw.githubusercontent.com/DeepLearnPhysics/spine/main/docs/source/_static/img/spine-logo-dark.png" alt='SPINE', width="400">
61
+ </h1><br>
62
+
63
+ [![CI](https://github.com/DeepLearnPhysics/spine/actions/workflows/ci.yml/badge.svg)](https://github.com/DeepLearnPhysics/spine/actions/workflows/ci.yml)
64
+ [![codecov](https://codecov.io/gh/DeepLearnPhysics/spine/branch/main/graph/badge.svg)](https://codecov.io/gh/DeepLearnPhysics/spine)
65
+ [![Documentation Status](https://readthedocs.org/projects/spine/badge/?version=latest)](https://spine.readthedocs.io/latest/)
66
+ [![PyPI version](https://badge.fury.io/py/spine.svg)](https://badge.fury.io/py/spine)
67
+ [![Python version](https://img.shields.io/pypi/pyversions/spine.svg)](https://pypi.org/project/spine/)
68
+
69
+ The Scalable Particle Imaging with Neural Embeddings (SPINE) package leverages state-of-the-art Machine Learning (ML) algorithms -- in particular Deep Neural Networks (DNNs) -- to reconstruct particle imaging detector data. This package was primarily developed for Liquid Argon Time-Projection Chamber (LArTPC) data and relies on Convolutional Neural Networks (CNNs) for pixel-level feature extraction and Graph Neural Networks (GNNs) for superstructure formation. The schematic below breaks down the full end-to-end reconstruction flow.
70
+
71
+ ![Full chain](https://raw.githubusercontent.com/DeepLearnPhysics/spine/main/docs/source/_static/img/spine-chain-alpha.png)
72
+
73
+ ## Installation
74
+
75
+ SPINE is now available on PyPI with flexible installation options to suit different needs:
76
+
77
+ ### Quick Start (Recommended)
78
+
79
+ For data analysis and visualization without machine learning:
80
+
81
+ ```bash
82
+ pip install spine[all]
83
+ ```
84
+
85
+ ### Installation Options
86
+
87
+ **1. Core Package (minimal dependencies)**
88
+ ```bash
89
+ # Essential dependencies: numpy, scipy, pandas, PyYAML, h5py, numba
90
+ pip install spine
91
+ ```
92
+
93
+ **2. With Visualization Tools**
94
+ ```bash
95
+ # Adds plotly, matplotlib, seaborn for data visualization
96
+ pip install spine[viz]
97
+ ```
98
+
99
+ **3. Development Environment**
100
+ ```bash
101
+ # Adds testing, formatting, and documentation tools
102
+ pip install spine[dev]
103
+ ```
104
+
105
+ **4. Everything (except PyTorch)**
106
+ ```bash
107
+ # All optional dependencies (visualization + development tools)
108
+ pip install spine[all]
109
+ ```
110
+
111
+ ### PyTorch ecosystem
112
+
113
+ #### Option 1: Container Approach (Recommended)
114
+
115
+ The easiest way to get a working PyTorch environment with LArCV support:
116
+
117
+ ```bash
118
+ # Pull the SPINE-compatible container with complete PyTorch ecosystem + LArCV
119
+ singularity pull spine.sif docker://deeplearnphysics/larcv2:ub2204-cu121-torch251-larndsim
120
+
121
+ # Install SPINE in the container
122
+ singularity exec spine.sif pip install spine[all]
123
+
124
+ # Run your analysis
125
+ singularity exec spine.sif spine --config your_config.cfg --source data.h5
126
+ ```
127
+
128
+ > This container includes: PyTorch 2.5.1, CUDA 12.1, torch-geometric, torch-scatter, torch-cluster, MinkowskiEngine, and **LArCV2**.
129
+
130
+ #### Option 2: Manual Installation** (advanced users):
131
+ ```bash
132
+ # Step 1: Install PyTorch with CUDA
133
+ pip install torch --index-url https://download.pytorch.org/whl/cu118
134
+
135
+ # Step 2: Install ecosystem packages (critical order)
136
+ pip install --no-build-isolation torch-scatter torch-cluster torch-geometric MinkowskiEngine
137
+
138
+ # Step 3: Install SPINE
139
+ pip install spine[all]
140
+ ```
141
+
142
+ > **� Why separate?** The PyTorch ecosystem (torch, torch-geometric, torch-scatter, torch-cluster, MinkowskiEngine) forms an interdependent group requiring exact version compatibility and complex compilation. Installing them together ensures compatibility.
143
+
144
+ ### LArCV2
145
+
146
+ #### Option 1: Use the container (recommended)*
147
+ ```bash
148
+ # LArCV2 is pre-installed in the DeepLearnPhysics container
149
+ singularity pull spine.sif docker://deeplearnphysics/larcv2:ub2204-cu121-torch251-larndsim
150
+ ```
151
+
152
+ #### Option 2: Build from source*
153
+ ```bash
154
+ # Clone and build the latest LArCV2
155
+ git clone https://github.com/DeepLearnPhysics/larcv2.git
156
+ cd larcv2
157
+ # Follow build instructions in the repository
158
+ ```
159
+
160
+ > **Note**: Avoid conda-forge larcv packages as they may be outdated. Use the container or build from the official source.
161
+
162
+ ### Development Installation
163
+
164
+ For developers who want to work with the source code:
165
+ ```bash
166
+ git clone https://github.com/DeepLearnPhysics/spine.git
167
+ cd spine
168
+ pip install -e .[dev]
169
+ ```
170
+
171
+ #### Quick Development Testing (No Installation)
172
+
173
+ For rapid development and testing without reinstalling the package:
174
+
175
+ ```bash
176
+ # Clone the repository
177
+ git clone https://github.com/DeepLearnPhysics/spine.git
178
+ cd spine
179
+
180
+ # Install only the dependencies (not the package itself)
181
+ # Or alternatively simple run the commands inside the above container
182
+ pip install numpy scipy pandas pyyaml h5py numba psutil
183
+
184
+ # Run directly from source
185
+ python src/spine/bin/run.py --config config/train_uresnet.cfg --source /path/to/data.h5
186
+
187
+ # Or make it executable and run directly
188
+ chmod +x src/spine/bin/run.py
189
+ ./src/spine/bin/run.py --config your_config.cfg --source data.h5
190
+ ```
191
+
192
+ > **💡 Development Tip**: This approach lets you test code changes immediately without reinstalling. Perfect for rapid iteration during development.
193
+
194
+ To build and test packages locally:
195
+ ```bash
196
+ # Build the package
197
+ ./build_packages.sh
198
+
199
+ # Install locally built package
200
+ pip install dist/spine-*.whl[all]
201
+ ```
202
+
203
+ ## Usage
204
+
205
+ ### Command Line Interface
206
+
207
+ **Option 1: After installation, use the `spine` command:**
208
+
209
+ ```bash
210
+ # Run training/inference/analysis
211
+ spine --config config/train_uresnet.cfg --source /path/to/data.h5
212
+ ```
213
+
214
+ **Option 2: Run directly from source (development):**
215
+
216
+ ```bash
217
+ # From the spine repository directory
218
+ python src/spine/bin/run.py --config config/train_uresnet.cfg --source /path/to/data.h5
219
+ ```
220
+
221
+ ### Python API
222
+
223
+ Basic example:
224
+ ```python
225
+ # Necessary imports
226
+ import yaml
227
+ from spine.driver import Driver
228
+
229
+ # Load configuration file
230
+ cfg_path = 'config/train_uresnet.cfg' # or your config file
231
+ with open(cfg_path, 'r') as f:
232
+ cfg = yaml.safe_load(f)
233
+
234
+ # Initialize driver class
235
+ driver = Driver(cfg)
236
+
237
+ # Execute model following the configuration regimen
238
+ driver.run()
239
+ ```
240
+
241
+ * Documentation is available at https://spine.readthedocs.io/latest/.
242
+ * Tutorials and examples can be found in the documentation.
243
+
244
+ ### Example Configuration Files
245
+
246
+ Example configurations are available in the `config` folder:
247
+
248
+ | Configuration name | Model |
249
+ | ------------------------------|----------------|
250
+ | `train_uresnet.cfg` | UResNet alone |
251
+ | `train_uresnet_ppn.cfg` | UResNet + PPN |
252
+ | `train_graph_spice.cfg` | GraphSpice |
253
+ | `train_grappa_shower.cfg` | GrapPA for shower fragments clustering |
254
+ | `train_grappa_track.cfg` | GrapPA for track fragments clustering |
255
+ | `train_grappa_inter.cfg` | GrapPA for interaction clustering |
256
+
257
+ To switch from training to inference mode, set `trainval.train: False` in your configuration file.
258
+
259
+ Key configuration parameters you may want to modify:
260
+ * `batch_size` - batch size for training/inference
261
+ * `weight_prefix` - directory to save model checkpoints
262
+ * `log_dir` - directory to save training logs
263
+ * `iterations` - number of training iterations
264
+ * `model_path` - path to checkpoint to load (optional)
265
+ * `train` - boolean flag for training vs inference mode
266
+ * `gpus` - GPU IDs to use (leave empty '' for CPU)
267
+
268
+
269
+ For more information on storing analysis outputs and running custom analysis scripts, see the documentation on `outputs` (formatters) and `analysis` (scripts) configurations.
270
+
271
+ ### Running A Configuration File
272
+
273
+ Basic usage with the `spine` command:
274
+ ```bash
275
+ # Run training/inference directly
276
+ spine --config config/train_uresnet.cfg --source /path/to/data.h5
277
+
278
+ # Or run in background with logging
279
+ nohup spine --config config/train_uresnet.cfg --source /path/to/data.h5 > log_uresnet.txt 2>&1 &
280
+ ```
281
+
282
+ You can load a configuration file into a Python dictionary using:
283
+ ```python
284
+ import yaml
285
+ # Load configuration file
286
+ with open('config/train_uresnet.cfg', 'r') as f:
287
+ cfg = yaml.safe_load(f)
288
+ ```
289
+
290
+ ### Reading a Log
291
+
292
+ A quick example of how to read a training log, and plot something
293
+ ```python
294
+ import pandas as pd
295
+ import matplotlib.pyplot as plt
296
+ fname = 'path/to/log.csv'
297
+ df = pd.read_csv(fname)
298
+
299
+ # plot moving average of accuracy over 10 iterations
300
+ df.accuracy.rolling(10, min_periods=1).mean().plot()
301
+ plt.ylabel("accuracy")
302
+ plt.xlabel("iteration")
303
+ plt.title("moving average of accuracy")
304
+ plt.show()
305
+
306
+ # list all column names
307
+ print(df.columns.values)
308
+ ```
309
+
310
+ ### Recording network output or running analysis
311
+ Documentation for analysis tools and output formatting is available in the main documentation at https://spine.readthedocs.io/latest/.
312
+
313
+ ## Repository Structure
314
+ * `bin` contains utility scripts for data processing
315
+ * `config` has example configuration files
316
+ * `docs` contains documentation source files
317
+ * `src/spine` contains the main package code
318
+ * `test` contains unit tests using pytest
319
+
320
+ Please consult the documentation for detailed information about each component.
321
+
322
+ ## Testing and Coverage
323
+
324
+ ### Running Tests
325
+
326
+ The SPINE package includes comprehensive unit tests using pytest:
327
+
328
+ ```bash
329
+ # Run all tests
330
+ pytest
331
+
332
+ # Run tests for a specific module
333
+ pytest test/test_data/
334
+
335
+ # Run with verbose output
336
+ pytest -v
337
+ ```
338
+
339
+ ### Checking Test Coverage
340
+
341
+ Test coverage tracking helps ensure code quality and identify untested areas. Coverage reports are automatically generated in our CI pipeline and uploaded to [Codecov](https://codecov.io/gh/DeepLearnPhysics/spine).
342
+
343
+ To check coverage locally:
344
+
345
+ ```bash
346
+ # Run the coverage script (generates terminal, HTML, and XML reports)
347
+ ./bin/coverage.sh
348
+
349
+ # Or run pytest with coverage flags directly
350
+ pytest --cov=spine --cov-report=term --cov-report=html
351
+
352
+ # View the HTML report
353
+ open htmlcov/index.html
354
+ ```
355
+
356
+ The coverage configuration is defined in `pyproject.toml` under `[tool.coverage.run]` and `[tool.coverage.report]`.
357
+
358
+ ## Contributing
359
+
360
+ Before you start contributing to the code, please see the [contribution guidelines](CONTRIBUTING.md).
361
+
362
+ ### Adding a new model
363
+
364
+ The SPINE framework is designed to be extensible. To add a new model:
365
+
366
+ 1. **Data Loading**: Parsers exist for various sparse tensor and particle outputs in `spine.io.core.parse`. If you need fundamentally different data formats, you may need to add new parsers or collation functions.
367
+
368
+ 2. **Model Implementation**: Add your model to the `spine.model` package. Include your model in the factory dictionary in `spine.model.factories` so it can be found by the configuration system.
369
+
370
+ 3. **Configuration**: Create a configuration file in the `config/` folder that specifies your model architecture and training parameters.
371
+
372
+ Once these steps are complete, you should be able to train your model using the standard SPINE workflow.