igm-model 2.2.1__tar.gz → 2.2.3__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 (184) hide show
  1. {igm-model-2.2.1 → igm_model-2.2.3}/PKG-INFO +16 -5
  2. {igm-model-2.2.1 → igm_model-2.2.3}/README.md +1 -1
  3. {igm-model-2.2.1 → igm_model-2.2.3}/igm/__init__.py +3 -2
  4. {igm-model-2.2.1 → igm_model-2.2.3}/igm/common.py +120 -47
  5. igm_model-2.2.3/igm/emulators/pinnbp_10_4_cnn_8_16_2_1/model.h5 +0 -0
  6. igm_model-2.2.3/igm/emulators/pinnbp_10_4_cnn_8_16_3_1/model.h5 +0 -0
  7. igm_model-2.2.3/igm/emulators/pinnbp_10_4_cnn_8_32_2_1/fieldin.dat +5 -0
  8. igm_model-2.2.3/igm/emulators/pinnbp_10_4_cnn_8_32_2_1/fieldout.dat +2 -0
  9. igm_model-2.2.3/igm/emulators/pinnbp_10_4_unet_16_32_2_1/fieldin.dat +5 -0
  10. igm_model-2.2.3/igm/emulators/pinnbp_10_4_unet_16_32_2_1/fieldout.dat +2 -0
  11. igm_model-2.2.3/igm/emulators/pinnbp_10_4_unet_16_32_2_1/model.h5 +0 -0
  12. igm_model-2.2.3/igm/emulators/pinnbp_30_4_cnn_12_32_3_1/fieldin.dat +5 -0
  13. igm_model-2.2.3/igm/emulators/pinnbp_30_4_cnn_12_32_3_1/fieldout.dat +2 -0
  14. igm_model-2.2.3/igm/igm_help.py +30 -0
  15. {igm-model-2.2.1 → igm_model-2.2.3}/igm/igm_run.py +8 -1
  16. {igm-model-2.2.1 → igm_model-2.2.3}/igm/instructed_oggm.py +4 -2
  17. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/__init__.py +1 -0
  18. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/anim_plotly/anim_plotly.py +33 -63
  19. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/plot2d/plot2d.py +26 -17
  20. igm_model-2.2.3/igm/modules/postproc/print_info/print_info.py +65 -0
  21. igm_model-2.2.3/igm/modules/postproc/texture/__init__.py +1 -0
  22. igm_model-2.2.3/igm/modules/postproc/texture/constants.py +20 -0
  23. igm_model-2.2.3/igm/modules/postproc/texture/emulator.py +19 -0
  24. igm_model-2.2.3/igm/modules/postproc/texture/exporter.py +95 -0
  25. igm_model-2.2.3/igm/modules/postproc/texture/image_data.py +114 -0
  26. igm_model-2.2.3/igm/modules/postproc/texture/normalizer.py +53 -0
  27. igm_model-2.2.3/igm/modules/postproc/texture/pix2pixhd.py +48 -0
  28. igm_model-2.2.3/igm/modules/postproc/texture/preparer.py +59 -0
  29. igm_model-2.2.3/igm/modules/postproc/texture/texture.py +177 -0
  30. igm_model-2.2.3/igm/modules/postproc/texture/utils.py +16 -0
  31. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/write_ncdf/write_ncdf.py +3 -0
  32. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/write_particles/write_particles.py +11 -9
  33. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/write_tif/write_tif.py +5 -5
  34. igm_model-2.2.3/igm/modules/preproc/infersmb/__init__.py +6 -0
  35. {igm-model-2.2.1/igm/modules/preproc → igm_model-2.2.3/igm/modules/preproc/infersmb}/infersmb.py +13 -4
  36. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/preproc/load_ncdf/load_ncdf.py +25 -10
  37. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/preproc/load_tif/load_tif.py +12 -5
  38. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/preproc/oggm_shop/oggm_shop.py +257 -59
  39. igm_model-2.2.3/igm/modules/process/avalanche/__init__.py +6 -0
  40. igm_model-2.2.3/igm/modules/process/avalanche/avalanche.py +145 -0
  41. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/clim_oggm/clim_oggm.py +7 -4
  42. igm_model-2.2.3/igm/modules/process/enthalpy/__init__.py +6 -0
  43. igm_model-2.2.3/igm/modules/process/enthalpy/enthalpy.py +868 -0
  44. igm_model-2.2.3/igm/modules/process/gflex/__init__.py +6 -0
  45. igm_model-2.2.3/igm/modules/process/gflex/gflex.py +193 -0
  46. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/glerosion/glerosion.py +2 -2
  47. igm_model-2.2.3/igm/modules/process/iceflow/diagnostic.py +60 -0
  48. igm_model-2.2.3/igm/modules/process/iceflow/emulate.py +325 -0
  49. igm_model-2.2.3/igm/modules/process/iceflow/energy_iceflow.py +416 -0
  50. igm_model-2.2.3/igm/modules/process/iceflow/iceflow.py +132 -0
  51. igm_model-2.2.3/igm/modules/process/iceflow/neural_network.py +70 -0
  52. igm_model-2.2.3/igm/modules/process/iceflow/optimize.py +691 -0
  53. igm_model-2.2.3/igm/modules/process/iceflow/optimize_outputs.py +461 -0
  54. igm_model-2.2.3/igm/modules/process/iceflow/optimize_params_cook.py +358 -0
  55. igm_model-2.2.3/igm/modules/process/iceflow/params_iceflow.py +332 -0
  56. igm_model-2.2.3/igm/modules/process/iceflow/params_optimize.py +267 -0
  57. igm_model-2.2.3/igm/modules/process/iceflow/params_pretraining.py +80 -0
  58. {igm-model-2.2.1/igm/modules/preproc/pretraining → igm_model-2.2.3/igm/modules/process/iceflow}/pretraining.py +46 -121
  59. igm_model-2.2.3/igm/modules/process/iceflow/solve.py +151 -0
  60. igm_model-2.2.3/igm/modules/process/iceflow/utils.py +67 -0
  61. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/particles/particles.py +87 -52
  62. igm_model-2.2.3/igm/modules/process/read_output/__init__.py +6 -0
  63. {igm-model-2.2.1/igm/modules/process → igm_model-2.2.3/igm/modules/process/read_output}/read_output.py +4 -4
  64. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/smb_oggm/smb_oggm.py +7 -2
  65. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/thk/thk.py +9 -3
  66. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/time/time.py +6 -7
  67. igm_model-2.2.3/igm/modules/process/vert_flow/vert_flow.py +231 -0
  68. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/utils.py +56 -18
  69. {igm-model-2.2.1 → igm_model-2.2.3}/igm_model.egg-info/PKG-INFO +16 -5
  70. {igm-model-2.2.1 → igm_model-2.2.3}/igm_model.egg-info/SOURCES.txt +58 -7
  71. {igm-model-2.2.1 → igm_model-2.2.3}/igm_model.egg-info/entry_points.txt +1 -0
  72. {igm-model-2.2.1 → igm_model-2.2.3}/igm_model.egg-info/requires.txt +3 -2
  73. {igm-model-2.2.1 → igm_model-2.2.3}/setup.py +6 -5
  74. igm_model-2.2.3/tests/test_full_glacier_evolution_oggm_shop/__init__.py +2 -0
  75. igm_model-2.2.3/tests/test_full_glacier_evolution_oggm_shop/test_full_glacier_evolution_oggm_shop.py +44 -0
  76. igm_model-2.2.3/tests/test_full_glacier_evolution_synthetic/__init__.py +2 -0
  77. igm_model-2.2.3/tests/test_full_glacier_evolution_synthetic/make_synthetic.py +42 -0
  78. igm_model-2.2.3/tests/test_full_glacier_evolution_synthetic/test_full_glacier_evolution_synthetic.py +43 -0
  79. {igm-model-2.2.1/tests/test_params → igm_model-2.2.3/tests/test_iceflow}/__init__.py +0 -0
  80. igm_model-2.2.3/tests/test_iceflow/test_iceflow.py +39 -0
  81. igm_model-2.2.3/tests/test_load_ncdf/__init__.py +2 -0
  82. igm_model-2.2.3/tests/test_load_ncdf/make_fake_ncdf.py +43 -0
  83. igm_model-2.2.3/tests/test_load_ncdf/test_load_ncdf.py +39 -0
  84. igm_model-2.2.3/tests/test_optimize/__init__.py +2 -0
  85. igm_model-2.2.3/tests/test_optimize/test_optimize.py +41 -0
  86. igm_model-2.2.3/tests/test_params/__init__.py +0 -0
  87. {igm-model-2.2.1 → igm_model-2.2.3}/tests/test_params/test_params.py +32 -1
  88. igm_model-2.2.3/tests/test_vert_flow/__init__.py +0 -0
  89. igm_model-2.2.3/tests/test_vert_flow/test_vert_flow.py +37 -0
  90. igm-model-2.2.1/igm/modules/postproc/print_info/print_info.py +0 -40
  91. igm-model-2.2.1/igm/modules/preproc/optimize/__init__.py +0 -8
  92. igm-model-2.2.1/igm/modules/preproc/optimize/optimize.py +0 -1144
  93. igm-model-2.2.1/igm/modules/preproc/pretraining/__init__.py +0 -6
  94. igm-model-2.2.1/igm/modules/process/iceflow/iceflow.py +0 -1292
  95. igm-model-2.2.1/igm/modules/process/vert_flow/vert_flow.py +0 -146
  96. {igm-model-2.2.1 → igm_model-2.2.3}/LICENSE +0 -0
  97. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/f15_cfsflow_GJ_22_a/100/fieldin.dat +0 -0
  98. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/f15_cfsflow_GJ_22_a/100/fieldout.dat +0 -0
  99. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/f15_cfsflow_GJ_22_a/100/model.h5 +0 -0
  100. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/f15_cfsflow_GJ_22_a/200/fieldin.dat +0 -0
  101. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/f15_cfsflow_GJ_22_a/200/fieldout.dat +0 -0
  102. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/f15_cfsflow_GJ_22_a/200/model.h5 +0 -0
  103. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/f15_cfsflow_GJ_22_a/50/fieldin.dat +0 -0
  104. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/f15_cfsflow_GJ_22_a/50/fieldout.dat +0 -0
  105. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/f15_cfsflow_GJ_22_a/50/model.h5 +0 -0
  106. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/f15_cfsflow_GJ_22_a/README.md +0 -0
  107. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/pinnbp_10_4_cnn_16_16_3_1/fieldin.dat +0 -0
  108. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/pinnbp_10_4_cnn_16_16_3_1/fieldout.dat +0 -0
  109. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/pinnbp_10_4_cnn_16_16_3_1/model.h5 +0 -0
  110. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/pinnbp_10_4_cnn_16_32_2_0/fieldin.dat +0 -0
  111. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/pinnbp_10_4_cnn_16_32_2_0/fieldout.dat +0 -0
  112. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/pinnbp_10_4_cnn_16_32_2_0/model.h5 +0 -0
  113. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/pinnbp_10_4_cnn_16_32_2_1/fieldin.dat +0 -0
  114. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/pinnbp_10_4_cnn_16_32_2_1/fieldout.dat +0 -0
  115. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/pinnbp_10_4_cnn_16_32_2_1/model.h5 +0 -0
  116. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/pinnbp_10_4_cnn_16_32_3_0/fieldin.dat +0 -0
  117. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/pinnbp_10_4_cnn_16_32_3_0/fieldout.dat +0 -0
  118. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/pinnbp_10_4_cnn_16_32_3_0/model.h5 +0 -0
  119. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/pinnbp_10_4_cnn_16_32_3_1/fieldin.dat +0 -0
  120. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/pinnbp_10_4_cnn_16_32_3_1/fieldout.dat +0 -0
  121. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/pinnbp_10_4_cnn_16_32_3_1/model.h5 +0 -0
  122. {igm-model-2.2.1/igm/emulators/pinnbp_10_4_cnn_8_32_2_0 → igm_model-2.2.3/igm/emulators/pinnbp_10_4_cnn_8_16_2_1}/fieldin.dat +0 -0
  123. {igm-model-2.2.1/igm/emulators/pinnbp_10_4_cnn_8_32_2_0 → igm_model-2.2.3/igm/emulators/pinnbp_10_4_cnn_8_16_2_1}/fieldout.dat +0 -0
  124. {igm-model-2.2.1/igm/emulators/pinnbp_10_4_cnn_8_32_2_1 → igm_model-2.2.3/igm/emulators/pinnbp_10_4_cnn_8_16_3_1}/fieldin.dat +0 -0
  125. {igm-model-2.2.1/igm/emulators/pinnbp_10_4_cnn_8_32_2_1 → igm_model-2.2.3/igm/emulators/pinnbp_10_4_cnn_8_16_3_1}/fieldout.dat +0 -0
  126. {igm-model-2.2.1/igm/emulators/pinnbp_30_4_cnn_12_32_3_1 → igm_model-2.2.3/igm/emulators/pinnbp_10_4_cnn_8_32_2_0}/fieldin.dat +0 -0
  127. {igm-model-2.2.1/igm/emulators/pinnbp_30_4_cnn_12_32_3_1 → igm_model-2.2.3/igm/emulators/pinnbp_10_4_cnn_8_32_2_0}/fieldout.dat +0 -0
  128. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/pinnbp_10_4_cnn_8_32_2_0/model.h5 +0 -0
  129. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/pinnbp_10_4_cnn_8_32_2_1/model.h5 +0 -0
  130. {igm-model-2.2.1 → igm_model-2.2.3}/igm/emulators/pinnbp_30_4_cnn_12_32_3_1/model.h5 +0 -0
  131. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/__init__.py +0 -0
  132. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/anim_mayavi/__init__.py +0 -0
  133. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/anim_mayavi/anim_mayavi.py +0 -0
  134. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/anim_plotly/__init__.py +0 -0
  135. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/anim_video/__init__.py +0 -0
  136. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/anim_video/anim_video.py +0 -0
  137. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/plot2d/__init__.py +0 -0
  138. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/print_comp/__init__.py +0 -0
  139. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/print_comp/print_comp.py +0 -0
  140. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/print_info/__init__.py +0 -0
  141. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/write_ncdf/__init__.py +0 -0
  142. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/write_particles/__init__.py +0 -0
  143. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/write_tif/__init__.py +0 -0
  144. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/write_ts/__init__.py +0 -0
  145. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/postproc/write_ts/write_ts.py +0 -0
  146. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/preproc/__init__.py +0 -0
  147. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/preproc/include_icemask/__init__.py +0 -0
  148. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/preproc/include_icemask/include_icemask.py +0 -0
  149. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/preproc/load_ncdf/__init__.py +0 -0
  150. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/preproc/load_tif/__init__.py +0 -0
  151. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/preproc/oggm_shop/__init__.py +0 -0
  152. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/preproc/optimize_v1/__init__.py +0 -0
  153. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/preproc/optimize_v1/optimize_v1.py +0 -0
  154. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/__init__.py +0 -0
  155. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/clim_oggm/__init__.py +0 -0
  156. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/flow_dt_thk/__init__.py +0 -0
  157. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/flow_dt_thk/flow_dt_thk.py +0 -0
  158. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/glerosion/__init__.py +0 -0
  159. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/iceflow/__init__.py +0 -0
  160. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/iceflow_v1/__init__.py +0 -0
  161. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/iceflow_v1/iceflow_v1.py +0 -0
  162. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/particles/__init__.py +0 -0
  163. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/particles_v1/__init__.py +0 -0
  164. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/particles_v1/particles_v1.py +0 -0
  165. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/rockflow/__init__.py +0 -0
  166. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/rockflow/rockflow.py +0 -0
  167. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/smb_oggm/__init__.py +0 -0
  168. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/smb_simple/__init__.py +0 -0
  169. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/smb_simple/smb_simple.py +0 -0
  170. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/thk/__init__.py +0 -0
  171. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/time/__init__.py +0 -0
  172. {igm-model-2.2.1 → igm_model-2.2.3}/igm/modules/process/vert_flow/__init__.py +0 -0
  173. {igm-model-2.2.1 → igm_model-2.2.3}/igm_model.egg-info/dependency_links.txt +0 -0
  174. {igm-model-2.2.1 → igm_model-2.2.3}/igm_model.egg-info/top_level.txt +0 -0
  175. {igm-model-2.2.1 → igm_model-2.2.3}/setup.cfg +0 -0
  176. {igm-model-2.2.1 → igm_model-2.2.3}/tests/__init__.py +0 -0
  177. {igm-model-2.2.1 → igm_model-2.2.3}/tests/test_modules/__init__.py +0 -0
  178. {igm-model-2.2.1 → igm_model-2.2.3}/tests/test_modules/invalid_custom_module_folder/__init__.py +0 -0
  179. {igm-model-2.2.1 → igm_model-2.2.3}/tests/test_modules/invalid_custom_module_folder/invalid_custom_module.py +0 -0
  180. {igm-model-2.2.1 → igm_model-2.2.3}/tests/test_modules/missing_function_custom_module.py +0 -0
  181. {igm-model-2.2.1 → igm_model-2.2.3}/tests/test_modules/test_loading_modules.py +0 -0
  182. {igm-model-2.2.1 → igm_model-2.2.3}/tests/test_modules/valid_custom_module.py +0 -0
  183. {igm-model-2.2.1 → igm_model-2.2.3}/tests/test_modules/valid_custom_module_folder/__init__.py +0 -0
  184. {igm-model-2.2.1 → igm_model-2.2.3}/tests/test_modules/valid_custom_module_folder/valid_custom_module.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: igm-model
