mergechannels 0.1.0__tar.gz → 0.1.2__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.

Potentially problematic release.


This version of mergechannels might be problematic. Click here for more details.

Files changed (176) hide show
  1. mergechannels-0.1.2/.gitattributes +7 -0
  2. {mergechannels-0.1.0 → mergechannels-0.1.2}/.github/workflows/CI.yml +58 -32
  3. {mergechannels-0.1.0 → mergechannels-0.1.2}/.gitignore +5 -1
  4. mergechannels-0.1.2/.pre-commit-config.yaml +16 -0
  5. {mergechannels-0.1.0 → mergechannels-0.1.2}/Cargo.lock +1 -1
  6. {mergechannels-0.1.0 → mergechannels-0.1.2}/Cargo.toml +1 -1
  7. {mergechannels-0.1.0 → mergechannels-0.1.2}/LICENSE +1 -1
  8. mergechannels-0.1.2/PKG-INFO +115 -0
  9. mergechannels-0.1.2/README.md +95 -0
  10. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/phase.lut +0 -1
  11. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/Turbo.lut +1 -1
  12. mergechannels-0.1.2/pyproject.toml +33 -0
  13. {mergechannels-0.1.0 → mergechannels-0.1.2}/pytests/test_colorize.py +28 -1
  14. {mergechannels-0.1.0 → mergechannels-0.1.2}/python/mergechannels/__init__.py +4 -4
  15. {mergechannels-0.1.0 → mergechannels-0.1.2}/python/mergechannels/__init__.pyi +8 -2
  16. {mergechannels-0.1.0 → mergechannels-0.1.2}/python/mergechannels/_internal.py +17 -26
  17. mergechannels-0.1.2/ruff.toml +86 -0
  18. {mergechannels-0.1.0 → mergechannels-0.1.2}/scripts/convert_luts_to_txt.ijm +1 -1
  19. {mergechannels-0.1.0 → mergechannels-0.1.2}/scripts/populate_luts.py +22 -19
  20. {mergechannels-0.1.0 → mergechannels-0.1.2}/src/interface.rs +0 -6
  21. mergechannels-0.1.2/tox.ini +11 -0
  22. mergechannels-0.1.2/uv.lock +662 -0
  23. mergechannels-0.1.0/PKG-INFO +0 -63
  24. mergechannels-0.1.0/README.md +0 -52
  25. mergechannels-0.1.0/pyproject.toml +0 -17
  26. mergechannels-0.1.0/test.ipynb +0 -262
  27. mergechannels-0.1.0/uv.lock +0 -48
  28. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/16_colors.lut +0 -0
  29. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/5_ramps.lut +0 -0
  30. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/6_shades.lut +0 -0
  31. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/Cyan Hot.lut +0 -0
  32. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/Green Fire Blue.lut +0 -0
  33. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/HiLo.lut +0 -0
  34. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/ICA.lut +0 -0
  35. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/ICA2.lut +0 -0
  36. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/ICA3.lut +0 -0
  37. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/Magenta Hot.lut +0 -0
  38. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/Orange Hot.lut +0 -0
  39. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/Rainbow RGB.lut +0 -0
  40. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/Red Hot.lut +0 -0
  41. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/Thermal.lut +0 -0
  42. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/Yellow Hot.lut +0 -0
  43. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/blue_orange_icb.lut +0 -0
  44. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/brgbcmyw.lut +0 -0
  45. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/cool.lut +0 -0
  46. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/edges.lut +0 -0
  47. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/gem.lut +0 -0
  48. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/glasbey.lut +0 -0
  49. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/glasbey_inverted.lut +0 -0
  50. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/glasbey_on_dark.lut +0 -0
  51. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/glow.lut +0 -0
  52. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/mpl-inferno.lut +0 -0
  53. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/mpl-magma.lut +0 -0
  54. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/mpl-plasma.lut +0 -0
  55. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/mpl-viridis.lut +0 -0
  56. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/physics.lut +0 -0
  57. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/royal.lut +0 -0
  58. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/sepia.lut +0 -0
  59. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/smart.lut +0 -0
  60. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/thal.lut +0 -0
  61. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/thallium.lut +0 -0
  62. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/builtin_luts/unionjack.lut +0 -0
  63. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/3color-BMR.lut +0 -0
  64. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/3color-CGY.lut +0 -0
  65. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/3color-RMB.lut +0 -0
  66. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/3color-YGC.lut +0 -0
  67. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/BOP blue.lut +0 -0
  68. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/BOP orange.lut +0 -0
  69. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/BOP purple.lut +0 -0
  70. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/I Blue.lut +0 -0
  71. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/I Bordeaux.lut +0 -0
  72. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/I Cyan.lut +0 -0
  73. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/I Forest.lut +0 -0
  74. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/I Green.lut +0 -0
  75. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/I Magenta.lut +0 -0
  76. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/I Purple.lut +0 -0
  77. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/I Red.lut +0 -0
  78. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/I Yellow.lut +0 -0
  79. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/NOTICE +0 -0
  80. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/OPF fresh.lut +0 -0
  81. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/OPF orange.lut +0 -0
  82. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/christ_luts/OPF purple.lut +0 -0
  83. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/16_colors.txt +0 -0
  84. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/3-3-2 RGB.txt +0 -0
  85. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/3color-BMR.txt +0 -0
  86. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/3color-CGY.txt +0 -0
  87. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/3color-RMB.txt +0 -0
  88. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/3color-YGC.txt +0 -0
  89. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/5_ramps.txt +0 -0
  90. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/6_shades.txt +0 -0
  91. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/BOP blue.txt +0 -0
  92. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/BOP orange.txt +0 -0
  93. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/BOP purple.txt +0 -0
  94. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Blue.txt +0 -0
  95. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Cyan Hot.txt +0 -0
  96. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Cyan.txt +0 -0
  97. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Fire.txt +0 -0
  98. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Grays.txt +0 -0
  99. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Green Fire Blue.txt +0 -0
  100. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Green.txt +0 -0
  101. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/HiLo.txt +0 -0
  102. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/I Blue.txt +0 -0
  103. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/I Bordeaux.txt +0 -0
  104. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/I Cyan.txt +0 -0
  105. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/I Forest.txt +0 -0
  106. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/I Green.txt +0 -0
  107. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/I Magenta.txt +0 -0
  108. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/I Purple.txt +0 -0
  109. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/I Red.txt +0 -0
  110. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/I Yellow.txt +0 -0
  111. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/ICA.txt +0 -0
  112. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/ICA2.txt +0 -0
  113. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/ICA3.txt +0 -0
  114. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Ice.txt +0 -0
  115. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Magenta Hot.txt +0 -0
  116. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Magenta.txt +0 -0
  117. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/OIMB1.txt +0 -0
  118. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/OIMB2.txt +0 -0
  119. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/OIMB3.txt +0 -0
  120. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/OPF fresh.txt +0 -0
  121. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/OPF orange.txt +0 -0
  122. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/OPF purple.txt +0 -0
  123. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Orange Hot.txt +0 -0
  124. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Rainbow RGB.txt +0 -0
  125. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Red Hot.txt +0 -0
  126. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Red%Green.txt +0 -0
  127. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Red.txt +0 -0
  128. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Spectrum.txt +0 -0
  129. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Thermal.txt +0 -0
  130. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Turbo.txt +0 -0
  131. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Yellow Hot.txt +0 -0
  132. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/Yellow.txt +0 -0
  133. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/betterBlue.txt +0 -0
  134. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/betterCyan.txt +0 -0
  135. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/betterGreen.txt +0 -0
  136. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/betterOrange.txt +0 -0
  137. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/betterRed.txt +0 -0
  138. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/betterYellow.txt +0 -0
  139. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/blue_orange_icb.txt +0 -0
  140. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/brgbcmyw.txt +0 -0
  141. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/cool.txt +0 -0
  142. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/edges.txt +0 -0
  143. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/gem.txt +0 -0
  144. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/glasbey.txt +0 -0
  145. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/glasbey_inverted.txt +0 -0
  146. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/glasbey_on_dark.txt +0 -0
  147. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/glow.txt +0 -0
  148. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/mpl-inferno.txt +0 -0
  149. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/mpl-magma.txt +0 -0
  150. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/mpl-plasma.txt +0 -0
  151. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/mpl-viridis.txt +0 -0
  152. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/phase.txt +0 -0
  153. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/physics.txt +0 -0
  154. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/royal.txt +0 -0
  155. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/sepia.txt +0 -0
  156. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/smart.txt +0 -0
  157. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/thal.txt +0 -0
  158. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/thallium.txt +0 -0
  159. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/converted/unionjack.txt +0 -0
  160. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/zac_luts/OIMB1.lut +0 -0
  161. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/zac_luts/OIMB2.lut +0 -0
  162. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/zac_luts/OIMB3.lut +0 -0
  163. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/zac_luts/betterBlue.lut +0 -0
  164. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/zac_luts/betterCyan.lut +0 -0
  165. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/zac_luts/betterGreen.lut +0 -0
  166. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/zac_luts/betterOrange.lut +0 -0
  167. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/zac_luts/betterRed.lut +0 -0
  168. {mergechannels-0.1.0 → mergechannels-0.1.2}/assets/zac_luts/betterYellow.lut +0 -0
  169. {mergechannels-0.1.0 → mergechannels-0.1.2}/python/mergechannels/_blending.py +0 -0
  170. {mergechannels-0.1.0 → mergechannels-0.1.2}/python/mergechannels/_luts.py +0 -0
  171. {mergechannels-0.1.0 → mergechannels-0.1.2}/python/mergechannels/py.typed +0 -0
  172. {mergechannels-0.1.0 → mergechannels-0.1.2}/src/blend.rs +0 -0
  173. {mergechannels-0.1.0 → mergechannels-0.1.2}/src/cmaps.rs +0 -0
  174. {mergechannels-0.1.0 → mergechannels-0.1.2}/src/colorize.rs +0 -0
  175. {mergechannels-0.1.0 → mergechannels-0.1.2}/src/lib.rs +0 -0
  176. {mergechannels-0.1.0 → mergechannels-0.1.2}/src/normalize.rs +0 -0
