matterviz 0.3.0 → 0.3.2

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 (286) hide show
  1. package/dist/FilePicker.svelte +37 -20
  2. package/dist/Icon.svelte +2 -2
  3. package/dist/MillerIndexInput.svelte +60 -0
  4. package/dist/MillerIndexInput.svelte.d.ts +7 -0
  5. package/dist/app.css +38 -2
  6. package/dist/brillouin/BrillouinZone.svelte +20 -62
  7. package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
  8. package/dist/brillouin/BrillouinZoneExportPane.svelte +12 -20
  9. package/dist/brillouin/BrillouinZoneScene.svelte +2 -2
  10. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
  11. package/dist/chempot-diagram/ChemPotDiagram.svelte +192 -0
  12. package/dist/chempot-diagram/ChemPotDiagram.svelte.d.ts +13 -0
  13. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +677 -0
  14. package/dist/chempot-diagram/ChemPotDiagram2D.svelte.d.ts +16 -0
  15. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +2688 -0
  16. package/dist/chempot-diagram/ChemPotDiagram3D.svelte.d.ts +16 -0
  17. package/dist/chempot-diagram/ChemPotScene3D.svelte +8 -0
  18. package/dist/chempot-diagram/ChemPotScene3D.svelte.d.ts +7 -0
  19. package/dist/chempot-diagram/color.d.ts +10 -0
  20. package/dist/chempot-diagram/color.js +33 -0
  21. package/dist/chempot-diagram/compute.d.ts +38 -0
  22. package/dist/chempot-diagram/compute.js +650 -0
  23. package/dist/chempot-diagram/index.d.ts +5 -0
  24. package/dist/chempot-diagram/index.js +5 -0
  25. package/dist/chempot-diagram/pointer.d.ts +16 -0
  26. package/dist/chempot-diagram/pointer.js +40 -0
  27. package/dist/chempot-diagram/temperature.d.ts +15 -0
  28. package/dist/chempot-diagram/temperature.js +37 -0
  29. package/dist/chempot-diagram/types.d.ts +83 -0
  30. package/dist/chempot-diagram/types.js +27 -0
  31. package/dist/colors/index.d.ts +3 -1
  32. package/dist/colors/index.js +4 -0
  33. package/dist/composition/BarChart.svelte +13 -22
  34. package/dist/composition/BubbleChart.svelte +5 -3
  35. package/dist/composition/FormulaFilter.svelte +770 -90
  36. package/dist/composition/FormulaFilter.svelte.d.ts +37 -1
  37. package/dist/composition/PieChart.svelte +43 -18
  38. package/dist/composition/PieChart.svelte.d.ts +1 -1
  39. package/dist/constants.d.ts +1 -0
  40. package/dist/constants.js +2 -0
  41. package/dist/convex-hull/ConvexHull.svelte +14 -1
  42. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
  43. package/dist/convex-hull/ConvexHull2D.svelte +14 -45
  44. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  45. package/dist/convex-hull/ConvexHull3D.svelte +396 -134
  46. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  47. package/dist/convex-hull/ConvexHull4D.svelte +93 -42
  48. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  49. package/dist/convex-hull/ConvexHullControls.svelte +94 -31
  50. package/dist/convex-hull/ConvexHullControls.svelte.d.ts +4 -2
  51. package/dist/convex-hull/ConvexHullStats.svelte +697 -128
  52. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +6 -1
  53. package/dist/convex-hull/ConvexHullTooltip.svelte +1 -0
  54. package/dist/convex-hull/GasPressureControls.svelte +72 -38
  55. package/dist/convex-hull/GasPressureControls.svelte.d.ts +2 -1
  56. package/dist/convex-hull/TemperatureSlider.svelte +46 -19
  57. package/dist/convex-hull/TemperatureSlider.svelte.d.ts +2 -1
  58. package/dist/convex-hull/demo-temperature.d.ts +6 -0
  59. package/dist/convex-hull/demo-temperature.js +36 -0
  60. package/dist/convex-hull/gas-thermodynamics.js +16 -5
  61. package/dist/convex-hull/helpers.d.ts +7 -1
  62. package/dist/convex-hull/helpers.js +45 -15
  63. package/dist/convex-hull/index.d.ts +15 -1
  64. package/dist/convex-hull/index.js +1 -0
  65. package/dist/convex-hull/thermodynamics.d.ts +8 -21
  66. package/dist/convex-hull/thermodynamics.js +106 -17
  67. package/dist/convex-hull/types.d.ts +7 -0
  68. package/dist/convex-hull/types.js +11 -0
  69. package/dist/coordination/CoordinationBarPlot.svelte +29 -46
  70. package/dist/element/BohrAtom.svelte +1 -1
  71. package/dist/element/data.js +2 -14
  72. package/dist/element/data.json.gz +0 -0
  73. package/dist/element/index.d.ts +1 -1
  74. package/dist/element/index.js +1 -0
  75. package/dist/element/types.d.ts +1 -0
  76. package/dist/fermi-surface/FermiSurface.svelte +21 -65
  77. package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
  78. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  79. package/dist/fermi-surface/FermiSurfaceScene.svelte +1 -1
  80. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
  81. package/dist/fermi-surface/compute.js +1 -21
  82. package/dist/fermi-surface/marching-cubes.d.ts +2 -13
  83. package/dist/fermi-surface/marching-cubes.js +2 -519
  84. package/dist/fermi-surface/parse.js +17 -23
  85. package/dist/heatmap-matrix/HeatmapMatrix.svelte +1273 -0
  86. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +110 -0
  87. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +171 -0
  88. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +31 -0
  89. package/dist/heatmap-matrix/index.d.ts +53 -0
  90. package/dist/heatmap-matrix/index.js +100 -0
  91. package/dist/heatmap-matrix/shared.d.ts +2 -0
  92. package/dist/heatmap-matrix/shared.js +4 -0
  93. package/dist/icons.d.ts +119 -0
  94. package/dist/icons.js +119 -0
  95. package/dist/index.d.ts +6 -1
  96. package/dist/index.js +6 -1
  97. package/dist/io/export.js +15 -3
  98. package/dist/io/file-drop.d.ts +7 -0
  99. package/dist/io/file-drop.js +43 -0
  100. package/dist/io/index.d.ts +2 -2
  101. package/dist/io/index.js +2 -112
  102. package/dist/io/types.d.ts +1 -0
  103. package/dist/io/url-drop.d.ts +2 -0
  104. package/dist/io/url-drop.js +118 -0
  105. package/dist/isosurface/Isosurface.svelte +231 -0
  106. package/dist/isosurface/Isosurface.svelte.d.ts +8 -0
  107. package/dist/isosurface/IsosurfaceControls.svelte +273 -0
  108. package/dist/isosurface/IsosurfaceControls.svelte.d.ts +9 -0
  109. package/dist/isosurface/index.d.ts +5 -0
  110. package/dist/isosurface/index.js +6 -0
  111. package/dist/isosurface/parse.d.ts +6 -0
  112. package/dist/isosurface/parse.js +548 -0
  113. package/dist/isosurface/slice.d.ts +11 -0
  114. package/dist/isosurface/slice.js +145 -0
  115. package/dist/isosurface/types.d.ts +55 -0
  116. package/dist/isosurface/types.js +178 -0
  117. package/dist/labels.d.ts +2 -1
  118. package/dist/labels.js +1 -0
  119. package/dist/layout/InfoTag.svelte +62 -62
  120. package/dist/layout/SubpageGrid.svelte +74 -0
  121. package/dist/layout/SubpageGrid.svelte.d.ts +14 -0
  122. package/dist/layout/index.d.ts +1 -0
  123. package/dist/layout/index.js +1 -0
  124. package/dist/layout/json-tree/JsonNode.svelte +226 -53
  125. package/dist/layout/json-tree/JsonTree.svelte +425 -51
  126. package/dist/layout/json-tree/JsonTree.svelte.d.ts +1 -1
  127. package/dist/layout/json-tree/JsonValue.svelte +218 -97
  128. package/dist/layout/json-tree/types.d.ts +27 -2
  129. package/dist/layout/json-tree/utils.d.ts +14 -1
  130. package/dist/layout/json-tree/utils.js +254 -0
  131. package/dist/marching-cubes.d.ts +14 -0
  132. package/dist/marching-cubes.js +519 -0
  133. package/dist/math.d.ts +8 -0
  134. package/dist/math.js +374 -7
  135. package/dist/overlays/ContextMenu.svelte +3 -2
  136. package/dist/overlays/DraggablePane.svelte +163 -58
  137. package/dist/overlays/DraggablePane.svelte.d.ts +2 -0
  138. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +232 -77
  139. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +6 -2
  140. package/dist/phase-diagram/PhaseDiagramControls.svelte +32 -11
  141. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +3 -2
  142. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +103 -0
  143. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte.d.ts +15 -0
  144. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +102 -95
  145. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +7 -0
  146. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +100 -26
  147. package/dist/phase-diagram/PhaseDiagramTooltip.svelte.d.ts +6 -3
  148. package/dist/phase-diagram/index.d.ts +2 -0
  149. package/dist/phase-diagram/index.js +2 -0
  150. package/dist/phase-diagram/svg-to-diagram.d.ts +2 -0
  151. package/dist/phase-diagram/svg-to-diagram.js +865 -0
  152. package/dist/phase-diagram/types.d.ts +10 -0
  153. package/dist/phase-diagram/utils.d.ts +7 -4
  154. package/dist/phase-diagram/utils.js +149 -59
  155. package/dist/plot/AxisLabel.svelte +26 -0
  156. package/dist/plot/AxisLabel.svelte.d.ts +16 -0
  157. package/dist/plot/BarPlot.svelte +473 -228
  158. package/dist/plot/BarPlot.svelte.d.ts +3 -3
  159. package/dist/plot/BarPlotControls.svelte +3 -2
  160. package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
  161. package/dist/plot/ColorBar.svelte +54 -54
  162. package/dist/plot/ColorBar.svelte.d.ts +1 -1
  163. package/dist/plot/ElementScatter.svelte +4 -3
  164. package/dist/plot/FillArea.svelte +4 -1
  165. package/dist/plot/Histogram.svelte +320 -230
  166. package/dist/plot/Histogram.svelte.d.ts +2 -2
  167. package/dist/plot/HistogramControls.svelte +29 -10
  168. package/dist/plot/HistogramControls.svelte.d.ts +6 -2
  169. package/dist/plot/InteractiveAxisLabel.svelte.d.ts +2 -2
  170. package/dist/plot/PlotControls.svelte +109 -27
  171. package/dist/plot/PlotControls.svelte.d.ts +1 -1
  172. package/dist/plot/PlotLegend.svelte +1 -1
  173. package/dist/plot/PortalSelect.svelte +2 -1
  174. package/dist/plot/ReferenceLine.svelte +2 -1
  175. package/dist/plot/ReferenceLine.svelte.d.ts +1 -0
  176. package/dist/plot/ReferencePlane.svelte +1 -3
  177. package/dist/plot/ScatterPlot.svelte +343 -209
  178. package/dist/plot/ScatterPlot.svelte.d.ts +3 -3
  179. package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
  180. package/dist/plot/ScatterPlot3DControls.svelte +203 -250
  181. package/dist/plot/ScatterPlot3DScene.svelte +4 -7
  182. package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
  183. package/dist/plot/ScatterPlotControls.svelte +95 -55
  184. package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
  185. package/dist/plot/ZeroLines.svelte +44 -0
  186. package/dist/plot/ZeroLines.svelte.d.ts +32 -0
  187. package/dist/plot/ZoomRect.svelte +21 -0
  188. package/dist/plot/ZoomRect.svelte.d.ts +8 -0
  189. package/dist/plot/axis-utils.d.ts +1 -1
  190. package/dist/plot/data-cleaning.js +1 -5
  191. package/dist/plot/index.d.ts +6 -2
  192. package/dist/plot/index.js +6 -2
  193. package/dist/plot/interactions.d.ts +8 -10
  194. package/dist/plot/interactions.js +10 -19
  195. package/dist/plot/layout.d.ts +7 -1
  196. package/dist/plot/layout.js +12 -4
  197. package/dist/plot/reference-line.d.ts +4 -21
  198. package/dist/plot/reference-line.js +7 -81
  199. package/dist/plot/types.d.ts +42 -17
  200. package/dist/plot/types.js +10 -0
  201. package/dist/plot/utils/label-placement.js +14 -11
  202. package/dist/plot/utils.d.ts +1 -0
  203. package/dist/plot/utils.js +14 -0
  204. package/dist/rdf/RdfPlot.svelte +55 -66
  205. package/dist/rdf/RdfPlot.svelte.d.ts +1 -1
  206. package/dist/rdf/index.d.ts +1 -1
  207. package/dist/rdf/index.js +1 -1
  208. package/dist/settings.d.ts +5 -0
  209. package/dist/settings.js +37 -3
  210. package/dist/spectral/Bands.svelte +515 -143
  211. package/dist/spectral/Bands.svelte.d.ts +22 -2
  212. package/dist/spectral/helpers.d.ts +23 -1
  213. package/dist/spectral/helpers.js +65 -9
  214. package/dist/spectral/types.d.ts +2 -0
  215. package/dist/structure/AtomLegend.svelte +31 -10
  216. package/dist/structure/AtomLegend.svelte.d.ts +1 -1
  217. package/dist/structure/CellSelect.svelte +92 -22
  218. package/dist/structure/Lattice.svelte +2 -0
  219. package/dist/structure/Structure.svelte +716 -173
  220. package/dist/structure/Structure.svelte.d.ts +7 -2
  221. package/dist/structure/StructureControls.svelte +26 -14
  222. package/dist/structure/StructureControls.svelte.d.ts +5 -1
  223. package/dist/structure/StructureInfoPane.svelte +7 -1
  224. package/dist/structure/StructureScene.svelte +386 -95
  225. package/dist/structure/StructureScene.svelte.d.ts +15 -4
  226. package/dist/structure/atom-properties.d.ts +6 -2
  227. package/dist/structure/atom-properties.js +38 -25
  228. package/dist/structure/export.js +10 -7
  229. package/dist/structure/ferrox-wasm-types.d.ts +3 -2
  230. package/dist/structure/ferrox-wasm-types.js +0 -3
  231. package/dist/structure/ferrox-wasm.d.ts +3 -2
  232. package/dist/structure/ferrox-wasm.js +1 -2
  233. package/dist/structure/index.d.ts +7 -0
  234. package/dist/structure/index.js +22 -0
  235. package/dist/structure/parse.js +19 -16
  236. package/dist/structure/partial-occupancy.d.ts +25 -0
  237. package/dist/structure/partial-occupancy.js +102 -0
  238. package/dist/structure/validation.js +6 -3
  239. package/dist/symmetry/SymmetryStats.svelte +18 -4
  240. package/dist/symmetry/WyckoffTable.svelte +18 -10
  241. package/dist/symmetry/index.d.ts +7 -4
  242. package/dist/symmetry/index.js +83 -18
  243. package/dist/table/HeatmapTable.svelte +468 -69
  244. package/dist/table/HeatmapTable.svelte.d.ts +13 -1
  245. package/dist/table/ToggleMenu.svelte +291 -44
  246. package/dist/table/ToggleMenu.svelte.d.ts +4 -1
  247. package/dist/table/index.d.ts +3 -0
  248. package/dist/tooltip/index.d.ts +1 -1
  249. package/dist/tooltip/index.js +1 -0
  250. package/dist/trajectory/Trajectory.svelte +147 -145
  251. package/dist/trajectory/TrajectoryExportPane.svelte +13 -9
  252. package/dist/trajectory/TrajectoryExportPane.svelte.d.ts +1 -1
  253. package/dist/trajectory/constants.d.ts +6 -0
  254. package/dist/trajectory/constants.js +7 -0
  255. package/dist/trajectory/extract.js +3 -5
  256. package/dist/trajectory/format-detect.d.ts +9 -0
  257. package/dist/trajectory/format-detect.js +76 -0
  258. package/dist/trajectory/frame-reader.d.ts +17 -0
  259. package/dist/trajectory/frame-reader.js +339 -0
  260. package/dist/trajectory/helpers.d.ts +15 -0
  261. package/dist/trajectory/helpers.js +187 -0
  262. package/dist/trajectory/index.d.ts +1 -0
  263. package/dist/trajectory/index.js +11 -4
  264. package/dist/trajectory/parse/ase.d.ts +2 -0
  265. package/dist/trajectory/parse/ase.js +76 -0
  266. package/dist/trajectory/parse/hdf5.d.ts +2 -0
  267. package/dist/trajectory/parse/hdf5.js +121 -0
  268. package/dist/trajectory/parse/index.d.ts +12 -0
  269. package/dist/trajectory/parse/index.js +304 -0
  270. package/dist/trajectory/parse/lammps.d.ts +5 -0
  271. package/dist/trajectory/parse/lammps.js +169 -0
  272. package/dist/trajectory/parse/vasp.d.ts +2 -0
  273. package/dist/trajectory/parse/vasp.js +65 -0
  274. package/dist/trajectory/parse/xyz.d.ts +2 -0
  275. package/dist/trajectory/parse/xyz.js +109 -0
  276. package/dist/trajectory/types.d.ts +11 -0
  277. package/dist/trajectory/types.js +1 -0
  278. package/dist/utils.d.ts +2 -0
  279. package/dist/utils.js +4 -0
  280. package/dist/xrd/XrdPlot.svelte +6 -4
  281. package/dist/xrd/calc-xrd.js +0 -1
  282. package/package.json +33 -23
  283. package/readme.md +4 -4
  284. package/dist/trajectory/parse.d.ts +0 -42
  285. package/dist/trajectory/parse.js +0 -1267
  286. /package/dist/element/{data.json.d.ts → data.json.gz.d.ts} +0 -0