3
- Version: 2.2.1
3
+ Version: 2.2.3
4
4
  Summary: IGM - a glacier evolution model
5
5
  Home-page: https://github.com/jouvetg/igm
6
6
  Author: Guillaume Jouvet
@@ -9,17 +9,28 @@ License: gpl-3.0
9
9
  Requires-Python: <3.11
10
10
  Description-Content-Type: text/markdown
11
11
  License-File: LICENSE
12
- Requires-Dist: tensorflow[and-cuda]==2.14.0
12
+ Requires-Dist: tensorflow[and-cuda]==2.15.1
13
13
  Requires-Dist: matplotlib
14
14
  Requires-Dist: scipy
15
- Requires-Dist: netCDF4
15
+ Requires-Dist: netCDF4==1.6.0
16
16
  Requires-Dist: xarray
17
17
  Requires-Dist: rasterio
18
18
  Requires-Dist: pyproj
19
19
  Requires-Dist: geopandas
20
20
  Requires-Dist: oggm
21
21
  Requires-Dist: salem
22
+ Requires-Dist: pyyaml
22
23
  Requires-Dist: importlib_resources
24
+ Dynamic: author
25
+ Dynamic: author-email
26
+ Dynamic: description
27
+ Dynamic: description-content-type
28
+ Dynamic: home-page
29
+ Dynamic: license
30
+ Dynamic: license-file
31
+ Dynamic: requires-dist
32
+ Dynamic: requires-python
33
+ Dynamic: summary
23
34
 