@@ -0,0 +1,7 @@
1
+ # LFS for image files
2
+ *.png filter=lfs diff=lfs merge=lfs -text
3
+ *.jpg filter=lfs diff=lfs merge=lfs -text
4
+ *.jpeg filter=lfs diff=lfs merge=lfs -text
5
+ *.gif filter=lfs diff=lfs merge=lfs -text
6
+ *.tif filter=lfs diff=lfs merge=lfs -text
7
+ *.tiff filter=lfs diff=lfs merge=lfs -text
@@ -8,8 +8,7 @@ name: CI
8
8
  on:
9
9
  push:
10
10
  branches:
11
- - main
12
- - mvp
11
+ - '*'
13
12
  tags:
14
13
  - '*'
15
14
  pull_request:
@@ -24,50 +23,73 @@ jobs:
24
23
  runs-on: ubuntu-latest
25
24
  steps:
26
25
  - uses: actions/checkout@v4
27
-
26
+
28
27
  # Setup Rust toolchain
29
28
  - name: Install Rust stable
30
29
  uses: dtolnay/rust-toolchain@stable
31
30
  with:
32
31
  components: rustfmt, clippy
33
-
34
- # Run Rust format check
32
+
35
33
  - name: Check Rust formatting
36
34
  run: cargo fmt --all -- --check