@@ -0,0 +1,231 @@
1
+ <script lang="ts">// Threlte component that renders isosurface meshes from volumetric data using marching cubes.
2
+ // Supports multiple layers at different isovalues with independent colors,
3
+ // plus positive/negative lobes and two-pass transparency.
4
+ import { marching_cubes } from '../marching-cubes';
5
+ import { T } from '@threlte/core';
6
+ import { BackSide, BufferAttribute, BufferGeometry, DoubleSide, FrontSide, Uint32BufferAttribute, } from 'three';
7
+ import { DEFAULT_ISOSURFACE_SETTINGS, downsample_grid, pad_periodic_grid, } from './types';
8
+ let { volume, settings = DEFAULT_ISOSURFACE_SETTINGS, } = $props();
9
+ // Resolve layers: use explicit layers array if provided, else build from single-isovalue settings
10
+ let resolved_layers = $derived.by(() => {
11
+ if (settings.layers?.length)
12
+ return settings.layers;
13
+ return [{
14
+ isovalue: settings.isovalue,
15
+ color: settings.positive_color,
16
+ opacity: settings.opacity,
17
+ visible: true,
18
+ show_negative: settings.show_negative,
19
+ negative_color: settings.negative_color,
20
+ }];
21
+ });
22
+ // Build indexed BufferGeometry from marching cubes output.
23
+ // Uses Three.js index buffer to avoid tripling vertex data, and
24
+ // computeVertexNormals() for fast GPU-friendly normals.
25
+ function build_geometry(vertices, faces) {
26
+ if (vertices.length === 0 || faces.length === 0)
27
+ return null;
28
+ // Flatten vertices: Vec3[] → Float32Array
29
+ const positions = new Float32Array(vertices.length * 3);
30
+ for (let idx = 0; idx < vertices.length; idx++) {
31
+ const vert = vertices[idx];
32
+ positions[idx * 3] = vert[0];
33
+ positions[idx * 3 + 1] = vert[1];
34
+ positions[idx * 3 + 2] = vert[2];
35
+ }
36
+ // Flatten face indices: number[][] → Uint32Array
37
+ const indices = new Uint32Array(faces.length * 3);
38
+ for (let idx = 0; idx < faces.length; idx++) {
39
+ const face = faces[idx];
40
+ indices[idx * 3] = face[0];
41
+ indices[idx * 3 + 1] = face[1];
42
+ indices[idx * 3 + 2] = face[2];
43
+ }
44
+ const geometry = new BufferGeometry();
45
+ geometry.setAttribute(`position`, new BufferAttribute(positions, 3));
46
+ geometry.setIndex(new Uint32BufferAttribute(indices, 1));
47
+ geometry.computeVertexNormals();
48
+ geometry.computeBoundingSphere();
49
+ return geometry;
50
+ }
51
+ // Downsample large grids once when volume changes to keep marching cubes interactive
52
+ let ds_result = $derived.by(() => {
53
+ if (!volume)
54
+ return undefined;
55
+ return downsample_grid(volume.grid, volume.grid_dims);
56
+ });
57
+ // Run marching cubes at the given isovalue with pre-prepared grid/lattice/shift.
58
+ function extract_surface(isovalue, mc_grid, mc_lattice, origin_shift) {
59
+ if (isovalue === 0)
60
+ return null;
61
+ const result = marching_cubes(mc_grid, isovalue, mc_lattice, {
62
+ periodic: false,
63
+ interpolate: true,
64
+ centered: false,
65
+ normals: false,
66
+ });
67
+ if (origin_shift) {
68
+ for (const vert of result.vertices) {
69
+ vert[0] += origin_shift[0];
70
+ vert[1] += origin_shift[1];
71
+ vert[2] += origin_shift[2];
72
+ }
73
+ }
74
+ return build_geometry(result.vertices, result.faces);
75
+ }
76
+ let active_geometries = $state([]);
77
+ let raf_id = 0;
78
+ let debounce_id = 0;
79
+ // Dispose all current geometries
80
+ function dispose_all() {
81
+ for (const entry of active_geometries)
82
+ entry.geometry.dispose();
83
+ active_geometries = [];
84
+ }
85
+ // Dispose on unmount
86
+ $effect(() => () => dispose_all());
87
+ function rebuild_geometries(layers) {
88
+ if (!volume || !ds_result)
89
+ return;
90
+ const old = active_geometries;
91
+ const entries = [];
92
+ // Prepare grid/lattice/shift once for all layers.
93
+ // When halo > 0 for periodic volumes, the downsampled grid is padded with
94
+ // halo cells from the opposite face so isosurfaces extend beyond the unit
95
+ // cell and close into complete enclosed shapes around boundary atoms.
96
+ let mc_grid = ds_result.grid;
97
+ let mc_lattice = volume.lattice;
98
+ let origin_shift = null;
99
+ if (settings.halo > 0 && volume.periodic) {
100
+ const padded = pad_periodic_grid(ds_result.grid, ds_result.dims, settings.halo);
101
+ mc_grid = padded.grid;
102
+ // marching_cubes maps [0,1] fractional -> Cartesian via lattice.
103
+ // The padded grid covers a wider fractional range, so scale the lattice
104
+ // to match. Then shift all vertices by the fractional offset.
105
+ const [la, lb, lc] = volume.lattice;
106
+ const sx = padded.dims[0] / ds_result.dims[0];
107
+ const sy = padded.dims[1] / ds_result.dims[1];
108
+ const sz = padded.dims[2] / ds_result.dims[2];
109
+ mc_lattice = [
110
+ [la[0] * sx, la[1] * sx, la[2] * sx],
111
+ [lb[0] * sy, lb[1] * sy, lb[2] * sy],
112
+ [lc[0] * sz, lc[1] * sz, lc[2] * sz],
113
+ ];
114
+ const [ox, oy, oz] = padded.offset;
115
+ origin_shift = [
116
+ ox * la[0] + oy * lb[0] + oz * lc[0],
117
+ ox * la[1] + oy * lb[1] + oz * lc[1],
118
+ ox * la[2] + oy * lb[2] + oz * lc[2],
119
+ ];
120
+ }
121
+ const surface_at = (isovalue) => extract_surface(isovalue, mc_grid, mc_lattice, origin_shift);
122
+ // Render lower-isovalue (outer) shells earlier so per-layer back/front passes
123
+ // interleave back-to-front across shells and reduce transparency artefacts.
124
+ const layer_render_rank = new Map(layers
125
+ .map((layer, layer_idx) => ({ layer_idx, isovalue: layer.isovalue }))
126
+ .sort((layer_a, layer_b) => layer_a.isovalue - layer_b.isovalue)
127
+ .map(({ layer_idx }, rank) => [layer_idx, rank]));
128
+ for (let layer_idx = 0; layer_idx < layers.length; layer_idx++) {
129
+ const layer = layers[layer_idx];
130
+ if (!layer.visible || layer.isovalue <= 0)
131
+ continue;
132
+ // Each layer gets 4 slots (positive back/front + negative back/front).
133
+ const base_order = (layer_render_rank.get(layer_idx) ?? layer_idx) * 4;
134
+ const pos_geo = surface_at(layer.isovalue);
135
+ if (pos_geo) {
136
+ entries.push({
137
+ geometry: pos_geo,
138
+ color: layer.color,
139
+ opacity: layer.opacity,
140
+ render_order: base_order,
141
+ });
142
+ }
143
+ if (layer.show_negative) {
144
+ const neg_geo = surface_at(-layer.isovalue);
145
+ if (neg_geo) {
146
+ entries.push({
147
+ geometry: neg_geo,
148
+ color: layer.negative_color,
149
+ opacity: layer.opacity,
150
+ render_order: base_order + 2,
151
+ });
152
+ }
153
+ }
154
+ }
155
+ active_geometries = entries;
156
+ for (const entry of old)
157
+ entry.geometry.dispose();
158
+ }
159
+ // Rebuild all layer geometries when layers or volume change.
160
+ // Debounces rapid changes (e.g. slider drags) to avoid repeated expensive marching cubes.
161
+ $effect(() => {
162
+ const layers = resolved_layers;
163
+ void settings.halo;
164
+ if (!ds_result) {
165
+ dispose_all();
166
+ return;
167
+ }
168
+ debounce_id = window.setTimeout(() => {
169
+ raf_id = requestAnimationFrame(() => rebuild_geometries(layers));
170
+ }, 50);
171
+ return () => {
172
+ clearTimeout(debounce_id);
173
+ cancelAnimationFrame(raf_id);
174
+ };
175
+ });
176
+ </script>
177
+
178
+ <!-- Render each geometry entry with appropriate material -->
179
+ {#each active_geometries as entry (entry)}
180
+ {#if settings.wireframe}
181
+ <T.Mesh geometry={entry.geometry} frustumCulled={false}>
182
+ <T.MeshBasicMaterial
183
+ color={entry.color}
184
+ wireframe
185
+ transparent={entry.opacity < 1}
186
+ opacity={entry.opacity}
187
+ />
188
+ </T.Mesh>
189
+ {:else if entry.opacity < 1}
190
+ <!-- Two-pass rendering for correct transparency -->
191
+ <T.Mesh
192
+ geometry={entry.geometry}
193
+ renderOrder={entry.render_order}
194
+ frustumCulled={false}
195
+ >
196
+ <T.MeshStandardMaterial
197
+ color={entry.color}
198
+ transparent
199
+ opacity={entry.opacity}
200
+ side={BackSide}
201
+ depthWrite={false}
202
+ metalness={0.1}
203
+ roughness={0.6}
204
+ />
205
+ </T.Mesh>
206
+ <T.Mesh
207
+ geometry={entry.geometry}
208
+ renderOrder={entry.render_order + 1}
209
+ frustumCulled={false}
210
+ >
211
+ <T.MeshStandardMaterial
212
+ color={entry.color}
213
+ transparent
214
+ opacity={entry.opacity}
215
+ side={FrontSide}
216
+ depthWrite={false}
217
+ metalness={0.1}
218
+ roughness={0.6}
219
+ />
220
+ </T.Mesh>
221
+ {:else}
222
+ <T.Mesh geometry={entry.geometry} frustumCulled={false}>
223
+ <T.MeshStandardMaterial
224
+ color={entry.color}
225
+ side={DoubleSide}
226
+ metalness={0.1}
227
+ roughness={0.6}
228
+ />
229
+ </T.Mesh>
230
+ {/if}
231
+ {/each}
@@ -0,0 +1,8 @@
1
+ import type { IsosurfaceSettings, VolumetricData } from './types';
2
+ type $$ComponentProps = {
3
+ volume: VolumetricData;
4
+ settings?: IsosurfaceSettings;
5
+ };
6
+ declare const Isosurface: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type Isosurface = ReturnType<typeof Isosurface>;
8
+ export default Isosurface;
@@ -0,0 +1,273 @@
1
+ <script lang="ts">// Controls panel for isosurface visualization settings (isovalue, opacity, colors, etc.)
2
+ // Supports both single-isovalue mode and multi-layer mode.
3
+ import { format_num } from '../labels';
4
+ import { SettingsSection } from '../layout';
5
+ import { tooltip } from 'svelte-multiselect/attachments';
6
+ import { DEFAULT_ISOSURFACE_SETTINGS, generate_layers } from './types';
7
+ let { settings = $bindable({ ...DEFAULT_ISOSURFACE_SETTINGS }), volumes = [], active_volume_idx = $bindable(0), } = $props();
8
+ // Clamp active_volume_idx when volumes list changes (e.g. dataset swap)
9
+ $effect(() => {
10
+ if (volumes.length > 0 && active_volume_idx >= volumes.length) {
11
+ active_volume_idx = 0;
12
+ }
13
+ });
14
+ // Use precomputed data_range from the active volume
15
+ let data_range = $derived(volumes[active_volume_idx]?.data_range ?? { min: 0, max: 1, abs_max: 1, mean: 0 });
16
+ let slider_max = $derived(Math.max(data_range.abs_max, 0.001));
17
+ let step = $derived(slider_max / 200);
18
+ let is_multi_layer = $derived((settings.layers?.length ?? 0) > 0);
19
+ let n_layers = $derived(settings.layers?.length ?? 1);
20
+ function set_layer_count(count) {
21
+ if (count <= 1) {
22
+ settings.layers = undefined;
23
+ }
24
+ else {
25
+ settings.layers = generate_layers(data_range, count);
26
+ }
27
+ }
28
+ function update_layer(idx, updates) {
29
+ if (!settings.layers)
30
+ return;
31
+ settings.layers = settings.layers.map((layer, layer_idx) => layer_idx === idx ? { ...layer, ...updates } : layer);
32
+ }
33
+ </script>
34
+
35
+ <SettingsSection
36
+ title="Isosurface"
37
+ current_values={{
38
+ isovalue: settings.isovalue,
39
+ opacity: settings.opacity,
40
+ show_negative: settings.show_negative,
41
+ wireframe: settings.wireframe,
42
+ halo: settings.halo,
43
+ layers: n_layers,
44
+ }}
45
+ on_reset={() => {
46
+ settings = { ...DEFAULT_ISOSURFACE_SETTINGS }
47
+ }}
48
+ >
49
+ <!-- Top row: volume selector (if multi-volume) + layer count + toggles -->
50
+ <div class="pane-row compact-row">
51
+ {#if volumes.length > 1}
52
+ <label
53
+ {@attach tooltip({
54
+ content: `Select which volume to display (e.g. charge vs magnetization)`,
55
+ })}
56
+ >
57
+ <span>Volume:</span>
58
+ <select bind:value={active_volume_idx}>
59
+ {#each volumes as vol, idx (idx)}
60
+ <option value={idx}>{vol.label ?? `Volume ${idx + 1}`}</option>
61
+ {/each}
62
+ </select>
63
+ </label>
64
+ {/if}
65
+ <label
66
+ {@attach tooltip({
67
+ content: `Number of isosurface shells at different density thresholds`,
68
+ })}
69
+ >
70
+ <span>Layers:</span>
71
+ <select
72
+ value={n_layers}
73
+ onchange={(event) =>
74
+ set_layer_count(Number((event.target as HTMLSelectElement).value))}
75
+ >
76
+ {#each [1, 2, 3, 4, 5] as count (count)}
77
+ <option value={count}>{count}</option>
78
+ {/each}
79
+ </select>
80
+ </label>
81
+ <!-- Sync both settings.show_negative (single-layer fallback) and all layer entries
82
+ so the toggle works consistently regardless of which mode is active -->
83
+ <label
84
+ {@attach tooltip({
85
+ content:
86
+ `Show negative lobe at −isovalue (for orbitals, ESP, magnetization)`,
87
+ })}
88
+ >
89
+ <span>Neg. lobe</span>
90
+ <input
91
+ type="checkbox"
92
+ checked={is_multi_layer
93
+ ? settings.layers?.some((layer) => layer.show_negative) ?? false
94
+ : settings.show_negative}
95
+ onchange={(event) => {
96
+ const checked = (event.target as HTMLInputElement).checked
97
+ settings.show_negative = checked
98
+ if (settings.layers) {
99
+ settings.layers = settings.layers.map((layer) => ({
100
+ ...layer,
101
+ show_negative: checked,
102
+ }))
103
+ }
104
+ }}
105
+ />
106
+ </label>
107
+ <label
108
+ {@attach tooltip({ content: `Render as wireframe mesh instead of solid surface` })}
109
+ >
110
+ <span>Wireframe</span>
111
+ <input type="checkbox" bind:checked={settings.wireframe} />
112
+ </label>
113
+ </div>
114
+
115
+ {#if is_multi_layer && settings.layers}
116
+ <!-- Multi-layer controls: each row has visibility, color, isovalue slider, opacity -->
117
+ {#each settings.layers as layer, idx (idx)}
118
+ <div class="layer-row">
119
+ <input
120
+ type="checkbox"
121
+ checked={layer.visible}
122
+ onchange={() => update_layer(idx, { visible: !layer.visible })}
123
+ />
124
+ <input
125
+ type="color"
126
+ value={layer.color}
127
+ onchange={(event) =>
128
+ update_layer(idx, { color: (event.target as HTMLInputElement).value })}
129
+ />
130
+ <input
131
+ type="range"
132
+ min={step}
133
+ max={slider_max}
134
+ {step}
135
+ value={layer.isovalue}
136
+ oninput={(event) =>
137
+ update_layer(idx, {
138
+ isovalue: Number((event.target as HTMLInputElement).value),
139
+ })}
140
+ style="flex: 1; min-width: 60px"
141
+ />
142
+ <span class="layer-value">{format_num(layer.isovalue, `.3~g`)}</span>
143
+ <input
144
+ type="range"
145
+ min={0.1}
146
+ max={1}
147
+ step={0.05}
148
+ value={layer.opacity}
149
+ oninput={(event) =>
150
+ update_layer(idx, {
151
+ opacity: Number((event.target as HTMLInputElement).value),
152
+ })}
153
+ style="width: 50px"
154
+ title="Opacity: {format_num(layer.opacity, `.2f`)}"
155
+ />
156
+ </div>
157
+ {/each}
158
+ {:else}
159
+ <!-- Single-layer: isovalue slider full width -->
160
+ <label
161
+ {@attach tooltip({
162
+ content: `Density threshold — surface is drawn where grid values equal this`,
163
+ })}
164
+ >
165
+ <span>Isovalue:</span>
166
+ <input
167
+ type="range"
168
+ min={step}
169
+ max={slider_max}
170
+ {step}
171
+ bind:value={settings.isovalue}
172
+ />
173
+ <span class="value">{format_num(settings.isovalue, `.4~g`)}</span>
174
+ </label>
175
+
176
+ <!-- Opacity + colors on one row -->
177
+ <div class="pane-row compact-row">
178
+ <label
179
+ {@attach tooltip({
180
+ content: `Surface transparency — lower values reveal inner structure`,
181
+ })}
182
+ >
183
+ <span>Opacity:</span>
184
+ <input
185
+ type="range"
186
+ min={0.1}
187
+ max={1}
188
+ step={0.05}
189
+ bind:value={settings.opacity}
190
+ style="width: 60px"
191
+ />
192
+ <span class="value">{format_num(settings.opacity, `.2f`)}</span>
193
+ </label>
194
+ <label {@attach tooltip({ content: `Color for the positive isovalue surface` })}>
195
+ <span>+ Color</span>
196
+ <input type="color" bind:value={settings.positive_color} />
197
+ </label>
198
+ {#if settings.show_negative}
199
+ <label
200
+ {@attach tooltip({ content: `Color for the negative (−isovalue) surface` })}
201
+ >
202
+ <span>&minus; Color</span>
203
+ <input type="color" bind:value={settings.negative_color} />
204
+ </label>
205
+ {/if}
206
+ </div>
207
+ {/if}
208
+
209
+ {#if volumes?.[active_volume_idx]?.periodic}
210
+ <label
211
+ {@attach tooltip({
212
+ content:
213
+ `Extend isosurface beyond cell boundaries to close partial spheres (fraction of cell)`,
214
+ })}
215
+ >
216
+ Halo: {format_num(settings.halo, `.2f`)}
217
+ <input
218
+ type="range"
219
+ min={0}
220
+ max={0.5}
221
+ step={0.01}
222
+ bind:value={settings.halo}
223
+ />
224
+ </label>
225
+ {/if}
226
+
227
+ {#if volumes[active_volume_idx]}
228
+ <div class="grid-info">
229
+ {volumes[active_volume_idx].grid_dims.join(` × `)} grid &nbsp;|&nbsp; [{
230
+ format_num(data_range.min, `.3~g`)
231
+ }, {format_num(data_range.max, `.3~g`)}]
232
+ </div>
233
+ {/if}
234
+ </SettingsSection>
235
+
236
+ <style>
237
+ .compact-row {
238
+ flex-wrap: wrap;
239
+ gap: 4pt 14pt;
240
+ }
241
+ label {
242
+ gap: 6pt;
243
+ }
244
+ .grid-info {
245
+ font-size: 0.75em;
246
+ opacity: 0.7;
247
+ padding: 2px 0;
248
+ }
249
+ .layer-row {
250
+ display: flex;
251
+ align-items: center;
252
+ gap: 0.3em;
253
+ font-size: 0.85em;
254
+ input[type='color'] {
255
+ width: 24px;
256
+ height: 20px;
257
+ padding: 0;
258
+ border: 1px solid var(--border-color, #ccc);
259
+ border-radius: 3px;
260
+ box-sizing: border-box;
261
+ cursor: pointer;
262
+ }
263
+ input[type='checkbox'] {
264
+ margin: 0;
265
+ }
266
+ }
267
+ .layer-value {
268
+ font-family: monospace;
269
+ font-size: 0.85em;
270
+ min-width: 3.5em;
271
+ text-align: right;
272
+ }
273
+ </style>
@@ -0,0 +1,9 @@
1
+ import type { IsosurfaceSettings, VolumetricData } from './types';
2
+ type $$ComponentProps = {
3
+ settings?: IsosurfaceSettings;
4
+ volumes?: VolumetricData[];
5
+ active_volume_idx?: number;
6
+ };
7
+ declare const IsosurfaceControls: import("svelte").Component<$$ComponentProps, {}, "settings" | "active_volume_idx">;
8
+ type IsosurfaceControls = ReturnType<typeof IsosurfaceControls>;
9
+ export default IsosurfaceControls;
@@ -0,0 +1,5 @@
1
+ export { default as Isosurface } from './Isosurface.svelte';
2
+ export { default as IsosurfaceControls } from './IsosurfaceControls.svelte';
3
+ export * from './parse';
4
+ export * from './slice';
5
+ export * from './types';
@@ -0,0 +1,6 @@
1
+ // Isosurface visualization module for volumetric data (CHGCAR, .cube files)
2
+ export { default as Isosurface } from './Isosurface.svelte';
3
+ export { default as IsosurfaceControls } from './IsosurfaceControls.svelte';
4
+ export * from './parse';
5
+ export * from './slice';
6
+ export * from './types';
@@ -0,0 +1,6 @@
1
+ import type { VolumetricFileData } from './types';
2
+ export declare function parse_chgcar(content: string): VolumetricFileData | null;
3
+ export declare function parse_cube(content: string, options?: {
4
+ periodic?: boolean;
5
+ }): VolumetricFileData | null;
6
+ export declare function parse_volumetric_file(content: string, filename?: string): VolumetricFileData | null;