24
35
  [![License badge](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
25
36
  ### <h1 align="center" id="title">The Instructed Glacier Model (IGM) </h1>
@@ -43,7 +54,7 @@ The Instructed Glacier Model (IGM) is an **open-source Python package**, which p
43
54
 
44
55
  # Documentation
45
56
 
46
- Start with the 10-min [video tutorial](https://vimeo.com/884003820). Then, all the documentation can be found on the dedicated [wiki](https://github.com/jouvetg/igm/wiki) and the the in-progress and open-to-contributions [technical paper](https://github.com/jouvetg/igm-paper/paper.pdf).
57
+ Start with the 10-min [video tutorial](https://vimeo.com/884003820). Then, all the documentation can be found on the dedicated [wiki](https://github.com/jouvetg/igm/wiki) and the the in-progress and open-to-contributions [technical paper](https://github.com/jouvetg/igm-paper/blob/main/paper.pdf).
47
58
 
48
59
  # Discord channel
49
60
 
@@ -20,7 +20,7 @@ The Instructed Glacier Model (IGM) is an **open-source Python package**, which p
20
20
 
21
21
  # Documentation
22
22
 
23
- Start with the 10-min [video tutorial](https://vimeo.com/884003820). Then, all the documentation can be found on the dedicated [wiki](https://github.com/jouvetg/igm/wiki) and the the in-progress and open-to-contributions [technical paper](https://github.com/jouvetg/igm-paper/paper.pdf).
23
+ Start with the 10-min [video tutorial](https://vimeo.com/884003820). Then, all the documentation can be found on the dedicated [wiki](https://github.com/jouvetg/igm/wiki) and the the in-progress and open-to-contributions [technical paper](https://github.com/jouvetg/igm-paper/blob/main/paper.pdf).
24
24
 
25
25
  # Discord channel
26
26
 
@@ -15,7 +15,7 @@ from .common import (
15
15
  load_modules,
16
16
  add_logger,
17
17
  print_params,
18
- load_dependent_modules,
18
+ # load_dependent_modules,
19
19
  get_modules_list,
20
20
  load_user_defined_params,
21
21
  run_intializers,
@@ -24,5 +24,6 @@ from .common import (
24
24
  setup_igm_modules,
25
25
  setup_igm_params,
26
26
  add_logger,
27
- print_gpu_info
27
+ print_gpu_info,
28
+ download_unzip_and_store
28
29
  )
@@ -23,9 +23,8 @@ import igm
23
23
 
24
24
  IGM_DESCRIPTION = r"""
25
25
  ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
26
- Welcome to IGM! The Iceflow Glacier Model (IGM) is a modular, open-source, and user-friendly glacier model.
27
- It is designed to be used in a variety of applications, including glacier evolution, ice flow, and ice
28
- │ dynamics. │
26
+ Welcome to IGM, a modular, open-source, fast, and user-friendly glacier evolution model!
27
+
29
28
  │ │
30
29
  │ __/\\\\\\\\\\\_____/\\\\\\\\\\\\__/\\\\____________/\\\\_ │
31
30
  │ _\/////\\\///____/\\\//////////__\/\\\\\\________/\\\\\\_ │
@@ -118,6 +117,18 @@ def params_core() -> argparse.ArgumentParser:
118
117
  default="params_saved",
119
118
  help="Name of the file to store the parameters used in the run (default: %(default)s)",
120
119
  )
120
+ parser.add_argument(
121
+ "--url_data",
122
+ type=str,
123
+ default="",
124
+ help="The URL of the ZIP file to download and unzip (default: %(default)s)",
125
+ )
126
+ parser.add_argument(
127
+ "--folder_data",
128
+ type=str,
129
+ default="data",
130
+ help="The name of the folder where are stored the data (default: %(default)s)",
131
+ )
121
132
 
122
133
  return parser
123
134
 
@@ -126,7 +137,7 @@ def setup_igm_modules(params: Namespace) -> List[ModuleType]:
126
137
 
127
138
  modules_dict = get_modules_list(params.param_file)
128
139
  imported_modules = load_modules(modules_dict)
129
- imported_modules = load_dependent_modules(imported_modules)
140
+ # imported_modules = load_dependent_modules(imported_modules) this is no more in used
130
141
 
131
142
  return imported_modules
132
143
 
@@ -207,14 +218,29 @@ def load_json_file(
207
218
  dic_params = json.loads(json_text)
208
219
  return dic_params
209
220
 
221
+ import yaml
222
+ def load_yaml_file(
223
+ param_file: str
224
+ ) -> Dict[str, Any]:
225
+ with open(param_file, "r") as file:
226
+ dic_params = yaml.safe_load(file)
227
+
228
+ return dic_params
229
+
210
230
 
211
231
  def get_modules_list(params_path: str) -> dict[str, List[str]]:
212
232
  try:
213
- with open(params_path) as f:
214
- # params_dict = json.load(f) #re-instate if you want to enforce no comments in the json file(remove all the lines that load the clean json in this case...)
215
- json_text = f.read()
216
- json_cleaned = remove_comments(json_text)
217
- params_dict = json.loads(json_cleaned)
233
+ with open(params_path, "r") as file:
234
+ if params_path.endswith(".json"):
235
+ json_text = file.read()
236
+ json_cleaned = remove_comments(json_text)
237
+ params_dict = json.loads(json_cleaned)
238
+ elif params_path.endswith(".yaml") or params_path.endswith(".yml"):
239
+ params_dict = yaml.safe_load(file)
240
+ else:
241
+ raise ValueError(
242
+ f"File type not supported. Please use a .json or .yaml file."
243
+ )
218
244
  module_dict = {
219
245
  "modules_preproc": params_dict["modules_preproc"],
220
246
  "modules_process": params_dict["modules_process"],
@@ -228,11 +254,21 @@ def get_modules_list(params_path: str) -> dict[str, List[str]]:
228
254
  doc=e.doc,
229
255
  pos=e.pos,
230
256
  )
257
+ # Create a custom error message for the YAML file (using yaml.YAMLError base exception)
231
258
 
232
259
 
233
260
  def load_user_defined_params(param_file: str, params_dict: dict[str, Any]):
261
+ if param_file.endswith(".json"):
262
+ loading_function = load_json_file
263
+ elif param_file.endswith(".yaml") or param_file.endswith(".yml"):
264
+ loading_function = load_yaml_file
265
+ else:
266
+ raise ValueError(
267
+ f"File type not supported. Please use a .json or .yaml file."
268
+ )
234
269
  try:
235
- json_defined_params = load_json_file(param_file=param_file)
270
+ json_defined_params = loading_function(param_file=param_file)
271
+
236
272
  except JSONDecodeError as e:
237
273
  raise JSONDecodeError(
238
274
  msg=f"Error decoding JSON: Please make sure your file path is correct or your json is properly formatted.",
@@ -273,7 +309,7 @@ def load_modules(modules_dict: Dict) -> List[ModuleType]:
273
309
  return (
274
310
  imported_preproc_modules
275
311
  + imported_process_modules
276
- + imported_postproc_modules # + imported_custom_modules
312
+ + imported_postproc_modules # + imported_custom_modules ? (see above)
277
313
  )
278
314
 
279
315
 
@@ -304,7 +340,10 @@ def load_modules_from_directory(
304
340
  logging.info(
305
341
  f"Trying to import custom module from current working directory (folder or .py): {module_name}"
306
342
  )
307
- module = importlib.import_module(module_name)
343
+ try:
344
+ module = importlib.import_module(module_name)
345
+ except ModuleNotFoundError:
346
+ module = importlib.import_module("modules_custom." + module_name)
308
347
  except ModuleNotFoundError:
309
348
  raise ModuleNotFoundError(
310
349
  f"Can not find module {module_name}. Make sure it is either in the 1) {Path(igm.__file__).parent}/modules/{module_folder} directory or 2) in your current working directory."
@@ -316,41 +355,41 @@ def load_modules_from_directory(
316
355
  return imported_modules
317
356
 
318
357
 
319
- def has_dependencies(module: Any) -> bool:
320
- if hasattr(module, "dependencies"):
321
- return True
322
- return False
323
-
324
-
325
- def load_dependent_modules(imported_modules: List) -> List[ModuleType]:
326
- imported_dependencies = set()
327
- for module in imported_modules:
328
- if has_dependencies(module):
329
- module_dependencies = module.dependencies
330
- directories_to_search = [
331
- "preproc",
332
- "process",
333
- "postproc",
334
- ] # will also check current working directory if any of them fail
335
- load_modules_partial = partial(
336
- load_modules_from_directory, module_dependencies
337
- )
338
- for directory in directories_to_search:
339
- try:
340
- dependent_module = load_modules_partial(module_folder=directory)
341
- imported_dependencies.add(
342
- dependent_module[0]
343
- ) # [0] because it returns a singleton list
344
- logging.info(
345
- f"Found dependencies in directory {directory} or current working directory. Checking next module for dependencies."
346
- )
347
- break
348
- except ModuleNotFoundError:
349
- logging.info(
350
- f"Could not find dependencies in directory {directory} or current working directory. Checking next IGM directory."
351
- )
352
-
353
- return imported_modules + list(imported_dependencies)
358
+ # def has_dependencies(module: Any) -> bool:
359
+ # if hasattr(module, "dependencies"):
360
+ # return True
361
+ # return False
362
+
363
+
364
+ # def load_dependent_modules(imported_modules: List) -> List[ModuleType]:
365
+ # imported_dependencies = set()
366
+ # for module in imported_modules:
367
+ # if has_dependencies(module):
368
+ # module_dependencies = module.dependencies
369
+ # directories_to_search = [
370
+ # "preproc",
371
+ # "process",
372
+ # "postproc",
373
+ # ] # will also check current working directory if any of them fail
374
+ # load_modules_partial = partial(
375
+ # load_modules_from_directory, module_dependencies
376
+ # )
377
+ # for directory in directories_to_search:
378
+ # try:
379
+ # dependent_module = load_modules_partial(module_folder=directory)
380
+ # imported_dependencies.add(
381
+ # dependent_module[0]
382
+ # ) # [0] because it returns a singleton list
383
+ # logging.info(
384
+ # f"Found dependencies in directory {directory} or current working directory. Checking next module for dependencies."
385
+ # )
386
+ # break
387
+ # except ModuleNotFoundError:
388
+ # logging.info(
389
+ # f"Could not find dependencies in directory {directory} or current working directory. Checking next IGM directory."
390
+ # )
391
+
392
+ # return imported_modules + list(imported_dependencies)
354
393
 
355
394
 
356
395
  def print_gpu_info() -> None:
@@ -378,3 +417,37 @@ def print_params(params: Namespace) -> None:
378
417
  json.dump(params.__dict__, json_file, indent=2)
379
418
 
380
419
  os.system("echo rm " + param_file + " >> clean.sh")
420
+
421
+
422
+ def download_unzip_and_store(url, folder_name='data') -> None:
423
+ """
424
+ Use wget to download a ZIP file and unzip its contents to a specified folder.
425
+
426
+ Args:
427
+ - url (str): The URL of the ZIP file to download.
428
+ - folder_name (str): The name of the folder where the ZIP file's contents will be extracted.
429
+ """
430
+
431
+ import subprocess
432
+ import os
433
+ import zipfile
434
+
435
+ # Ensure the destination folder exists
436
+ if not os.path.exists(folder_name):
437
+ os.makedirs(folder_name)
438
+
439
+ # Download the file with wget
440
+ print("Downloading the ZIP file with wget...")
441
+ subprocess.run(['wget', '-O', 'downloaded_file.zip', url])
442
+
443
+ # Unzipping the file
444
+ print("Unzipping the file...")
445
+ with zipfile.ZipFile('downloaded_file.zip', 'r') as zip_ref:
446
+ zip_ref.extractall(folder_name)
447
+
448
+ # Clean up (delete) the zip file after extraction
449
+ os.remove('downloaded_file.zip')
450
+ print(f"File successfully downloaded and extracted to '{folder_name}'")
451
+
452
+ else:
453
+ print(f"The data already existing at '{folder_name}'")
@@ -0,0 +1,5 @@
1
+ thk
2
+ usurf
3
+ arrhenius
4
+ slidingco
5
+ dX
@@ -0,0 +1,5 @@
1
+ thk
2
+ usurf
3
+ arrhenius
4
+ slidingco
5
+ dX
@@ -0,0 +1,5 @@
1
+ thk
2
+ usurf
3
+ arrhenius
4
+ slidingco
5
+ dX
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env python3
2
+
3
+ # Copyright (C) 2021-2023 Guillaume Jouvet <guillaume.jouvet@unil.ch>
4
+ # Published under the GNU GPL (Version 3), check at the LICENSE file
5
+
6
+ import tensorflow as tf
7
+ import sys
8
+ from igm import (
9
+ State,
10
+ params_core,
11
+ setup_igm_modules,
12
+ setup_igm_params
13
+ )
14
+
15
+
16
+ def main() -> None:
17
+
18
+ parser = params_core()
19
+ params = State()
20
+ params.param_file = parser.get_default('param_file')
21
+ imported_modules = setup_igm_modules(params)
22
+ params = setup_igm_params(parser, imported_modules)
23
+
24
+ # Check if no arguments were provided
25
+ if len(sys.argv) == 1:
26
+ parser.print_help()
27
+ sys.exit(1) # Exit after displaying the help
28
+
29
+ if __name__ == "__main__":
30
+ main()
@@ -3,6 +3,7 @@
3
3
  # Copyright (C) 2021-2023 Guillaume Jouvet <guillaume.jouvet@unil.ch>
4
4
  # Published under the GNU GPL (Version 3), check at the LICENSE file
5
5
 
6
+ import os
6
7
  import tensorflow as tf
7
8
  from igm import (
8
9
  State,
@@ -14,7 +15,8 @@ from igm import (
14
15
  setup_igm_modules,
15
16
  setup_igm_params,
16
17
  print_gpu_info,
17
- add_logger
18
+ add_logger,
19
+ download_unzip_and_store
18
20
  )
19
21
 
20
22
 
@@ -35,6 +37,11 @@ def main() -> None:
35
37
 
36
38
  if params.print_params:
37
39
  print_params(params=params)
40
+
41
+ if not params.url_data=="":
42
+ download_unzip_and_store(params.url_data,params.folder_data)
43
+
44
+ os.environ["CUDA_VISIBLE_DEVICES"] = str(params.gpu_id)
38
45
 
39
46
  # Place the computation on your device GPU ('/GPU:0') or CPU ('/CPU:0')
40
47
  with tf.device(f"/GPU:{params.gpu_id}"): # type: ignore for linting checks
@@ -80,8 +80,10 @@ class IGM_Model2D(Model2D):
80
80
  parser = igm.params_core()
81
81
 
82
82
  params, __ = parser.parse_known_args() # args=[] add this for jupyter notebook
83
+
84
+ modules_dict = { "modules_preproc": [ ], "modules_process": ["iceflow"], "modules_postproc": [ ] }
83
85
 
84
- imported_modules = igm.load_modules(params)
86
+ imported_modules = igm.load_modules(modules_dict)
85
87
 
86
88
  for module in imported_modules:
87
89
  module.params(parser)
@@ -109,7 +111,7 @@ class IGM_Model2D(Model2D):
109
111
  self.state.arrhenius = (
110
112
  tf.ones_like(self.state.thk) * cfg.PARAMS["glen_a"] * SEC_IN_YEAR * 1e18
111
113
  )
112
- self.state.slidingco = tf.ones_like(self.state.thk) * 10000
114
+ self.state.slidingco = tf.ones_like(self.state.thk) * 0.045
113
115
  self.state.dX = tf.ones_like(self.state.thk) * self.dx
114
116
 
115
117
  self.state.x = tf.constant(self.x)
@@ -2,3 +2,4 @@
2
2
 
3
3
  # Copyright (C) 2021-2023 Guillaume Jouvet <guillaume.jouvet@unil.ch>
4
4
  # Published under the GNU GPL (Version 3), check at the LICENSE file
5
+
@@ -1,10 +1,7 @@
1
1
  #!/usr/bin/env python3
2
2
  import copy
3
-
4
3
  import numpy as np
5
- import os
6
4
  import json
7
- from types import SimpleNamespace
8
5
  import xarray as xr
9
6
 
10
7
 
@@ -45,45 +42,11 @@ def finalize(params, state):
45
42
  ],
46
43
  style={"margin-bottom": "10px"},
47
44
  ),
48
- # slider for camera-position in x-y-plane
49
- html.Div(
50
- dcc.Slider(
51
- id="camera_angle",
52
- step=9,
53
- value=45,
54
- min=0,
55
- max=180,
56
- marks=None,
57
- drag_value=45,
58
- included=False,
59
- )
60
- ),
45
+
61
46
  # 3D surface plot
62
47
  dcc.Graph(id="mnt_surface", figure=fig),
63
48
  ],
64
- style={"width": "95%", "height": "800px", "display": "inline-block"},
65
- ),
66
- # slider for camera-position on z-axis
67
- html.Div(
68
- children=[
69
- dcc.Slider(
70
- id="camera_height",
71
- step=0.2,
72
- value=1.5,
73
- min=0,
74
- max=2,
75
- vertical=True,
76
- drag_value=1.5,
77
- marks=None,
78
- verticalHeight=600,
79
- included=False,
80
- )
81
- ],
82
- style={
83
- "width": "5%",
84
- "display": "inline-block",
85
- "text_align": "center",
86
- },
49
+ style={"width": "100%", "height": "800px", "display": "inline-block"},
87
50
  ),
88
51
  ],
89
52
  style={
@@ -96,18 +59,11 @@ def finalize(params, state):
96
59
  @app.callback(
97
60
  Output("mnt_surface", "figure"),
98
61
  Input("property", "value"),
99
- Input("camera_angle", "drag_value"),
100
- Input("camera_height", "drag_value"),
101
62
  )
102
- def updata_graph(property, camera_angle, camera_height):
103
- # load params
104
- path_to_json_saved = "params_saved.json"
105
- with open(path_to_json_saved, "r") as json_file:
106
- json_text = json_file.read()
107
- params = json.loads(json_text, object_hook=lambda d: SimpleNamespace(**d))
108
-
63
+ def updata_graph(property):
109
64
  # read output.nc
110
- ds = xr.open_dataset("output.nc", engine="netcdf4")
65
+ output_file = params.wncd_output_file
66
+ ds = xr.open_dataset(output_file, engine="netcdf4")
111
67
 
112
68
  # get attributes from ds
113
69
  bedrock = np.array(ds.topg[0])
@@ -204,7 +160,7 @@ def finalize(params, state):
204
160
  z=bedrock_border,
205
161
  x=lat_range,
206
162
  y=lon_range,
207
- colorscale='speed_r',
163
+ colorscale='gray',
208
164
  opacity=1,
209
165
  showlegend=True,
210
166
  name="bedrock",
@@ -261,40 +217,35 @@ def finalize(params, state):
261
217
  ratio_z = (max_bedrock - min_bedrock) / (bedrock.shape[0] * resolution)
262
218
  ratio_z *= 2 # emphasize z-axis to make mountians look twice as steep
263
219
 
264
- # transform angle[0-180] into values between [0, 1] for camera postion
265
- radians = math.radians(camera_angle - 180)
266
- camera_x = math.sin(-radians)
267
- camera_y = math.cos(-radians)
268
-
269
220
  fig_dict = dict(
270
221
  data=frames[0]["data"],
271
222
  frames=frames,
272
223
  layout=dict( # width=1800,
273
- height=800,
224
+ height=900,
274
225
  margin=dict(l=0, r=0, t=30, b=0),
275
226
  sliders=[sliders_dict],
276
227
  title=title,
277
228
  font=dict(family="monospace"),
278
229
  legend={"orientation": "h", "yanchor": "bottom", "xanchor": "left"},
279
230
  scene=dict(
280
- zaxis=dict(showbackground=True, showticklabels=False, title=""),
231
+ zaxis=dict(showbackground=False, showticklabels=False, title=""),
281
232
  xaxis=dict(
282
233
  showbackground=False,
283
- showticklabels=True,
234
+ showticklabels=False,
284
235
  visible=True,
285
236
  range=[lat_range[0], lat_range[-1]],
286
- title="Longitude",
237
+ title=""#"Longitude",
287
238
  ),
288
239
  yaxis=dict(
289
240
  showbackground=False,
290
- showticklabels=True,
241
+ showticklabels=False,
291
242
  visible=True,
292
243
  range=[lon_range[0], lon_range[-1]],
293
- title="Latitude",
244
+ title=""#"Latitude",
245
+
294
246
  ),
295
247
  ),
296
248
  scene_aspectratio=dict(x=1, y=ratio_y, z=ratio_z),
297
- scene_camera_eye=dict(x=camera_x, y=camera_y, z=camera_height),
298
249
  updatemenus=[
299
250
  dict(
300
251
  buttons=[
@@ -347,4 +298,23 @@ def finalize(params, state):
347
298
 
348
299
 
349
300
  if __name__ == "__main__":
350
- finalize_anim_plotly(None, None)
301
+ import argparse
302
+ # Set up argument parser
303
+ parser = argparse.ArgumentParser(description="Load a JSON file and pass its content to finalize.")
304
+ parser.add_argument('--param_file',
305
+ type=str,
306
+ default='params_saved.json',
307
+ help='Path to the JSON parameter file')
308
+
309
+ # Parse the command-line arguments
310
+ args = parser.parse_args()
311
+
312
+ # Load the JSON file
313
+ with open(args.param_file, 'r') as f:
314
+ param_dict = json.load(f)
315
+
316
+ # Convert the loaded JSON dictionary into a Namespace
317
+ param_data = argparse.Namespace(**param_dict)
318
+
319
+ # Call finalize with the loaded JSON data as the first argument
320
+ finalize(param_data, None)
@@ -41,7 +41,7 @@ def params(parser):
41
41
  parser.add_argument(
42
42
  "--plt2d_var_max",
43
43
  type=float,
44
- default=250,
44
+ default=1000,
45
45
  help="Maximum value of the varplot variable used to adjust the scaling of the colorbar",
46
46
  )
47
47
 
@@ -72,28 +72,37 @@ def update(params, state):
72
72
  im0 = state.ax.imshow(
73
73
  state.topg,
74
74
  origin="lower",
75
- cmap=matplotlib.cm.terrain,
76
- extent=state.extent,
77
- alpha=0.65,
78
- )
79
-
80
- im = state.ax.imshow(
81
- np.where(state.thk > 0, vars(state)[params.plt2d_var], np.nan),
82
- origin="lower",
83
- cmap=matplotlib.cm.viridis,
84
- vmin=0,
85
- vmax=params.plt2d_var_max,
86
- extent=state.extent,
75
+ cmap='binary', # matplotlib.cm.terrain,
76
+ extent=state.extent
77
+ # alpha=0.65,
87
78
  )
79
+
80
+ if params.plt2d_var=="velbar_mag":
81
+ im = state.ax.imshow(
82
+ np.where(state.thk > 0, vars(state)[params.plt2d_var], np.nan),
83
+ origin="lower",
84
+ cmap="turbo",
85
+ extent=state.extent,
86
+ norm=matplotlib.colors.LogNorm(vmin=1, vmax=params.plt2d_var_max)
87
+ )
88
+ else:
89
+ im = state.ax.imshow(
90
+ np.where(state.thk > 0, vars(state)[params.plt2d_var], np.nan),
91
+ origin="lower",
92
+ cmap='jet',
93
+ vmin=0,
94
+ vmax=params.plt2d_var_max,
95
+ extent=state.extent,
96
+ )
88
97
  if params.plt2d_particles:
89
- if hasattr(state, "xpos"):
98
+ if hasattr(state, "particle_x"):
90
99
  if hasattr(state, "ip"):
91
100
  state.ip.set_visible(False)
92
101
  r = 1
93
102
  state.ip = state.ax.scatter(
94
- x=state.xpos[::r],
95
- y=state.ypos[::r],
96
- c=1 - state.rhpos[::r].numpy(),
103
+ x = state.particle_x[::r] + state.x[0],
104
+ y = state.particle_y[::r] + state.y[0],
105
+ c = 1 - state.particle_r[::r].numpy(), #or r ?
97
106
  vmin=0,
98
107
  vmax=1,
99
108
  s=0.5,