37
-
38
- # Run Clippy
35
+
39
36
  - name: Run Clippy
40
37
  run: cargo clippy -- -D warnings
41
-
42
- # Run Cargo tests
38
+
43
39
  - name: Run Cargo tests
44
40
  run: cargo test
45
-
46
- # # Setup Python for testing
47
- # - uses: actions/setup-python@v5
48
- # with:
49
- # python-version: 3.x
50
-
51
- # Install UV
41
+
52
42
  - name: Install UV
53
43
  uses: astral-sh/setup-uv@v5
54
-
55
- # Create virtual environment and install the project
56
- - name: Create virtual environment and install
57
- run: |
58
- uv venv .venv --python 3.11
59
- source .venv/bin/activate
60
- pip install -e .
61
-
62
- # Run pytest
63
- - name: Run pytest
44
+ with:
45
+ enable-cache: true
46
+
47
+ - name: Install the project
48
+ run: uv sync --all-extras --dev
49
+
50
+ - name: Run pre-commit
51
+ shell: bash -l {0}
52
+ run: uv run pre-commit run --all-files
53
+
54
+ tox_tests:
55
+ name: Tox Tests (${{ matrix.python-version }}) # Add python version to name for clarity
56
+ runs-on: ubuntu-latest
57
+ strategy:
58
+ matrix:
59
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
60
+ fail-fast: true # Optional: prevent other matrix jobs from cancelling if one fails
61
+ steps:
62
+ - uses: actions/checkout@v4
63
+
64
+ # Set up the specific Python version for this matrix job
65
+ - name: Set up Python ${{ matrix.python-version }}
66
+ uses: actions/setup-python@v5
67
+ with:
68
+ python-version: ${{ matrix.python-version }}
69
+
70
+ # Install UV using the official action, enabling caching
71
+ - name: Install UV
72
+ uses: astral-sh/setup-uv@v5
73
+ with:
74
+ # Enable uv's cache for faster subsequent runs
75
+ enable-cache: true
76
+
77
+ # Install tox and tox-uv using uv tool install
78
+ # This installs them into an isolated environment managed by uv
79
+ - name: Install Tox with tox-uv plugin using UV
80
+ run: uv tool install tox --with tox-uv
81
+
82
+ # Run Tox using uvx
83
+ # uvx ensures that the 'tox' command installed via 'uv tool install' is used
84
+ - name: Run Tox tests via uvx
64
85
  run: |
65
- source .venv/bin/activate
66
- pip install pytest
67
- pytest
86
+ PY_VERSION=$(echo ${{ matrix.python-version }} | tr -d '.')
87
+ uvx tox -e py$PY_VERSION
68
88
 
69
- linux:
70
- needs: rust_checks_and_python_tests
89
+
90
+ build:
91
+ needs: [rust_checks_and_python_tests, tox_tests]
92
+ if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }}
71
93
  runs-on: ${{ matrix.platform.runner }}
