issue_1221.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. import numpy as np
  2. from vedo import download, dataurl, precision, settings
  3. from vedo import Volume, Point, Plotter, Axes
  4. def extract_geoanomaly(input_vol, xind, yind) -> np.array:
  5. # variable to store output volume
  6. out_vol = np.zeros_like(input_vol, dtype=np.float32)
  7. # extract data corresponding to anomaly position in input volume
  8. sub_vol = input_vol[xind[0] : xind[1], yind[0] : yind[1], :].copy()
  9. # replace the section in the output volume corresponding to
  10. # the location of the extracted anomaly
  11. out_vol[xind[0] : xind[1], yind[0] : yind[1], :] = sub_vol
  12. return out_vol
  13. def slider_isovalue(widget, _event, init_value=None):
  14. global prev_value
  15. value = init_value if init_value else widget.value
  16. # snap to the closest allowed value
  17. idx = (np.abs(allowed_vals - value)).argmin()
  18. value = allowed_vals[idx]
  19. prev_value = value
  20. value_name = precision(value, 2)
  21. if value_name in bacts: # reusing the already existing mesh
  22. torender = bacts[value_name]
  23. else: # else generate
  24. torender = [
  25. iso,
  26. vol1.isosurface(value).c("#afe1af").flat(),
  27. vol2.isosurface(value).c("#ffa500").flat(),
  28. vol3.isosurface(value).c("#8A8AFF").flat(),
  29. vol4.isosurface(value).c("#faa0a0").flat(),
  30. ]
  31. bacts.update({value_name: torender}) # store it
  32. for m in torender:
  33. m.name = "AnomalyIsoSurface"
  34. plt.remove("AnomalyIsoSurface").add(torender)
  35. ######################################################
  36. # general settings
  37. settings.default_font = "Roboto"
  38. path = download(dataurl+"geo_dataset.npy")
  39. dataset = np.load(path)
  40. # invert the 'z-axis' in a way the shallow depth values
  41. # are displayed on top in the rendered window
  42. dataset = np.flip(dataset, axis=2)
  43. min_value = np.nanmin(dataset)
  44. rmin = min_value - 0.1
  45. # replace NaNs with a value to mask them in the rendered window
  46. nan_ind = np.isnan(dataset)
  47. dataset[nan_ind] = 0
  48. # generate a volume object
  49. vol = Volume(dataset, spacing=[15, 15, 2])
  50. # generate a surface object
  51. iso = vol.isosurface(value=rmin).smooth()
  52. iso.c("k5").alpha(0.15).lighting("off")
  53. ###########################
  54. # get the central-western anomaly defined by:
  55. X_ind = (1, 30)
  56. Y_ind = (22, 46)
  57. vol1 = extract_geoanomaly(dataset, X_ind, Y_ind)
  58. vol1 = Volume(vol1, spacing=[15, 15, 2])
  59. txt = "Central-western geoanomaly\n"
  60. txt += "(mid to strong S-wave values)"
  61. capt1 = Point((581, 207, 212)).caption(txt, size=(0.2, 0.05), justify='center-left', c="k")
  62. ###########################
  63. # get the central geoanomaly defined by:
  64. X_ind = (32, 41)
  65. Y_ind = (26, 35)
  66. vol2 = extract_geoanomaly(dataset, X_ind, Y_ind)
  67. vol2 = Volume(vol2, spacing=[15, 15, 2])
  68. txt = "Central geoanomaly\n"
  69. txt += "(low to mid S-wave values)"
  70. capt2 = Point([514, 475, 193]).caption(txt, size=(0.2, 0.05), justify='center-left', c="k")
  71. ###########################
  72. # get the south-eastern geoanomaly defined by:
  73. X_ind = (26, 53)
  74. Y_ind = (1, 25)
  75. vol3 = extract_geoanomaly(dataset, X_ind, Y_ind)
  76. vol3 = Volume(vol3, spacing=[15, 15, 2])
  77. txt = "Soth-eastern geoanomaly\n"
  78. txt += "(mid to strong S-wave values)"
  79. capt3 = Point([215, 500, 211]).caption(txt, size=(0.2, 0.05), justify='center-left', c="k")
  80. ###########################
  81. # get the north-eastern geoanomaly defined by:
  82. X_ind = (42, 56)
  83. Y_ind = (37, 53)
  84. vol4 = extract_geoanomaly(dataset, X_ind, Y_ind)
  85. vol4 = Volume(vol4, spacing=[15, 15, 2])
  86. txt = "North-eastern geoanomaly\n"
  87. txt += "(mid to strong S-wave values)"
  88. capt4 = Point([712, 630, 201]).caption(txt, size=(0.2, 0.05), justify='center-left', c="k")
  89. ###########################
  90. # add slider options to rendered window based on code at
  91. # https://github.com/marcomusy/vedo/blob/master/vedo/applications.py
  92. scalar_range = [2.80, 3.60]
  93. prev_value = 1e30
  94. allowed_vals = np.array([2.80, 2.90, 3.00, 3.10, 3.20, 3.30, 3.40, 3.50, 3.60])
  95. bacts = {} # catch the meshes so we don't need to recompute
  96. axs = Axes(
  97. iso,
  98. xtitle="Easting",
  99. xtitle_color="dr",
  100. xline_color="dr",
  101. xtitle_backface_color="w",
  102. ytitle="Northing",
  103. ytitle_color="dg",
  104. yline_color="dg",
  105. ytitle_backface_color="w",
  106. ztitle="Depth",
  107. ztitle_color="db",
  108. zline_color="db",
  109. ztitle_backface_color="w",
  110. text_scale=1.25,
  111. xygrid=False,
  112. z_inverted=True,
  113. xlabel_size=0.0,
  114. ylabel_size=0.0,
  115. zlabel_size=0.0,
  116. )
  117. plt = Plotter(size=(1400, 1200))
  118. plt.add_slider(
  119. slider_isovalue,
  120. scalar_range[0], scalar_range[1],
  121. value=scalar_range[0],
  122. pos=4, title="value", show_value=True, delayed=False
  123. )
  124. plt.show(iso, axs, capt1, capt2, capt3, capt4, viewup="z", interactive=False)
  125. slider_isovalue(None, None, init_value=scalar_range[0]) # init the first value
  126. plt.interactive().close()