driftlessmap 1.5.0__tar.gz → 1.6.1__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 (272) hide show
  1. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/CITATION.cff +2 -2
  2. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/MANUAL.md +73 -10
  3. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/PKG-INFO +7 -5
  4. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/README.md +5 -4
  5. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/UpdateLog.md +10 -0
  6. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/WhatsNew.md +74 -0
  7. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/app.py +203 -4
  8. driftlessmap-1.6.1/driftlessmap/atlas_matching.py +558 -0
  9. driftlessmap-1.6.1/driftlessmap/auto_registration.py +348 -0
  10. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/main_window.ui +19 -0
  11. driftlessmap-1.6.1/driftlessmap/section_suggestion_dialog.py +177 -0
  12. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/slice_stacks.py +3 -1
  13. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/version.py +1 -1
  14. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap.egg-info/PKG-INFO +7 -5
  15. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap.egg-info/SOURCES.txt +5 -0
  16. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap.egg-info/requires.txt +1 -0
  17. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/pyproject.toml +3 -0
  18. driftlessmap-1.6.1/tests/test_atlas_matching.py +246 -0
  19. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_atlas_view.py +9 -0
  20. driftlessmap-1.6.1/tests/test_auto_registration.py +185 -0
  21. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_packaging_metadata.py +1 -0
  22. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_project_persistence.py +80 -0
  23. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_version.py +1 -1
  24. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/AUTHOR.txt +0 -0
  25. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/CONTRIBUTING.md +0 -0
  26. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/CONTRIBUTORS.md +0 -0
  27. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/LICENSE.txt +0 -0
  28. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/MANIFEST.in +0 -0
  29. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/ORIGINS.md +0 -0
  30. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/THANKS.txt +0 -0
  31. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/__init__.py +0 -0
  32. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/__main__.py +0 -0
  33. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/about.py +0 -0
  34. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/allen_downloader.py +0 -0
  35. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/atlas_downloader.py +0 -0
  36. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/atlas_loader.py +0 -0
  37. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/atlas_processor.py +0 -0
  38. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/atlas_transform.py +0 -0
  39. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/atlas_view.py +0 -0
  40. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/background.py +0 -0
  41. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/cell_detection.py +0 -0
  42. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/coordinate_validation.py +0 -0
  43. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/czi_reader.py +0 -0
  44. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/data/atlas_labels.pkl +0 -0
  45. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/data/query.csv +0 -0
  46. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/download_utils.py +0 -0
  47. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/app/driftlessmap.icns +0 -0
  48. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/app/driftlessmap.ico +0 -0
  49. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/app/driftlessmap.png +0 -0
  50. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/backward.svg +0 -0
  51. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/dot.svg +0 -0
  52. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/down-arrow.svg +0 -0
  53. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/fast_backward.svg +0 -0
  54. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/fast_forward.svg +0 -0
  55. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/forward.svg +0 -0
  56. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/layers/add.png +0 -0
  57. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/layers/ai.png +0 -0
  58. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/layers/eye_off.png +0 -0
  59. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/layers/eye_on.png +0 -0
  60. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/layers/eye_white.png +0 -0
  61. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/layers/hi.png +0 -0
  62. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/layers/trash.png +0 -0
  63. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/object.svg +0 -0
  64. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/add.png +0 -0
  65. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/atlascontrol.png +0 -0
  66. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/atlascontrol.svg +0 -0
  67. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/bnd.svg +0 -0
  68. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/c_section.png +0 -0
  69. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/c_section2.png +0 -0
  70. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/cell.svg +0 -0
  71. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/check.svg +0 -0
  72. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/compare.svg +0 -0
  73. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/contour.svg +0 -0
  74. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/h_section.png +0 -0
  75. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/info.svg +0 -0
  76. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/layers.png +0 -0
  77. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/layers.svg +0 -0
  78. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/line.svg +0 -0
  79. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/link.svg +0 -0
  80. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/link_off.svg +0 -0
  81. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/merge.svg +0 -0
  82. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/object.svg +0 -0
  83. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/probe.png +0 -0
  84. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/probe.svg +0 -0
  85. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/rotation_horizontal.svg +0 -0
  86. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/rotation_vertical.svg +0 -0
  87. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/s_section.png +0 -0
  88. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/tool.png +0 -0
  89. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/tool.svg +0 -0
  90. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/trash.png +0 -0
  91. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/tree_checked.svg +0 -0
  92. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/treeview.png +0 -0
  93. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/treeview.svg +0 -0
  94. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/treeview2.png +0 -0
  95. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/sidebar/virus.svg +0 -0
  96. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/tdown.svg +0 -0
  97. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/accept.svg +0 -0
  98. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/accept2.svg +0 -0
  99. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/aim.svg +0 -0
  100. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/aim_not.svg +0 -0
  101. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/anchor.svg +0 -0
  102. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/anticlockwise_rotation.svg +0 -0
  103. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/atlas_icon.png +0 -0
  104. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/boundary_register.svg +0 -0
  105. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/cancel.svg +0 -0
  106. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/cell_select.svg +0 -0
  107. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/cell_select_not.svg +0 -0
  108. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/check.svg +0 -0
  109. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/clockwise_rotation.svg +0 -0
  110. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/closed_path.svg +0 -0
  111. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/closed_path2 copy.svg +0 -0
  112. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/closed_path2.svg +0 -0
  113. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/eraser.png +0 -0
  114. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/eraser.svg +0 -0
  115. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/eye.svg +0 -0
  116. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/eye_closed.svg +0 -0
  117. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/fill.svg +0 -0
  118. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/gps.svg +0 -0
  119. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/h_flip.png +0 -0
  120. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/handle.png +0 -0
  121. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/image_icon.png +0 -0
  122. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/image_icon.svg +0 -0
  123. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/info.svg +0 -0
  124. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/inpart.png +0 -0
  125. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/inpart.svg +0 -0
  126. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/lasso.png +0 -0
  127. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/lasso.svg +0 -0
  128. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/left90.png +0 -0
  129. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/line.svg +0 -0
  130. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/line_sites.svg +0 -0
  131. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/linear_silicon.png +0 -0
  132. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/linear_silicon.svg +0 -0
  133. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/list.svg +0 -0
  134. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/location.svg +0 -0
  135. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/magic-wand.svg +0 -0
  136. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/magic_white.png +0 -0
  137. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/mask.svg +0 -0
  138. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/match.svg +0 -0
  139. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/matchbnd.svg +0 -0
  140. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/matching.svg +0 -0
  141. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/merge.svg +0 -0
  142. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/move_down.png +0 -0
  143. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/move_left.png +0 -0
  144. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/move_right.png +0 -0
  145. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/move_up.png +0 -0
  146. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/moving.png +0 -0
  147. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/multi-probe.svg +0 -0
  148. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/multi_pencil.svg +0 -0
  149. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/multi_probe.png +0 -0
  150. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/object.svg +0 -0
  151. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/open_path.svg +0 -0
  152. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/outpart.png +0 -0
  153. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/outpart.svg +0 -0
  154. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/pencil.png +0 -0
  155. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/pencil.svg +0 -0
  156. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/plasso.png +0 -0
  157. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/probe.svg +0 -0
  158. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/radar.svg +0 -0
  159. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/rotation.svg +0 -0
  160. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/rotation_clockwise.svg +0 -0
  161. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/rotation_counter_clockwise.svg +0 -0
  162. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/ruler.svg +0 -0
  163. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/separate_sites.svg +0 -0
  164. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/single_pencil.svg +0 -0
  165. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/toa.svg +0 -0
  166. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/toa_delete.svg +0 -0
  167. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/toaa.svg +0 -0
  168. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/toh.svg +0 -0
  169. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/toh_delete.svg +0 -0
  170. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/tohh.svg +0 -0
  171. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/trans.png +0 -0
  172. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/trans.svg +0 -0
  173. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/triangulation.svg +0 -0
  174. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/two_window.png +0 -0
  175. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/unmerge.svg +0 -0
  176. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/v_flip.png +0 -0
  177. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/virus.svg +0 -0
  178. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/virus_register.svg +0 -0
  179. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/vis2d.svg +0 -0
  180. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/window2.png +0 -0
  181. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/window3.png +0 -0
  182. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/toolbar/window4.png +0 -0
  183. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/tree_close.svg +0 -0
  184. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/tree_open.svg +0 -0
  185. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/icons/up-arrow.svg +0 -0
  186. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/image_curves.py +0 -0
  187. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/image_reader.py +0 -0
  188. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/image_stacks.py +0 -0
  189. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/image_view.py +0 -0
  190. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/label_tree.py +0 -0
  191. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/landmarks.py +0 -0
  192. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/layer_geometry.py +0 -0
  193. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/layer_validation.py +0 -0
  194. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/layers_control.py +0 -0
  195. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/movable_points.py +0 -0
  196. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/obj_items.py +0 -0
  197. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/object_control.py +0 -0
  198. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/persistence.py +0 -0
  199. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/probe_csv.py +0 -0
  200. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/probe_reconstruction.py +0 -0
  201. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/probe_utiles.py +0 -0
  202. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/project_io.py +0 -0
  203. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/provenance.py +0 -0
  204. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/qss/atlas_view_group_box.qss +0 -0
  205. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/qss/box_label.qss +0 -0
  206. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/qss/channel_selector.qss +0 -0
  207. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/qss/color_combo.qss +0 -0
  208. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/qss/decor_label.qss +0 -0
  209. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/qss/dialogs.qss +0 -0
  210. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/qss/hidden_line_edit.qss +0 -0
  211. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/qss/label_tree.qss +0 -0
  212. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/qss/main_window.qss +0 -0
  213. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/qss/menu_bar.qss +0 -0
  214. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/qss/multi_handle_slider.qss +0 -0
  215. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/qss/obj_ctrl_bottom_button.qss +0 -0
  216. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/qss/object_text_button.qss +0 -0
  217. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/qss/page_control.qss +0 -0
  218. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/qss/rotation_button.qss +0 -0
  219. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/qss/side_bar.qss +0 -0
  220. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/qss/spinbox.qss +0 -0
  221. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/qss/tabs.qss +0 -0
  222. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/qss/tool_bar.qss +0 -0
  223. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/resources.py +0 -0
  224. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/roi_analysis.py +0 -0
  225. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/run_driftlessmap.py +0 -0
  226. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/slice_validation.py +0 -0
  227. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/toolbox.py +0 -0
  228. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/triangulation.py +0 -0
  229. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/user_settings.py +0 -0
  230. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/utils.py +0 -0
  231. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/widgets_utils.py +0 -0
  232. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap/wtiles.py +0 -0
  233. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap.egg-info/dependency_links.txt +0 -0
  234. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap.egg-info/entry_points.txt +0 -0
  235. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/driftlessmap.egg-info/top_level.txt +0 -0
  236. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/setup.cfg +0 -0
  237. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/setup.py +0 -0
  238. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/atlas_fixture.py +0 -0
  239. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/run_test_suite.py +0 -0
  240. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_allen_downloader.py +0 -0
  241. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_atlas_cache_integrity.py +0 -0
  242. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_atlas_loader.py +0 -0
  243. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_atlas_transform.py +0 -0
  244. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_atlas_workers.py +0 -0
  245. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_background.py +0 -0
  246. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_cell_detection.py +0 -0
  247. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_coordinate_validation.py +0 -0
  248. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_czi_reader.py +0 -0
  249. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_download_utils.py +0 -0
  250. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_editing_tools.py +0 -0
  251. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_histogram_data.py +0 -0
  252. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_image_geometry.py +0 -0
  253. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_image_reader.py +0 -0
  254. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_label_tree.py +0 -0
  255. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_landmarks.py +0 -0
  256. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_layer_transforms.py +0 -0
  257. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_layer_validation.py +0 -0
  258. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_layers_control.py +0 -0
  259. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_mesh_cache.py +0 -0
  260. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_object_control.py +0 -0
  261. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_persistence.py +0 -0
  262. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_probe_csv.py +0 -0
  263. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_probe_dialogs.py +0 -0
  264. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_probe_mapping.py +0 -0
  265. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_probe_reconstruction.py +0 -0
  266. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_project_io.py +0 -0
  267. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_provenance.py +0 -0
  268. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_roi_analysis.py +0 -0
  269. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_runtime_paths.py +0 -0
  270. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_slice_validation.py +0 -0
  271. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_triangulation.py +0 -0
  272. {driftlessmap-1.5.0 → driftlessmap-1.6.1}/tests/test_widgets.py +0 -0