72
94
  strategy:
73
95
  matrix:
@@ -104,6 +126,7 @@ jobs:
104
126
 
105
127
  musllinux:
106
128
  needs: rust_checks_and_python_tests
129
+ if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }}
107
130
  runs-on: ${{ matrix.platform.runner }}
108
131
  strategy:
109
132
  matrix:
@@ -136,6 +159,7 @@ jobs:
136
159
 
137
160
  windows:
138
161
  needs: rust_checks_and_python_tests
162
+ if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }}
139
163
  runs-on: ${{ matrix.platform.runner }}
140
164
  strategy:
141
165
  matrix:
@@ -164,6 +188,7 @@ jobs:
164
188
 
165
189
  macos:
166
190
  needs: rust_checks_and_python_tests
191
+ if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }}
167
192
  runs-on: ${{ matrix.platform.runner }}
168
193
  strategy:
169
194
  matrix:
@@ -191,6 +216,7 @@ jobs:
191
216
 
192
217
  sdist:
193
218
  needs: rust_checks_and_python_tests
219
+ if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }}
194
220
  runs-on: ubuntu-latest
195
221
  steps:
196
222
  - uses: actions/checkout@v4
@@ -209,7 +235,7 @@ jobs:
209
235
  name: Release
210
236
  runs-on: ubuntu-latest
211
237
  if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }}
212
- needs: [linux, musllinux, windows, macos, sdist]
238
+ needs: [build, musllinux, windows, macos, sdist]
213
239
  permissions:
214
240
  # Use to sign the release artifacts
215
241
  id-token: write
@@ -72,4 +72,8 @@ docs/_build/
72
72
  .python-version
73
73
 
74
74
  # ignore images
