matsci-parse 0.2.0 → 0.3.1

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 (2) hide show
  1. package/dist/main.js +694 -327
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -1,42 +1,61 @@
1
- class x {
2
- constructor(t, e, i = {}) {
3
- this.speciesIndex = t, this.cart = e, this.props = i;
1
+ class S {
2
+ constructor(s, e, t = {}) {
3
+ this.speciesIndex = s, this.cart = e, this.props = t;
4
4
  }
5
- getProp(t) {
6
- return this.props[t];
5
+ getProp(s) {
6
+ return this.props[s];
7
7
  }
8
- setProp(t, e) {
9
- this.props[t] = e;
8
+ setProp(s, e) {
9
+ this.props[s] = e;
10
10
  }
11
11
  }
12
- function C(s) {
13
- return s.sites.some((t) => Array.isArray(t.props.selectiveDynamics));
12
+ function B(i) {
13
+ return i.sites.some((s) => Array.isArray(s.props.selectiveDynamics));
14
14
  }
15
- function F(s) {
16
- return s * Math.PI / 180;
15
+ function M(i) {
16
+ return i * Math.PI / 180;
17
17
  }
18
- function M(s, t) {
19
- return s.map(
20
- (e) => e[0] * t[0] + e[1] * t[1] + e[2] * t[2]
18
+ function O(i, s) {
19
+ return i.map(
20
+ (e) => e[0] * s[0] + e[1] * s[1] + e[2] * s[2]
21
21
  );
22
22
  }
23
- function P(s, t, e, i, o, n) {
24
- const a = F(i), h = F(o), l = F(n), p = [s, 0, 0], f = [
25
- t * Math.cos(l),
26
- t * Math.sin(l),
23
+ function k(i, s, e, t, m, o) {
24
+ const n = M(t), u = M(m), a = M(o), b = [i, 0, 0], h = [
25
+ s * Math.cos(a),
26
+ s * Math.sin(a),
27
27
  0
28
- ], r = e * Math.cos(h), u = e * (Math.cos(a) - Math.cos(h) * Math.cos(l)) / Math.sin(l), g = Math.sqrt(e * e - r * r - u * u);
29
- return [p, f, [r, u, g]];
28
+ ], r = e * Math.cos(u), l = e * (Math.cos(n) - Math.cos(u) * Math.cos(a)) / Math.sin(a), y = Math.sqrt(e * e - r * r - l * l);
29
+ return [b, h, [r, l, y]];
30
30
  }
31
- function O(s, t) {
32
- const [e, i, o] = t;
31
+ function U(i, s) {
32
+ const [e, t, m] = s;
33
33
  return [
34
- s[0] * e[0] + s[1] * i[0] + s[2] * o[0],
35
- s[0] * e[1] + s[1] * i[1] + s[2] * o[1],
36
- s[0] * e[2] + s[1] * i[2] + s[2] * o[2]
34
+ i[0] * e[0] + i[1] * t[0] + i[2] * m[0],
35
+ i[0] * e[1] + i[1] * t[1] + i[2] * m[1],
36
+ i[0] * e[2] + i[1] * t[2] + i[2] * m[2]
37
37
  ];
38
38
  }
39
- class S {
39
+ function X(i) {
40
+ const [[s, e, t], [m, o, n], [u, a, b]] = i, h = o * b - n * a, r = -(m * b - n * u), l = m * a - o * u, y = -(e * b - t * a), c = s * b - t * u, p = -(s * a - e * u), N = e * n - t * o, g = -(s * n - t * m), _ = s * o - e * m, v = s * h + e * r + t * l;
41
+ if (Math.abs(v) < 1e-12)
42
+ throw new Error("Matrix is singular and cannot be inverted");
43
+ const f = 1 / v;
44
+ return [
45
+ [h * f, y * f, N * f],
46
+ [r * f, c * f, g * f],
47
+ [l * f, p * f, _ * f]
48
+ ];
49
+ }
50
+ function J(i, s) {
51
+ const [e, t, m] = s, o = [
52
+ [e[0], t[0], m[0]],
53
+ [e[1], t[1], m[1]],
54
+ [e[2], t[2], m[2]]
55
+ ], n = X(o);
56
+ return O(n, i);
57
+ }
58
+ class F {
40
59
  /**
41
60
  * Creates a new CrystalStructure.
42
61
  *
@@ -48,11 +67,11 @@ class S {
48
67
  * @throws Will throw an error if lattice is not 3x3, species is not an array of strings, or sites are invalid
49
68
  */
50
69
  constructor({
51
- lattice: t,
70
+ lattice: s,
52
71
  species: e,
53
- sites: i
72
+ sites: t
54
73
  }) {
55
- this.lattice = this._validateLattice(t), this.species = this._validateSpecies(e), this.sites = this._validateSites(i);
74
+ this.lattice = this._validateLattice(s), this.species = this._validateSpecies(e), this.sites = this._validateSites(t);
56
75
  }
57
76
  // ---------- Simple methods ----------
58
77
  /** Number of sites in the structure */
@@ -63,22 +82,22 @@ class S {
63
82
  * Returns the site at the specified index.
64
83
  * @param i - Site index
65
84
  */
66
- site(t) {
67
- return this.sites[t];
85
+ site(s) {
86
+ return this.sites[s];
68
87
  }
69
88
  /**
70
89
  * Returns the Cartesian coordinates of a site.
71
90
  * @param i - Site index
72
91
  */
73
- cartCoords(t) {
74
- return this.sites[t].cart;
92
+ cartCoords(s) {
93
+ return this.sites[s].cart;
75
94
  }
76
95
  /**
77
96
  * Returns the chemical species of a site.
78
97
  * @param i - Site index
79
98
  */
80
- siteSpecies(t) {
81
- return this.species[this.sites[t].speciesIndex];
99
+ siteSpecies(s) {
100
+ return this.species[this.sites[s].speciesIndex];
82
101
  }
83
102
  /** Returns the array of elements (species) in the structure */
84
103
  get elements() {
@@ -92,11 +111,11 @@ class S {
92
111
  * @param cart - Cartesian coordinates of the new site
93
112
  * @param position - Optional index at which to insert the site. Defaults to appending at the end.
94
113
  */
95
- addSite(t, e, i) {
96
- let o = this.species.indexOf(t);
97
- o === -1 && (this.species.push(t), o = this.species.length - 1);
98
- const n = new x(o, e);
99
- i === void 0 || i >= this.sites.length ? this.sites.push(n) : i < 0 ? this.sites.unshift(n) : this.sites.splice(i, 0, n);
114
+ addSite(s, e, t) {
115
+ let m = this.species.indexOf(s);
116
+ m === -1 && (this.species.push(s), m = this.species.length - 1);
117
+ const o = new S(m, e);
118
+ t === void 0 || t >= this.sites.length ? this.sites.push(o) : t < 0 ? this.sites.unshift(o) : this.sites.splice(t, 0, o);
100
119
  }
101
120
  /**
102
121
  * Removes a site from the crystal.
@@ -107,14 +126,14 @@ class S {
107
126
  *
108
127
  * @throws Will throw an error if index is out of bounds
109
128
  */
110
- removeSite(t) {
111
- if (t < 0 || t >= this.sites.length)
129
+ removeSite(s) {
130
+ if (s < 0 || s >= this.sites.length)
112
131
  throw new Error("siteIndex out of bounds");
113
- const i = this.sites.splice(t, 1)[0].speciesIndex;
132
+ const t = this.sites.splice(s, 1)[0].speciesIndex;
114
133
  this.sites.some(
115
- (n) => n.speciesIndex === i
116
- ) || (this.species.splice(i, 1), this.sites.forEach((n) => {
117
- n.speciesIndex > i && (n.speciesIndex -= 1);
134
+ (o) => o.speciesIndex === t
135
+ ) || (this.species.splice(t, 1), this.sites.forEach((o) => {
136
+ o.speciesIndex > t && (o.speciesIndex -= 1);
118
137
  }));
119
138
  }
120
139
  /**
@@ -127,11 +146,11 @@ class S {
127
146
  *
128
147
  * @throws Will throw an error if siteIndex is out of bounds
129
148
  */
130
- replaceSite(t, e) {
131
- if (t < 0 || t >= this.sites.length)
149
+ replaceSite(s, e) {
150
+ if (s < 0 || s >= this.sites.length)
132
151
  throw new Error("siteIndex out of bounds");
133
- const i = [...this.sites[t].cart];
134
- this.removeSite(t), this.addSite(e, i, t);
152
+ const t = [...this.sites[s].cart];
153
+ this.removeSite(s), this.addSite(e, t, s);
135
154
  }
136
155
  /**
137
156
  * Returns a new CrystalStructure transformed by a linear matrix.
@@ -146,39 +165,39 @@ class S {
146
165
  *
147
166
  * @throws Will throw an error if scale is not a number, a 3-element array, or a 3x3 matrix
148
167
  */
149
- applyLatticeTransformation(t) {
168
+ applyLatticeTransformation(s) {
150
169
  let e;
151
- if (typeof t == "number")
170
+ if (typeof s == "number")
152
171
  e = [
153
- [t, 0, 0],
154
- [0, t, 0],
155
- [0, 0, t]
172
+ [s, 0, 0],
173
+ [0, s, 0],
174
+ [0, 0, s]
156
175
  ];
157
- else if (Array.isArray(t) && t.length === 3 && t.every((n) => typeof n == "number"))
176
+ else if (Array.isArray(s) && s.length === 3 && s.every((o) => typeof o == "number"))
158
177
  e = [
159
- [t[0], 0, 0],
160
- [0, t[1], 0],
161
- [0, 0, t[2]]
178
+ [s[0], 0, 0],
179
+ [0, s[1], 0],
180
+ [0, 0, s[2]]
162
181
  ];
163
- else if (Array.isArray(t) && t.length === 3 && t.every((n) => Array.isArray(n) && n.length === 3))
164
- e = t;
182
+ else if (Array.isArray(s) && s.length === 3 && s.every((o) => Array.isArray(o) && o.length === 3))
183
+ e = s;
165
184
  else
166
185
  throw new Error(
167
186
  "Scale must be a number, a 3-element array, or a 3x3 matrix"
168
187
  );
169
- const i = this.lattice.map(
170
- (n) => M(e, n)
171
- ), o = this.sites.map((n) => {
172
- const a = M(
188
+ const t = this.lattice.map(
189
+ (o) => O(e, o)
190
+ ), m = this.sites.map((o) => {
191
+ const n = O(
173
192
  e,
174
- n.cart
193
+ o.cart
175
194
  );
176
- return new x(n.speciesIndex, a, n.props);
195
+ return new S(o.speciesIndex, n, o.props);
177
196
  });
178
- return new S({
179
- lattice: i,
197
+ return new F({
198
+ lattice: t,
180
199
  species: [...this.species],
181
- sites: o
200
+ sites: m
182
201
  });
183
202
  }
184
203
  // ---------- Internal validation ----------
@@ -186,35 +205,35 @@ class S {
186
205
  * Validates that the lattice is a 3x3 array of Cartesian vectors.
187
206
  * @throws Will throw an error if lattice is invalid
188
207
  */
189
- _validateLattice(t) {
190
- if (!Array.isArray(t) || t.length !== 3)
208
+ _validateLattice(s) {
209
+ if (!Array.isArray(s) || s.length !== 3)
191
210
  throw new Error("Lattice must be a 3x3 matrix");
192
- return t.forEach((e) => {
211
+ return s.forEach((e) => {
193
212
  if (!Array.isArray(e) || e.length !== 3)
194
213
  throw new Error("Lattice vectors must be length 3");
195
- }), t;
214
+ }), s;
196
215
  }
197
216
  /**
198
217
  * Validates that species is an array of strings.
199
218
  * @throws Will throw an error if species array is invalid
200
219
  */
201
- _validateSpecies(t) {
202
- if (!Array.isArray(t)) throw new Error("Species must be an array");
203
- return t.forEach((e) => {
220
+ _validateSpecies(s) {
221
+ if (!Array.isArray(s)) throw new Error("Species must be an array");
222
+ return s.forEach((e) => {
204
223
  if (typeof e != "string")
205
224
  throw new Error("Species entries must be strings");
206
- }), t;
225
+ }), s;
207
226
  }
208
227
  /**
209
228
  * Validates the sites array, ensuring each site is a Site instance or a valid object.
210
229
  * @throws Will throw an error if sites array is invalid
211
230
  */
212
- _validateSites(t) {
213
- if (!Array.isArray(t)) throw new Error("Sites must be an array");
214
- return t.map((e) => {
215
- if (e instanceof x) return e;
231
+ _validateSites(s) {
232
+ if (!Array.isArray(s)) throw new Error("Sites must be an array");
233
+ return s.map((e) => {
234
+ if (e instanceof S) return e;
216
235
  if (typeof e == "object" && typeof e.speciesIndex == "number" && Array.isArray(e.cart) && e.cart.length === 3)
217
- return this._validateSpeciesIndex(e.speciesIndex), new x(
236
+ return this._validateSpeciesIndex(e.speciesIndex), new S(
218
237
  e.speciesIndex,
219
238
  e.cart,
220
239
  e.props ?? {}
@@ -228,230 +247,305 @@ class S {
228
247
  * Validates that a species index is within bounds.
229
248
  * @throws Will throw an error if index is out of range
230
249
  */
231
- _validateSpeciesIndex(t) {
232
- if (t < 0 || t >= this.species.length)
250
+ _validateSpeciesIndex(s) {
251
+ if (s < 0 || s >= this.species.length)
233
252
  throw new Error("speciesIndex out of bounds");
234
253
  }
235
254
  }
236
- function E(s) {
237
- return s.split(/\r?\n/).map((t) => t.trim()).filter(Boolean);
255
+ class Z {
256
+ constructor(s) {
257
+ this.spatialUnits = "angstrom", this._invalid = !0;
258
+ const { origin: e, basis: t, shape: m, values: o, components: n = 1, units: u } = s, [a, b, h] = m;
259
+ if (o.length !== a * b * h * n)
260
+ throw new Error(
261
+ `Invalid values length: expected ${a * b * h * n}, got ${o.length}`
262
+ );
263
+ this.origin = e, this.basis = t, this.shape = m, this.values = o, this.components = n, this.units = u;
264
+ }
265
+ invalidate() {
266
+ this._invalid = !0;
267
+ }
268
+ map(s) {
269
+ const [e, t, m] = this.shape;
270
+ for (let o = 0; o < m; o++)
271
+ for (let n = 0; n < t; n++)
272
+ for (let u = 0; u < e; u++)
273
+ for (let a = 0; a < this.components; a++) {
274
+ const b = this.index(u, n, o, a);
275
+ this.values[b] = s(this.values[b], u, n, o, a);
276
+ }
277
+ this.invalidate();
278
+ }
279
+ min() {
280
+ return (this._invalid || this._min === void 0) && this.computeStats(), this._min;
281
+ }
282
+ max() {
283
+ return (this._invalid || this._max === void 0) && this.computeStats(), this._max;
284
+ }
285
+ mean() {
286
+ return (this._invalid || this._mean === void 0) && this.computeStats(), this._mean;
287
+ }
288
+ index(s, e, t, m = 0) {
289
+ const [o, n] = this.shape;
290
+ return (s + o * (e + n * t)) * this.components + m;
291
+ }
292
+ get(s, e, t, m = 0) {
293
+ return this.values[this.index(s, e, t, m)];
294
+ }
295
+ set(s, e, t, m, o = 0) {
296
+ this.values[this.index(s, e, t, o)] = m, this.invalidate();
297
+ }
298
+ normalize() {
299
+ const s = this.min(), e = this.max();
300
+ this.map((t) => (t - s) / (e - s));
301
+ }
302
+ /** Convert grid index → Cartesian position */
303
+ position(s, e, t) {
304
+ const [m, o, n] = this.basis;
305
+ return [
306
+ this.origin[0] + s * m[0] + e * o[0] + t * n[0],
307
+ this.origin[1] + s * m[1] + e * o[1] + t * n[1],
308
+ this.origin[2] + s * m[2] + e * o[2] + t * n[2]
309
+ ];
310
+ }
311
+ voxelVolume() {
312
+ const [s, e, t] = this.basis;
313
+ return Math.abs(
314
+ s[0] * (e[1] * t[2] - e[2] * t[1]) - s[1] * (e[0] * t[2] - e[2] * t[0]) + s[2] * (e[0] * t[1] - e[1] * t[0])
315
+ );
316
+ }
317
+ integral() {
318
+ return this.mean() * this.values.length * this.voxelVolume();
319
+ }
320
+ computeStats() {
321
+ const s = this.values.length;
322
+ let e = 1 / 0, t = -1 / 0, m = 0;
323
+ for (let o = 0; o < s; o++) {
324
+ const n = this.values[o];
325
+ n < e && (e = n), n > t && (t = n), m += n;
326
+ }
327
+ this._min = e, this._max = t, this._mean = m / s, this._invalid = !1;
328
+ }
329
+ }
330
+ function I(i) {
331
+ return i.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
238
332
  }
239
- function D(s, t = 6) {
240
- const e = [], i = C(s);
241
- e.push("Generated by matsci-parse"), e.push("1.0"), s.lattice.forEach((a) => {
242
- e.push(a.map((h) => h.toFixed(t)).join(" "));
333
+ function Q(i, s = 6) {
334
+ const e = [], t = B(i);
335
+ e.push("Generated by matsci-parse"), e.push("1.0"), i.lattice.forEach((n) => {
336
+ e.push(n.map((u) => u.toFixed(s)).join(" "));
243
337
  });
244
- const o = Array.from(
245
- new Set(s.sites.map((a) => s.species[a.speciesIndex]))
246
- ), n = o.map(
247
- (a) => s.sites.filter((h) => s.species[h.speciesIndex] === a).length
338
+ const m = Array.from(
339
+ new Set(i.sites.map((n) => i.species[n.speciesIndex]))
340
+ ), o = m.map(
341
+ (n) => i.sites.filter((u) => i.species[u.speciesIndex] === n).length
248
342
  );
249
- return e.push(o.join(" ")), e.push(n.join(" ")), i && e.push("Selective dynamics"), e.push("Cartesian"), o.forEach((a) => {
250
- s.sites.filter((h) => s.species[h.speciesIndex] === a).forEach((h) => {
251
- const l = h.cart.map((p) => p.toFixed(t)).join(" ");
252
- if (i) {
253
- const f = (Array.isArray(h.props?.selectiveDynamics) ? h.props.selectiveDynamics : [!0, !0, !0]).map((r) => r ? "T" : "F").join(" ");
254
- e.push(`${l} ${f}`);
343
+ return e.push(m.join(" ")), e.push(o.join(" ")), t && e.push("Selective dynamics"), e.push("Cartesian"), m.forEach((n) => {
344
+ i.sites.filter((u) => i.species[u.speciesIndex] === n).forEach((u) => {
345
+ const a = u.cart.map((b) => b.toFixed(s)).join(" ");
346
+ if (t) {
347
+ const h = (Array.isArray(u.props?.selectiveDynamics) ? u.props.selectiveDynamics : [!0, !0, !0]).map((r) => r ? "T" : "F").join(" ");
348
+ e.push(`${a} ${h}`);
255
349
  } else
256
- e.push(l);
350
+ e.push(a);
257
351
  });
258
352
  }), e.join(`
259
353
  `);
260
354
  }
261
- function R(s) {
262
- let t = 0;
263
- t++;
264
- const e = parseFloat(s[t++]), i = [];
355
+ function z(i) {
356
+ let s = 0;
357
+ s++;
358
+ const e = parseFloat(i[s++]), t = [];
265
359
  for (let r = 0; r < 3; r++)
266
- i.push(
267
- s[t++].split(/\s+/).map((u) => parseFloat(u) * e)
360
+ t.push(
361
+ i[s++].split(/\s+/).map((l) => parseFloat(l) * e)
268
362
  );
269
- let o = s[t].trim(), n;
270
- /^[A-Za-z]/.test(o) && (n = o.split(/\s+/), t++);
271
- const a = s[t++].split(/\s+/).map(Number);
272
- n || (n = a.map((r, u) => `X${u + 1}`));
273
- let h = !1;
274
- s[t]?.toLowerCase().startsWith("s") && (h = !0, t++);
275
- const p = s[t++].toLowerCase().startsWith("d"), f = [];
276
- return n.forEach((r, u) => {
277
- for (let g = 0; g < a[u]; g++) {
278
- const c = s[t++].split(/\s+/).map(Number);
279
- let m;
280
- p ? m = [
281
- c[0] * i[0][0] + c[1] * i[1][0] + c[2] * i[2][0],
282
- c[0] * i[0][1] + c[1] * i[1][1] + c[2] * i[2][1],
283
- c[0] * i[0][2] + c[1] * i[1][2] + c[2] * i[2][2]
284
- ] : m = c.slice(0, 3);
285
- const w = {};
286
- if (h) {
287
- const y = c.slice(3, 6).map((b) => b === 1);
288
- y.length === 3 && (w.selectiveDynamics = y);
363
+ let m = i[s].trim(), o;
364
+ /^[A-Za-z]/.test(m) && (o = m.split(/\s+/), s++);
365
+ const n = i[s++].split(/\s+/).map(Number);
366
+ o || (o = n.map((r, l) => `X${l + 1}`));
367
+ let u = !1;
368
+ i[s]?.toLowerCase().startsWith("s") && (u = !0, s++);
369
+ const b = i[s++].toLowerCase().startsWith("d"), h = [];
370
+ return o.forEach((r, l) => {
371
+ for (let y = 0; y < n[l]; y++) {
372
+ const c = i[s++].split(/\s+/).map(Number);
373
+ let p;
374
+ b ? p = [
375
+ c[0] * t[0][0] + c[1] * t[1][0] + c[2] * t[2][0],
376
+ c[0] * t[0][1] + c[1] * t[1][1] + c[2] * t[2][1],
377
+ c[0] * t[0][2] + c[1] * t[1][2] + c[2] * t[2][2]
378
+ ] : p = c.slice(0, 3);
379
+ const N = {};
380
+ if (u) {
381
+ const g = c.slice(3, 6).map((_) => _ === 1);
382
+ g.length === 3 && (N.selectiveDynamics = g);
289
383
  }
290
- f.push(new x(u, m, w));
384
+ h.push(new S(l, p, N));
291
385
  }
292
386
  }), {
293
- structure: new S({ lattice: i, species: n, sites: f }),
294
- linesConsumed: t
387
+ structure: new F({ lattice: t, species: o, sites: h }),
388
+ linesConsumed: s
295
389
  };
296
390
  }
297
- function W(s) {
298
- const t = E(s);
299
- return R(t).structure;
391
+ function ss(i) {
392
+ const s = I(i);
393
+ return z(s).structure;
300
394
  }
301
- function k(s, t = 6) {
395
+ function es(i, s = 6) {
302
396
  const e = [];
303
- return e.push("CRYSTAL"), e.push("PRIMVEC"), s.lattice.forEach((i) => {
304
- e.push(i.map((o) => o.toFixed(t)).join(" "));
305
- }), e.push("PRIMCOORD"), e.push(`${s.numSites} 1`), s.sites.forEach((i) => {
306
- const o = s.species[i.speciesIndex];
397
+ return e.push("CRYSTAL"), e.push("PRIMVEC"), i.lattice.forEach((t) => {
398
+ e.push(t.map((m) => m.toFixed(s)).join(" "));
399
+ }), e.push("PRIMCOORD"), e.push(`${i.numSites} 1`), i.sites.forEach((t) => {
400
+ const m = i.species[t.speciesIndex];
307
401
  e.push(
308
- `${o} ${i.cart.map((n) => n.toFixed(t)).join(" ")}`
402
+ `${m} ${t.cart.map((o) => o.toFixed(s)).join(" ")}`
309
403
  );
310
404
  }), e.join(`
311
405
  `);
312
406
  }
313
- function X(s) {
314
- const t = E(s), e = [], i = [], o = [];
315
- let n = 0;
316
- for (; n < t.length && t[n].toUpperCase() !== "PRIMVEC"; ) n++;
317
- if (n === t.length) throw new Error("PRIMVEC block not found in XSF");
318
- n++;
319
- for (let h = 0; h < 3; h++)
320
- e.push(t[n++].split(/\s+/).map(Number));
321
- for (; n < t.length && t[n].toUpperCase() !== "PRIMCOORD"; ) n++;
322
- if (n === t.length) throw new Error("PRIMCOORD block not found in XSF");
323
- n++;
324
- const [a] = t[n++].split(/\s+/).map(Number);
325
- for (let h = 0; h < a; h++) {
326
- const l = t[n++].split(/\s+/), p = l[0], f = l.slice(1, 4).map(Number);
327
- let r = i.indexOf(p);
328
- r === -1 && (i.push(p), r = i.length - 1), o.push(new x(r, f));
329
- }
330
- return new S({ lattice: e, species: i, sites: o });
407
+ function ts(i) {
408
+ const s = I(i), e = [], t = [], m = [];
409
+ let o = 0;
410
+ for (; o < s.length && s[o].toUpperCase() !== "PRIMVEC"; ) o++;
411
+ if (o === s.length) throw new Error("PRIMVEC block not found in XSF");
412
+ o++;
413
+ for (let u = 0; u < 3; u++)
414
+ e.push(s[o++].split(/\s+/).map(Number));
415
+ for (; o < s.length && s[o].toUpperCase() !== "PRIMCOORD"; ) o++;
416
+ if (o === s.length) throw new Error("PRIMCOORD block not found in XSF");
417
+ o++;
418
+ const [n] = s[o++].split(/\s+/).map(Number);
419
+ for (let u = 0; u < n; u++) {
420
+ const a = s[o++].split(/\s+/), b = a[0], h = a.slice(1, 4).map(Number);
421
+ let r = t.indexOf(b);
422
+ r === -1 && (t.push(b), r = t.length - 1), m.push(new S(r, h));
423
+ }
424
+ return new F({ lattice: e, species: t, sites: m });
331
425
  }
332
- function z(s, t = 6) {
333
- const e = [], i = s.sites.length;
334
- e.push(String(i));
335
- const o = C(s), n = s.lattice, a = [
336
- n[0][0],
337
- n[1][0],
338
- n[2][0],
339
- n[0][1],
340
- n[1][1],
341
- n[2][1],
342
- n[0][2],
343
- n[1][2],
344
- n[2][2]
345
- ].join(" "), h = [
426
+ function os(i, s = 6) {
427
+ const e = [], t = i.sites.length;
428
+ e.push(String(t));
429
+ const m = B(i), o = i.lattice, n = [
430
+ o[0][0],
431
+ o[1][0],
432
+ o[2][0],
433
+ o[0][1],
434
+ o[1][1],
435
+ o[2][1],
436
+ o[0][2],
437
+ o[1][2],
438
+ o[2][2]
439
+ ].join(" "), u = [
346
440
  "species:S:1",
347
441
  "pos:R:3",
348
- o ? "selectiveDynamics:L:3" : null
442
+ m ? "selectiveDynamics:L:3" : null
349
443
  ].filter(Boolean).join(":");
350
- e.push(`Lattice="${a}" Properties=${h}`);
351
- for (const l of s.sites) {
352
- const p = s.species[l.speciesIndex], [f, r, u] = l.cart;
353
- let g = `${p} ${f.toFixed(t)} ${r.toFixed(t)} ${u.toFixed(t)}`;
354
- if (o) {
355
- const c = Array.isArray(l.props?.selectiveDynamics) ? l.props.selectiveDynamics : [!0, !0, !0];
356
- g += " " + c.map((m) => m ? "T" : "F").join(" ");
444
+ e.push(`Lattice="${n}" Properties=${u}`);
445
+ for (const a of i.sites) {
446
+ const b = i.species[a.speciesIndex], [h, r, l] = a.cart;
447
+ let y = `${b} ${h.toFixed(s)} ${r.toFixed(s)} ${l.toFixed(s)}`;
448
+ if (m) {
449
+ const c = Array.isArray(a.props?.selectiveDynamics) ? a.props.selectiveDynamics : [!0, !0, !0];
450
+ y += " " + c.map((p) => p ? "T" : "F").join(" ");
357
451
  }
358
- e.push(g);
452
+ e.push(y);
359
453
  }
360
454
  return e.join(`
361
455
  `);
362
456
  }
363
- function Z(s) {
364
- const t = E(s);
457
+ function is(i) {
458
+ const s = I(i);
365
459
  let e = 0;
366
- const i = parseInt(t[e++], 10);
367
- if (!Number.isFinite(i))
460
+ const t = parseInt(s[e++], 10);
461
+ if (!Number.isFinite(t))
368
462
  throw new Error("Invalid XYZ: first line must be atom count");
369
- const o = t[e++], n = {}, a = /(\w+)=(".*?"|\S+)/g;
370
- for (const c of o.matchAll(a)) {
371
- let m = c[2];
372
- m.startsWith('"') && (m = m.slice(1, -1)), n[c[1]] = m;
373
- }
374
- let h;
375
- if (n.Lattice) {
376
- const c = n.Lattice.split(/\s+/).map(Number);
463
+ const m = s[e++], o = {}, n = /(\w+)=(".*?"|\S+)/g;
464
+ for (const c of m.matchAll(n)) {
465
+ let p = c[2];
466
+ p.startsWith('"') && (p = p.slice(1, -1)), o[c[1]] = p;
467
+ }
468
+ let u;
469
+ if (o.Lattice) {
470
+ const c = o.Lattice.split(/\s+/).map(Number);
377
471
  if (c.length !== 9) throw new Error("Invalid Lattice in extended XYZ");
378
- h = [
472
+ u = [
379
473
  [c[0], c[3], c[6]],
380
474
  [c[1], c[4], c[7]],
381
475
  [c[2], c[5], c[8]]
382
476
  ];
383
477
  } else
384
478
  throw new Error("Lattice must be present in extended XYZ format");
385
- let l = 0, p = 1, f = null;
386
- if (n.Properties) {
387
- const c = n.Properties.split(":");
388
- let m = 0;
389
- for (let w = 0; w < c.length; w += 3) {
390
- const y = c[w], b = parseInt(c[w + 2], 10);
391
- y === "species" && (l = m), y === "pos" && (p = m), y === "selectiveDynamics" && (f = m), m += b;
479
+ let a = 0, b = 1, h = null;
480
+ if (o.Properties) {
481
+ const c = o.Properties.split(":");
482
+ let p = 0;
483
+ for (let N = 0; N < c.length; N += 3) {
484
+ const g = c[N], _ = parseInt(c[N + 2], 10);
485
+ g === "species" && (a = p), g === "pos" && (b = p), g === "selectiveDynamics" && (h = p), p += _;
392
486
  }
393
487
  }
394
- const r = [], u = /* @__PURE__ */ new Map(), g = [];
395
- for (let c = 0; c < i; c++) {
396
- const m = t[e++].split(/\s+/), w = m[l];
397
- u.has(w) || (u.set(w, r.length), r.push(w));
398
- const y = u.get(w), b = m.slice(p, p + 3).map(Number), I = {};
399
- if (f !== null) {
400
- const _ = m.slice(f, f + 3).map((d) => d.toUpperCase() === "T");
401
- _.length === 3 && (I.selectiveDynamics = _);
488
+ const r = [], l = /* @__PURE__ */ new Map(), y = [];
489
+ for (let c = 0; c < t; c++) {
490
+ const p = s[e++].split(/\s+/), N = p[a];
491
+ l.has(N) || (l.set(N, r.length), r.push(N));
492
+ const g = l.get(N), _ = p.slice(b, b + 3).map(Number), v = {};
493
+ if (h !== null) {
494
+ const f = p.slice(h, h + 3).map((d) => d.toUpperCase() === "T");
495
+ f.length === 3 && (v.selectiveDynamics = f);
402
496
  }
403
- g.push(new x(y, b, I));
497
+ y.push(new S(g, _, v));
404
498
  }
405
- return new S({ lattice: h, species: r, sites: g });
499
+ return new F({ lattice: u, species: r, sites: y });
406
500
  }
407
- function A(s, t) {
408
- return s[0] * t[0] + s[1] * t[1] + s[2] * t[2];
501
+ function C(i, s) {
502
+ return i[0] * s[0] + i[1] * s[1] + i[2] * s[2];
409
503
  }
410
- function T(s) {
411
- return Math.sqrt(A(s, s));
504
+ function L(i) {
505
+ return Math.sqrt(C(i, i));
412
506
  }
413
- function L(s) {
414
- return s * 180 / Math.PI;
507
+ function P(i) {
508
+ return i * 180 / Math.PI;
415
509
  }
416
- function j(s, t) {
417
- const [e, i, o] = t, n = e[0] * (i[1] * o[2] - i[2] * o[1]) - e[1] * (i[0] * o[2] - i[2] * o[0]) + e[2] * (i[0] * o[1] - i[1] * o[0]);
418
- if (Math.abs(n) < 1e-12)
510
+ function G(i, s) {
511
+ const [e, t, m] = s, o = e[0] * (t[1] * m[2] - t[2] * m[1]) - e[1] * (t[0] * m[2] - t[2] * m[0]) + e[2] * (t[0] * m[1] - t[1] * m[0]);
512
+ if (Math.abs(o) < 1e-12)
419
513
  throw new Error("Singular lattice matrix");
420
- const a = [
514
+ const n = [
421
515
  [
422
- (i[1] * o[2] - i[2] * o[1]) / n,
423
- (e[2] * o[1] - e[1] * o[2]) / n,
424
- (e[1] * i[2] - e[2] * i[1]) / n
516
+ (t[1] * m[2] - t[2] * m[1]) / o,
517
+ (e[2] * m[1] - e[1] * m[2]) / o,
518
+ (e[1] * t[2] - e[2] * t[1]) / o
425
519
  ],
426
520
  [
427
- (i[2] * o[0] - i[0] * o[2]) / n,
428
- (e[0] * o[2] - e[2] * o[0]) / n,
429
- (e[2] * i[0] - e[0] * i[2]) / n
521
+ (t[2] * m[0] - t[0] * m[2]) / o,
522
+ (e[0] * m[2] - e[2] * m[0]) / o,
523
+ (e[2] * t[0] - e[0] * t[2]) / o
430
524
  ],
431
525
  [
432
- (i[0] * o[1] - i[1] * o[0]) / n,
433
- (e[1] * o[0] - e[0] * o[1]) / n,
434
- (e[0] * i[1] - e[1] * i[0]) / n
526
+ (t[0] * m[1] - t[1] * m[0]) / o,
527
+ (e[1] * m[0] - e[0] * m[1]) / o,
528
+ (e[0] * t[1] - e[1] * t[0]) / o
435
529
  ]
436
530
  ];
437
531
  return [
438
- s[0] * a[0][0] + s[1] * a[1][0] + s[2] * a[2][0],
439
- s[0] * a[0][1] + s[1] * a[1][1] + s[2] * a[2][1],
440
- s[0] * a[0][2] + s[1] * a[1][2] + s[2] * a[2][2]
532
+ i[0] * n[0][0] + i[1] * n[1][0] + i[2] * n[2][0],
533
+ i[0] * n[0][1] + i[1] * n[1][1] + i[2] * n[2][1],
534
+ i[0] * n[0][2] + i[1] * n[1][2] + i[2] * n[2][2]
441
535
  ];
442
536
  }
443
- function V(s, t = 6) {
444
- const [e, i, o] = s.lattice, n = T(e), a = T(i), h = T(o), l = L(Math.acos(A(i, o) / (a * h))), p = L(Math.acos(A(e, o) / (n * h))), f = L(Math.acos(A(e, i) / (n * a)));
537
+ function ms(i, s = 6) {
538
+ const [e, t, m] = i.lattice, o = L(e), n = L(t), u = L(m), a = P(Math.acos(C(t, m) / (n * u))), b = P(Math.acos(C(e, m) / (o * u))), h = P(Math.acos(C(e, t) / (o * n)));
445
539
  let r = `data_made_with_matsci-parse
446
540
  _symmetry_space_group_name_H-M 'P 1'
447
541
  _symmetry_Int_Tables_number 1
448
542
 
449
- _cell_length_a ${n.toFixed(t)}
450
- _cell_length_b ${a.toFixed(t)}
451
- _cell_length_c ${h.toFixed(t)}
452
- _cell_angle_alpha ${l.toFixed(t)}
453
- _cell_angle_beta ${p.toFixed(t)}
454
- _cell_angle_gamma ${f.toFixed(t)}
543
+ _cell_length_a ${o.toFixed(s)}
544
+ _cell_length_b ${n.toFixed(s)}
545
+ _cell_length_c ${u.toFixed(s)}
546
+ _cell_angle_alpha ${a.toFixed(s)}
547
+ _cell_angle_beta ${b.toFixed(s)}
548
+ _cell_angle_gamma ${h.toFixed(s)}
455
549
 
456
550
  loop_
457
551
  _atom_site_label
@@ -460,134 +554,407 @@ function V(s, t = 6) {
460
554
  _atom_site_fract_y
461
555
  _atom_site_fract_z
462
556
  `;
463
- return s.sites.forEach((u, g) => {
464
- const c = s.species[u.speciesIndex], m = j(u.cart, s.lattice);
465
- r += `${c}${g + 1} ${c} ${m[0].toFixed(t)} ${m[1].toFixed(
557
+ return i.sites.forEach((l, y) => {
558
+ const c = i.species[l.speciesIndex], p = G(l.cart, i.lattice);
559
+ r += `${c}${y + 1} ${c} ${p[0].toFixed(s)} ${p[1].toFixed(
466
560
  6
467
- )} ${m[2].toFixed(t)}
561
+ )} ${p[2].toFixed(s)}
468
562
  `;
469
563
  }), r;
470
564
  }
471
- function U(s) {
472
- const t = E(s);
473
- let e = 0, i = 0, o = 0, n = 0, a = 0, h = 0, l = [];
474
- const p = [];
475
- let f = !1, r = [], u = !1;
476
- for (const _ of t) {
477
- const d = _.trim();
565
+ function ns(i) {
566
+ const s = I(i);
567
+ let e = 0, t = 0, m = 0, o = 0, n = 0, u = 0, a = [];
568
+ const b = [];
569
+ let h = !1, r = [], l = !1;
570
+ for (const f of s) {
571
+ const d = f.trim();
478
572
  if (d) {
479
573
  if (d.startsWith("_cell_length_a")) e = parseFloat(d.split(/\s+/)[1]);
480
574
  else if (d.startsWith("_cell_length_b"))
481
- i = parseFloat(d.split(/\s+/)[1]);
575
+ t = parseFloat(d.split(/\s+/)[1]);
482
576
  else if (d.startsWith("_cell_length_c"))
483
- o = parseFloat(d.split(/\s+/)[1]);
577
+ m = parseFloat(d.split(/\s+/)[1]);
484
578
  else if (d.startsWith("_cell_angle_alpha"))
485
- n = parseFloat(d.split(/\s+/)[1]);
579
+ o = parseFloat(d.split(/\s+/)[1]);
486
580
  else if (d.startsWith("_cell_angle_beta"))
487
- a = parseFloat(d.split(/\s+/)[1]);
581
+ n = parseFloat(d.split(/\s+/)[1]);
488
582
  else if (d.startsWith("_cell_angle_gamma"))
489
- h = parseFloat(d.split(/\s+/)[1]);
583
+ u = parseFloat(d.split(/\s+/)[1]);
490
584
  else if (d.startsWith("loop_")) {
491
- f = !0, r = [], u = !1;
585
+ h = !0, r = [], l = !1;
492
586
  continue;
493
587
  }
494
- if (f && d.startsWith("_")) {
495
- r.push(d), d.includes("_atom_site_") && (u = !0);
588
+ if (h && d.startsWith("_")) {
589
+ r.push(d), d.includes("_atom_site_") && (l = !0);
496
590
  continue;
497
591
  }
498
- if (f && !d.startsWith("_")) {
499
- u && (l.length === 0 && (l = [...r]), p.push(d.split(/\s+/)));
592
+ if (h && !d.startsWith("_")) {
593
+ l && (a.length === 0 && (a = [...r]), b.push(d.split(/\s+/)));
500
594
  continue;
501
595
  }
502
596
  }
503
597
  }
504
- if (l.length === 0)
598
+ if (a.length === 0)
505
599
  throw new Error("No _atom_site loop found in CIF");
506
- const g = P(e, i, o, n, a, h), c = [], m = [], w = l.findIndex((_) => _.includes("fract_x")), y = l.findIndex((_) => _.includes("fract_y")), b = l.findIndex((_) => _.includes("fract_z")), I = l.findIndex((_) => _.includes("type_symbol"));
507
- if (w < 0 || y < 0 || b < 0 || I < 0)
600
+ const y = k(e, t, m, o, n, u), c = [], p = [], N = a.findIndex((f) => f.includes("fract_x")), g = a.findIndex((f) => f.includes("fract_y")), _ = a.findIndex((f) => f.includes("fract_z")), v = a.findIndex((f) => f.includes("type_symbol"));
601
+ if (N < 0 || g < 0 || _ < 0 || v < 0)
508
602
  throw new Error("CIF missing required _atom_site columns");
509
- for (const _ of p) {
603
+ for (const f of b) {
510
604
  const d = [
511
- parseFloat(_[w]),
512
- parseFloat(_[y]),
513
- parseFloat(_[b])
514
- ], $ = O(d, g);
515
- let v = c.indexOf(_[I]);
516
- v === -1 && (v = c.length, c.push(_[I])), m.push(new x(v, $));
517
- }
518
- return new S({ lattice: g, species: c, sites: m });
605
+ parseFloat(f[N]),
606
+ parseFloat(f[g]),
607
+ parseFloat(f[_])
608
+ ], w = U(d, y);
609
+ let x = c.indexOf(f[v]);
610
+ x === -1 && (x = c.length, c.push(f[v])), p.push(new S(x, w));
611
+ }
612
+ return new F({ lattice: y, species: c, sites: p });
519
613
  }
520
- function N(s) {
521
- let t = [];
614
+ function Y(i) {
615
+ let s = [];
522
616
  const e = [];
523
- for (let l = 0; l < s.length; l++) {
524
- const p = s[l].trim();
525
- if (!(!p || p.startsWith("&")) && /^CELL_PARAMETERS/i.test(p)) {
526
- let f = 0, r = l + 1;
527
- for (; f < 3 && r < s.length; ) {
528
- const u = s[r].trim();
529
- u !== "" && (t.push(u.split(/\s+/).map(Number)), f++), r++;
617
+ for (let a = 0; a < i.length; a++) {
618
+ const b = i[a].trim();
619
+ if (!(!b || b.startsWith("&")) && /^CELL_PARAMETERS/i.test(b)) {
620
+ let h = 0, r = a + 1;
621
+ for (; h < 3 && r < i.length; ) {
622
+ const l = i[r].trim();
623
+ l !== "" && (s.push(l.split(/\s+/).map(Number)), h++), r++;
530
624
  }
531
- if (f < 3) throw new Error("Incomplete CELL_PARAMETERS block");
625
+ if (h < 3) throw new Error("Incomplete CELL_PARAMETERS block");
532
626
  break;
533
627
  }
534
628
  }
535
- if (t.length !== 3)
629
+ if (s.length !== 3)
536
630
  throw new Error("CELL_PARAMETERS block not found or incomplete");
537
- let i = !1, o = "angstrom";
538
- for (let l = 0; l < s.length; l++) {
539
- const p = s[l].trim();
540
- if (!(!p || p.startsWith("&"))) {
541
- if (/^ATOMIC_POSITIONS/i.test(p)) {
542
- i = !0;
543
- const f = p.match(/^ATOMIC_POSITIONS\s+(\w+)/i);
544
- o = f ? f[1].toLowerCase() : "angstrom";
631
+ let t = !1, m = "angstrom";
632
+ for (let a = 0; a < i.length; a++) {
633
+ const b = i[a].trim();
634
+ if (!(!b || b.startsWith("&"))) {
635
+ if (/^ATOMIC_POSITIONS/i.test(b)) {
636
+ t = !0;
637
+ const h = b.match(/^ATOMIC_POSITIONS\s+(\w+)/i);
638
+ m = h ? h[1].toLowerCase() : "angstrom";
545
639
  continue;
546
640
  }
547
- if (i) {
548
- const f = p.split(/\s+/);
549
- if (f.length < 4 || !/^[A-Za-z]/.test(f[0]) || f.slice(1, 4).some((r) => Number.isNaN(Number(r))))
641
+ if (t) {
642
+ const h = b.split(/\s+/);
643
+ if (h.length < 4 || !/^[A-Za-z]/.test(h[0]) || h.slice(1, 4).some((r) => Number.isNaN(Number(r))))
550
644
  break;
551
- e.push(p);
645
+ e.push(b);
552
646
  }
553
647
  }
554
648
  }
555
649
  if (e.length === 0)
556
650
  throw new Error("ATOMIC_POSITIONS block not found");
557
- const n = o === "crystal", a = [];
558
- for (const l of e) {
559
- const p = l.split(/\s+/)[0];
560
- a.includes(p) || a.push(p);
561
- }
562
- const h = [];
563
- for (const l of e) {
564
- const p = l.split(/\s+/), f = p[0], r = p.slice(1, 4).map(Number);
565
- let u;
566
- n ? u = [
567
- r[0] * t[0][0] + r[1] * t[1][0] + r[2] * t[2][0],
568
- r[0] * t[0][1] + r[1] * t[1][1] + r[2] * t[2][1],
569
- r[0] * t[0][2] + r[1] * t[1][2] + r[2] * t[2][2]
570
- ] : u = r, h.push(new x(a.indexOf(f), u));
651
+ const o = m === "crystal", n = [];
652
+ for (const a of e) {
653
+ const b = a.split(/\s+/)[0];
654
+ n.includes(b) || n.push(b);
655
+ }
656
+ const u = [];
657
+ for (const a of e) {
658
+ const b = a.split(/\s+/), h = b[0], r = b.slice(1, 4).map(Number);
659
+ let l;
660
+ o ? l = [
661
+ r[0] * s[0][0] + r[1] * s[1][0] + r[2] * s[2][0],
662
+ r[0] * s[0][1] + r[1] * s[1][1] + r[2] * s[2][1],
663
+ r[0] * s[0][2] + r[1] * s[1][2] + r[2] * s[2][2]
664
+ ] : l = r, u.push(new S(n.indexOf(h), l));
571
665
  }
572
666
  return {
573
- structure: new S({ lattice: t, species: a, sites: h }),
574
- linesConsumed: s.length
667
+ structure: new F({ lattice: s, species: n, sites: u }),
668
+ linesConsumed: i.length
575
669
  };
576
670
  }
577
- function Y(s) {
578
- const t = E(s);
579
- return N(t).structure;
671
+ function as(i) {
672
+ const s = I(i);
673
+ return Y(s).structure;
674
+ }
675
+ const D = {
676
+ 1: { atomicNumber: 1, symbol: "H", name: "Hydrogen", mass: 1.008 },
677
+ 2: { atomicNumber: 2, symbol: "He", name: "Helium", mass: 4.0026 },
678
+ 3: { atomicNumber: 3, symbol: "Li", name: "Lithium", mass: 6.94 },
679
+ 4: { atomicNumber: 4, symbol: "Be", name: "Beryllium", mass: 9.0122 },
680
+ 5: { atomicNumber: 5, symbol: "B", name: "Boron", mass: 10.81 },
681
+ 6: { atomicNumber: 6, symbol: "C", name: "Carbon", mass: 12.011 },
682
+ 7: { atomicNumber: 7, symbol: "N", name: "Nitrogen", mass: 14.007 },
683
+ 8: { atomicNumber: 8, symbol: "O", name: "Oxygen", mass: 15.999 },
684
+ 9: { atomicNumber: 9, symbol: "F", name: "Fluorine", mass: 18.998 },
685
+ 10: { atomicNumber: 10, symbol: "Ne", name: "Neon", mass: 20.18 },
686
+ 11: { atomicNumber: 11, symbol: "Na", name: "Sodium", mass: 22.99 },
687
+ 12: { atomicNumber: 12, symbol: "Mg", name: "Magnesium", mass: 24.305 },
688
+ 13: { atomicNumber: 13, symbol: "Al", name: "Aluminum", mass: 26.982 },
689
+ 14: { atomicNumber: 14, symbol: "Si", name: "Silicon", mass: 28.085 },
690
+ 15: { atomicNumber: 15, symbol: "P", name: "Phosphorus", mass: 30.974 },
691
+ 16: { atomicNumber: 16, symbol: "S", name: "Sulfur", mass: 32.06 },
692
+ 17: { atomicNumber: 17, symbol: "Cl", name: "Chlorine", mass: 35.45 },
693
+ 18: { atomicNumber: 18, symbol: "Ar", name: "Argon", mass: 39.948 },
694
+ 19: { atomicNumber: 19, symbol: "K", name: "Potassium", mass: 39.098 },
695
+ 20: { atomicNumber: 20, symbol: "Ca", name: "Calcium", mass: 40.078 },
696
+ 21: { atomicNumber: 21, symbol: "Sc", name: "Scandium", mass: 44.956 },
697
+ 22: { atomicNumber: 22, symbol: "Ti", name: "Titanium", mass: 47.867 },
698
+ 23: { atomicNumber: 23, symbol: "V", name: "Vanadium", mass: 50.942 },
699
+ 24: { atomicNumber: 24, symbol: "Cr", name: "Chromium", mass: 51.996 },
700
+ 25: { atomicNumber: 25, symbol: "Mn", name: "Manganese", mass: 54.938 },
701
+ 26: { atomicNumber: 26, symbol: "Fe", name: "Iron", mass: 55.845 },
702
+ 27: { atomicNumber: 27, symbol: "Co", name: "Cobalt", mass: 58.933 },
703
+ 28: { atomicNumber: 28, symbol: "Ni", name: "Nickel", mass: 58.693 },
704
+ 29: { atomicNumber: 29, symbol: "Cu", name: "Copper", mass: 63.546 },
705
+ 30: { atomicNumber: 30, symbol: "Zn", name: "Zinc", mass: 65.38 },
706
+ 31: { atomicNumber: 31, symbol: "Ga", name: "Gallium", mass: 69.723 },
707
+ 32: { atomicNumber: 32, symbol: "Ge", name: "Germanium", mass: 72.63 },
708
+ 33: { atomicNumber: 33, symbol: "As", name: "Arsenic", mass: 74.922 },
709
+ 34: { atomicNumber: 34, symbol: "Se", name: "Selenium", mass: 78.971 },
710
+ 35: { atomicNumber: 35, symbol: "Br", name: "Bromine", mass: 79.904 },
711
+ 36: { atomicNumber: 36, symbol: "Kr", name: "Krypton", mass: 83.798 },
712
+ 37: { atomicNumber: 37, symbol: "Rb", name: "Rubidium", mass: 85.468 },
713
+ 38: { atomicNumber: 38, symbol: "Sr", name: "Strontium", mass: 87.62 },
714
+ 39: { atomicNumber: 39, symbol: "Y", name: "Yttrium", mass: 88.906 },
715
+ 40: { atomicNumber: 40, symbol: "Zr", name: "Zirconium", mass: 91.224 },
716
+ 41: { atomicNumber: 41, symbol: "Nb", name: "Niobium", mass: 92.906 },
717
+ 42: { atomicNumber: 42, symbol: "Mo", name: "Molybdenum", mass: 95.95 },
718
+ 43: { atomicNumber: 43, symbol: "Tc", name: "Technetium", mass: 98 },
719
+ 44: { atomicNumber: 44, symbol: "Ru", name: "Ruthenium", mass: 101.07 },
720
+ 45: { atomicNumber: 45, symbol: "Rh", name: "Rhodium", mass: 102.91 },
721
+ 46: { atomicNumber: 46, symbol: "Pd", name: "Palladium", mass: 106.42 },
722
+ 47: { atomicNumber: 47, symbol: "Ag", name: "Silver", mass: 107.868 },
723
+ 48: { atomicNumber: 48, symbol: "Cd", name: "Cadmium", mass: 112.414 },
724
+ 49: { atomicNumber: 49, symbol: "In", name: "Indium", mass: 114.818 },
725
+ 50: { atomicNumber: 50, symbol: "Sn", name: "Tin", mass: 118.71 },
726
+ 51: { atomicNumber: 51, symbol: "Sb", name: "Antimony", mass: 121.76 },
727
+ 52: { atomicNumber: 52, symbol: "Te", name: "Tellurium", mass: 127.6 },
728
+ 53: { atomicNumber: 53, symbol: "I", name: "Iodine", mass: 126.904 },
729
+ 54: { atomicNumber: 54, symbol: "Xe", name: "Xenon", mass: 131.293 },
730
+ 55: { atomicNumber: 55, symbol: "Cs", name: "Cesium", mass: 132.905 },
731
+ 56: { atomicNumber: 56, symbol: "Ba", name: "Barium", mass: 137.33 },
732
+ 57: { atomicNumber: 57, symbol: "La", name: "Lanthanum", mass: 138.905 },
733
+ 58: { atomicNumber: 58, symbol: "Ce", name: "Cerium", mass: 140.12 },
734
+ 59: { atomicNumber: 59, symbol: "Pr", name: "Praseodymium", mass: 140.91 },
735
+ 60: { atomicNumber: 60, symbol: "Nd", name: "Neodymium", mass: 144.24 },
736
+ 61: { atomicNumber: 61, symbol: "Pm", name: "Promethium", mass: 145 },
737
+ 62: { atomicNumber: 62, symbol: "Sm", name: "Samarium", mass: 150.36 },
738
+ 63: { atomicNumber: 63, symbol: "Eu", name: "Europium", mass: 151.964 },
739
+ 64: { atomicNumber: 64, symbol: "Gd", name: "Gadolinium", mass: 157.25 },
740
+ 65: { atomicNumber: 65, symbol: "Tb", name: "Terbium", mass: 158.93 },
741
+ 66: { atomicNumber: 66, symbol: "Dy", name: "Dysprosium", mass: 162.5 },
742
+ 67: { atomicNumber: 67, symbol: "Ho", name: "Holmium", mass: 164.93 },
743
+ 68: { atomicNumber: 68, symbol: "Er", name: "Erbium", mass: 167.26 },
744
+ 69: { atomicNumber: 69, symbol: "Tm", name: "Thulium", mass: 168.93 },
745
+ 70: { atomicNumber: 70, symbol: "Yb", name: "Ytterbium", mass: 173.05 },
746
+ 71: { atomicNumber: 71, symbol: "Lu", name: "Lutetium", mass: 174.97 },
747
+ 72: { atomicNumber: 72, symbol: "Hf", name: "Hafnium", mass: 178.49 },
748
+ 73: { atomicNumber: 73, symbol: "Ta", name: "Tantalum", mass: 180.95 },
749
+ 74: { atomicNumber: 74, symbol: "W", name: "Tungsten", mass: 183.84 },
750
+ 75: { atomicNumber: 75, symbol: "Re", name: "Rhenium", mass: 186.207 },
751
+ 76: { atomicNumber: 76, symbol: "Os", name: "Osmium", mass: 190.23 },
752
+ 77: { atomicNumber: 77, symbol: "Ir", name: "Iridium", mass: 192.217 },
753
+ 78: { atomicNumber: 78, symbol: "Pt", name: "Platinum", mass: 195.084 },
754
+ 79: { atomicNumber: 79, symbol: "Au", name: "Gold", mass: 196.967 },
755
+ 80: { atomicNumber: 80, symbol: "Hg", name: "Mercury", mass: 200.592 },
756
+ 81: { atomicNumber: 81, symbol: "Tl", name: "Thallium", mass: 204.38 },
757
+ 82: { atomicNumber: 82, symbol: "Pb", name: "Lead", mass: 207.2 },
758
+ 83: { atomicNumber: 83, symbol: "Bi", name: "Bismuth", mass: 208.98 },
759
+ 84: { atomicNumber: 84, symbol: "Po", name: "Polonium", mass: 209 },
760
+ 85: { atomicNumber: 85, symbol: "At", name: "Astatine", mass: 210 },
761
+ 86: { atomicNumber: 86, symbol: "Rn", name: "Radon", mass: 222 },
762
+ 87: { atomicNumber: 87, symbol: "Fr", name: "Francium", mass: 223 },
763
+ 88: { atomicNumber: 88, symbol: "Ra", name: "Radium", mass: 226 },
764
+ 89: { atomicNumber: 89, symbol: "Ac", name: "Actinium", mass: 227 },
765
+ 90: { atomicNumber: 90, symbol: "Th", name: "Thorium", mass: 232.04 },
766
+ 91: { atomicNumber: 91, symbol: "Pa", name: "Protactinium", mass: 231.04 },
767
+ 92: { atomicNumber: 92, symbol: "U", name: "Uranium", mass: 238.03 },
768
+ 93: { atomicNumber: 93, symbol: "Np", name: "Neptunium", mass: 237 },
769
+ 94: { atomicNumber: 94, symbol: "Pu", name: "Plutonium", mass: 244 },
770
+ 95: { atomicNumber: 95, symbol: "Am", name: "Americium", mass: 243 },
771
+ 96: { atomicNumber: 96, symbol: "Cm", name: "Curium", mass: 247 },
772
+ 97: { atomicNumber: 97, symbol: "Bk", name: "Berkelium", mass: 247 },
773
+ 98: { atomicNumber: 98, symbol: "Cf", name: "Californium", mass: 251 },
774
+ 99: { atomicNumber: 99, symbol: "Es", name: "Einsteinium", mass: 252 },
775
+ 100: { atomicNumber: 100, symbol: "Fm", name: "Fermium", mass: 257 },
776
+ 101: { atomicNumber: 101, symbol: "Md", name: "Mendelevium", mass: 258 },
777
+ 102: { atomicNumber: 102, symbol: "No", name: "Nobelium", mass: 259 },
778
+ 103: { atomicNumber: 103, symbol: "Lr", name: "Lawrencium", mass: 262 },
779
+ 104: { atomicNumber: 104, symbol: "Rf", name: "Rutherfordium", mass: 267 },
780
+ 105: { atomicNumber: 105, symbol: "Db", name: "Dubnium", mass: 270 },
781
+ 106: { atomicNumber: 106, symbol: "Sg", name: "Seaborgium", mass: 269 },
782
+ 107: { atomicNumber: 107, symbol: "Bh", name: "Bohrium", mass: 270 },
783
+ 108: { atomicNumber: 108, symbol: "Hs", name: "Hassium", mass: 277 },
784
+ 109: { atomicNumber: 109, symbol: "Mt", name: "Meitnerium", mass: 278 },
785
+ 110: { atomicNumber: 110, symbol: "Ds", name: "Darmstadtium", mass: 281 },
786
+ 111: { atomicNumber: 111, symbol: "Rg", name: "Roentgenium", mass: 282 },
787
+ 112: { atomicNumber: 112, symbol: "Cn", name: "Copernicium", mass: 285 },
788
+ 113: { atomicNumber: 113, symbol: "Nh", name: "Nihonium", mass: 286 },
789
+ 114: { atomicNumber: 114, symbol: "Fl", name: "Flerovium", mass: 289 },
790
+ 115: { atomicNumber: 115, symbol: "Mc", name: "Moscovium", mass: 289 },
791
+ 116: { atomicNumber: 116, symbol: "Lv", name: "Livermorium", mass: 293 },
792
+ 117: { atomicNumber: 117, symbol: "Ts", name: "Tennessine", mass: 294 },
793
+ 118: { atomicNumber: 118, symbol: "Og", name: "Oganesson", mass: 294 }
794
+ }, q = {
795
+ angstrom: 1,
796
+ // canonical
797
+ bohr: 0.529177,
798
+ nm: 10,
799
+ pm: 0.01,
800
+ um: 1e4,
801
+ cm: 1e8,
802
+ m: 1e10,
803
+ fm: 1e-5
804
+ }, K = {
805
+ Å: "angstrom",
806
+ μm: "um"
807
+ }, $ = {
808
+ conversions: q,
809
+ aliases: K,
810
+ convert(i, s, e) {
811
+ const t = (n) => this.aliases[n] ?? n, m = t(s), o = t(e);
812
+ return m === o ? i : i * this.conversions[m] / this.conversions[o];
813
+ },
814
+ convertArray(i, s, e) {
815
+ return i.map((t) => this.convert(t, s, e));
816
+ }
817
+ }, R = 1.8897268;
818
+ function rs(i, s) {
819
+ const e = [];
820
+ e.push("Generated by matsci-parse"), e.push("Volumetric data export");
821
+ const m = [...s.origin].map((l) => l * R);
822
+ e.push(
823
+ `${i.numSites} ${m.map((l) => l.toFixed(6)).join(" ")}`
824
+ );
825
+ const o = s.shape, n = s.basis;
826
+ for (let l = 0; l < 3; l++) {
827
+ n[l];
828
+ const y = n[l].map((c) => c * R);
829
+ e.push(`${o[l]} ${y.map((c) => c.toFixed(6)).join(" ")}`);
830
+ }
831
+ for (const l of i.sites) {
832
+ const y = i.species[l.speciesIndex], c = Object.values(D).find(
833
+ (g) => g.symbol === y
834
+ )?.atomicNumber;
835
+ if (!c)
836
+ throw new Error(`Unknown element symbol: ${y}`);
837
+ [...l.cart];
838
+ const p = l.cart.map((g) => g * R), N = (l.getProp("charge") ?? 0).toFixed(6);
839
+ e.push(
840
+ `${c} ${N} ${p.map((g) => g.toFixed(6)).join(" ")}`
841
+ );
842
+ }
843
+ const u = s.values, [a, b, h] = o;
844
+ let r = [];
845
+ for (let l = 0; l < h; l++)
846
+ for (let y = 0; y < b; y++)
847
+ for (let c = 0; c < a; c++) {
848
+ const p = s.index(c, y, l);
849
+ r.push(u[p].toExponential(8)), r.length === 6 && (e.push(r.join(" ")), r = []);
850
+ }
851
+ return r.length > 0 && e.push(r.join(" ")), e.join(`
852
+ `);
853
+ }
854
+ function H(i, s = "bohr", e = "bohr", t = "bohr") {
855
+ let m = 0;
856
+ m += 2;
857
+ const o = i[m].split(/\s+/), n = parseInt(o[0]);
858
+ let u = [
859
+ parseFloat(o[1]),
860
+ parseFloat(o[2]),
861
+ parseFloat(o[3])
862
+ ];
863
+ m++;
864
+ const a = i[m++].split(/\s+/), b = i[m++].split(/\s+/), h = i[m++].split(/\s+/);
865
+ let r = [
866
+ [parseFloat(a[1]), parseFloat(a[2]), parseFloat(a[3])],
867
+ [parseFloat(b[1]), parseFloat(b[2]), parseFloat(b[3])],
868
+ [
869
+ parseFloat(h[1]),
870
+ parseFloat(h[2]),
871
+ parseFloat(h[3])
872
+ ]
873
+ ];
874
+ const l = [
875
+ parseInt(a[0], 10),
876
+ parseInt(b[0], 10),
877
+ parseInt(h[0], 10)
878
+ ], y = [], c = /* @__PURE__ */ new Map(), p = [];
879
+ for (let w = 0; w < n; w++, m++) {
880
+ const x = i[m].trim().split(/\s+/);
881
+ if (x.length < 5) throw new Error(`Malformed atom line: "${i[m]}"`);
882
+ const A = parseInt(x[0], 10), V = parseFloat(x[1]), W = [
883
+ parseFloat(x[2]),
884
+ parseFloat(x[3]),
885
+ parseFloat(x[4])
886
+ ], j = D[A];
887
+ if (!j) throw new Error(`Unknown atomic number: ${A}`);
888
+ const E = j.symbol;
889
+ let T = c.get(E);
890
+ T === void 0 && (T = y.length, y.push(E), c.set(E, T)), p.push(new S(T, W, { charge: V }));
891
+ }
892
+ u = $.convertArray(
893
+ u,
894
+ s,
895
+ "angstrom"
896
+ ), r = r.map(
897
+ (w) => $.convertArray(
898
+ w,
899
+ t,
900
+ "angstrom"
901
+ )
902
+ ), p.forEach((w) => {
903
+ w.cart = $.convertArray(
904
+ w.cart,
905
+ e,
906
+ "angstrom"
907
+ );
908
+ });
909
+ const N = r.map(
910
+ (w, x) => w.map((A) => A * l[x])
911
+ ), g = new F({
912
+ lattice: N,
913
+ species: y,
914
+ sites: p
915
+ }), _ = l[0] * l[1] * l[2], v = new Float32Array(_);
916
+ let f = 0;
917
+ for (; m < i.length && f < _; ) {
918
+ const w = i[m++].trim().split(/\s+/);
919
+ for (const x of w)
920
+ x && f < _ && (v[f] = parseFloat(x), f++);
921
+ }
922
+ if (f !== _)
923
+ throw new Error(`Cube file truncated: expected ${_}, got ${f}`);
924
+ const d = new Z({
925
+ origin: u,
926
+ basis: r,
927
+ shape: l,
928
+ values: v,
929
+ units: "e/ų"
930
+ });
931
+ return { structure: g, volumetricData: d, linesConsumed: m };
932
+ }
933
+ function cs(i) {
934
+ const s = I(i);
935
+ return H(s).volumetricData;
936
+ }
937
+ function ls(i) {
938
+ const s = I(i);
939
+ return H(s).structure;
580
940
  }
581
941
  export {
582
- S as CrystalStructure,
583
- x as Site,
584
- U as cifToStructure,
585
- W as poscarToStructure,
586
- Y as pwToStructure,
587
- V as structureToCif,
588
- D as structureToPoscar,
589
- k as structureToXsf,
590
- z as structureToXyz,
591
- X as xsfToStructure,
592
- Z as xyzToStructure
942
+ F as CrystalStructure,
943
+ S as Site,
944
+ Z as VolumetricData,
945
+ J as cartesianToFractional,
946
+ ns as cifToStructure,
947
+ ls as cubeToStructure,
948
+ cs as cubeToVolumetric,
949
+ U as fractionalToCartesian,
950
+ H as parseCube,
951
+ ss as poscarToStructure,
952
+ as as pwToStructure,
953
+ ms as structureToCif,
954
+ Q as structureToPoscar,
955
+ es as structureToXsf,
956
+ os as structureToXyz,
957
+ rs as volumetricToCube,
958
+ ts as xsfToStructure,
959
+ is as xyzToStructure
593
960
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "matsci-parse",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "main": "dist/main.js",
6
6
  "module": "dist/main.js",