@@ -4,8 +4,8 @@ message: >-
4
4
  HERBS paper listed under references.
5
5
  title: DriftlessMap
6
6
  type: software
7
- version: 1.5.0
8
- date-released: 2026-09-27
7
+ version: 1.6.1
8
+ date-released: 2026-09-28
9
9
  authors:
10
10
  - name: Mohebi & Associates
11
11
  website: https://www.mohebi-associates.org/
@@ -1,6 +1,6 @@
1
1
  # DriftlessMap User Manual
2
2
 
3
- This manual applies to **DriftlessMap 1.5.0**.
3
+ This manual applies to **DriftlessMap 1.6.1**.
4
4
 
5
5
  DriftlessMap - Histological E-data Registration in Brain Space - is a desktop
6
6
  application for aligning rodent histology with a reference atlas, reconstructing
@@ -107,7 +107,7 @@ purposes. See [Saving, loading, and exporting](#18-saving-loading-and-exporting)
107
107
 
108
108
  ### 2.1 Requirements
109
109
 
110
- DriftlessMap 1.5.0 requires:
110
+ DriftlessMap 1.6.1 requires:
111
111
 
112
112
  - A 64-bit operating system and 64-bit Python 3.10 or newer.
113
113
  - Python 3.10-3.14 for the core application.
@@ -126,7 +126,7 @@ page. The macOS DMG (`-macOS-arm64.dmg`) is built for Apple Silicon; on an Intel
126
126
  Mac, use the developer installation below.
127
127
  The desktop builds include Python and all runtime dependencies. Windows users
128
128
  extract the entire ZIP and run `DriftlessMap.exe`; macOS users open the DMG and
129
- drag `DriftlessMap.app` to Applications. The 1.5.0 release is unsigned, so the
129
+ drag `DriftlessMap.app` to Applications. The 1.6.1 release is unsigned, so the
130
130
  first launch may require Windows SmartScreen confirmation or Control-clicking
131
131
  the macOS app and choosing **Open**.
132
132
 
@@ -174,7 +174,7 @@ python -m pip --version
174
174
  python -c "import driftlessmap; print(driftlessmap.__version__)"
175
175
  ```
176
176
 
177
- The final command should print `1.5.0`.
177
+ The final command should print `1.6.1`.
178
178
 
179
179
  ### 2.5 Launching DriftlessMap
180
180
 
@@ -714,7 +714,68 @@ probe, virus, cell, contour, and drawing transfer.
714
714
  4. Show **Volume + Histology** or **Slice + Histology**.
715
715
  5. Avoid resizing or rotating the source image after placing landmarks.
716
716
 
717
- ### 8.2 Place paired landmarks
717
+ ### 8.2 Suggest the section and landmarks automatically
718
+
719
+ DriftlessMap can propose a starting point for registration with a volume
720
+ atlas. Both steps are suggestions: always review the result before
721
+ transferring anything.
722
+
723
+ **Atlas > Suggest Atlas Section...** compares the loaded histology with the
724
+ atlas and ranks candidate sections:
725
+
726
+ 1. Load the volume atlas and the histology section. A single, whole section
727
+ on a plain background works best; the tissue outline is found by
728
+ thresholding.
729
+ 2. Choose **Atlas > Suggest Atlas Section...**. The comparison runs in the
730
+ background and usually takes a few seconds.
731
+ 3. The dialog reports the most likely plane (coronal, sagittal or horizontal)
732
+ and how clearly it was preferred (**clear**, **uncertain** or
733
+ **ambiguous**), the orientation the section needs, and up to six candidate
734
+ sections. Each shows your section on the left and the atlas on the right,
735
+ with its depth and cutting-angle tilt.
736
+ 4. Pick the candidate that looks best. Brain outlines are left-right
737
+ symmetric, so the hemisphere cannot be detected: choose **Other
738
+ hemisphere** if the section comes from the other side.
739
+ 5. Leave **Apply the suggested cutting-angle tilt** on to use the tilt, and
740
+ **Rotate/flip the histology to match** on to orient the image. Rotating
741
+ the histology resets its landmarks.
742
+ 6. Press **Apply**. DriftlessMap switches to the plane, shows the section and
743
+ sets the tilt. For coronal and horizontal sections the sagittal pivot is
744
+ moved to the midline.
745
+
746
+ The plane is found from the outline, the depth mainly from internal anatomy,
747
+ and the tilt from a small search of about ±6°. Damaged or partial sections,
748
+ sections with more than one piece of tissue, and strongly uneven staining make
749
+ suggestions less reliable.
750
+
751
+ **Atlas > Propose Landmarks** then fits the displayed atlas slice to the
752
+ section and fills the Triangulation tool with paired landmarks:
753
+
754
+ 1. Show the matching atlas slice and orient the histology to it, for example
755
+ with **Suggest Atlas Section...**. Remove any transform overlay first.
756
+ 2. Choose **Atlas > Propose Landmarks**. If landmarks already exist, you are
757
+ asked before they are replaced.
758
+ 3. DriftlessMap fits the outlines, then refines the fit on the image
759
+ intensities where that improves the match. It suggests up to 10 landmarks:
760
+ up to 5 at the sharpest tips and notches of the outline, snapped onto the
761
+ section outline, and the rest on strong internal edges that both images
762
+ show, such as the corpus callosum. It moves the boundary anchors with the
763
+ same fit. The landmarks are suggestions to confirm and edit.
764
+ 4. The status bar reports how many pairs are on the outline and how many are
765
+ on internal edges, and the outline overlap. The
766
+ Triangulation tool opens so you can check the mesh. Drag any landmark that
767
+ is off, add more where the anatomy needs them, and check mesh quality
768
+ (Section 8.5) before transferring.
769
+
770
+ The fit follows the outline and the overall shape well, but internal
771
+ boundaries can still be several voxels off. Treat the proposal as a first
772
+ draft of the manual landmarks, not as a finished registration.
773
+
774
+ The tutorial [Automatic Section Matching and Landmark Proposal](Tutorial/Registration_Related/automatic_section_and_landmarks.md)
775
+ walks through both steps on a real section, with screenshots, and explains
776
+ how each stage works.
777
+
778
+ ### 8.3 Place paired landmarks
718
779
 
719
780
  1. Activate Triangulation.
720
781
  2. Choose a point color visible in both windows.
@@ -741,7 +802,7 @@ Landmarks can be dragged. With Eraser active, clicking a numbered landmark
741
802
  deletes the corresponding point in both windows and renumbers the remaining
742
803
  pairs.
743
804
 
744
- ### 8.3 Match boundary rectangles
805
+ ### 8.4 Match boundary rectangles
745
806
 
746
807
  The automatically generated outer points define the warp domain. After
747
808
  interior points are placed, use **Match Boundaries** when the atlas and
@@ -751,7 +812,7 @@ anchors while retaining the paired interior anatomy.
751
812
  For a volume atlas, boundary matching can derive the atlas extent from the
752
813
  nonzero label area. A slice atlas requires interior landmarks in both images.
753
814
 
754
- ### 8.4 Evaluate mesh quality
815
+ ### 8.5 Evaluate mesh quality
755
816
 
756
817
  The Triangulation controls report:
757
818
 
@@ -773,7 +834,7 @@ To repair a mesh:
773
834
  - Confirm that pair order has not been confused.
774
835
  - Recheck the atlas slice and tilt.
775
836
 
776
- ### 8.5 Create and refine an overlay
837
+ ### 8.6 Create and refine an overlay
777
838
 
778
839
  To overlay histology onto the atlas:
779
840
 
@@ -793,7 +854,7 @@ repeatedly warping an already transformed preview, preventing accumulated blur.
793
854
  Atlas labels and masks use nearest-neighbor mapping where discrete values must
794
855
  be preserved; histology display uses smooth interpolation.
795
856
 
796
- ### 8.6 Transfer annotations
857
+ ### 8.7 Transfer annotations
797
858
 
798
859
  Once the registration is accepted:
799
860
 
@@ -812,7 +873,7 @@ Points outside the registration mesh cannot be assigned a valid atlas
812
873
  coordinate. DriftlessMap preserves or rejects them according to the data type and
813
874
  reports the count; do not silently treat them as registered.
814
875
 
815
- ### 8.7 Save registration landmarks
876
+ ### 8.8 Save registration landmarks
816
877
 
817
878
  Use:
818
879
 
@@ -1488,6 +1549,8 @@ still read when a DriftlessMap setting has not been created.
1488
1549
  | Download Waxholm Rat Atlas | Download/process standard rat atlas. |
1489
1550
  | Download Allen Mice Atlas | Download/process Allen 10, 25, or 50 um atlas. |
1490
1551
  | Atlas Processor | Process a custom volume atlas. |
1552
+ | Suggest Atlas Section... | Rank atlas plane, section, tilt and orientation for the loaded histology. |
1553
+ | Propose Landmarks | Fit the shown atlas slice to the histology and fill in registration landmarks. |
1491
1554
  | Save/Load Triangulation Points | Write/read `.dmaptri`. |
1492
1555
  | Load Slice | Load a raw or processed 2D atlas plate. |
1493
1556
  | Register Slice Info | Set plane, dimensions, and Bregma distance. |
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: driftlessmap
3
- Version: 1.5.0
3
+ Version: 1.6.1
4
4
  Summary: Interactive histology registration and brain-atlas mapping
5
5
  Author: Pearl Saldanha, Jacopo Paglia, Jonathan R. Whitlock, Mohebi & Associates, Ali Mohebi
6
6
  Author-email: Jingyi Guo Fuglstad <jingyi.g.fuglstad@gmail.com>
@@ -44,6 +44,7 @@ Requires-Dist: tifffile>=2024.7
44
44
  Requires-Dist: pandas<4,>=2.2
45
45
  Requires-Dist: natsort<9,>=8.4
46
46
  Requires-Dist: imagecodecs>=2024.6
47
+ Requires-Dist: SimpleITK<3,>=2.3
47
48
  Provides-Extra: czi
48
49
  Requires-Dist: aicspylibczi>=3.3.1; python_version < "3.14" and extra == "czi"
49
50
  Provides-Extra: test
@@ -95,6 +96,7 @@ See [CITATION.cff](CITATION.cff) for machine-readable citation metadata.
95
96
 
96
97
  - 2D and 3D visualization of volumetric brain atlases and arbitrary slices.
97
98
  - Interactive histology-to-atlas registration with local elastic deformation.
99
+ - Automatic suggestions for the matching atlas section and starting landmarks.
98
100
  - Probe planning, reconstruction, contact mapping, and CSV export.
99
101
  - Drawing, cell, virus-expression, and user-defined object workflows.
100
102
  - Safe, versioned project and object archives.
@@ -102,7 +104,7 @@ See [CITATION.cff](CITATION.cff) for machine-readable citation metadata.
102
104
 
103
105
  ## Installation
104
106
 
105
- DriftlessMap 1.5.0 is available as a desktop application for end users and as
107
+ DriftlessMap 1.6.1 is available as a desktop application for end users and as
106
108
  a Python package for developers.
107
109
 
108
110
  ### Mode 1: desktop application for end users
@@ -110,10 +112,10 @@ a Python package for developers.
110
112
  No Python or Conda installation is required. Download the asset for your
111
113
  computer from [GitHub Releases](https://github.com/mohebi-n-associates/DriftlessMap/releases):
112
114
 
113
- - **Windows 64-bit:** download `DriftlessMap-1.5.0-Windows-x64.zip`, extract
115
+ - **Windows 64-bit:** download `DriftlessMap-1.6.1-Windows-x64.zip`, extract
114
116
  the complete folder, and double-click `DriftlessMap.exe`. Do not move the
115
117
  executable out of its extracted folder.
116
- - **macOS (Apple Silicon):** download `DriftlessMap-1.5.0-macOS-arm64.dmg`,
118
+ - **macOS (Apple Silicon):** download `DriftlessMap-1.6.1-macOS-arm64.dmg`,
117
119
  open it, and drag `DriftlessMap.app` to Applications. The application bundle
118
120
  includes the DriftlessMap icon and all Python dependencies. Intel Macs are
119
121
  not covered by the desktop build; use the Conda/pip installation below.
@@ -137,7 +139,7 @@ malware:
137
139
  required only for the first launch.
138
140
 
139
141
  Only use **Open Anyway** for a copy downloaded from the
140
- [official DriftlessMap 1.5.0 release](https://github.com/mohebi-n-associates/DriftlessMap/releases/tag/v1.5.0).
142
+ [official DriftlessMap 1.6.1 release](https://github.com/mohebi-n-associates/DriftlessMap/releases/tag/v1.6.1).
141
143
  The official macOS DMG has this SHA-256 digest:
142
144
 
143
145
  ```text
@@ -38,6 +38,7 @@ See [CITATION.cff](CITATION.cff) for machine-readable citation metadata.
38
38
 
39
39
  - 2D and 3D visualization of volumetric brain atlases and arbitrary slices.
40
40
  - Interactive histology-to-atlas registration with local elastic deformation.
41
+ - Automatic suggestions for the matching atlas section and starting landmarks.
41
42
  - Probe planning, reconstruction, contact mapping, and CSV export.
42
43
  - Drawing, cell, virus-expression, and user-defined object workflows.
43
44
  - Safe, versioned project and object archives.
@@ -45,7 +46,7 @@ See [CITATION.cff](CITATION.cff) for machine-readable citation metadata.
45
46
 
46
47
  ## Installation
47
48
 
48
- DriftlessMap 1.5.0 is available as a desktop application for end users and as
49
+ DriftlessMap 1.6.1 is available as a desktop application for end users and as
49
50
  a Python package for developers.
50
51
 
51
52
  ### Mode 1: desktop application for end users
@@ -53,10 +54,10 @@ a Python package for developers.
53
54
  No Python or Conda installation is required. Download the asset for your
54
55
  computer from [GitHub Releases](https://github.com/mohebi-n-associates/DriftlessMap/releases):
55
56
 
56
- - **Windows 64-bit:** download `DriftlessMap-1.5.0-Windows-x64.zip`, extract
57
+ - **Windows 64-bit:** download `DriftlessMap-1.6.1-Windows-x64.zip`, extract
57
58
  the complete folder, and double-click `DriftlessMap.exe`. Do not move the
58
59
  executable out of its extracted folder.
59
- - **macOS (Apple Silicon):** download `DriftlessMap-1.5.0-macOS-arm64.dmg`,
60
+ - **macOS (Apple Silicon):** download `DriftlessMap-1.6.1-macOS-arm64.dmg`,
60
61
  open it, and drag `DriftlessMap.app` to Applications. The application bundle
61
62
  includes the DriftlessMap icon and all Python dependencies. Intel Macs are
62
63
  not covered by the desktop build; use the Conda/pip installation below.
@@ -80,7 +81,7 @@ malware:
80
81
  required only for the first launch.
81
82
 
82
83
  Only use **Open Anyway** for a copy downloaded from the
83
- [official DriftlessMap 1.5.0 release](https://github.com/mohebi-n-associates/DriftlessMap/releases/tag/v1.5.0).
84
+ [official DriftlessMap 1.6.1 release](https://github.com/mohebi-n-associates/DriftlessMap/releases/tag/v1.6.1).
84
85
  The official macOS DMG has this SHA-256 digest:
85
86
 
86
87
  ```text
@@ -1,5 +1,15 @@
1
1
  # Update Log
2
2
 
3
+ ### 28th September 2026
4
+ ##### DriftlessMap 1.6.1
5
+
6
+ Fixes **Show Boundary**, which drew atlas region boundaries almost black and therefore invisibly. **Propose Landmarks** now suggests up to 10 landmarks on features both images show (outline tips and notches, shared internal edges) instead of about 36. Adds a tutorial for the automatic section and landmark suggestions.
7
+
8
+ ### 27th September 2026
9
+ ##### DriftlessMap 1.6.0
10
+
11
+ Adds **Atlas > Suggest Atlas Section...**, which suggests the atlas plane, section, tilt and histology orientation for a loaded section. Also adds **Atlas > Propose Landmarks**, which fits the shown atlas slice to the histology and fills in registration landmarks for review. SimpleITK is now a required dependency.
12
+
3
13
  ### 27th September 2026
4
14
  ##### DriftlessMap 1.5.0
5
15
 
@@ -3,6 +3,80 @@
3
3
  This cumulative release history is maintained as a single document. New
4
4
  releases are added at the top; earlier release notes remain below them.
5
5
 
6
+ ## DriftlessMap 1.6.1
7
+
8
+ Release date: 28 September 2026
9
+
10
+ ### Fixed
11
+
12
+ - **Show Boundary** now draws atlas region boundaries in white. Since the
13
+ boundary images were stored as one byte per pixel, they had been drawn
14
+ almost black, so the button appeared to do nothing.
15
+
16
+ ### Changed
17
+
18
+ - **Propose Landmarks** now suggests up to 10 landmarks instead of about 36,
19
+ each on a feature you can see and check in both images:
20
+ - up to 5 at the sharpest tips and notches of the brain outline, snapped
21
+ onto the section outline;
22
+ - the rest on strong internal edges that both images show, such as the
23
+ corpus callosum and the ventricles.
24
+
25
+ An edge seen in only one image is never chosen: an atlas region border in
26
+ uniform-looking tissue, or a dye track in the section. The status bar says
27
+ how many points are on the outline and how many are internal. Confirm or
28
+ drag each point, and add more by hand where the anatomy needs them.
29
+
30
+ ### Documentation
31
+
32
+ - A new tutorial, [Automatic Section Matching and Landmark Proposal](Tutorial/Registration_Related/automatic_section_and_landmarks.md),
33
+ walks through **Suggest Atlas Section...** and **Propose Landmarks** on a
34
+ real sagittal section and explains how each stage works.
35
+
36
+ ## DriftlessMap 1.6.0
37
+
38
+ Release date: 27 September 2026
39
+
40
+ This release adds two assistants for volume-atlas registration. They suggest
41
+ where a section sits in the atlas and propose starting landmarks. You review
42
+ and confirm every suggestion; nothing is transferred automatically. Files
43
+ saved by 1.5.0 open unchanged, and nothing needs to be re-exported.
44
+
45
+ ### Suggest Atlas Section
46
+
47
+ **Atlas > Suggest Atlas Section...** compares the loaded histology with the
48
+ volume atlas and suggests the section it came from:
49
+
50
+ - the plane (coronal, sagittal or horizontal), found from the tissue outline,
51
+ with a note on how clearly it was preferred;
52
+ - the orientation the histology needs (rotation and flip);
53
+ - the depth, ranked mainly by internal anatomy;
54
+ - a small cutting-angle tilt, searched within about ±6°.
55
+
56
+ A dialog shows up to six candidates as side-by-side thumbnails. Choose one and
57
+ press **Apply**: DriftlessMap switches the plane, shows the section and sets
58
+ the tilt, and can also rotate or flip the histology to match. Because brain
59
+ outlines are left-right symmetric, you choose the hemisphere yourself.
60
+
61
+ ### Propose Landmarks
62
+
63
+ **Atlas > Propose Landmarks** fits the displayed atlas slice to the section.
64
+ It first fits the outlines, then refines the fit on image intensities where
65
+ that improves the match. It then fills the Triangulation tool with about 36
66
+ paired landmarks and moves the boundary anchors with the same fit. Drag,
67
+ add or delete landmarks as usual before transferring. Existing landmarks are
68
+ replaced only after you confirm.
69
+
70
+ The fit follows the outline and overall shape well. Internal boundaries can
71
+ still be several voxels off, so treat the proposal as a first draft.
72
+
73
+ ### Other changes
74
+
75
+ - DriftlessMap now requires SimpleITK, which the desktop builds and a normal
76
+ `pip install` include.
77
+ - The Registering chapter of the manual gains Section 8.2, which describes
78
+ both assistants. Later sections in that chapter are renumbered.
79
+
6
80
  ## DriftlessMap 1.5.0
7
81
 
8
82
  Release date: 27 September 2026
@@ -141,7 +141,10 @@ from .probe_reconstruction import (
141
141
  source_vox_to_herbs_vox,
142
142
  )
143
143
  from .roi_analysis import build_drawing_roi_info
144
+ from .atlas_matching import suggest_sections
145
+ from .auto_registration import propose_landmarks
144
146
  from .background import run_in_background
147
+ from .section_suggestion_dialog import SectionSuggestionDialog
145
148
  from .landmarks import LANDMARK_FIELDS, LandmarkModel, triangulation_payload_error
146
149
  from .project_io import (
147
150
  default_working_atlas_data,
@@ -525,6 +528,8 @@ class DriftlessMap(QMainWindow, FORM_Main):
525
528
  self.actionRegister_Slice_Info.triggered.connect(self.register_slice_info)
526
529
  self.actionSave_Slice.triggered.connect(self.save_processed_slice)
527
530
  self.actionSwitch_Atlas.triggered.connect(self.switch_atlas)
531
+ self.actionSuggest_Atlas_Section.triggered.connect(self.suggest_atlas_section)
532
+ self.actionPropose_Landmarks.triggered.connect(self.propose_registration_landmarks)
528
533
  self.actionBregma_Picker.setCheckable(True)
529
534
  self.actionBregma_Picker.triggered.connect(self.pick_bregma)
530
535
  self.actionCreate_Slice_Layer.triggered.connect(self.process_slice)
@@ -1756,6 +1761,200 @@ class DriftlessMap(QMainWindow, FORM_Main):
1756
1761
  "Current Slice is saved successfully.", self.normal_color
1757
1762
  )
1758
1763
 
1764
+ def suggest_atlas_section(self):
1765
+ """Suggest and apply the atlas plane, slice and tilt for the section."""
1766
+ if (
1767
+ self.current_atlas != "volume"
1768
+ or self.atlas_view.atlas_data is None
1769
+ or self.atlas_view.atlas_label is None
1770
+ ):
1771
+ self.print_message(
1772
+ "Load a volume atlas before suggesting an atlas section.",
1773
+ self.error_message_color,
1774
+ )
1775
+ return
1776
+ if self.image_view.current_img is None:
1777
+ self.print_message(
1778
+ "Load a histology section before suggesting an atlas section.",
1779
+ self.error_message_color,
1780
+ )
1781
+ return
1782
+ view = self.atlas_view
1783
+ section = np.asarray(self.image_view.current_img)
1784
+ midline = int(view.origin_3d[0])
1785
+ # Tilts for coronal/horizontal pivot on the midline (see above); the
1786
+ # sagittal pivot is its own page, so its value here does not matter.
1787
+ pivot = (int(view.current_coronal_index), midline,
1788
+ int(view.current_horizontal_index))
1789
+ try:
1790
+ report = run_in_background(
1791
+ self,
1792
+ "Comparing the section with the atlas...",
1793
+ suggest_sections,
1794
+ section,
1795
+ view.atlas_label,
1796
+ view.atlas_data,
1797
+ midline,
1798
+ pivot,
1799
+ )
1800
+ except ValueError as exc:
1801
+ self.print_message(
1802
+ "No atlas section could be suggested: {}".format(exc),
1803
+ self.error_message_color,
1804
+ )
1805
+ return
1806
+ if not report.suggestions:
1807
+ self.print_message(
1808
+ "No atlas section could be suggested for this image.",
1809
+ self.error_message_color,
1810
+ )
1811
+ return
1812
+ dialog = SectionSuggestionDialog(
1813
+ report, section, view.atlas_data, pivot, view.vox_size_um, self
1814
+ )
1815
+ if dialog.exec() != QDialog.DialogCode.Accepted:
1816
+ return
1817
+ choice = dialog.choice()
1818
+ if choice is not None:
1819
+ self.apply_section_suggestion(*choice)
1820
+
1821
+ def apply_section_suggestion(self, plane, index, orientation, tilt, rotate_histology):
1822
+ """Show ``plane``/``index`` at ``tilt`` and orient the histology."""
1823
+ view = self.atlas_view
1824
+ if rotate_histology:
1825
+ for _ in range(orientation.quarter_turns % 4):
1826
+ self.image_view.image_90_counter_rotate()
1827
+ if orientation.mirrored:
1828
+ self.image_view.image_horizon_flip()
1829
+ buttons = {"coronal": view.section_rabnt1, "sagittal": view.section_rabnt2,
1830
+ "horizontal": view.section_rabnt3}
1831
+ pages = {"coronal": view.cpage_ctrl, "sagittal": view.spage_ctrl,
1832
+ "horizontal": view.hpage_ctrl}
1833
+ rotations = {"coronal": view.crotation_ctrl, "sagittal": view.srotation_ctrl,
1834
+ "horizontal": view.hrotation_ctrl}
1835
+ buttons[plane].setChecked(True)
1836
+ if plane in ("coronal", "horizontal"):
1837
+ view.spage_ctrl.set_val(int(view.origin_3d[0]))
1838
+ pages[plane].set_val(int(index))
1839
+ rotation = rotations[plane]
1840
+ rotation.h_spinbox.setValue(float(tilt[0]))
1841
+ rotation.v_spinbox.setValue(float(tilt[1]))
1842
+ self.print_message(
1843
+ "Showing the suggested {} slice {} at tilt ({:+.1f}°, {:+.1f}°). "
1844
+ "Check the match before placing landmarks.".format(
1845
+ plane, index, tilt[0], tilt[1]
1846
+ ),
1847
+ self.normal_color,
1848
+ )
1849
+
1850
+ def propose_registration_landmarks(self):
1851
+ """Register the section to the displayed atlas slice and propose
1852
+ paired landmarks, which the user reviews with the triangulation tool."""
1853
+ if (
1854
+ self.current_atlas != "volume"
1855
+ or self.atlas_view.atlas_data is None
1856
+ or self.atlas_view.working_atlas.label_data is None
1857
+ ):
1858
+ self.print_message(
1859
+ "Show a volume atlas slice before proposing landmarks.",
1860
+ self.error_message_color,
1861
+ )
1862
+ return
1863
+ if self.image_view.current_img is None:
1864
+ self.print_message(
1865
+ "Load a histology section before proposing landmarks.",
1866
+ self.error_message_color,
1867
+ )
1868
+ return
1869
+ if self.a2h_transferred or self.h2a_transferred:
1870
+ self.print_message(
1871
+ "Remove the current transform overlay before proposing landmarks.",
1872
+ self.error_message_color,
1873
+ )
1874
+ return
1875
+ if self.atlas_tri_inside_data or self.histo_tri_inside_data:
1876
+ reply = QMessageBox.question(
1877
+ self,
1878
+ "Propose Landmarks",
1879
+ "Replace the current registration landmarks with proposed ones?",
1880
+ QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
1881
+ QMessageBox.StandardButton.No,
1882
+ )
1883
+ if reply != QMessageBox.StandardButton.Yes:
1884
+ return
1885
+ stack = self.atlas_view.working_atlas
1886
+ try:
1887
+ proposal = run_in_background(
1888
+ self,
1889
+ "Registering the section to the atlas slice...",
1890
+ propose_landmarks,
1891
+ np.asarray(stack.img.image),
1892
+ np.asarray(stack.label_data),
1893
+ np.asarray(self.image_view.current_img),
1894
+ boundary_points=np.asarray(self.atlas_tri_onside_data, dtype=float),
1895
+ )
1896
+ except (ValueError, RuntimeError) as exc:
1897
+ self.print_message(
1898
+ "Landmarks could not be proposed: {}".format(exc),
1899
+ self.error_message_color,
1900
+ )
1901
+ return
1902
+ if len(proposal.atlas_points) < 3:
1903
+ self.print_message(
1904
+ "Too few landmarks could be proposed; place them by hand.",
1905
+ self.error_message_color,
1906
+ )
1907
+ return
1908
+ self.apply_landmark_proposal(proposal)
1909
+
1910
+ def apply_landmark_proposal(self, proposal):
1911
+ """Replace interior landmarks with a proposal and show them."""
1912
+ self._invalidate_triangulation(clear_topology=True)
1913
+ self.atlas_tri_inside_data = [
1914
+ [round(float(x), 2), round(float(y), 2)] for x, y in proposal.atlas_points
1915
+ ]
1916
+ self.histo_tri_inside_data = [
1917
+ [round(float(x), 2), round(float(y), 2)] for x, y in proposal.histology_points
1918
+ ]
1919
+ if len(proposal.boundary_points) == len(self.atlas_tri_onside_data):
1920
+ # Carry the mesh frame through the fit too, so the fixed frame
1921
+ # points do not contradict the interior landmarks.
1922
+ self.histo_tri_onside_data = [
1923
+ [round(float(x), 2), round(float(y), 2)]
1924
+ for x, y in proposal.boundary_points
1925
+ ]
1926
+ self.atlas_tri_data = self.atlas_tri_onside_data + self.atlas_tri_inside_data
1927
+ self.histo_tri_data = self.histo_tri_onside_data + self.histo_tri_inside_data
1928
+ self.atlas_view.working_atlas.image_dict["tri_pnts"].setData(
1929
+ pos=np.asarray(self.atlas_tri_data)
1930
+ )
1931
+ self.image_view.img_stacks.image_dict["tri_pnts"].setData(
1932
+ pos=np.asarray(self.histo_tri_data)
1933
+ )
1934
+ self._refresh_triangulation_text("atlas")
1935
+ self._refresh_triangulation_text("image")
1936
+ # Show the proposal in the triangulation tool, ready for editing.
1937
+ button = self.tool_box.checkable_btn_dict["triang_btn"]
1938
+ if not button.isChecked():
1939
+ button.setChecked(True)
1940
+ self.triang_btn_clicked()
1941
+ if self.tool_box.triang_vis_btn.isChecked():
1942
+ self.update_atlas_tri_lines()
1943
+ self.update_histo_tri_lines()
1944
+ else:
1945
+ self._build_triangulation_registration(strict=False, show_error=False)
1946
+ stage = "outline and intensity" if proposal.deformable_used else "outline"
1947
+ on_outline = sum(kind == "outline" for kind in proposal.kinds)
1948
+ self.print_message(
1949
+ "Suggested {} landmark pairs ({} on the outline, {} on internal edges) "
1950
+ "from the {} fit (outline overlap {:.2f}). Confirm or drag each one "
1951
+ "before transferring.".format(
1952
+ len(proposal.atlas_points), on_outline,
1953
+ len(proposal.atlas_points) - on_outline, stage, proposal.overlap_final
1954
+ ),
1955
+ self.normal_color,
1956
+ )
1957
+
1759
1958
  def switch_atlas(self):
1760
1959
  if (
1761
1960
  self.atlas_view.atlas_data is None
@@ -2929,7 +3128,7 @@ class DriftlessMap(QMainWindow, FORM_Main):
2929
3128
  True
2930
3129
  )
2931
3130
  if (
2932
- self.atlas_tri_inside_data
3131
+ self.working_atlas_text
2933
3132
  and not self.working_atlas_text[0].isVisible()
2934
3133
  ):
2935
3134
  for i in range(len(self.working_atlas_text)):
@@ -2938,7 +3137,7 @@ class DriftlessMap(QMainWindow, FORM_Main):
2938
3137
  if not self.image_view.img_stacks.image_dict["tri_pnts"].isVisible():
2939
3138
  self.image_view.img_stacks.image_dict["tri_pnts"].setVisible(True)
2940
3139
  if (
2941
- self.histo_tri_inside_data
3140
+ self.working_img_text
2942
3141
  and not self.working_img_text[0].isVisible()
2943
3142
  ):
2944
3143
  for i in range(len(self.working_img_text)):
@@ -2950,7 +3149,7 @@ class DriftlessMap(QMainWindow, FORM_Main):
2950
3149
  False
2951
3150
  )
2952
3151
  if (
2953
- self.atlas_tri_inside_data
3152
+ self.working_atlas_text
2954
3153
  and self.working_atlas_text[0].isVisible()
2955
3154
  ):
2956
3155
  for i in range(len(self.working_atlas_text)):
@@ -2958,7 +3157,7 @@ class DriftlessMap(QMainWindow, FORM_Main):
2958
3157
  if self.histo_tri_data:
2959
3158
  if self.image_view.img_stacks.image_dict["tri_pnts"].isVisible():
2960
3159
  self.image_view.img_stacks.image_dict["tri_pnts"].setVisible(False)
2961
- if self.histo_tri_inside_data and self.working_img_text[0].isVisible():
3160
+ if self.working_img_text and self.working_img_text[0].isVisible():
2962
3161
  for i in range(len(self.working_img_text)):
2963
3162
  self.working_img_text[i].setVisible(False)
2964
3163