75
- *.tif*
75
+ *.tif*
76
+
77
+ # ignore notebooks
78
+ *.ipynb
79
+ *.ju.py
@@ -0,0 +1,16 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v4.6.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ - id: check-toml
9
+ - id: check-added-large-files
10
+
11
+ - repo: https://github.com/astral-sh/ruff-pre-commit
12
+ rev: v0.3.3
13
+ hooks:
14
+ - id: ruff
15
+ types_or: [ python, pyi, jupyter ]
16
+ args: [ --fix ]
@@ -59,7 +59,7 @@ dependencies = [
59
59
 
60
60
  [[package]]
61
61
  name = "mergechannels"
62
- version = "0.1.0"
62
+ version = "0.1.2"
63
63
  dependencies = [
64
64
  "lazy_static",
65
65
  "ndarray",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "mergechannels"
3
- version = "0.1.0"
3
+ version = "0.1.2"
4
4
  edition = "2021"
5
5
 
6
6
  # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
18
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
21
+ SOFTWARE.
@@ -0,0 +1,115 @@
1
+ Metadata-Version: 2.4
2
+ Name: mergechannels
3
+ Version: 0.1.2
4
+ Classifier: Programming Language :: Rust
5
+ Classifier: Programming Language :: Python :: Implementation :: CPython
6
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.9
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Requires-Dist: numpy>1.25.0
15
+ License-File: LICENSE
16
+ License: MIT
17
+ Requires-Python: >=3.9, <=3.13
18
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
19
+
20
+ [![CI](https://github.com/zacswider/mergechannels/actions/workflows/CI.yml/badge.svg)](https://github.com/zacswider/mergechannels/actions/workflows/CI.yml)
21
+ ![PyPI - License](https://img.shields.io/pypi/l/mergechannels)
22
+ ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/mergechannels)
23
+ ![PyPI](https://img.shields.io/pypi/v/mergechannels)
24
+
25
+ # mergechannels
26
+
27
+ This project was originally conceived because I often find myself wanting to apply and blend colormaps to images while working from Python, and for historical reasons many of my favorite colormaps are distributed as [FIJI](https://imagej.net/software/fiji/) lookup tables. I also care about things likes speed and memory usage (e.g., not casting large arrays to floating point dtypes, not creating multiple whole arrays just to add them together), so I was interested in seeing if I could at least match matplotlib's colormapping performance with my own hand-rolled colorizer in Rust.
28
+
29
+
30
+
31
+ ## Installation
32
+
33
+ Install pre-compiled binaries from [PyPI](https://pypi.org/project/mergechannels/):
34
+ ```bash
35
+ pip install mergechannels
36
+ ```
37
+
38
+ Build from source on your own machine:
39
+ ```bash
40
+ pip install git+https://github.com/zacswider/mergechannels.git
41
+ ```
42
+
43
+ ## Usage
44
+ *NOTE*: scikit-image is not a dependency of this project, but is used in the examples below to fetch images.
45
+
46
+ ### colorize a single image
47
+
48
+ ```python
49
+ from skimage import data
50
+ import mergechannels as mc
51
+
52
+ img = data.camera()
53
+ colorized = mc.apply_color_map(img, 'Red/Green')
54
+ fig, axes = plt.subplots(1, 2, figsize=(6, 3), dpi=150)
55
+ for ax in axes: ax.axis('off')
56
+ (a, b) = axes
57
+ a.imshow(img, cmap='gray')
58
+ b.imshow(colorized)
59
+ plt.show()
60
+ print(colorized.shape, colorized.dtype)
61
+ >> (512, 512, 3) uint8
62
+ ```
63
+ ![colorize a single image](https://raw.githubusercontent.com/zacswider/README_Images/main/camera_red-green.png
64
+ )
65
+
66
+
67
+ ### apply a different colormap to each channel
68
+ ```python
69
+ from skimage import data
70
+ import matplotlib.pyplot as plt
71
+ import mergechannels as mc
72
+
73
+ cells, nuclei = data.cells3d().max(axis=0)
74
+ cells = to_uint8(cells) # normalize your own arrays, mergechannels doesn't currently handle this
75
+ nuclei = to_uint8(nuclei) # normalize your own arrays, mergechannels doesn't currently handle this
76
+
77
+ fig, axes = plt.subplots(2, 2, figsize=(6, 6), dpi=150)
78
+ for ax in axes.ravel(): ax.axis('off')
79
+ (a, b, c, d) = axes.ravel()
80
+ a.imshow(cells, cmap='gray')
81
+ b.imshow(nuclei, cmap='gray')
82
+ c.imshow(
83
+ mc.merge(
84
+ [cells, nuclei],
85
+ ['Orange Hot', 'Cyan Hot'], # maximum blending is the default
86
+ ),
87
+ )
88
+ d.imshow(
89
+ mc.merge(
90
+ [cells, nuclei],
91
+ ['I Blue', 'I Forest'],
92
+ blending='min', # use minimum blending with inverted colormaps
93
+ ),
94
+ )
95
+ fig.tight_layout()
96
+ plt.show()
97
+ ```
98
+ ![max and min multicolor blending](https://raw.githubusercontent.com/zacswider/README_Images/main/cells_multicolor.png)
99
+
100
+
101
+ ## Roadmap
102
+ mergechannels is currently incredibly simple. It can apply one or more colormaps to one or more 2D 8-bit images and that's it.
103
+ - Add support for any numerical dtype
104
+ - Add support for 3D images
105
+ - Add option to return any colormap as a matplotlib colormap
106
+ - Add support for directly passing matplotlib colormaps instead of colormap names
107
+ - Parallelize colormap application on large images (if it's helpful)
108
+ - Add option to overlay binary or instance masks onto colorized images
109
+
110
+ ## Acknowledgements
111
+
112
+ There are other great colormapping libraries available (e.g., [microfilm](https://github.com/guiwitz/microfilm), [cmap](https://github.com/pyapp-kit/cmap)) that are more feature-rich than this one, but which don't address my goals. My hope is that this project can fill an un-met niche and otherwise maintain full compatibility with these and similar libraries.
113
+
114
+ This project incorporates a number of colormaps that were hand-crafted by Christophe Leterrier and were originally distributed here under the MIT license: https://github.com/cleterrier/ChrisLUTs
115
+
@@ -0,0 +1,95 @@
1
+ [![CI](https://github.com/zacswider/mergechannels/actions/workflows/CI.yml/badge.svg)](https://github.com/zacswider/mergechannels/actions/workflows/CI.yml)
2
+ ![PyPI - License](https://img.shields.io/pypi/l/mergechannels)
3
+ ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/mergechannels)
4
+ ![PyPI](https://img.shields.io/pypi/v/mergechannels)
5
+
6
+ # mergechannels
7
+
8
+ This project was originally conceived because I often find myself wanting to apply and blend colormaps to images while working from Python, and for historical reasons many of my favorite colormaps are distributed as [FIJI](https://imagej.net/software/fiji/) lookup tables. I also care about things likes speed and memory usage (e.g., not casting large arrays to floating point dtypes, not creating multiple whole arrays just to add them together), so I was interested in seeing if I could at least match matplotlib's colormapping performance with my own hand-rolled colorizer in Rust.
9
+
10
+
11
+
12
+ ## Installation
13
+
14
+ Install pre-compiled binaries from [PyPI](https://pypi.org/project/mergechannels/):
15
+ ```bash
16
+ pip install mergechannels
17
+ ```
18
+
19
+ Build from source on your own machine:
20
+ ```bash
21
+ pip install git+https://github.com/zacswider/mergechannels.git
22
+ ```
23
+
24
+ ## Usage
25
+ *NOTE*: scikit-image is not a dependency of this project, but is used in the examples below to fetch images.
26
+
27
+ ### colorize a single image
28
+
29
+ ```python
30
+ from skimage import data
31
+ import mergechannels as mc
32
+
33
+ img = data.camera()
34
+ colorized = mc.apply_color_map(img, 'Red/Green')
35
+ fig, axes = plt.subplots(1, 2, figsize=(6, 3), dpi=150)
36
+ for ax in axes: ax.axis('off')
37
+ (a, b) = axes
38
+ a.imshow(img, cmap='gray')
39
+ b.imshow(colorized)
40
+ plt.show()
41
+ print(colorized.shape, colorized.dtype)
42
+ >> (512, 512, 3) uint8
43
+ ```
44
+ ![colorize a single image](https://raw.githubusercontent.com/zacswider/README_Images/main/camera_red-green.png
45
+ )
46
+
47
+
48
+ ### apply a different colormap to each channel
49
+ ```python
50
+ from skimage import data
51
+ import matplotlib.pyplot as plt
52
+ import mergechannels as mc
53
+
54
+ cells, nuclei = data.cells3d().max(axis=0)
55
+ cells = to_uint8(cells) # normalize your own arrays, mergechannels doesn't currently handle this
56
+ nuclei = to_uint8(nuclei) # normalize your own arrays, mergechannels doesn't currently handle this
57
+
58
+ fig, axes = plt.subplots(2, 2, figsize=(6, 6), dpi=150)
59
+ for ax in axes.ravel(): ax.axis('off')
60
+ (a, b, c, d) = axes.ravel()
61
+ a.imshow(cells, cmap='gray')
62
+ b.imshow(nuclei, cmap='gray')
63
+ c.imshow(
64
+ mc.merge(
65
+ [cells, nuclei],
66
+ ['Orange Hot', 'Cyan Hot'], # maximum blending is the default
67
+ ),
68
+ )
69
+ d.imshow(
70
+ mc.merge(
71
+ [cells, nuclei],
72
+ ['I Blue', 'I Forest'],
73
+ blending='min', # use minimum blending with inverted colormaps
74
+ ),
75
+ )
76
+ fig.tight_layout()
77
+ plt.show()
78
+ ```
79
+ ![max and min multicolor blending](https://raw.githubusercontent.com/zacswider/README_Images/main/cells_multicolor.png)
80
+
81
+
82
+ ## Roadmap
83
+ mergechannels is currently incredibly simple. It can apply one or more colormaps to one or more 2D 8-bit images and that's it.
84
+ - Add support for any numerical dtype
85
+ - Add support for 3D images
86
+ - Add option to return any colormap as a matplotlib colormap
87
+ - Add support for directly passing matplotlib colormaps instead of colormap names
88
+ - Parallelize colormap application on large images (if it's helpful)
89
+ - Add option to overlay binary or instance masks onto colorized images
90
+
91
+ ## Acknowledgements
92
+
93
+ There are other great colormapping libraries available (e.g., [microfilm](https://github.com/guiwitz/microfilm), [cmap](https://github.com/pyapp-kit/cmap)) that are more feature-rich than this one, but which don't address my goals. My hope is that this project can fill an un-met niche and otherwise maintain full compatibility with these and similar libraries.
94
+
95
+ This project incorporates a number of colormaps that were hand-crafted by Christophe Leterrier and were originally distributed here under the MIT license: https://github.com/cleterrier/ChrisLUTs
@@ -254,4 +254,4 @@ Index Red Green Blue
254
254
  252 133 7 2
255
255
  253 129 6 2
256
256
  254 126 5 2
257
- 255 122 4 3
257
+ 255 122 4 3
@@ -0,0 +1,33 @@
1
+ [build-system]
2
+ requires = ["maturin>=1.8,<2.0"]
3
+ build-backend = "maturin"
4
+
5
+ [project]
6
+ name = "mergechannels"
7
+ license = { text = "MIT" }
8
+ requires-python = ">=3.9, <=3.13"
9
+ classifiers = [
10
+ "Programming Language :: Rust",
11
+ "Programming Language :: Python :: Implementation :: CPython",
12
+ "Programming Language :: Python :: Implementation :: PyPy",
13
+ "License :: OSI Approved :: MIT License",
14
+ "Programming Language :: Python :: 3",
15
+ "Programming Language :: Python :: 3.9",
16
+ "Programming Language :: Python :: 3.10",
17
+ "Programming Language :: Python :: 3.11",
18
+ "Programming Language :: Python :: 3.12",
19
+ "Programming Language :: Python :: 3.13",
20
+ ]
21
+ dynamic = ["version"]
22
+ dependencies = ["numpy>1.25.0"]
23
+ [tool.maturin]
24
+ features = ["pyo3/extension-module"]
25
+ python-source = "python"
26
+
27
+ [dependency-groups]
28
+ dev = [
29
+ "matplotlib>=3.7.5",
30
+ "pre-commit>=3.5.0",
31
+ "pytest-benchmark>=4.0.0",
32
+ "pytest>=8.3.5",
33
+ ]
@@ -3,6 +3,9 @@ import mergechannels as mc
3
3
 
4
4
 
5
5
  def test_apply_color_map():
6
+ '''
7
+ Test that the color map is applied correctly
8
+ '''
6
9
  x = np.ones((1, 1), dtype=np.uint8)
7
10
  rgb = mc.apply_color_map(x, 'betterBlue')
8
11
  assert rgb.shape == (1,1,3)
@@ -23,6 +26,9 @@ def test_apply_color_map():
23
26
  )
24
27
 
25
28
  def test_apply_colors_and_merge_low_sum():
29
+ '''
30
+ Test that the colors are merged correctly with sum blending and low values
31
+ '''
26
32
  x = np.ones((1, 1), dtype=np.uint8)
27
33
  y = np.ones((1, 1), dtype=np.uint8)
28
34
  rgb_sum = mc.apply_colors_and_merge_nc([x, y], ['betterBlue', 'betterOrange'], 'sum')
@@ -36,6 +42,9 @@ def test_apply_colors_and_merge_low_sum():
36
42
  )
37
43
 
38
44
  def test_apply_colors_and_merge_high_sum():
45
+ '''
46
+ Test that the colors are merged correctly with sum blending and high values
47
+ '''
39
48
  x = np.ones((1, 1), dtype=np.uint8) * 255
40
49
  y = np.ones((1, 1), dtype=np.uint8) * 255
41
50
  rgb_sum = mc.apply_colors_and_merge_nc([x, y], ['betterBlue', 'betterOrange'], 'sum')
@@ -49,6 +58,9 @@ def test_apply_colors_and_merge_high_sum():
49
58
  )
50
59
 
51
60
  def test_apply_colors_and_merge_low_max():
61
+ '''
62
+ Test that the colors are merged correctly with max blending and low values
63
+ '''
52
64
  x = np.ones((1, 1), dtype=np.uint8)
53
65
  y = np.ones((1, 1), dtype=np.uint8)
54
66
  rgb_max = mc.apply_colors_and_merge_nc([x, y], ['betterBlue', 'betterOrange'], 'max')
@@ -62,6 +74,9 @@ def test_apply_colors_and_merge_low_max():
62
74
  )
63
75
 
64
76
  def test_apply_colors_and_merge_high_max():
77
+ '''
78
+ Test that the colors are merged correctly with max blending and high values
79
+ '''
65
80
  x = np.ones((1, 1), dtype=np.uint8) * 255
66
81
  y = np.ones((1, 1), dtype=np.uint8) * 255
67
82
  rgb_max = mc.apply_colors_and_merge_nc([x, y], ['betterBlue', 'betterOrange'], 'max')
@@ -75,6 +90,9 @@ def test_apply_colors_and_merge_high_max():
75
90
  )
76
91
 
77
92
  def test_apply_colors_and_merge_low_min():
93
+ '''
94
+ Test that the colors are merged correctly with min blending and low values
95
+ '''
78
96
  x = np.ones((1, 1), dtype=np.uint8)
79
97
  y = np.ones((1, 1), dtype=np.uint8)
80
98
  rgb_min = mc.apply_colors_and_merge_nc([x, y], ['betterBlue', 'betterOrange'], 'min')
@@ -88,6 +106,9 @@ def test_apply_colors_and_merge_low_min():
88
106
  )
89
107
 
90
108
  def test_apply_colors_and_merge_high_min():
109
+ '''
110
+ Test that the colors are merged correctly with min blending and high values
111
+ '''
91
112
  x = np.ones((1, 1), dtype=np.uint8) * 255
92
113
  y = np.ones((1, 1), dtype=np.uint8) * 255
93
114
  rgb_min = mc.apply_colors_and_merge_nc([x, y], ['betterBlue', 'betterOrange'], 'min')
@@ -101,6 +122,9 @@ def test_apply_colors_and_merge_high_min():
101
122
  )
102
123
 
103
124
  def test_apply_colors_and_merge_low_mean():
125
+ '''
126
+ Test that the colors are merged correctly with mean blending and low values
127
+ '''
104
128
  x = np.ones((1, 1), dtype=np.uint8)
105
129
  y = np.ones((1, 1), dtype=np.uint8)
106
130
  rgb_mean = mc.apply_colors_and_merge_nc([x, y], ['betterBlue', 'betterOrange'], 'mean')
@@ -116,6 +140,9 @@ def test_apply_colors_and_merge_low_mean():
116
140
  )
117
141
 
118
142
  def test_apply_colors_and_merge_high_mean():
143
+ '''
144
+ Test that the colors are merged correctly with mean blending and high values
145
+ '''
119
146
  x = np.ones((1, 1), dtype=np.uint8) * 255
120
147
  y = np.ones((1, 1), dtype=np.uint8) * 255
121
148
  rgb_mean = mc.apply_colors_and_merge_nc([x, y], ['betterBlue', 'betterOrange'], 'mean')
@@ -128,4 +155,4 @@ def test_apply_colors_and_merge_high_mean():
128
155
  np.array(
129
156
  [[[127, 168, 127]]]
130
157
  )
131
- )
158
+ )
@@ -2,12 +2,12 @@
2
2
  from .mergechannels import ( # type: ignore
3
3
  apply_color_map,
4
4
  apply_colors_and_merge_nc,
5
- )
5
+ )
6
6
 
7
7
  from ._internal import merge
8
8
 
9
9
  __all__ = [
10
- "apply_color_map",
11
- "apply_colors_and_merge_nc",
12
- "merge",
10
+ 'apply_color_map',
11
+ 'apply_colors_and_merge_nc',
12
+ 'merge',
13
13
  ]
@@ -9,13 +9,19 @@ def merge(
9
9
  arrs: Sequence[np.ndarray],
10
10
  colors: Sequence[COLORMAPS] = (),
11
11
  blending: Literal[BLENDING_OPTIONS] = 'max',
12
+ saturation_limits: tuple[float, float] = (0.2, 99.8),
12
13
  ) -> np.ndarray:
13
14
  ...
14
15
 
15
- def apply_color_map(arr: np.ndarray, cmap_name: COLORMAPS) -> np.ndarray: ...
16
+ def apply_color_map(
17
+ arr: np.ndarray,
18
+ cmap_name: COLORMAPS,
19
+ saturation_limits: tuple[float, float] = (0.2, 99.8),
20
+ ) -> np.ndarray: ...
16
21
 
17
22
  def apply_colors_and_merge_nc(
18
23
  arrs: Sequence[np.ndarray],
19
24
  colors: Sequence[COLORMAPS] = (),
20
25
  blending: Literal[BLENDING_OPTIONS] = 'max',
21
- ) -> np.ndarray: ...
26
+ saturation_limits: Sequence[tuple[float, float]] = (),
27
+ ) -> np.ndarray: ...
@@ -11,24 +11,16 @@ from ._blending import BLENDING_OPTIONS
11
11
 
12
12
  def merge(
13
13
  arrs: Sequence[np.ndarray],
14
- colors: Sequence[COLORMAPS] = (),
14
+ colors: Sequence[COLORMAPS],
15
15
  blending: BLENDING_OPTIONS = 'max',
16
16
  ) -> np.ndarray:
17
17
  '''
18
18
  apply cmaps to arrays and blend the colors
19
19
  '''
20
+ # region validation
20
21
  n_arrs = len(arrs)
21
22
  n_colors = len(colors)
22
- if n_arrs > 0 and n_colors == 0:
23
- arr_shapes = [arr.shape for arr in arrs]
24
- if not all([len(arr_shape) == 3 for arr_shape in arr_shapes]):
25
- raise ValueError(
26
- 'Expected a sequence of pre-colorized arrays, '
27
- f'got {n_arrs} arrays of shapes {arr_shapes}'
28
- )
29
- # call merge rgb arrs here
30
- return np.zeros((3,3))
31
- if not n_arrs == n_colors:
23
+ if not n_arrs == n_colors and n_arrs > 0:
32
24
  raise ValueError(
33
25
  'Expected an equal number of arrays to colorize and colormap names to apply. '
34
26
  f'Got {n_arrs} arrays and {n_colors} colors'
@@ -38,19 +30,18 @@ def merge(
38
30
  raise ValueError(
39
31
  f'Expected every array to have the same shape, got {arr_shapes}'
40
32
  )
41
- # call apply and merge rgb arrs here
42
- match n_arrs:
43
- case 1:
44
- return apply_color_map(arr=arrs[0], cmap_name=colors[0])
45
- case _:
46
- return apply_colors_and_merge_nc(arrs, colors, blending)
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
33
+ if not len(arr_shapes[0]) == 2:
34
+ raise ValueError(
35
+ f'Expected every array to be 2D, got {arr_shapes[0]}'
36
+ )
37
+ arr_dtypes = [arr.dtype for arr in arrs]
38
+ if not len(set(arr_dtypes)) == 1:
39
+ raise ValueError(
40
+ f'Expected every array to have the same dtype, got {arr_dtypes}'
41
+ )
42
+ # endregion
56
43
 
44
+ if n_arrs == 1:
45
+ return apply_color_map(arr=arrs[0], cmap_name=colors[0])
46
+ else:
47
+ return apply_colors_and_merge_nc(arrs, colors, blending)