matterviz 0.3.2 → 0.3.4

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 (281) hide show
  1. package/dist/EmptyState.svelte +10 -2
  2. package/dist/FilePicker.svelte +123 -82
  3. package/dist/Icon.svelte +18 -12
  4. package/dist/MillerIndexInput.svelte +27 -21
  5. package/dist/api/optimade.js +6 -6
  6. package/dist/app.css +216 -207
  7. package/dist/brillouin/BrillouinZone.svelte +292 -149
  8. package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
  9. package/dist/brillouin/BrillouinZoneControls.svelte +32 -5
  10. package/dist/brillouin/BrillouinZoneExportPane.svelte +69 -42
  11. package/dist/brillouin/BrillouinZoneExportPane.svelte.d.ts +1 -1
  12. package/dist/brillouin/BrillouinZoneInfoPane.svelte +99 -68
  13. package/dist/brillouin/BrillouinZoneScene.svelte +275 -163
  14. package/dist/brillouin/BrillouinZoneScene.svelte.d.ts +1 -1
  15. package/dist/brillouin/BrillouinZoneTooltip.svelte +17 -7
  16. package/dist/brillouin/compute.js +11 -6
  17. package/dist/chempot-diagram/ChemPotDiagram.svelte +162 -27
  18. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +451 -281
  19. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +2148 -1642
  20. package/dist/chempot-diagram/ChemPotScene3D.svelte +8 -5
  21. package/dist/chempot-diagram/async-compute.svelte.d.ts +3 -0
  22. package/dist/chempot-diagram/async-compute.svelte.js +77 -0
  23. package/dist/chempot-diagram/chempot-worker.d.ts +1 -0
  24. package/dist/chempot-diagram/chempot-worker.js +11 -0
  25. package/dist/chempot-diagram/color.js +1 -2
  26. package/dist/chempot-diagram/compute.d.ts +10 -0
  27. package/dist/chempot-diagram/compute.js +250 -88
  28. package/dist/chempot-diagram/index.d.ts +2 -1
  29. package/dist/chempot-diagram/index.js +2 -1
  30. package/dist/chempot-diagram/temperature.js +8 -9
  31. package/dist/chempot-diagram/types.d.ts +3 -0
  32. package/dist/chempot-diagram/types.js +1 -0
  33. package/dist/colors/index.d.ts +1 -1
  34. package/dist/colors/index.js +5 -3
  35. package/dist/composition/BarChart.svelte +128 -55
  36. package/dist/composition/BubbleChart.svelte +102 -49
  37. package/dist/composition/Composition.svelte +100 -79
  38. package/dist/composition/Formula.svelte +108 -62
  39. package/dist/composition/FormulaFilter.svelte +665 -537
  40. package/dist/composition/PieChart.svelte +183 -108
  41. package/dist/composition/format.d.ts +5 -0
  42. package/dist/composition/format.js +20 -3
  43. package/dist/composition/parse.js +14 -9
  44. package/dist/convex-hull/ConvexHull.svelte +93 -40
  45. package/dist/convex-hull/ConvexHull.svelte.d.ts +1 -1
  46. package/dist/convex-hull/ConvexHull2D.svelte +549 -360
  47. package/dist/convex-hull/ConvexHull2D.svelte.d.ts +1 -1
  48. package/dist/convex-hull/ConvexHull3D.svelte +1296 -827
  49. package/dist/convex-hull/ConvexHull3D.svelte.d.ts +1 -1
  50. package/dist/convex-hull/ConvexHull4D.svelte +1004 -688
  51. package/dist/convex-hull/ConvexHull4D.svelte.d.ts +1 -1
  52. package/dist/convex-hull/ConvexHullControls.svelte +115 -28
  53. package/dist/convex-hull/ConvexHullControls.svelte.d.ts +1 -1
  54. package/dist/convex-hull/ConvexHullInfoPane.svelte +29 -3
  55. package/dist/convex-hull/ConvexHullStats.svelte +425 -328
  56. package/dist/convex-hull/ConvexHullTooltip.svelte +40 -16
  57. package/dist/convex-hull/GasPressureControls.svelte +104 -61
  58. package/dist/convex-hull/StructurePopup.svelte +25 -4
  59. package/dist/convex-hull/TemperatureSlider.svelte +45 -25
  60. package/dist/convex-hull/barycentric-coords.js +13 -7
  61. package/dist/convex-hull/demo-temperature.js +8 -4
  62. package/dist/convex-hull/gas-thermodynamics.js +17 -12
  63. package/dist/convex-hull/helpers.d.ts +9 -0
  64. package/dist/convex-hull/helpers.js +77 -34
  65. package/dist/convex-hull/thermodynamics.js +61 -56
  66. package/dist/convex-hull/types.d.ts +9 -14
  67. package/dist/convex-hull/types.js +0 -17
  68. package/dist/coordination/CoordinationBarPlot.svelte +227 -154
  69. package/dist/element/BohrAtom.svelte +55 -12
  70. package/dist/element/ElementHeading.svelte +7 -2
  71. package/dist/element/ElementPhoto.svelte +15 -9
  72. package/dist/element/ElementStats.svelte +10 -4
  73. package/dist/element/ElementTile.svelte +137 -73
  74. package/dist/element/Nucleus.svelte +39 -11
  75. package/dist/element/data.js +1 -1
  76. package/dist/feedback/ClickFeedback.svelte +16 -5
  77. package/dist/feedback/DragOverlay.svelte +10 -2
  78. package/dist/feedback/Spinner.svelte +4 -2
  79. package/dist/feedback/StatusMessage.svelte +8 -2
  80. package/dist/fermi-surface/FermiSlice.svelte +118 -88
  81. package/dist/fermi-surface/FermiSurface.svelte +328 -187
  82. package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
  83. package/dist/fermi-surface/FermiSurfaceControls.svelte +113 -46
  84. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  85. package/dist/fermi-surface/FermiSurfaceScene.svelte +535 -342
  86. package/dist/fermi-surface/FermiSurfaceScene.svelte.d.ts +1 -1
  87. package/dist/fermi-surface/FermiSurfaceTooltip.svelte +14 -5
  88. package/dist/fermi-surface/compute.js +16 -20
  89. package/dist/fermi-surface/parse.js +24 -14
  90. package/dist/fermi-surface/symmetry.js +2 -7
  91. package/dist/fermi-surface/types.d.ts +3 -5
  92. package/dist/heatmap-matrix/HeatmapMatrix.svelte +1019 -765
  93. package/dist/heatmap-matrix/HeatmapMatrix.svelte.d.ts +1 -1
  94. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte +76 -22
  95. package/dist/heatmap-matrix/HeatmapMatrixControls.svelte.d.ts +2 -3
  96. package/dist/icons.js +47 -0
  97. package/dist/index.d.ts +2 -1
  98. package/dist/index.js +2 -1
  99. package/dist/io/decompress.js +1 -1
  100. package/dist/io/export.d.ts +3 -0
  101. package/dist/io/export.js +129 -143
  102. package/dist/io/is-binary.js +2 -3
  103. package/dist/io/url-drop.js +1 -2
  104. package/dist/isosurface/Isosurface.svelte +202 -148
  105. package/dist/isosurface/IsosurfaceControls.svelte +46 -28
  106. package/dist/isosurface/parse.js +34 -29
  107. package/dist/isosurface/slice.js +5 -10
  108. package/dist/isosurface/types.d.ts +2 -1
  109. package/dist/isosurface/types.js +61 -12
  110. package/dist/labels.js +11 -8
  111. package/dist/layout/FullscreenToggle.svelte +11 -2
  112. package/dist/layout/InfoCard.svelte +38 -6
  113. package/dist/layout/InfoTag.svelte +63 -32
  114. package/dist/layout/PropertyFilter.svelte +82 -37
  115. package/dist/layout/SettingsSection.svelte +85 -55
  116. package/dist/layout/SubpageGrid.svelte +10 -2
  117. package/dist/layout/json-tree/JsonNode.svelte +183 -138
  118. package/dist/layout/json-tree/JsonTree.svelte +499 -413
  119. package/dist/layout/json-tree/JsonValue.svelte +127 -99
  120. package/dist/layout/json-tree/utils.js +4 -2
  121. package/dist/marching-cubes.js +25 -2
  122. package/dist/math.d.ts +13 -17
  123. package/dist/math.js +133 -67
  124. package/dist/overlays/ContextMenu.svelte +65 -40
  125. package/dist/overlays/DraggablePane.svelte +211 -139
  126. package/dist/periodic-table/PeriodicTable.svelte +278 -145
  127. package/dist/periodic-table/PeriodicTableControls.svelte +178 -128
  128. package/dist/periodic-table/PropertySelect.svelte +25 -7
  129. package/dist/periodic-table/TableInset.svelte +8 -3
  130. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +446 -309
  131. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
  132. package/dist/phase-diagram/PhaseDiagramControls.svelte +102 -43
  133. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
  134. package/dist/phase-diagram/PhaseDiagramEditorPane.svelte +63 -40
  135. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +71 -28
  136. package/dist/phase-diagram/PhaseDiagramExportPane.svelte.d.ts +1 -1
  137. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +158 -101
  138. package/dist/phase-diagram/TdbInfoPanel.svelte +28 -4
  139. package/dist/phase-diagram/build-diagram.js +9 -9
  140. package/dist/phase-diagram/colors.js +1 -3
  141. package/dist/phase-diagram/parse.js +10 -9
  142. package/dist/phase-diagram/svg-to-diagram.js +53 -49
  143. package/dist/phase-diagram/utils.d.ts +1 -0
  144. package/dist/phase-diagram/utils.js +80 -25
  145. package/dist/plot/AxisLabel.svelte +28 -3
  146. package/dist/plot/BarPlot.svelte +1182 -734
  147. package/dist/plot/BarPlot.svelte.d.ts +2 -2
  148. package/dist/plot/BarPlotControls.svelte +31 -5
  149. package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
  150. package/dist/plot/ColorBar.svelte +479 -329
  151. package/dist/plot/ColorScaleSelect.svelte +27 -6
  152. package/dist/plot/ElementScatter.svelte +36 -15
  153. package/dist/plot/FillArea.svelte +152 -95
  154. package/dist/plot/Histogram.svelte +934 -571
  155. package/dist/plot/Histogram.svelte.d.ts +1 -1
  156. package/dist/plot/HistogramControls.svelte +53 -9
  157. package/dist/plot/HistogramControls.svelte.d.ts +1 -1
  158. package/dist/plot/InteractiveAxisLabel.svelte +34 -11
  159. package/dist/plot/InteractiveAxisLabel.svelte.d.ts +1 -1
  160. package/dist/plot/Line.svelte +63 -28
  161. package/dist/plot/PlotControls.svelte +157 -114
  162. package/dist/plot/PlotControls.svelte.d.ts +1 -1
  163. package/dist/plot/PlotLegend.svelte +174 -91
  164. package/dist/plot/PlotTooltip.svelte +45 -6
  165. package/dist/plot/PortalSelect.svelte +175 -147
  166. package/dist/plot/ReferenceLine.svelte +76 -22
  167. package/dist/plot/ReferenceLine3D.svelte +132 -107
  168. package/dist/plot/ReferencePlane.svelte +146 -121
  169. package/dist/plot/ScatterPlot.svelte +1681 -1091
  170. package/dist/plot/ScatterPlot.svelte.d.ts +2 -2
  171. package/dist/plot/ScatterPlot3D.svelte +256 -131
  172. package/dist/plot/ScatterPlot3D.svelte.d.ts +2 -2
  173. package/dist/plot/ScatterPlot3DControls.svelte +113 -63
  174. package/dist/plot/ScatterPlot3DControls.svelte.d.ts +2 -1
  175. package/dist/plot/ScatterPlot3DScene.svelte +608 -403
  176. package/dist/plot/ScatterPlot3DScene.svelte.d.ts +2 -2
  177. package/dist/plot/ScatterPlotControls.svelte +65 -25
  178. package/dist/plot/ScatterPlotControls.svelte.d.ts +1 -1
  179. package/dist/plot/ScatterPoint.svelte +98 -26
  180. package/dist/plot/ScatterPoint.svelte.d.ts +1 -0
  181. package/dist/plot/SpacegroupBarPlot.svelte +142 -85
  182. package/dist/plot/Surface3D.svelte +159 -108
  183. package/dist/plot/ZeroLines.svelte +55 -3
  184. package/dist/plot/ZoomRect.svelte +4 -2
  185. package/dist/plot/axis-utils.js +1 -3
  186. package/dist/plot/data-cleaning.js +12 -28
  187. package/dist/plot/data-transform.js +2 -1
  188. package/dist/plot/fill-utils.js +2 -0
  189. package/dist/plot/layout.d.ts +4 -1
  190. package/dist/plot/layout.js +33 -14
  191. package/dist/plot/reference-line.d.ts +2 -2
  192. package/dist/plot/reference-line.js +7 -5
  193. package/dist/plot/scales.js +24 -36
  194. package/dist/plot/types.d.ts +11 -23
  195. package/dist/plot/types.js +6 -11
  196. package/dist/plot/utils/label-placement.d.ts +32 -15
  197. package/dist/plot/utils/label-placement.js +227 -66
  198. package/dist/plot/utils/series-visibility.js +2 -3
  199. package/dist/rdf/RdfPlot.svelte +143 -91
  200. package/dist/rdf/calc-rdf.js +4 -5
  201. package/dist/sanitize.d.ts +4 -0
  202. package/dist/sanitize.js +107 -0
  203. package/dist/settings.d.ts +18 -6
  204. package/dist/settings.js +46 -16
  205. package/dist/spectral/Bands.svelte +632 -453
  206. package/dist/spectral/BandsAndDos.svelte +90 -49
  207. package/dist/spectral/BrillouinBandsDos.svelte +151 -93
  208. package/dist/spectral/Dos.svelte +389 -258
  209. package/dist/spectral/helpers.js +55 -43
  210. package/dist/state.svelte.d.ts +1 -1
  211. package/dist/state.svelte.js +3 -2
  212. package/dist/structure/Arrow.svelte +59 -20
  213. package/dist/structure/AtomLegend.svelte +215 -134
  214. package/dist/structure/Bond.svelte +73 -47
  215. package/dist/structure/CanvasTooltip.svelte +10 -2
  216. package/dist/structure/CellSelect.svelte +72 -45
  217. package/dist/structure/Cylinder.svelte +33 -17
  218. package/dist/structure/Lattice.svelte +88 -33
  219. package/dist/structure/Structure.svelte +1063 -797
  220. package/dist/structure/Structure.svelte.d.ts +1 -1
  221. package/dist/structure/StructureControls.svelte +349 -118
  222. package/dist/structure/StructureExportPane.svelte +124 -89
  223. package/dist/structure/StructureExportPane.svelte.d.ts +1 -1
  224. package/dist/structure/StructureInfoPane.svelte +304 -237
  225. package/dist/structure/StructureScene.svelte +879 -443
  226. package/dist/structure/StructureScene.svelte.d.ts +15 -7
  227. package/dist/structure/atom-properties.js +8 -8
  228. package/dist/structure/bonding.js +6 -7
  229. package/dist/structure/export.js +14 -29
  230. package/dist/structure/ferrox-wasm.js +1 -1
  231. package/dist/structure/index.d.ts +13 -3
  232. package/dist/structure/index.js +83 -23
  233. package/dist/structure/measure.d.ts +2 -2
  234. package/dist/structure/measure.js +4 -44
  235. package/dist/structure/parse.js +113 -141
  236. package/dist/structure/partial-occupancy.js +7 -10
  237. package/dist/structure/pbc.d.ts +1 -0
  238. package/dist/structure/pbc.js +16 -6
  239. package/dist/structure/supercell.d.ts +2 -2
  240. package/dist/structure/supercell.js +12 -22
  241. package/dist/structure/validation.js +1 -2
  242. package/dist/symmetry/SymmetryStats.svelte +84 -41
  243. package/dist/symmetry/WyckoffTable.svelte +26 -6
  244. package/dist/symmetry/cell-transform.js +5 -3
  245. package/dist/symmetry/index.js +8 -7
  246. package/dist/symmetry/spacegroups.js +148 -148
  247. package/dist/table/HeatmapTable.svelte +790 -554
  248. package/dist/table/HeatmapTable.svelte.d.ts +1 -1
  249. package/dist/table/ToggleMenu.svelte +125 -92
  250. package/dist/table/index.js +2 -4
  251. package/dist/theme/ThemeControl.svelte +21 -12
  252. package/dist/time.js +4 -1
  253. package/dist/tooltip/TooltipContent.svelte +33 -8
  254. package/dist/trajectory/Trajectory.svelte +758 -558
  255. package/dist/trajectory/TrajectoryError.svelte +14 -3
  256. package/dist/trajectory/TrajectoryExportPane.svelte +137 -83
  257. package/dist/trajectory/TrajectoryInfoPane.svelte +272 -143
  258. package/dist/trajectory/extract.js +10 -26
  259. package/dist/trajectory/format-detect.js +5 -5
  260. package/dist/trajectory/frame-reader.d.ts +1 -1
  261. package/dist/trajectory/frame-reader.js +5 -12
  262. package/dist/trajectory/helpers.d.ts +0 -1
  263. package/dist/trajectory/helpers.js +2 -17
  264. package/dist/trajectory/index.js +14 -12
  265. package/dist/trajectory/parse/ase.js +5 -4
  266. package/dist/trajectory/parse/hdf5.js +26 -18
  267. package/dist/trajectory/parse/index.js +13 -18
  268. package/dist/trajectory/parse/lammps.js +17 -7
  269. package/dist/trajectory/parse/vasp.js +5 -2
  270. package/dist/trajectory/parse/xyz.js +8 -7
  271. package/dist/trajectory/plotting.js +13 -8
  272. package/dist/utils.d.ts +1 -0
  273. package/dist/utils.js +13 -0
  274. package/dist/xrd/XrdPlot.svelte +337 -247
  275. package/dist/xrd/broadening.js +14 -9
  276. package/dist/xrd/calc-xrd.js +12 -18
  277. package/dist/xrd/parse.d.ts +1 -1
  278. package/dist/xrd/parse.js +17 -17
  279. package/package.json +99 -103
  280. package/readme.md +1 -1
  281. /package/dist/theme/{themes.js → themes.mjs} +0 -0
