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
@@ -1,8 +1,11 @@
1
- <script lang="ts">// Scene wrapper that enables Threlte pointer events for hover tooltips.
2
- // Must be rendered inside <Canvas>, mirroring ScatterPlot3DScene / StructureScene pattern.
3
- import { interactivity } from '@threlte/extras';
4
- let { children } = $props();
5
- interactivity();
1
+ <script lang="ts">
2
+ // Scene wrapper that enables Threlte pointer events for hover tooltips.
3
+ // Must be rendered inside <Canvas>, mirroring ScatterPlot3DScene / StructureScene pattern.
4
+ import { interactivity } from '@threlte/extras'
5
+ import type { Snippet } from 'svelte'
6
+
7
+ let { children }: { children?: Snippet } = $props()
8
+ interactivity()
6
9
  </script>
7
10
 
8
11
  {@render children?.()}
@@ -0,0 +1,3 @@
1
+ import type { ChemPotDiagramConfig, ChemPotDiagramData } from './types';
2
+ import type { PhaseData } from '../convex-hull/types';
3
+ export declare function compute_chempot_async(entries: PhaseData[], config?: ChemPotDiagramConfig): Promise<ChemPotDiagramData>;
@@ -0,0 +1,77 @@
1
+ // Async wrapper for compute_chempot_diagram via Web Worker.
2
+ // Falls back to synchronous main-thread computation during SSR.
3
+ import { compute_chempot_diagram, formula_key_from_composition } from './compute';
4
+ let worker = null;
5
+ let next_id = 0;
6
+ const pending = new Map();
7
+ const pending_by_key = new Map();
8
+ function make_compute_request_key(entries, config) {
9
+ const keyed_entries = entries
10
+ .map((entry) => [
11
+ formula_key_from_composition(entry.composition),
12
+ entry.energy,
13
+ entry.energy_per_atom ?? ``,
14
+ entry.e_form_per_atom ?? ``,
15
+ entry.is_stable ?? ``,
16
+ entry.e_above_hull ?? ``,
17
+ entry.exclude_from_hull ?? ``,
18
+ ].join(`:`))
19
+ .sort();
20
+ return `${keyed_entries.join(`,`)}|${JSON.stringify(config)}`;
21
+ }
22
+ function track_pending(request_key, promise) {
23
+ pending_by_key.set(request_key, promise);
24
+ promise.then(() => pending_by_key.delete(request_key), () => pending_by_key.delete(request_key));
25
+ return promise;
26
+ }
27
+ function get_worker() {
28
+ if (typeof Worker === `undefined`)
29
+ return null;
30
+ if (!worker) {
31
+ worker = new Worker(new URL(`./chempot-worker.js`, import.meta.url), { type: `module` });
32
+ worker.onmessage = ({ data: { id, result, error } }) => {
33
+ const req = pending.get(id);
34
+ if (!req)
35
+ return;
36
+ pending.delete(id);
37
+ if (error || !result)
38
+ req.reject(new Error(error ?? `Worker returned null`));
39
+ else
40
+ req.resolve(result);
41
+ };
42
+ worker.onerror = (event) => {
43
+ event.preventDefault();
44
+ const err = new Error(event.message || `Worker initialization error`);
45
+ for (const req of pending.values())
46
+ req.reject(err);
47
+ pending.clear();
48
+ worker = null;
49
+ };
50
+ }
51
+ return worker;
52
+ }
53
+ export function compute_chempot_async(entries, config = {}) {
54
+ const request_key = make_compute_request_key(entries, config);
55
+ const existing = pending_by_key.get(request_key);
56
+ if (existing)
57
+ return existing;
58
+ const wkr = get_worker();
59
+ // SSR / no-Worker fallback: run synchronously (wrapped so throws → rejections)
60
+ if (!wkr) {
61
+ const promise = Promise.resolve().then(() => compute_chempot_diagram(entries, config));
62
+ return track_pending(request_key, promise);
63
+ }
64
+ const promise = new Promise((resolve, reject) => {
65
+ const id = ++next_id;
66
+ pending.set(id, { resolve, reject });
67
+ try {
68
+ // $state.snapshot strips Svelte $state proxies (not structured-cloneable)
69
+ wkr.postMessage($state.snapshot({ id, entries, config }));
70
+ }
71
+ catch (err) {
72
+ pending.delete(id);
73
+ reject(err instanceof Error ? err : new Error(String(err)));
74
+ }
75
+ });
76
+ return track_pending(request_key, promise);
77
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ import { compute_chempot_diagram } from './compute';
2
+ self.onmessage = (event) => {
3
+ const { id, entries, config } = event.data;
4
+ try {
5
+ const result = compute_chempot_diagram(entries, config);
6
+ postMessage({ id, result, error: null });
7
+ }
8
+ catch (err) {
9
+ postMessage({ id, result: null, error: err instanceof Error ? err.message : String(err) });
10
+ }
11
+ };
@@ -10,8 +10,7 @@ export function make_chempot_color_scale(values, interpolator_name, reverse) {
10
10
  const finite_values = values.filter(Number.isFinite);
11
11
  if (finite_values.length === 0)
12
12
  return null;
13
- let min_value = finite_values[0];
14
- let max_raw_value = finite_values[0];
13
+ let [min_value, max_raw_value] = [finite_values[0], finite_values[0]];
15
14
  for (let idx = 1; idx < finite_values.length; idx++) {
16
15
  if (finite_values[idx] < min_value)
17
16
  min_value = finite_values[idx];
@@ -35,4 +35,14 @@ export declare function get_3d_domain_simplexes_and_ann_loc(points_3d: number[][
35
35
  simplex_indices: number[][];
36
36
  ann_loc: number[];
37
37
  };
38
+ export declare function bbox_diagonal(points: number[][]): number;
39
+ export declare function scale_to_font_range(sizes: number[], min_font: number, max_font: number): number[];
40
+ export interface VisibleDomainLabel {
41
+ formula: string;
42
+ position: [number, number, number];
43
+ label_font_size: number;
44
+ }
45
+ export declare function get_visible_domain_labels(face_positions: ArrayLike<number>, face_domain_map: string[], label_font_size_by_formula: ReadonlyMap<string, number>, pinned_labels?: VisibleDomainLabel[]): VisibleDomainLabel[];
46
+ export declare function get_ternary_combinations(elements: string[]): string[][];
47
+ export declare function make_nd_cache_key(entries: PhaseData[], formal_chempots: boolean, default_min_limit: number, limits: ChemPotDiagramConfig[`limits`]): string;
38
48
  export declare function compute_chempot_diagram(entries: PhaseData[], config?: ChemPotDiagramConfig): ChemPotDiagramData;
@@ -1,9 +1,39 @@
1
1
  // Core computational logic for chemical potential diagrams.
2
2
  // Ports pymatgen's ChemicalPotentialDiagram algorithm to TypeScript.
3
3
  // Reference: pymatgen/analysis/chempot_diagram.py
4
- import { count_atoms_in_composition, get_reduced_formula } from '../composition';
5
- import { convex_hull_2d, EPS, polygon_centroid, solve_linear_system, } from '../math';
6
- import { CHEMPOT_DEFAULTS, } from './types';
4
+ import { convex_hull_2d, EPS, polygon_centroid, solve_linear_system } from '../math';
5
+ import { CHEMPOT_DEFAULTS } from './types';
6
+ // Inlined from $lib/composition/parse to keep this module worker-safe
7
+ // ($lib/composition barrel transitively imports binary .json.gz data
8
+ // that the worker bundler can't handle).
9
+ const count_atoms_in_composition = (composition) => Object.values(composition).reduce((sum, count) => sum + (count ?? 0), 0);
10
+ const gcd = (num_a, num_b) => num_b === 0 ? num_a : gcd(num_b, num_a % num_b);
11
+ const get_reduced_formula = (composition) => {
12
+ const amounts = Object.values(composition).filter((amt) => amt > 0);
13
+ if (amounts.length === 0)
14
+ return {};
15
+ // For fractional amounts, find smallest multiplier (1–100) that yields near-integer ratios
16
+ let scale = 1;
17
+ if (!amounts.every((amt) => Number.isInteger(amt))) {
18
+ scale = 0;
19
+ for (let mult = 1; mult <= 100; mult++) {
20
+ if (amounts.every((amt) => Math.abs(amt * mult - Math.round(amt * mult)) < 0.03)) {
21
+ scale = mult;
22
+ break;
23
+ }
24
+ }
25
+ if (scale === 0)
26
+ return composition;
27
+ }
28
+ const int_amounts = amounts.map((amt) => Math.round(amt * scale));
29
+ const divisor = int_amounts.reduce((acc, amt) => gcd(acc, amt));
30
+ if (scale === 1 && divisor <= 1)
31
+ return composition;
32
+ const factor = scale / divisor;
33
+ return Object.fromEntries(Object.entries(composition)
34
+ .filter(([, amt]) => amt > 0)
35
+ .map(([elem, amt]) => [elem, Math.round(amt * factor)]));
36
+ };
7
37
  // === Entry Helpers ===
8
38
  // Get energy per atom for a PhaseData entry
9
39
  export function get_energy_per_atom(entry) {
@@ -88,9 +118,7 @@ export function renormalize_entries(entries, el_refs, elements) {
88
118
  const atoms = count_atoms_in_composition(entry.composition);
89
119
  let renorm_energy = 0;
90
120
  for (const el of elements) {
91
- const frac = atoms > 0
92
- ? (entry.composition[el] ?? 0) / atoms
93
- : 0;
121
+ const frac = atoms > 0 ? (entry.composition[el] ?? 0) / atoms : 0;
94
122
  const ref = el_refs[el];
95
123
  if (ref)
96
124
  renorm_energy += frac * get_energy_per_atom(ref);
@@ -114,6 +142,7 @@ export function build_hyperplanes(min_entries, el_refs, elements) {
114
142
  });
115
143
  const always_include = new Set(Object.values(el_refs));
116
144
  const tol = 1e-6; // PhaseDiagram.formation_energy_tol
145
+ const use_precomputed_hull = min_entries.every((entry) => typeof entry.is_stable === `boolean` || typeof entry.e_above_hull === `number`);
117
146
  const hyperplanes = [];
118
147
  const hyperplane_entries = [];
119
148
  for (const entry of min_entries) {
@@ -129,7 +158,14 @@ export function build_hyperplanes(min_entries, el_refs, elements) {
129
158
  ref_energy += fraction * element_ref_energies[elem_idx];
130
159
  }
131
160
  const form_energy = energy_per_atom - ref_energy;
132
- if (form_energy < -tol || always_include.has(entry)) {
161
+ const on_precomputed_hull = use_precomputed_hull &&
162
+ !entry.exclude_from_hull &&
163
+ (entry.is_stable === true ||
164
+ (typeof entry.e_above_hull === `number` && entry.e_above_hull <= tol));
165
+ const include_entry = use_precomputed_hull
166
+ ? on_precomputed_hull || always_include.has(entry)
167
+ : form_energy < -tol || always_include.has(entry);
168
+ if (include_entry) {
133
169
  row[n_elems] = -energy_per_atom;
134
170
  hyperplanes.push(row);
135
171
  hyperplane_entries.push(entry);
@@ -175,15 +211,21 @@ function solve_3x3(a, b, c, offsets, out) {
175
211
  if (Math.abs(det) < EPS)
176
212
  return false;
177
213
  const inv = 1 / det;
178
- out[0] = (offsets[0] * (b[1] * c[2] - b[2] * c[1]) -
179
- a[1] * (offsets[1] * c[2] - b[2] * offsets[2]) +
180
- a[2] * (offsets[1] * c[1] - b[1] * offsets[2])) * inv;
181
- out[1] = (a[0] * (offsets[1] * c[2] - b[2] * offsets[2]) -
182
- offsets[0] * (b[0] * c[2] - b[2] * c[0]) +
183
- a[2] * (b[0] * offsets[2] - offsets[1] * c[0])) * inv;
184
- out[2] = (a[0] * (b[1] * offsets[2] - offsets[1] * c[1]) -
185
- a[1] * (b[0] * offsets[2] - offsets[1] * c[0]) +
186
- offsets[0] * (b[0] * c[1] - b[1] * c[0])) * inv;
214
+ out[0] =
215
+ (offsets[0] * (b[1] * c[2] - b[2] * c[1]) -
216
+ a[1] * (offsets[1] * c[2] - b[2] * offsets[2]) +
217
+ a[2] * (offsets[1] * c[1] - b[1] * offsets[2])) *
218
+ inv;
219
+ out[1] =
220
+ (a[0] * (offsets[1] * c[2] - b[2] * offsets[2]) -
221
+ offsets[0] * (b[0] * c[2] - b[2] * c[0]) +
222
+ a[2] * (b[0] * offsets[2] - offsets[1] * c[0])) *
223
+ inv;
224
+ out[2] =
225
+ (a[0] * (b[1] * offsets[2] - offsets[1] * c[1]) -
226
+ a[1] * (b[0] * offsets[2] - offsets[1] * c[0]) +
227
+ offsets[0] * (b[0] * c[1] - b[1] * c[0])) *
228
+ inv;
187
229
  return true;
188
230
  }
189
231
  // Compute chemical potential domains via vertex enumeration.
@@ -207,9 +249,7 @@ export function compute_domains(hyperplanes, border_hyperplanes, hyperplane_entr
207
249
  const mu = new Array(dim).fill(0);
208
250
  const offsets = new Array(dim).fill(0);
209
251
  // For dim <= 3, use inline solvers; for larger dims, build A on the fly
210
- const A_rows = dim > 3
211
- ? Array.from({ length: dim }, () => new Array(dim).fill(0))
212
- : [];
252
+ const A_rows = dim > 3 ? Array.from({ length: dim }, () => new Array(dim).fill(0)) : [];
213
253
  // Generate all combinations of dim indices from n_total halfspaces
214
254
  const combo = new Array(dim).fill(0);
215
255
  for (let idx = 0; idx < dim; idx++)
@@ -233,8 +273,8 @@ export function compute_domains(hyperplanes, border_hyperplanes, hyperplane_entr
233
273
  has_entry_hyperplane = combo[0] < n_entries || combo[1] < n_entries;
234
274
  }
235
275
  else if (dim === 3) {
236
- has_entry_hyperplane = combo[0] < n_entries || combo[1] < n_entries ||
237
- combo[2] < n_entries;
276
+ has_entry_hyperplane =
277
+ combo[0] < n_entries || combo[1] < n_entries || combo[2] < n_entries;
238
278
  }
239
279
  else {
240
280
  for (let row = 0; row < dim; row++) {
@@ -283,7 +323,8 @@ export function compute_domains(hyperplanes, border_hyperplanes, hyperplane_entr
283
323
  const selected_hs_idx_2 = dim > 2 ? combo[2] : -1;
284
324
  for (let idx = 0; idx < n_total; idx++) {
285
325
  if (dim <= 3) {
286
- if (idx === selected_hs_idx_0 || idx === selected_hs_idx_1 ||
326
+ if (idx === selected_hs_idx_0 ||
327
+ idx === selected_hs_idx_1 ||
287
328
  idx === selected_hs_idx_2)
288
329
  continue;
289
330
  }
@@ -317,11 +358,7 @@ export function compute_domains(hyperplanes, border_hyperplanes, hyperplane_entr
317
358
  }
318
359
  if (solved) {
319
360
  // Assign vertex to entries whose hyperplanes are active
320
- const vertex = dim === 2
321
- ? [mu[0], mu[1]]
322
- : dim === 3
323
- ? [mu[0], mu[1], mu[2]]
324
- : [...mu];
361
+ const vertex = dim === 2 ? [mu[0], mu[1]] : dim === 3 ? [mu[0], mu[1], mu[2]] : [...mu];
325
362
  for (let idx = 0; idx < dim; idx++) {
326
363
  const hs_idx = combo[idx];
327
364
  if (hs_idx < n_entries) {
@@ -376,8 +413,7 @@ export function pad_domain_points(pts, elem_indices, new_lims, default_min_limit
376
413
  // Build per-axis min/max ranges for a set of points
377
414
  export function build_axis_ranges(points, elements) {
378
415
  return elements.map((element, axis_idx) => {
379
- let min_val = Infinity;
380
- let max_val = -Infinity;
416
+ let [min_val, max_val] = [Infinity, -Infinity];
381
417
  for (const point of points) {
382
418
  const val = point[axis_idx];
383
419
  if (val < min_val)
@@ -518,8 +554,7 @@ export function get_3d_domain_simplexes_and_ann_loc(points_3d) {
518
554
  // Map hull vertices back to original point indices using nearest projected
519
555
  // vertex instead of stringified coordinates to avoid precision aliasing.
520
556
  function nearest_projected_idx(target) {
521
- let nearest_idx = 0;
522
- let min_sq_dist = Infinity;
557
+ let [nearest_idx, min_sq_dist] = [0, Infinity];
523
558
  for (let idx = 0; idx < pts_2d.length; idx++) {
524
559
  const dx = pts_2d[idx][0] - target[0];
525
560
  const dy = pts_2d[idx][1] - target[1];
@@ -542,6 +577,119 @@ export function get_3d_domain_simplexes_and_ann_loc(points_3d) {
542
577
  }
543
578
  return { simplex_indices, ann_loc };
544
579
  }
580
+ // === Label Sizing ===
581
+ // Bounding box diagonal of a set of N-D points (Euclidean distance between
582
+ // the min and max corners). Returns 0 for fewer than 2 points.
583
+ export function bbox_diagonal(points) {
584
+ if (points.length < 2)
585
+ return 0;
586
+ let sq_sum = 0;
587
+ for (let col = 0; col < points[0].length; col++) {
588
+ let lo = Infinity, hi = -Infinity;
589
+ for (const pt of points) {
590
+ lo = Math.min(lo, pt[col]);
591
+ hi = Math.max(hi, pt[col]);
592
+ }
593
+ sq_sum += (hi - lo) ** 2;
594
+ }
595
+ return Math.sqrt(sq_sum);
596
+ }
597
+ // Map an array of raw size values to font sizes via linear interpolation.
598
+ // Returns a new array of font sizes in [min_font, max_font].
599
+ // If all sizes are equal, returns the midpoint for all.
600
+ export function scale_to_font_range(sizes, min_font, max_font) {
601
+ const min_size = Math.min(...sizes);
602
+ const max_size = Math.max(...sizes);
603
+ const range = max_size - min_size;
604
+ const mid = (min_font + max_font) / 2;
605
+ return sizes.map((size) => range > 0 ? min_font + ((max_font - min_font) * (size - min_size)) / range : mid);
606
+ }
607
+ export function get_visible_domain_labels(face_positions, face_domain_map, label_font_size_by_formula, pinned_labels = []) {
608
+ const n_faces = Math.min(Math.floor(face_positions.length / 9), face_domain_map.length);
609
+ const accum = new Map();
610
+ for (let face_idx = 0; face_idx < n_faces; face_idx++) {
611
+ const formula = face_domain_map[face_idx];
612
+ if (!formula || !label_font_size_by_formula.has(formula))
613
+ continue;
614
+ const base = face_idx * 9;
615
+ const ax = face_positions[base];
616
+ const ay = face_positions[base + 1];
617
+ const az = face_positions[base + 2];
618
+ const bx = face_positions[base + 3];
619
+ const by = face_positions[base + 4];
620
+ const bz = face_positions[base + 5];
621
+ const cx = face_positions[base + 6];
622
+ const cy = face_positions[base + 7];
623
+ const cz = face_positions[base + 8];
624
+ const abx = bx - ax;
625
+ const aby = by - ay;
626
+ const abz = bz - az;
627
+ const acx = cx - ax;
628
+ const acy = cy - ay;
629
+ const acz = cz - az;
630
+ const cross_x = aby * acz - abz * acy;
631
+ const cross_y = abz * acx - abx * acz;
632
+ const cross_z = abx * acy - aby * acx;
633
+ const area = Math.hypot(cross_x, cross_y, cross_z) / 2;
634
+ if (area <= EPS)
635
+ continue;
636
+ const centroid_x = (ax + bx + cx) / 3;
637
+ const centroid_y = (ay + by + cy) / 3;
638
+ const centroid_z = (az + bz + cz) / 3;
639
+ const entry = accum.get(formula) ?? { area: 0, x: 0, y: 0, z: 0 };
640
+ entry.area += area;
641
+ entry.x += centroid_x * area;
642
+ entry.y += centroid_y * area;
643
+ entry.z += centroid_z * area;
644
+ accum.set(formula, entry);
645
+ }
646
+ const visible_labels = [...accum.entries()]
647
+ .filter(([, entry]) => entry.area > EPS)
648
+ .map(([formula, entry]) => ({
649
+ formula,
650
+ position: [entry.x / entry.area, entry.y / entry.area, entry.z / entry.area],
651
+ label_font_size: label_font_size_by_formula.get(formula) ?? 12,
652
+ }));
653
+ for (const label of pinned_labels) {
654
+ if (!visible_labels.some((visible_label) => visible_label.formula === label.formula)) {
655
+ visible_labels.push(label);
656
+ }
657
+ }
658
+ return visible_labels.sort((label_a, label_b) => label_a.formula.localeCompare(label_b.formula));
659
+ }
660
+ // === Ternary Combinations ===
661
+ // Generate all C(n,3) ternary element combinations from a sorted element list.
662
+ // Each triplet is sorted alphabetically. Returns empty array for fewer than 3 elements.
663
+ export function get_ternary_combinations(elements) {
664
+ const sorted = [...elements].sort();
665
+ const n_elems = sorted.length;
666
+ if (n_elems < 3)
667
+ return [];
668
+ const combos = [];
669
+ for (let first = 0; first < n_elems - 2; first++) {
670
+ for (let second = first + 1; second < n_elems - 1; second++) {
671
+ for (let third = second + 1; third < n_elems; third++) {
672
+ combos.push([sorted[first], sorted[second], sorted[third]]);
673
+ }
674
+ }
675
+ }
676
+ return combos;
677
+ }
678
+ let _nd_cache = null;
679
+ // Content-based fingerprint for N-D result caching. Uses sorted formula keys
680
+ // so deserialized Web Worker copies match and different compositions never collide.
681
+ export function make_nd_cache_key(entries, formal_chempots, default_min_limit, limits) {
682
+ const keyed = entries
683
+ .map((entry) => [
684
+ formula_key_from_composition(entry.composition),
685
+ entry.energy,
686
+ entry.is_stable ?? ``,
687
+ entry.e_above_hull ?? ``,
688
+ entry.exclude_from_hull ?? ``,
689
+ ].join(`:`))
690
+ .sort();
691
+ return `${keyed.join(`,`)}|${formal_chempots}|${default_min_limit}|${JSON.stringify(limits ?? {})}`;
692
+ }
545
693
  // === Main Pipeline ===
546
694
  // Compute the full chemical potential diagram from entries and config.
547
695
  // Returns domains, elements, refs, and all intermediate data.
@@ -564,69 +712,83 @@ export function compute_chempot_diagram(entries, config = {}) {
564
712
  }
565
713
  const all_data_elements = Array.from(all_data_elements_set).sort();
566
714
  // Display elements: user-specified order (controls axis mapping), or auto-detect
567
- const display_elements = config.elements?.length
568
- ? [...config.elements]
569
- : all_data_elements;
715
+ const display_elements = config.elements?.length ? [...config.elements] : all_data_elements;
570
716
  // Projection mode: display fewer axes than the data has elements
571
717
  // In this mode, compute in full N-D and project afterward
572
718
  const is_projection = display_elements.length < all_data_elements.length &&
573
719
  display_elements.every((el) => all_data_elements.includes(el));
574
720
  // Computation elements: full element set for projection, display set for subsystem
575
721
  const compute_elements = is_projection ? all_data_elements : display_elements;
576
- // In subsystem mode, filter entries to only those within the element set
577
- let working_entries = entries;
578
- if (!is_projection && config.elements?.length) {
579
- const target_set = new Set(config.elements);
580
- working_entries = entries.filter((entry) => {
581
- for (const [element, amount] of Object.entries(entry.composition)) {
582
- if (amount > 0 && !target_set.has(element))
583
- return false;
584
- }
585
- return true;
722
+ // Try cache for projection mode (same entries + config = same N-D domains)
723
+ const cache_key = is_projection
724
+ ? make_nd_cache_key(entries, formal_chempots, default_min_limit, limits)
725
+ : ``;
726
+ let nd_result = is_projection && _nd_cache?.key === cache_key ? _nd_cache.result : null;
727
+ if (!nd_result) {
728
+ // In subsystem mode, filter entries to only those within the element set
729
+ let working_entries = entries;
730
+ if (!is_projection && config.elements?.length) {
731
+ const target_set = new Set(config.elements);
732
+ working_entries = entries.filter((entry) => {
733
+ for (const [element, amount] of Object.entries(entry.composition)) {
734
+ if (amount > 0 && !target_set.has(element))
735
+ return false;
736
+ }
737
+ return true;
738
+ });
739
+ }
740
+ // Sort entries by composition (Schwartzian transform to avoid recomputing keys)
741
+ const sorted_entries = working_entries
742
+ .map((entry) => ({ entry, key: formula_key_from_composition(entry.composition) }))
743
+ .sort((a, b) => a.key.localeCompare(b.key))
744
+ .map(({ entry }) => entry);
745
+ // Get min entries and elemental references
746
+ let { min_entries, el_refs } = get_min_entries_and_el_refs(sorted_entries);
747
+ const dim = compute_elements.length;
748
+ if (dim < 2) {
749
+ throw new Error(`ChemicalPotentialDiagram requires 2+ elements, got ${dim}`);
750
+ }
751
+ // Check all elemental refs exist for the computation elements
752
+ const missing_refs = compute_elements.filter((el) => !el_refs[el]);
753
+ if (missing_refs.length > 0) {
754
+ throw new Error(`Missing elemental reference entries for: ${missing_refs.join(`, `)}`);
755
+ }
756
+ // Renormalize if using formal chemical potentials
757
+ if (formal_chempots) {
758
+ min_entries = renormalize_entries(min_entries, el_refs, compute_elements);
759
+ const renorm_result = get_min_entries_and_el_refs(min_entries);
760
+ el_refs = renorm_result.el_refs;
761
+ }
762
+ // Build limits array for computation elements
763
+ const compute_lims = compute_elements.map((el) => {
764
+ if (limits?.[el])
765
+ return limits[el];
766
+ return [default_min_limit, 0];
586
767
  });
768
+ // Build hyperplanes and compute domains in full dimensionality
769
+ const { hyperplanes, hyperplane_entries } = build_hyperplanes(min_entries, el_refs, compute_elements);
770
+ const border_hyperplanes = build_border_hyperplanes(compute_lims);
771
+ const domains = compute_domains(hyperplanes, border_hyperplanes, hyperplane_entries, dim);
772
+ nd_result = {
773
+ domains,
774
+ el_refs,
775
+ min_entries,
776
+ hyperplanes,
777
+ hyperplane_entries,
778
+ compute_lims,
779
+ };
780
+ // Cache for projection mode reuse
781
+ if (is_projection) {
782
+ _nd_cache = { key: cache_key, result: nd_result };
783
+ }
587
784
  }
588
- // Sort entries by composition (Schwartzian transform to avoid recomputing keys)
589
- const sorted_entries = working_entries
590
- .map((entry) => ({ entry, key: formula_key_from_composition(entry.composition) }))
591
- .sort((a, b) => a.key.localeCompare(b.key))
592
- .map(({ entry }) => entry);
593
- // Get min entries and elemental references
594
- let { min_entries, el_refs } = get_min_entries_and_el_refs(sorted_entries);
595
- const dim = compute_elements.length;
596
- if (dim < 2) {
597
- throw new Error(`ChemicalPotentialDiagram requires 2+ elements, got ${dim}`);
598
- }
599
- // Check all elemental refs exist for the computation elements
600
- const missing_refs = compute_elements.filter((el) => !el_refs[el]);
601
- if (missing_refs.length > 0) {
602
- throw new Error(`Missing elemental reference entries for: ${missing_refs.join(`, `)}`);
603
- }
604
- // Renormalize if using formal chemical potentials
605
- if (formal_chempots) {
606
- min_entries = renormalize_entries(min_entries, el_refs, compute_elements);
607
- const renorm_result = get_min_entries_and_el_refs(min_entries);
608
- el_refs = renorm_result.el_refs;
609
- }
610
- // Build limits array for computation elements
611
- const compute_lims = compute_elements.map((el) => {
612
- if (limits?.[el])
613
- return limits[el];
614
- return [default_min_limit, 0];
615
- });
616
- // Build hyperplanes and compute domains in full dimensionality
617
- const { hyperplanes, hyperplane_entries } = build_hyperplanes(min_entries, el_refs, compute_elements);
618
- const border_hyperplanes = build_border_hyperplanes(compute_lims);
619
- let domains = compute_domains(hyperplanes, border_hyperplanes, hyperplane_entries, dim);
785
+ let domains = nd_result.domains;
786
+ let output_lims = nd_result.compute_lims;
620
787
  // Project domain vertices from N-D to display axes (column extraction)
621
- let output_lims = compute_lims;
622
788
  if (is_projection) {
623
- const compute_index_by_element = new Map();
624
- for (let idx = 0; idx < compute_elements.length; idx++) {
625
- compute_index_by_element.set(compute_elements[idx], idx);
626
- }
627
789
  const col_indices = display_elements.map((element) => {
628
- const idx = compute_index_by_element.get(element);
629
- if (idx === undefined) {
790
+ const idx = compute_elements.indexOf(element);
791
+ if (idx < 0) {
630
792
  throw new Error(`Display element ${element} not present in compute element set`);
631
793
  }
632
794
  return idx;
@@ -636,15 +798,15 @@ export function compute_chempot_diagram(entries, config = {}) {
636
798
  projected[formula] = pts.map((pt) => col_indices.map((idx) => pt[idx]));
637
799
  }
638
800
  domains = projected;
639
- output_lims = col_indices.map((idx) => compute_lims[idx]);
801
+ output_lims = col_indices.map((col_idx) => nd_result.compute_lims[col_idx]);
640
802
  }
641
803
  return {
642
804
  domains,
643
805
  elements: display_elements,
644
- el_refs,
645
- min_entries,
646
- hyperplanes,
647
- hyperplane_entries,
806
+ el_refs: nd_result.el_refs,
807
+ min_entries: nd_result.min_entries,
808
+ hyperplanes: nd_result.hyperplanes,
809
+ hyperplane_entries: nd_result.hyperplane_entries,
648
810
  lims: output_lims,
649
811
  };
650
812
  }
@@ -1,5 +1,6 @@
1
1
  export { default as ChemPotDiagram } from './ChemPotDiagram.svelte';
2
2
  export { default as ChemPotDiagram2D } from './ChemPotDiagram2D.svelte';
3
3
  export { default as ChemPotDiagram3D } from './ChemPotDiagram3D.svelte';
4
- export { compute_chempot_diagram } from './compute';
4
+ export { compute_chempot_async } from './async-compute.svelte';
5
+ export { compute_chempot_diagram, get_ternary_combinations } from './compute';
5
6
  export * from './types';
@@ -1,5 +1,6 @@
1
1
  export { default as ChemPotDiagram } from './ChemPotDiagram.svelte';
2
2
  export { default as ChemPotDiagram2D } from './ChemPotDiagram2D.svelte';
3
3
  export { default as ChemPotDiagram3D } from './ChemPotDiagram3D.svelte';
4
- export { compute_chempot_diagram } from './compute';
4
+ export { compute_chempot_async } from './async-compute.svelte';
5
+ export { compute_chempot_diagram, get_ternary_combinations } from './compute';
5
6
  export * from './types';
@@ -3,15 +3,14 @@ import { CHEMPOT_DEFAULTS } from './types';
3
3
  export function get_projection_source_entries(entries, temp_filtered_entries) {
4
4
  return temp_filtered_entries.length > 0 ? temp_filtered_entries : entries;
5
5
  }
6
- function resolve_temp_filter_options(config, props) {
7
- return {
8
- interpolate: config.interpolate_temperature ?? props.interpolate_temperature ??
9
- CHEMPOT_DEFAULTS.interpolate_temperature,
10
- max_interpolation_gap: config.max_interpolation_gap ??
11
- props.max_interpolation_gap ??
12
- CHEMPOT_DEFAULTS.max_interpolation_gap,
13
- };
14
- }
6
+ const resolve_temp_filter_options = (config, props) => ({
7
+ interpolate: config.interpolate_temperature ??
8
+ props.interpolate_temperature ??
9
+ CHEMPOT_DEFAULTS.interpolate_temperature,
10
+ max_interpolation_gap: config.max_interpolation_gap ??
11
+ props.max_interpolation_gap ??
12
+ CHEMPOT_DEFAULTS.max_interpolation_gap,
13
+ });
15
14
  export function get_temp_filter_payload(entries, temperature, config, props) {
16
15
  const { has_temp_data, available_temperatures } = analyze_temperature_data(entries);
17
16
  if (!has_temp_data || temperature === undefined) {
@@ -2,6 +2,7 @@ import type { D3InterpolateName } from '../colors';
2
2
  import type { PhaseData } from '../convex-hull/types';
3
3
  export type ChemPotLimits = Partial<Record<string, [number, number]>>;
4
4
  export type ChemPotColorMode = `none` | `energy` | `formation_energy` | `arity` | `entries`;
5
+ export type ChemPotProjectionMode = `single` | `grid`;
5
6
  export interface ChemPotDiagramConfig {
6
7
  formal_chempots?: boolean;
7
8
  default_min_limit?: number;
@@ -20,6 +21,7 @@ export interface ChemPotDiagramConfig {
20
21
  reverse_color_scale?: boolean;
21
22
  interpolate_temperature?: boolean;
22
23
  max_interpolation_gap?: number;
24
+ projection_mode?: ChemPotProjectionMode;
23
25
  }
24
26
  export interface ChemPotDiagramData {
25
27
  domains: Record<string, number[][]>;
@@ -79,5 +81,6 @@ export declare const CHEMPOT_DEFAULTS: {
79
81
  readonly reverse_color_scale: true;
80
82
  readonly interpolate_temperature: true;
81
83
  readonly max_interpolation_gap: 500;
84
+ readonly projection_mode: ChemPotProjectionMode;
82
85
  readonly formula_colors: readonly ["#1b9e77", "#d95f02", "#7570b3", "#e7298a", "#66a61e", "#e6ab02", "#a6761d", "#666666"];
83
86
  };