@@ -11,6 +11,7 @@ export function caglioti_fwhm(two_theta, // Angle in degrees (2θ)
11
11
  U, // Caglioti parameter U
12
12
  V, // Caglioti parameter V
13
13
  W) {
14
+ // FWHM in degrees (2θ)
14
15
  const theta_rad = (two_theta / 2) * (Math.PI / 180);
15
16
  const tan_theta = Math.tan(theta_rad);
16
17
  const fwhm_sq = U * tan_theta ** 2 + V * tan_theta + W;
@@ -19,6 +20,7 @@ W) {
19
20
  }
20
21
  // Normalized Gaussian profile. x: position, x0: peak center, fwhm: Full Width at Half Maximum
21
22
  function gaussian(x, x0, fwhm) {
23
+ // Intensity at x
22
24
  const safe_fwhm = Math.max(fwhm, 1e-9);
23
25
  const sigma = safe_fwhm / (2 * Math.sqrt(2 * LOG_2));
24
26
  const prefactor = 1 / (sigma * Math.sqrt(2 * Math.PI));
@@ -27,6 +29,7 @@ function gaussian(x, x0, fwhm) {
27
29
  }
28
30
  // Normalized Lorentzian profile. x: position, x0: peak center, fwhm: Full Width at Half Maximum
29
31
  function lorentzian(x, x0, fwhm) {
32
+ // Intensity at x
30
33
  const safe_fwhm = Math.max(fwhm, 1e-9);
31
34
  const gamma = safe_fwhm / 2;
32
35
  const prefactor = 1 / (Math.PI * gamma);
@@ -38,15 +41,17 @@ export function pseudo_voigt(x, // Position
38
41
  x0, // Peak center
39
42
  fwhm, // Full Width at Half Maximum
40
43
  eta) {
44
+ // Intensity at x
41
45
  // Clamp eta to [0, 1]
42
46
  const safe_eta = Math.max(0, Math.min(1, eta));
43
- return (safe_eta * lorentzian(x, x0, fwhm) + (1 - safe_eta) * gaussian(x, x0, fwhm));
47
+ return safe_eta * lorentzian(x, x0, fwhm) + (1 - safe_eta) * gaussian(x, x0, fwhm);
44
48
  }
45
49
  // Computes a broadened XRD pattern from discrete peaks.
46
50
  export function compute_broadened_pattern(pattern, // Discrete XRD pattern (peaks)
47
51
  params, // Broadening parameters (U, V, W, shape_factor)
48
52
  range, // Angular range [min, max] in degrees
49
53
  step_size = 0.02) {
54
+ // Continuous broadened pattern
50
55
  if (!Number.isFinite(step_size) || step_size <= 0) {
51
56
  throw new Error(`step_size must be > 0 and finite`);
52
57
  }
@@ -59,14 +64,14 @@ step_size = 0.02) {
59
64
  const n_steps = Math.ceil((max_angle - min_angle) / step_size);
60
65
  const xs = new Float32Array(n_steps);
61
66
  const ys = new Float32Array(n_steps);
62
- for (let i = 0; i < n_steps; i++) {
63
- xs[i] = min_angle + i * step_size;
67
+ for (let idx = 0; idx < n_steps; idx++) {
68
+ xs[idx] = min_angle + idx * step_size;
64
69
  }
65
70
  const { x: peak_pos, y: peak_int } = pattern;
66
71
  // Optimization: Process each peak and add to grid
67
- for (let p = 0; p < peak_pos.length; p++) {
68
- const x0 = peak_pos[p];
69
- const intensity = peak_int[p];
72
+ for (let peak_idx = 0; peak_idx < peak_pos.length; peak_idx++) {
73
+ const x0 = peak_pos[peak_idx];
74
+ const intensity = peak_int[peak_idx];
70
75
  // Skip negligible peaks
71
76
  if (intensity < 1e-5)
72
77
  continue;
@@ -80,9 +85,9 @@ step_size = 0.02) {
80
85
  const window = 20 * fwhm;
81
86
  const start_idx = Math.max(0, Math.floor((x0 - window - min_angle) / step_size));
82
87
  const end_idx = Math.min(n_steps - 1, Math.ceil((x0 + window - min_angle) / step_size));
83
- for (let i = start_idx; i <= end_idx; i++) {
84
- const x = xs[i];
85
- ys[i] += intensity * pseudo_voigt(x, x0, fwhm, shape_factor);
88
+ for (let idx = start_idx; idx <= end_idx; idx++) {
89
+ const x = xs[idx];
90
+ ys[idx] += intensity * pseudo_voigt(x, x0, fwhm, shape_factor);
86
91
  }
87
92
  }
88
93
  // Convert back to number[]
@@ -2,11 +2,8 @@ import { element_data } from '../element';
2
2
  import * as math from '../math';
3
3
  import { parse_any_structure } from '../structure/parse';
4
4
  import { is_crystal } from '../structure/validation';
5
- // Single source of truth for atomic scattering params (shared with Rust/ferrox)
6
- // Development: imports from extensions/rust/src/, Production: copied to dist/xrd/ by package script
7
- import ATOMIC_SCATTERING_PARAMS from './atomic_scattering_params.json' with {
8
- type: 'json'
9
- };
5
+ // Single source of truth for atomic scattering params
6
+ import ATOMIC_SCATTERING_PARAMS from './atomic_scattering_params.json' with { type: 'json' };
10
7
  import { is_xrd_data_file, parse_xrd_file } from './parse';
11
8
  // XRD wavelengths in Angstrom (Å)
12
9
  export const WAVELENGTHS = {
@@ -47,7 +44,7 @@ function get_unique_families(hkls) {
47
44
  // Port of pymatgen's get_unique_families: group Miller indices by absolute-value permutations
48
45
  const key_map = new Map();
49
46
  for (const hkl of hkls) {
50
- const abs_sorted = [...hkl.map((v) => Math.abs(v))].sort((x, y) => x - y);
47
+ const abs_sorted = [...hkl.map((val) => Math.abs(val))].sort((x, y) => x - y);
51
48
  const key = abs_sorted.join(`,`);
52
49
  const list = key_map.get(key);
53
50
  if (list)
@@ -85,9 +82,9 @@ function enumerate_reciprocal_points(recip_rows, max_radius, min_radius) {
85
82
  const n1 = Math.max(Math.hypot(...recip_b1), 1e-12);
86
83
  const n2 = Math.max(Math.hypot(...recip_b2), 1e-12);
87
84
  const n3 = Math.max(Math.hypot(...recip_b3), 1e-12);
88
- const h_max = Math.ceil((max_radius / n1) + 2);
89
- const k_max = Math.ceil((max_radius / n2) + 2);
90
- const l_max = Math.ceil((max_radius / n3) + 2);
85
+ const h_max = Math.ceil(max_radius / n1 + 2);
86
+ const k_max = Math.ceil(max_radius / n2 + 2);
87
+ const l_max = Math.ceil(max_radius / n3 + 2);
91
88
  // Safety cap to avoid pathological enumeration volume
92
89
  const CAP = 512;
93
90
  if (Math.max(h_max, k_max, l_max) > CAP) {
@@ -140,9 +137,7 @@ export function compute_xrd_pattern(structure, options = {}) {
140
137
  // const symprec = options.symprec ?? 0
141
138
  const recip_rows = compute_reciprocal_lattice_rows(structure);
142
139
  // Bragg condition bounds: reciprocal vector length r = 2 sin(theta) / lambda
143
- const two_theta_range = options.two_theta_range === null
144
- ? null
145
- : options.two_theta_range ?? [0, 180];
140
+ const two_theta_range = options.two_theta_range === null ? null : (options.two_theta_range ?? [0, 180]);
146
141
  const [min_radius, max_radius] = two_theta_range === null
147
142
  ? [0, 2 / wavelength]
148
143
  : (([t_min, t_max]) => {
@@ -219,7 +214,7 @@ export function compute_xrd_pattern(structure, options = {}) {
219
214
  }, { real: 0, imag: 0 });
220
215
  const sin_theta = Math.sin(theta);
221
216
  const cos_theta = Math.cos(theta);
222
- const denom_raw = (sin_theta * sin_theta) * Math.abs(cos_theta);
217
+ const denom_raw = sin_theta * sin_theta * Math.abs(cos_theta);
223
218
  // Clamp denominator away from zero to avoid Inf/NaN when 2θ → 180° (cosθ → 0)
224
219
  const denom = Math.max(denom_raw, 1e-12);
225
220
  const lorentz = (1 + Math.cos(2 * theta) ** 2) / denom;
@@ -253,7 +248,7 @@ export function compute_xrd_pattern(structure, options = {}) {
253
248
  if (peaks.size === 0)
254
249
  return { x: [], y: [] };
255
250
  // Scale intensities so that the max intensity is 100, and filter by scaled tol
256
- const max_intensity = Math.max(...Array.from(peaks.values()).map((p) => p.intensity));
251
+ const max_intensity = Math.max(...Array.from(peaks.values()).map((peak) => peak.intensity));
257
252
  const xs = [];
258
253
  const ys = [];
259
254
  const hkls_out = [];
@@ -270,7 +265,7 @@ export function compute_xrd_pattern(structure, options = {}) {
270
265
  const fam = get_unique_families(item.hkls);
271
266
  const fam_array = [];
272
267
  for (const [repr_key, multiplicity] of fam.entries()) {
273
- const repr = repr_key.split(`,`).map((n) => parseInt(n, 10));
268
+ const repr = repr_key.split(`,`).map((num_str) => parseInt(num_str, 10));
274
269
  fam_array.push({ hkl: repr, multiplicity });
275
270
  }
276
271
  hkls_out.push(fam_array);
@@ -291,6 +286,7 @@ export function compute_xrd_pattern(structure, options = {}) {
291
286
  export async function add_xrd_pattern(content, // File content as string or ArrayBuffer
292
287
  filename, // Name of the file (used to detect format)
293
288
  wavelength) {
289
+ // Object with pattern entry or error message
294
290
  try {
295
291
  // Check if file is a direct XRD data file (.xy, .brml)
296
292
  if (is_xrd_data_file(filename)) {
@@ -319,9 +315,7 @@ wavelength) {
319
315
  return { error: `Failed to parse ${ext} file: no valid data found. ${hint}` };
320
316
  }
321
317
  // Otherwise, try to parse as a structure file and compute XRD pattern
322
- const text_content = typeof content === `string`
323
- ? content
324
- : new TextDecoder().decode(content);
318
+ const text_content = typeof content === `string` ? content : new TextDecoder().decode(content);
325
319
  const parsed_structure = parse_any_structure(text_content, filename);
326
320
  if (is_crystal(parsed_structure)) {
327
321
  const pattern = compute_xrd_pattern(parsed_structure, {
@@ -8,6 +8,6 @@ export declare function parse_bruker_raw_file(data: ArrayBuffer): XrdPattern | n
8
8
  export declare function parse_brml_file(data: ArrayBuffer): Promise<XrdPattern | null>;
9
9
  export declare function parse_xrdml_file(content: string): XrdPattern | null;
10
10
  export declare const XRD_FILE_EXTENSIONS: readonly ["xy", "xye", "csv", "dat", "asc", "txt", "ras", "uxd", "gsas", "gsa", "gda", "fxye", "xrdml", "brml", "raw"];
11
- export type XrdFileExtension = typeof XRD_FILE_EXTENSIONS[number];
11
+ export type XrdFileExtension = (typeof XRD_FILE_EXTENSIONS)[number];
12
12
  export declare function parse_xrd_file(content: string | ArrayBuffer, filename: string): Promise<XrdPattern | null>;
13
13
  export declare function is_xrd_data_file(filename: string): boolean;
package/dist/xrd/parse.js CHANGED
@@ -15,7 +15,11 @@ function create_pattern(start, step, intensities) {
15
15
  return { x: normalized.x, y: normalized.y };
16
16
  }
17
17
  // Parse whitespace-separated numbers from text. Used by multiple formats.
18
- const parse_number_list = (text) => text.trim().split(/\s+/).map(parseFloat).filter((val) => !isNaN(val));
18
+ const parse_number_list = (text) => text
19
+ .trim()
20
+ .split(/\s+/)
21
+ .map(parseFloat)
22
+ .filter((val) => !isNaN(val));
19
23
  // Extract numeric value from header line matching "KEY=VALUE" or "KEY VALUE" pattern.
20
24
  // Returns null if not found or not a valid number.
21
25
  function extract_header_value(lines, key_pattern) {
@@ -71,7 +75,7 @@ function subsample_preserve_peaks(x_values, y_values, target_points) {
71
75
  .map((idx) => ({ idx, y: y_values[idx] }))
72
76
  .sort((a, b) => b.y - a.y)
73
77
  .slice(0, peak_slots)
74
- .map((p) => p.idx);
78
+ .map((peak) => peak.idx);
75
79
  // Uniform sampling (guard against division by zero)
76
80
  const uniform_indices = new Set();
77
81
  if (uniform_slots > 1) {
@@ -174,14 +178,12 @@ export function parse_ras_file(content) {
174
178
  // Detect by: 2-3 values per line, multiple rows, first column monotonically increasing
175
179
  // (angles increase during a scan, intensities do not follow this pattern)
176
180
  const first_values = parse_number_list(data_lines[0]);
177
- const has_column_structure = first_values.length >= 2 && first_values.length <= 3 &&
178
- data_lines.length > 1;
181
+ const has_column_structure = first_values.length >= 2 && first_values.length <= 3 && data_lines.length > 1;
179
182
  if (has_column_structure) {
180
183
  // Check if first column values are monotonically increasing (characteristic of angle data)
181
184
  // Sample a few lines to verify the pattern
182
185
  const sample_count = Math.min(5, data_lines.length);
183
- let is_monotonic = true;
184
- let prev_angle = first_values[0];
186
+ let [is_monotonic, prev_angle] = [true, first_values[0]];
185
187
  for (let idx = 1; idx < sample_count; idx++) {
186
188
  const values = parse_number_list(data_lines[idx]);
187
189
  if (values.length < 2 || values[0] <= prev_angle) {
@@ -245,7 +247,7 @@ export function parse_gsas_file(content) {
245
247
  let bin_type = `CONST`; // CONST, RALF, or others
246
248
  let found_bank = false;
247
249
  for (const line of lines) {
248
- const bank_match = line.match(/BANK\s+\d+\s+(\d+)\s+\d+\s+(\w+)\s+([\d.+-]+)\s+([\d.+-]+)/i);
250
+ const bank_match = /BANK\s+\d+\s+(\d+)\s+\d+\s+(\w+)\s+([\d.+-]+)\s+([\d.+-]+)/i.exec(line);
249
251
  if (bank_match) {
250
252
  bin_type = bank_match[2].toUpperCase();
251
253
  // For CONST type: BCOEF1 is start*100 (centidegrees), BCOEF2 is step*100
@@ -333,9 +335,9 @@ function parse_bruker_raw_v1(view, bytes) {
333
335
  // V1 has ASCII header with scan parameters followed by binary data
334
336
  const header_text = String.fromCharCode(...bytes.slice(0, 512));
335
337
  // Try to find scan parameters in ASCII header
336
- const start_match = header_text.match(/START\s*=\s*([\d.+-]+)/i);
337
- const step_match = header_text.match(/STEP\s*=\s*([\d.+-]+)/i);
338
- const count_match = header_text.match(/(?:COUNT|POINTS|NPTS)\s*=\s*(\d+)/i);
338
+ const start_match = /START\s*=\s*([\d.+-]+)/i.exec(header_text);
339
+ const step_match = /STEP\s*=\s*([\d.+-]+)/i.exec(header_text);
340
+ const count_match = /(?:COUNT|POINTS|NPTS)\s*=\s*(\d+)/i.exec(header_text);
339
341
  const start = start_match ? parseFloat(start_match[1]) : 0;
340
342
  const step = step_match ? parseFloat(step_match[1]) : DEFAULT_STEP_SIZE;
341
343
  // Find where binary data starts (after header)
@@ -397,9 +399,9 @@ function parse_rigaku_raw_file(data) {
397
399
  const bytes = new Uint8Array(data);
398
400
  // Try to find ASCII header section with scan parameters
399
401
  const header_text = String.fromCharCode(...bytes.slice(0, Math.min(2048, bytes.length)));
400
- const start_match = header_text.match(/(?:START|2THETA_START|SCAN_START)\s*[:=]?\s*([\d.+-]+)/i);
401
- const step_match = header_text.match(/(?:STEP|STEP_SIZE|SCAN_STEP)\s*[:=]?\s*([\d.+-]+)/i);
402
- const count_match = header_text.match(/(?:COUNT|POINTS|NPTS|STEPS)\s*[:=]?\s*(\d+)/i);
402
+ const start_match = /(?:START|2THETA_START|SCAN_START)\s*[:=]?\s*([\d.+-]+)/i.exec(header_text);
403
+ const step_match = /(?:STEP|STEP_SIZE|SCAN_STEP)\s*[:=]?\s*([\d.+-]+)/i.exec(header_text);
404
+ const count_match = /(?:COUNT|POINTS|NPTS|STEPS)\s*[:=]?\s*(\d+)/i.exec(header_text);
403
405
  if (!start_match && !step_match && !count_match)
404
406
  return null; // Not a recognizable Rigaku format
405
407
  const start = start_match ? parseFloat(start_match[1]) : 0;
@@ -457,7 +459,7 @@ function read_float32_array(view, offset, count) {
457
459
  // Extracts 2θ and intensity data from the RawData XML within the archive.
458
460
  export async function parse_brml_file(data) {
459
461
  try {
460
- // Lazy import fflate to avoid bundling in SSR (Deno compatibility)
462
+ // Lazy import fflate to avoid bundling in SSR
461
463
  const { unzipSync } = await import(`fflate`);
462
464
  const files = unzipSync(new Uint8Array(data));
463
465
  // Find the RawData XML file (usually named RawData0.xml or similar)
@@ -703,9 +705,7 @@ export async function parse_xrd_file(content, filename) {
703
705
  if (!ext)
704
706
  return null;
705
707
  // Helper to get text content
706
- const get_text = () => typeof content === `string`
707
- ? content
708
- : new TextDecoder().decode(content);
708
+ const get_text = () => typeof content === `string` ? content : new TextDecoder().decode(content);
709
709
  // Helper to get binary content
710
710
  const get_buffer = () => {
711
711
  if (typeof content === `string`) {
package/package.json CHANGED
@@ -1,104 +1,26 @@
1
1
  {
2
2
  "name": "matterviz",
3
+ "version": "0.3.4",
3
4
  "description": "Interactive visualizations for materials science: periodic tables, 3D structures, MD trajectories, heatmaps, scatter plots.",
4
- "author": "Janosh Riebesell <janosh.riebesell@gmail.com>",
5
- "homepage": "https://janosh.github.io/matterviz",
6
- "repository": "https://github.com/janosh/matterviz",
7
- "license": "MIT",
8
- "version": "0.3.2",
9
- "type": "module",
10
- "engines": {
11
- "node": ">=24"
12
- },
13
- "svelte": "./dist/index.js",
14
- "bugs": "https://github.com/janosh/matterviz/issues",
15
- "scripts": {
16
- "dev": "vite dev",
17
- "build": "vite build",
18
- "preview": "vite preview",
19
- "test": "vitest --run && playwright test",
20
- "package-dist-assets": "node scripts/package-dist-assets.mjs",
21
- "package:dist": "svelte-package && pnpm run package-dist-assets",
22
- "package": "pnpm run package:dist",
23
- "prepare": "NODE_OPTIONS=--experimental-strip-types svelte-kit sync && pnpm run package:dist",
24
- "prepublishOnly": "pnpm run package:dist"
25
- },
26
- "dependencies": {
27
- "@spglib/moyo-wasm": "^0.7.9",
28
- "@sveltejs/kit": "2.53.4",
29
- "@threlte/core": "^8.4.1",
30
- "@threlte/extras": "^9.8.1",
31
- "@types/d3-force": "^3.0.10",
32
- "@types/d3-hierarchy": "^3.1.7",
33
- "@types/js-yaml": "^4.0.9",
34
- "d3": "^7.9.0",
35
- "d3-array": "^3.2.4",
36
- "d3-color": "^3.1.0",
37
- "d3-force": "^3.0.0",
38
- "d3-format": "^3.1.2",
39
- "d3-hierarchy": "^3.1.2",
40
- "d3-interpolate-path": "^2.3.0",
41
- "d3-scale": "^4.0.2",
42
- "d3-scale-chromatic": "^3.1.0",
43
- "d3-shape": "^3.2.0",
44
- "fflate": "^0.8.2",
45
- "h5wasm": "^0.9.0",
46
- "highlight.js": "^11.11.1",
47
- "js-yaml": "^4.1.1",
48
- "svelte": "5.52.0",
49
- "svelte-multiselect": "^11.6.2",
50
- "svelte-toc": "^0.6.3",
51
- "three": "^0.183.2"
52
- },
53
- "devDependencies": {
54
- "@playwright/test": "^1.58.2",
55
- "@rollup/plugin-yaml": "^4.1.2",
56
- "@stylistic/eslint-plugin": "^5.9.0",
57
- "@sveltejs/adapter-static": "3.0.10",
58
- "@sveltejs/package": "^2.5.7",
59
- "@sveltejs/vite-plugin-svelte": "^6.2.4",
60
- "@types/d3-array": "^3.2.2",
61
- "@types/d3-color": "^3.1.3",
62
- "@types/d3-format": "^3.0.4",
63
- "@types/d3-interpolate-path": "^2.0.3",
64
- "@types/d3-scale": "^4.0.9",
65
- "@types/d3-scale-chromatic": "^3.1.0",
66
- "@types/d3-shape": "^3.1.8",
67
- "@types/d3-time-format": "^4.0.3",
68
- "@types/three": "^0.183.1",
69
- "@typescript/native-preview": "7.0.0-dev.20260304.1",
70
- "@vitest/coverage-v8": "^4.0.18",
71
- "@wooorm/starry-night": "^3.9.0",
72
- "abstract-syntax-tree": "^2.22.0",
73
- "d3-time-format": "^4.1.0",
74
- "eslint": "^10.0.2",
75
- "eslint-plugin-svelte": "^3.15.0",
76
- "happy-dom": "^20.8.3",
77
- "matterviz-wasm": "^0.0.7",
78
- "mdsvex": "^0.12.6",
79
- "rehype-katex": "^7.0.1",
80
- "remark-math": "3.0.1",
81
- "svelte-check-rs": "0.9.5",
82
- "svelte-preprocess": "^6.0.3",
83
- "svelte2tsx": "^0.7.51",
84
- "typedoc": "^0.28.17",
85
- "typedoc-plugin-markdown": "^4.10.0",
86
- "typescript": "5.9.3",
87
- "typescript-eslint": "^8.56.1",
88
- "vite": "^7.3.1",
89
- "vitest": "^4.0.18"
90
- },
91
5
  "keywords": [
92
- "svelte",
93
- "periodic table",
94
6
  "chemistry",
7
+ "component",
95
8
  "data viz",
9
+ "periodic table",
96
10
  "plotting",
97
- "component"
11
+ "svelte"
98
12
  ],
99
- "publishConfig": {
100
- "access": "public"
101
- },
13
+ "homepage": "https://janosh.github.io/matterviz",
14
+ "bugs": "https://github.com/janosh/matterviz/issues",
15
+ "license": "MIT",
16
+ "author": "Janosh Riebesell <janosh.riebesell@gmail.com>",
17
+ "repository": "https://github.com/janosh/matterviz",
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "type": "module",
22
+ "types": "./dist/index.d.ts",
23
+ "svelte": "./dist/index.js",
102
24
  "exports": {
103
25
  ".": {
104
26
  "types": "./dist/index.d.ts",
@@ -211,7 +133,7 @@
211
133
  },
212
134
  "./theme/themes": {
213
135
  "types": "./dist/theme/themes.d.ts",
214
- "default": "./dist/theme/themes.js"
136
+ "default": "./dist/theme/themes.mjs"
215
137
  },
216
138
  "./tooltip": {
217
139
  "types": "./dist/tooltip/index.d.ts",
@@ -235,13 +157,87 @@
235
157
  },
236
158
  "./xrd/atomic_scattering_params.json": "./dist/xrd/atomic_scattering_params.json"
237
159
  },
238
- "types": "./dist/index.d.ts",
239
- "files": [
240
- "dist"
241
- ],
242
- "pnpm": {
243
- "allowBuilds": [
244
- "esbuild"
245
- ]
246
- }
160
+ "publishConfig": {
161
+ "access": "public"
162
+ },
163
+ "scripts": {
164
+ "dev": "vp dev",
165
+ "build": "vp build",
166
+ "preview": "vp preview",
167
+ "test": "vp test --run && playwright test",
168
+ "check": "vp check",
169
+ "lint": "vp lint",
170
+ "fmt": "vp fmt --write",
171
+ "package-dist-assets": "NODE_OPTIONS=--experimental-strip-types node scripts/package-dist-assets.ts",
172
+ "package:dist": "svelte-package && npm run package-dist-assets",
173
+ "package": "npm run package:dist",
174
+ "prepare": "NODE_OPTIONS=--experimental-strip-types svelte-kit sync && npm run package:dist",
175
+ "prepublishOnly": "npm run package:dist"
176
+ },
177
+ "dependencies": {
178
+ "@spglib/moyo-wasm": "^0.7.9",
179
+ "@sveltejs/kit": "2.58.0",
180
+ "@threlte/core": "^8.5.10",
181
+ "@threlte/extras": "^9.15.0",
182
+ "@types/d3-hierarchy": "^3.1.7",
183
+ "@types/js-yaml": "^4.0.9",
184
+ "d3": "^7.9.0",
185
+ "d3-array": "^3.2.4",
186
+ "d3-color": "^3.1.0",
187
+ "d3-format": "^3.1.2",
188
+ "d3-hierarchy": "^3.1.2",
189
+ "d3-interpolate-path": "^2.3.0",
190
+ "d3-scale": "^4.0.2",
191
+ "d3-scale-chromatic": "^3.1.0",
192
+ "d3-shape": "^3.2.0",
193
+ "dompurify": "^3.4.1",
194
+ "fflate": "^0.8.2",
195
+ "h5wasm": "^0.10.1",
196
+ "js-yaml": "^4.1.1",
197
+ "svelte-multiselect": "^11.7.0",
198
+ "three": "^0.184.0"
199
+ },
200
+ "devDependencies": {
201
+ "@playwright/test": "^1.59.1",
202
+ "@rollup/plugin-yaml": "^4.1.2",
203
+ "@sveltejs/adapter-static": "3.0.10",
204
+ "@sveltejs/package": "^2.5.7",
205
+ "@sveltejs/vite-plugin-svelte": "^7.0.0",
206
+ "@types/d3-array": "^3.2.2",
207
+ "@types/d3-color": "^3.1.3",
208
+ "@types/d3-format": "^3.0.4",
209
+ "@types/d3-interpolate-path": "^2.0.3",
210
+ "@types/d3-scale": "^4.0.9",
211
+ "@types/d3-scale-chromatic": "^3.1.0",
212
+ "@types/d3-shape": "^3.1.8",
213
+ "@types/d3-time-format": "^4.0.3",
214
+ "@types/node": "^25.6.0",
215
+ "@types/three": "^0.184.0",
216
+ "@typescript/native-preview": "7.0.0-dev.20260429.1",
217
+ "@vitest/coverage-v8": "4.1.5",
218
+ "@wooorm/starry-night": "^3.9.0",
219
+ "d3-time-format": "^4.1.0",
220
+ "happy-dom": "^20.9.0",
221
+ "matterviz-wasm": "^0.0.10",
222
+ "mdsvex": "^0.12.7",
223
+ "rehype-katex": "^7.0.1",
224
+ "remark-math": "3.0.1",
225
+ "svelte": "5.55.5",
226
+ "svelte-check-rs": "0.9.7",
227
+ "typescript": "6.0.3",
228
+ "vite": "npm:@voidzero-dev/vite-plus-core@^0.1.20",
229
+ "vite-plus": "latest",
230
+ "vitest": "npm:@voidzero-dev/vite-plus-test@^0.1.20"
231
+ },
232
+ "peerDependencies": {
233
+ "svelte": "^5.0.0"
234
+ },
235
+ "overrides": {
236
+ "vite": "npm:@voidzero-dev/vite-plus-core@^0.1.20",
237
+ "vitest": "npm:@voidzero-dev/vite-plus-test@^0.1.20"
238
+ },
239
+ "engines": {
240
+ "node": ">=24"
241
+ },
242
+ "packageManager": "pnpm@10.33.0"
247
243
  }
package/readme.md CHANGED
@@ -55,7 +55,7 @@ Rich element pages with physical properties, electron configurations, Bohr atom
55
55
  ## 🔨 &thinsp; Installation
56
56
 
57
57
  ```sh
58
- pnpm add -D matterviz
58
+ npm add -D matterviz
59
59
  ```
60
60
 
61
61
  ## 📙 &thinsp; Usage
File without changes