-
+
diff --git a/docs/source/_static/images/example_color_by_species.png b/docs/source/_static/images/example_color_by_kind.png
similarity index 100%
rename from docs/source/_static/images/example_color_by_species.png
rename to docs/source/_static/images/example_color_by_kind.png
diff --git a/docs/source/atoms/atoms.rst b/docs/source/atoms/atoms.rst
index 373360f..a87ca6d 100644
--- a/docs/source/atoms/atoms.rst
+++ b/docs/source/atoms/atoms.rst
@@ -1,6 +1,6 @@
Atoms
=========
-The Atoms object represents a collection of atoms. It is used to store the positions, species, and other properties of the atoms. The sytax is very similar to ASE `Atoms `_ object. However, there are also some key differences regarding the species and attributes.
+The Atoms object represents a collection of atoms. It is used to store the positions, symbols, and other properties of the atoms. The sytax is very similar to ASE `Atoms `_ object. However, there are also some key differences regarding the kinds and attributes.
Example:
@@ -16,42 +16,42 @@ Example:
In this example, an Atoms object is created to represent a water molecule within a cubic unit cell with periodic boundaries. The object includes definitions for the symbols, positions of the atoms.
-Species
+Kind
-------
-Why do we use species instead of elements? Because of we want to store different properties for the same element:
+Why do we use kinds instead of elements? Because of we want to store different properties for the same element:
- such as: colors, bonds, etc.
- In DFT calculation, different potentials, basis sets, charge, magnetic moment, etc.
-A species has:
+A kind has:
-- symbol: the name of the species, e.g. 'O', 'H1', 'Fe_up', etc.
+- symbol: the name of the kind, e.g. 'O', 'H1', 'Fe_up', etc.
- element: the element symbol, e.g. 'O', 'H', 'Fe', etc.
- number: the atomic number of the element, e.g. 8, 1, 26, etc.
-One can define the species explicitly using the `species` attribute.
+One can define the kinds explicitly using the `kinds` attribute.
.. code-block:: javascript
const myAtoms = new Atoms({
symbols: ['O', 'H1', 'H2'], // symbols of the atoms
- species: {'H1': 'H', 'H2': 'H'}, // Defining the species
+ kinds: {'H1': 'H', 'H2': 'H'}, // Defining the kinds
});
Attributes and domain
----------------------
One can store additional data in the Atoms object using the `attributes`. The `attributes` has two domains:
-- `atoms`: store data that is specific to each atom, such as the charge or force.
-- `species`: store data that is specific to each species, such as the mass, color, or radius.
+- `atom`: store data that is specific to each atom, such as the charge or force.
+- `kind`: store data that is specific to each kind, such as the mass, color, or radius.
.. code-block:: javascript
- attributes: {'atoms': {'charge': [0, 0, 0],
+ attributes: {'atom': {'charge': [0, 0, 0],
'force': [[0, 0, 0], [0, 0, 0], [0, 0, 0]],
},
- 'species': {'mass': {'O': 15.999, 'H': 1.008},
+ 'kind': {'mass': {'O': 15.999, 'H': 1.008},
"color", {C: "red", H: "#b434eb", O: "#34eb77", S: "#FFFF00" },
"radius", {C: 0.77, H: 0.37, O: 0.66, S: 1.04},
},
@@ -63,13 +63,12 @@ Methods
The Atoms object has a number of methods that can be used to manipulate the data. These include methods to:
-Atomic and Species Manipulation
+Atomic and Kind Manipulation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- addSpecies(symbol, element = null)
+- addKind(symbol, element = null)
- addAtom(atom)
-- removeAtom(index)
-- replaceAtoms(indices, newSpeciesSymbol)
+- replaceAtoms(indices, newKindSymbol)
Cell and Boundary Conditions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -100,7 +99,7 @@ Information and Export
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- getAtomsCount()
-- getSpeciesCount()
+- getKindsCount()
- getCellLengthsAndAngles()
- calculateFractionalCoordinates()
- toDict()
diff --git a/docs/source/atoms/color.rst b/docs/source/atoms/color.rst
index 46434fc..52a7066 100644
--- a/docs/source/atoms/color.rst
+++ b/docs/source/atoms/color.rst
@@ -21,9 +21,9 @@ Supported style are:
-----------------------------
-Custom color for each species
+Custom color for each kind
-----------------------------
-Use can set custom color for each species. The color can be in the form of hex code or color name.
+Use can set custom color for each kind. The color can be in the form of hex code or color name.
.. code-block:: javascript
@@ -35,7 +35,7 @@ Use can set custom color for each species. The color can be in the form of hex c
weas.avr.drawModels()
-.. image:: ../_static/images/example_color_by_species.png
+.. image:: ../_static/images/example_color_by_kind.png
:width: 6cm
diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst
index 001389e..bf05f6b 100644
--- a/docs/source/quickstart.rst
+++ b/docs/source/quickstart.rst
@@ -77,7 +77,7 @@ Here is the result of the above code:
Features
--------
-- **Structure Manipulation**: Enables manipulation of the structure, such as adding, removing, translating, rotating atoms and modifying species, and cell parameters.
+- **Structure Manipulation**: Enables manipulation of the structure, such as adding, removing, translating, rotating atoms and modifying kind, and cell parameters.
- **Customizable Appearance**: Allows customization of atom and bond appearances, including colors, sizes, and visibility, polyhedra, and unit cell.
diff --git a/src/atoms/AtomsViewer.js b/src/atoms/AtomsViewer.js
index 2434934..7e4822d 100644
--- a/src/atoms/AtomsViewer.js
+++ b/src/atoms/AtomsViewer.js
@@ -369,7 +369,7 @@ class AtomsViewer {
// Remove labels
this.ALManager.settings = [];
} else if (newValue === "Symbol") {
- this.ALManager.settings = [{ origins: "positions", texts: "species" }];
+ this.ALManager.settings = [{ origins: "positions", texts: "symbols" }];
} else if (newValue === "Index") {
this.ALManager.settings = [{ origins: "positions", texts: "index" }];
}
@@ -572,7 +572,7 @@ class AtomsViewer {
addAtom(element, position = { x: 0, y: 0, z: 0 }) {
// Remove the selected atoms from the scene and data
const atom = new Atom(element, [position.x, position.y, position.z]);
- this.atoms.addSpecies(element);
+ this.atoms.addKind(element);
this.atoms.addAtom(atom);
// this.logger.debug("atoms: ", this.atoms);
@@ -598,7 +598,7 @@ class AtomsViewer {
}
const copied_atoms = this.atoms.getAtomsByIndices(indices);
this.logger.debug("copied_atoms: ", copied_atoms);
- this.atoms.addToSelf(copied_atoms);
+ this.atoms.add(copied_atoms);
this.logger.debug("atoms: ", this.atoms);
// also copy the properties, e.g. modelStyles, that are associated with the copied atoms
diff --git a/src/atoms/atoms.js b/src/atoms/atoms.js
index 7225d99..3df3607 100644
--- a/src/atoms/atoms.js
+++ b/src/atoms/atoms.js
@@ -1,12 +1,10 @@
import { elementAtomicNumbers } from "./atoms_data.js";
import { convertToMatrixFromABCAlphaBetaGamma, calculateInverseMatrix } from "../utils.js";
-class Species {
- constructor(symbol, element = null) {
- this.symbol = symbol; // Symbol of the species (e.g., 'C', 'C_1' for carbon)
- this._element = null;
- if (element === null) {
- element = symbol;
+class Kind {
+ constructor(element) {
+ if (!element) {
+ throw new Error("Element is required for Kind.");
}
this.element = element;
}
@@ -16,9 +14,8 @@ class Species {
}
set element(value) {
- // if value not in elementAtomicNumbers, raise a error
if (!elementAtomicNumbers[value]) {
- throw new Error(`Element '${value}' is wrong.`);
+ throw new Error(`Element '${value}' is invalid.`);
}
this._element = value;
}
@@ -29,8 +26,8 @@ class Species {
}
class Atom {
- constructor(species, position) {
- this.species = species; // the species in the species array
+ constructor(symbol, position) {
+ this.symbol = symbol; // the symbol in the symbols array
this.position = [...position]; // Position of the atom as a Float32Array
}
}
@@ -45,48 +42,41 @@ class Atoms {
[0, 0, 0],
],
pbc = [true, true, true],
- species = {},
- attributes = { atom: {}, species: {} },
+ kinds = {},
+ attributes = { atom: {}, kind: {} },
} = {}) {
this.uuid = null;
- // length of symbols should be the same with positions
if (symbols.length !== positions.length) {
throw new Error("The length of symbols should be the same with positions.");
}
this.symbols = symbols;
this.positions = positions;
- this.setSpecies(species, symbols);
+ this.setKinds(kinds, symbols);
this.setCell(cell);
this.setPBC(pbc);
this.setAttributes(attributes);
}
- setSpecies(species, symbols = null) {
- /*Initialize the Atoms instance from a dictionary of data.
- */
- this.species = {};
- if (typeof species !== "object") {
- throw new Error("Species should be a dictionary.");
+ setKinds(kinds, symbols = null) {
+ this.kinds = {};
+ if (typeof kinds !== "object") {
+ throw new Error("Kinds should be a dictionary.");
}
- // Iterate over each key-value pair in the species dictionary
- Object.entries(species).forEach(([symbol, element]) => {
- this.addSpecies(symbol, element);
+ Object.entries(kinds).forEach(([symbol, element]) => {
+ this.addKind(symbol, element);
});
- // find out species which not added
if (symbols) {
- const species = new Set(symbols);
- species.forEach((s) => {
- if (!this.species[s]) {
- this.addSpecies(s);
+ const kindsSet = new Set(symbols);
+ kindsSet.forEach((s) => {
+ if (!this.kinds[s]) {
+ this.addKind(s);
}
});
}
}
setAttributes(attributes) {
- /*Set the attributes of the Atoms instance.
- */
- this.attributes = { atom: {}, species: {}, "inter-species": {} };
+ this.attributes = { atom: {}, kind: {}, "inter-kind": {} };
for (const domain in attributes) {
for (const name in attributes[domain]) {
this.newAttribute(name, attributes[domain][name], domain);
@@ -95,38 +85,30 @@ class Atoms {
}
newAttribute(name, values, domain = "atom") {
- /*Add a new attribute to the Atoms instance.*/
if (domain === "atom") {
- // Ensure the length of values matches the number of atoms
if (values.length !== this.positions.length) {
throw new Error("The number of values does not match the number of atoms.");
}
- // copy the values, values could be a array of N-d array
this.attributes["atom"][name] = JSON.parse(JSON.stringify(values));
- } else if (domain === "species") {
- // Ensure that values are provided for each species
- for (const key of Object.keys(this.species)) {
+ } else if (domain === "kind") {
+ for (const key of Object.keys(this.kinds)) {
if (!(key in values)) {
- throw new Error(`Value for species '${key}' is missing.`);
+ throw new Error(`Value for kind '${key}' is missing.`);
}
}
- this.attributes["species"][name] = JSON.parse(JSON.stringify(values));
- } else if (domain === "inter-species") {
- // We don't require the values to be provided for each species
- this.attributes["species"][name] = JSON.parse(JSON.stringify(values));
+ this.attributes["kind"][name] = JSON.parse(JSON.stringify(values));
+ } else if (domain === "inter-kind") {
+ this.attributes["inter-kind"][name] = JSON.parse(JSON.stringify(values));
} else {
- throw new Error('Invalid domain. Must be either "atom", "species", or "inter-species".');
+ throw new Error('Invalid domain. Must be either "atom", "kind", or "inter-kind".');
}
}
getAttribute(name, domain = "atom") {
- /*Get the attribute of the Atoms instance.
- Species attributes read from the atoms directly: positions, species, index
- */
if (domain === "atom") {
if (name === "positions") {
return this.positions;
- } else if (name === "species") {
+ } else if (name === "symbols") {
return this.symbols;
} else if (name === "index") {
return Array.from({ length: this.positions.length }, (_, i) => i);
@@ -135,35 +117,31 @@ class Atoms {
throw new Error(`Attribute '${name}' is not defined. The available attributes are: ${Object.keys(this.attributes["atom"])}`);
}
return this.attributes["atom"][name];
- } else if (domain === "species") {
- if (!this.attributes["species"][name]) {
- throw new Error(`Attribute '${name}' is not defined. The available attributes are: ${Object.keys(this.attributes["species"])}`);
+ } else if (domain === "kind") {
+ if (!this.attributes["kind"][name]) {
+ throw new Error(`Attribute '${name}' is not defined. The available attributes are: ${Object.keys(this.attributes["kind"])}`);
}
- return this.attributes["species"][name];
- } else if (domain === "inter-species") {
+ return this.attributes["kind"][name];
+ } else if (domain === "inter-kind") {
if (!this.attributes[domain][name]) {
- throw new Error(`Attribute '${name}' is not defined in inter-species domain. The available attributes are: ${Object.keys(this.attributes[domain])}`);
+ throw new Error(`Attribute '${name}' is not defined in inter-kind domain. The available attributes are: ${Object.keys(this.attributes[domain])}`);
}
return this.attributes[domain][name];
} else {
- throw new Error('Invalid domain. Must be either "atom" or "species".');
+ throw new Error('Invalid domain. Must be either "atom", "kind", or "inter-kind".');
}
}
setCell(cell) {
- /*Set the unit cell of the Atoms instance.*/
if (cell.length === 9) {
- // Convert 1x9 array into 3x3 matrix format
this.cell = [
[cell[0], cell[1], cell[2]],
[cell[3], cell[4], cell[5]],
[cell[6], cell[7], cell[8]],
];
} else if (cell.length === 6) {
- // 1x6 array [a, b, c, alpha, beta, gamma]
this.cell = convertToMatrixFromABCAlphaBetaGamma(cell);
} else if (cell.length === 3) {
- // 1x3 array [a, b, c], assuming 90-degree angles
if (cell[0].length === 3) {
this.cell = cell;
} else {
@@ -176,11 +154,9 @@ class Atoms {
}
isUndefinedCell() {
- /*Check if the unit cell is undefined.*/
return this.cell.some((row) => row.every((cell) => cell === 0));
}
- // get cell length and angles
getCellLengthsAndAngles() {
const [a, b, c] = this.cell.map((row) => Math.sqrt(row[0] ** 2 + row[1] ** 2 + row[2] ** 2));
const alpha = (Math.acos((this.cell[1][0] * this.cell[2][0] + this.cell[1][1] * this.cell[2][1] + this.cell[1][2] * this.cell[2][2]) / (b * c)) * 180) / Math.PI;
@@ -190,103 +166,119 @@ class Atoms {
}
setPBC(pbc) {
- // if pbc is a boolean, convert it to a 3-element array
if (typeof pbc === "boolean") {
pbc = [pbc, pbc, pbc];
}
this.pbc = pbc;
}
- addSpecies(symbol, element = null) {
- // Create a new Species and add it to the species object
- if (!this.species[symbol]) {
- this.species[symbol] = new Species(symbol, element);
+ addKind(symbol, element = null) {
+ // if the kind is already defined, raise an error
+ if (this.kinds[symbol]) {
+ throw new Error(`Kind '${symbol}' is already defined.`);
+ } else {
+ if (!element) {
+ element = symbol;
+ }
+ // if element is a Kind, add it directly
+ if (element instanceof Kind) {
+ this.kinds[symbol] = element;
+ } else {
+ this.kinds[symbol] = new Kind(element);
+ }
}
}
getSymbols() {
- // Get the symbols of the species in the atoms
- return this.symbols.map((key) => this.species[key].symbol);
+ return this.symbols;
+ }
+
+ getElements() {
+ return this.symbols.map((symbol) => this.kinds[symbol].element);
}
addAtom(atom) {
- // Add an atom to the atoms
- if (!this.species[atom.species]) {
- this.addSpecies(atom.species);
+ if (!this.kinds[atom.symbol]) {
+ throw new Error(`Kind '${atom.symbol}' is not defined.`);
}
this.positions.push(atom.position);
- this.symbols.push(atom.species);
+ this.symbols.push(atom.symbol);
}
removeAtom(index) {
- // Remove an atom from the atoms by its index
- this.positions.splice(index * 4, 4);
+ this.positions.splice(index, 1);
+ this.symbols.splice(index, 1);
+ // Remove attributes in atom domain
+ for (const domain in this.attributes) {
+ for (const name in this.attributes["atom"]) {
+ this.attributes[domain][name].splice(index, 1);
+ }
+ }
}
- getSpeciesCount() {
- // Get the number of species in the atoms
- return this.species.length;
+ getKindsCount() {
+ return Object.keys(this.kinds).length;
}
getAtomsCount() {
- // Get the number of atoms in the atoms
- return this.positions.length; // Each atom uses 4 values (species index + x, y, z)
+ return this.positions.length;
}
- // Overload the "+" operator to concatenate two Atoms objects
add(otherAtoms) {
- const result = new Atoms();
- // Concatenate species
- result.species = { ...this.species, ...otherAtoms.species };
- // Concatenate positions
- result.positions = [...this.positions, ...otherAtoms.positions];
- // Additional attributes can be handled here if needed
- return result;
- }
-
- // Overload the "+=" operator to concatenate another Atoms object
- addToSelf(otherAtoms) {
- // Concatenate species
- this.species = { ...this.species, ...otherAtoms.species };
- // Concatenate positions
+ // if there same kind symbol, check if the element is the same
+ for (const symbol in otherAtoms.kinds) {
+ if (this.kinds[symbol] && this.kinds[symbol].element !== otherAtoms.kinds[symbol].element) {
+ throw new Error(`Kind '${symbol}' is defined in both Atoms objects with different elements.`);
+ }
+ }
+ this.kinds = { ...this.kinds, ...otherAtoms.kinds };
this.positions = [...this.positions, ...otherAtoms.positions];
this.symbols = [...this.symbols, ...otherAtoms.symbols];
-
- // Additional attributes can be handled here if needed
+ // Merge attributes in atom domain
+ for (const name in this.attributes["atom"]) {
+ this.attributes["atom"][name] = [...this.attributes["atom"][name], ...otherAtoms.attributes["atom"][name]];
+ }
+ // Merge attributes in kind domain
+ for (const name in this.attributes["kind"]) {
+ this.attributes["kind"][name] = {
+ // the order is important, the attributes of the added atoms should not overwrite the original ones
+ ...otherAtoms.attributes["kind"][name],
+ ...this.attributes["kind"][name],
+ };
+ }
+ return result;
}
multiply(mx, my, mz) {
- // Multiply the atoms in the Atoms object by the given dimensions
- console.time("multiply");
if (this.isUndefinedCell()) {
throw new Error("Cell matrix is not defined.");
}
const newAtoms = new Atoms();
- // Copy species object
- newAtoms.species = { ...this.species };
+ newAtoms.kinds = { ...this.kinds };
const [[ax, ay, az], [bx, by, bz], [cx, cy, cz]] = this.cell;
- newAtoms.setCell([ax * mx, ay * my, az * mz, bx * mx, by * my, bz * mz, cx * mx, cy * my, cz * mz]);
+ newAtoms.setCell([
+ [ax * mx, ay * mx, az * mx],
+ [bx * my, by * my, bz * my],
+ [cx * mz, cy * mz, cz * mz],
+ ]);
- // Replicate atoms
for (let ix = 0; ix < mx; ix++) {
for (let iy = 0; iy < my; iy++) {
for (let iz = 0; iz < mz; iz++) {
for (let i = 0; i < this.positions.length; i++) {
const [x, y, z] = this.positions[i];
- // Calculate new position considering the unit cell dimensions
const newX = x + ix * this.cell[0][0] + iy * this.cell[1][0] + iz * this.cell[2][0];
const newY = y + ix * this.cell[0][1] + iy * this.cell[1][1] + iz * this.cell[2][1];
const newZ = z + ix * this.cell[0][2] + iy * this.cell[1][2] + iz * this.cell[2][2];
- // Add the new atom to the newAtoms
newAtoms.symbols.push(this.symbols[i]);
newAtoms.positions.push([newX, newY, newZ]);
}
}
}
}
- // repeat attributes for each atom
+
for (const name in this.attributes["atom"]) {
const values = this.attributes["atom"][name];
const newValues = [];
@@ -301,25 +293,22 @@ class Atoms {
}
newAtoms.newAttribute(name, newValues, "atom");
}
- // console.timeEnd("multiply");
- // Return the new Atoms object
+ // copy attributes in kind domain, copy is necessary because the attributes of the added atoms should not overwrite the original ones
+ for (const name in this.attributes["kind"]) {
+ newAtoms.newAttribute(name, JSON.parse(JSON.stringify(this.attributes["kind"][name])), "kind");
+ }
return newAtoms;
}
translate(t) {
- for (let i = 0; i < this.positions.length; i++) {
- this.positions[i][0] += t[0]; // Shift x-coordinate
- this.positions[i][1] += t[1]; // Shift y-coordinate
- this.positions[i][2] += t[2]; // Shift z-coordinate
- }
+ this.positions = this.positions.map(([x, y, z]) => [x + t[0], y + t[1], z + t[2]]);
}
rotate(axis, angle, rotate_cell = false) {
const angleRad = (angle * Math.PI) / 180;
- const norm = Math.sqrt(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2]);
- const [u, v, w] = [axis[0] / norm, axis[1] / norm, axis[2] / norm]; // Normalized axis components
+ const norm = Math.sqrt(axis[0] ** 2 + axis[1] ** 2 + axis[2] ** 2);
+ const [u, v, w] = [axis[0] / norm, axis[1] / norm, axis[2] / norm];
- // Rodrigues' rotation formula components
const cosA = Math.cos(angleRad);
const sinA = Math.sin(angleRad);
const matrix = [
@@ -354,12 +343,11 @@ class Atoms {
}
}
- center(vacuum = 0.0, axis = (0, 1, 2), center = null) {
+ center(vacuum = 0.0, axis = [0, 1, 2], center = null) {
if (!this.cell) {
throw new Error("Cell is not defined.");
}
- // Calculate current center of mass or geometry
let centerOfMass = [0, 0, 0];
for (let i = 0; i < this.positions.length; i++) {
centerOfMass[0] += this.positions[i][0];
@@ -368,79 +356,87 @@ class Atoms {
}
centerOfMass = centerOfMass.map((x) => x / this.positions.length);
- // Determine target center point
let targetCenter = [0, 0, 0];
if (center) {
targetCenter = center;
} else {
for (let i = 0; i < 3; i++) {
if (axis.includes(i)) {
- targetCenter[i] = this.cell[i][i] / 2;
+ targetCenter[i] = (this.cell[0][i] + this.cell[1][i] + this.cell[2][i]) / 2;
}
}
}
- // Translate atoms to the target center
const translationVector = targetCenter.map((x, i) => x - centerOfMass[i]);
- this.translate(...translationVector);
+ this.translate(translationVector);
- // Adjust cell size if vacuum padding is specified
if (vacuum !== null) {
for (let i = 0; i < 3; i++) {
if (axis.includes(i)) {
- this.cell[i][i] += 2 * vacuum; // Increase the cell dimension
+ this.cell[i][i] += 2 * vacuum;
}
}
}
}
deleteAtoms(indices) {
- // Sort the indices in descending order to avoid index shifting
- indices.sort((a, b) => b - a);
-
- for (const index of indices) {
- if (index >= 0 && index < this.positions.length) {
- this.positions.splice(index, 1); // Remove the atom's position data
- this.symbols.splice(index, 1); // Remove the atom's species index
+ if (!Array.isArray(indices)) {
+ indices = [indices];
+ }
+ const indexSet = new Set(indices);
+ this.positions = this.positions.filter((_, i) => !indexSet.has(i));
+ this.symbols = this.symbols.filter((_, i) => !indexSet.has(i));
+ // Remove attributes in atom domain
+ for (const domain in this.attributes) {
+ for (const name in this.attributes["atom"]) {
+ this.attributes[domain][name] = this.attributes[domain][name].filter((_, i) => !indexSet.has(i));
+ }
+ }
+ // Remove kind symbols that are not used anymore and their attributes
+ const usedSymbols = new Set(this.symbols);
+ for (const symbol in this.kinds) {
+ if (!usedSymbols.has(symbol)) {
+ delete this.kinds[symbol];
+ for (const name in this.attributes["kind"]) {
+ delete this.attributes["kind"][name][symbol];
+ }
}
}
}
- replaceAtoms(indices, newSpeciesSymbol) {
- // if newSpeciesSymbol is not in species, add it
- if (!this.species[newSpeciesSymbol]) {
- this.addSpecies(newSpeciesSymbol);
+
+ replaceAtoms(indices, newKindSymbol, newKindElement = null) {
+ if (!this.kinds[newKindSymbol]) {
+ this.addKind(newKindSymbol, newKindElement);
}
for (const index of indices) {
if (index >= 0 && index < this.symbols.length) {
- // Replace the species of the atom at the specified index
- this.symbols[index] = newSpeciesSymbol;
+ this.symbols[index] = newKindSymbol;
+ } else {
+ throw new Error("Index out of bounds.");
}
}
}
+
toDict() {
const dict = {
uuid: this.uuid,
- species: {},
+ kinds: {},
positions: [],
cell: Array.from(this.cell || []),
pbc: Array.from(this.pbc),
symbols: [],
};
- // Populate species dictionary
- for (const [symbol, specie] of Object.entries(this.species)) {
- dict.species[symbol] = specie.element;
+ for (const [symbol, kind] of Object.entries(this.kinds)) {
+ dict.kinds[symbol] = kind.element;
}
- // Populate positions and symbols
- for (let i = 0; i < this.positions.length; i++) {
- dict.positions.push(Array.from(this.positions[i]));
- dict.symbols.push(this.symbols[i]);
- }
+ dict.positions = this.positions.map((position) => [...position]);
+ dict.symbols = [...this.symbols];
return dict;
}
- // Function to calculate fractional coordinates
+
calculateFractionalCoordinates() {
if (this.isUndefinedCell()) {
throw new Error("Cell matrix is not defined.");
@@ -460,13 +456,12 @@ class Atoms {
const newAtomsData = {
cell: JSON.parse(JSON.stringify(this.cell)),
pbc: JSON.parse(JSON.stringify(this.pbc)),
- species: {}, // Shallow copy is usually sufficient for an object of primitives
+ kinds: {},
symbols: [],
positions: [],
};
- // Initialize attributes for the new Atoms instance
- const newAttributes = { atom: {}, species: {} };
+ const newAttributes = { atom: {}, kind: {} };
for (const domain in this.attributes) {
for (const name in this.attributes[domain]) {
newAttributes[domain][name] = domain === "atom" ? [] : this.attributes[domain][name];
@@ -477,18 +472,16 @@ class Atoms {
if (index < 0 || index >= this.positions.length) {
throw new Error("Index out of bounds.");
}
- // Add species and position for each atom
newAtomsData.symbols.push(this.symbols[index]);
newAtomsData.positions.push(this.positions[index]);
- // Add attributes for each atom
for (const name in this.attributes["atom"]) {
newAttributes["atom"][name].push(this.attributes["atom"][name][index]);
}
});
- const species = new Set(newAtomsData.symbols);
- species.forEach((species) => {
- newAtomsData.species[species] = this.species[species].element;
+ const kindsSet = new Set(newAtomsData.symbols);
+ kindsSet.forEach((kind) => {
+ newAtomsData.kinds[kind] = this.kinds[kind].element;
});
const newAtoms = new Atoms(newAtomsData);
@@ -513,12 +506,10 @@ class Atoms {
copy() {
const newAtomsData = this.toDict();
const newAtoms = new Atoms(newAtomsData);
- // Copy attributes
- // copy all attributes
- const newAttributes = { atom: {}, species: {} };
+ const newAttributes = { atom: {}, kind: {}, "inter-kind": {} };
for (const domain in this.attributes) {
for (const name in this.attributes[domain]) {
- newAttributes[domain][name] = this.attributes[domain][name].slice();
+ newAttributes[domain][name] = JSON.parse(JSON.stringify(this.attributes[domain][name]));
}
}
newAtoms.attributes = newAttributes;
@@ -526,4 +517,4 @@ class Atoms {
}
}
-export { Species, Atom, Atoms };
+export { Kind, Atom, Atoms };
diff --git a/src/atoms/plugins/atom.js b/src/atoms/plugins/atom.js
index a591e9b..47a23b1 100644
--- a/src/atoms/plugins/atom.js
+++ b/src/atoms/plugins/atom.js
@@ -34,13 +34,13 @@ export class AtomManager {
}
init() {
- /* Initialize the species settings from the viewer.atoms
+ /* Initialize the settings from the viewer.atoms
*/
this.viewer.logger.debug("init atom settings");
this.settings = {};
- Object.entries(this.viewer.originalAtoms.species).forEach(([symbol, species]) => {
- this.settings[symbol] = this.getDefaultSetting(symbol, species.element);
+ Object.entries(this.viewer.originalAtoms.kinds).forEach(([symbol, kind]) => {
+ this.settings[symbol] = this.getDefaultSetting(symbol, kind.element);
});
this.updateAtomColors();
}
@@ -48,7 +48,7 @@ export class AtomManager {
updateAtomColors() {
const colors = [];
this.viewer.atoms.symbols.forEach((symbol, globalIndex) => {
- // if this.viewer.atoms has color attribute in the species domain, use it
+ // if this.viewer.atoms has color attribute in the kind domain, use it
const color = new THREE.Color(this.settings[symbol].color);
colors.push(color);
});
@@ -59,18 +59,18 @@ export class AtomManager {
}
getDefaultSetting(symbol, element) {
- /* Get the default bond setting for the species1 and species2 */
+ /* Get the default bond setting for the kind1 and kind2 */
let color;
let radius;
- // if species has color attribute in the species domain, use it
- if ("color" in this.viewer.atoms.attributes["species"]) {
- color = this.viewer.atoms.attributes["species"]["color"][symbol] || "#3d82ed";
+ // if color attribute in the kind domain, use it
+ if ("color" in this.viewer.atoms.attributes["kind"]) {
+ color = this.viewer.atoms.attributes["kind"]["color"][symbol] || "#3d82ed";
} else {
color = elementColors[this.viewer.colorType][element];
}
- // if atoms has radii attribute in the species domain, use it
- if ("radii" in this.viewer.atoms.attributes["species"]) {
- radius = this.viewer.atoms.attributes["species"]["radii"][symbol] || 1;
+ // if atoms has radii attribute in the kind domain, use it
+ if ("radii" in this.viewer.atoms.attributes["kind"]) {
+ radius = this.viewer.atoms.attributes["kind"]["radii"][symbol] || 1;
} else {
radius = radiiData[this.viewer.radiusType][element] || 1;
}
@@ -130,7 +130,7 @@ export class AtomManager {
}
const atomColors = [];
imageAtomsList.symbols.forEach((symbol, globalIndex) => {
- // if this.viewer.atoms has color attribute in the species domain, use it
+ // if this.viewer.atoms has color attribute in the kind domain, use it
const color = new THREE.Color(this.settings[symbol].color);
atomColors.push(color);
});
diff --git a/src/atoms/plugins/bond.js b/src/atoms/plugins/bond.js
index cd1917c..8168526 100644
--- a/src/atoms/plugins/bond.js
+++ b/src/atoms/plugins/bond.js
@@ -7,9 +7,9 @@ import { kdTree } from "../../geometry/kdTree.js";
import { searchBoundary } from "./boundary.js";
class Setting {
- constructor({ species1, species2, min = 0.0, max = 3.0, color1 = "#3d82ed", color2 = "#3d82ed", radius = 0.1, order = 1, type = 0 }) {
- this.species1 = species1;
- this.species2 = species2;
+ constructor({ kind1, kind2, min = 0.0, max = 3.0, color1 = "#3d82ed", color2 = "#3d82ed", radius = 0.1, order = 1, type = 0 }) {
+ this.kind1 = kind1;
+ this.kind2 = kind2;
this.min = min;
this.max = max;
this.color1 = convertColor(color1);
@@ -21,8 +21,8 @@ class Setting {
toDict() {
return {
- species1: this.species1,
- species2: this.species2,
+ kind1: this.kind1,
+ kind2: this.kind2,
min: this.min,
max: this.max,
color1: this.color1,
@@ -48,7 +48,7 @@ export class BondManager {
init() {
/* Initialize the bond settings from the viewer.atoms
- The default max is the sum of two radius of the species.
+ The default max is the sum of two radius of the kinds.
The default color is from the elementColors.
*/
this.viewer.logger.debug("init bond settings");
@@ -56,30 +56,28 @@ export class BondManager {
this.stickBonds = [];
this.lineBonds = [];
this.springBonds = [];
- Object.entries(this.viewer.originalAtoms.species).forEach(([symbol1, species1]) => {
- Object.entries(this.viewer.originalAtoms.species).forEach(([symbol2, species2]) => {
- const elementPair = species1.element + "-" + species2.element;
+ Object.entries(this.viewer.originalAtoms.kinds).forEach(([symbol1, kind1]) => {
+ Object.entries(this.viewer.originalAtoms.kinds).forEach(([symbol2, kind2]) => {
+ const elementPair = kind1.element + "-" + kind2.element;
// if the elementPair is not in the default_bond_pairs, skip
if (default_bond_pairs[elementPair] === undefined) {
return;
}
- const key = species1.symbol + "-" + species2.symbol;
- this.settings[key] = this.getDefaultSetting(species1, species2);
+ const key = symbol1 + "-" + symbol2;
+ this.settings[key] = this.getDefaultSetting(symbol1, kind1, symbol2, kind2);
});
});
}
- getDefaultSetting(species1, species2) {
- /* Get the default bond setting for the species1 and species2 */
- let color1 = this.viewer.atomManager.settings[species1.symbol].color;
- let color2 = this.viewer.atomManager.settings[species2.symbol].color;
- const radius1 = this.viewer.atomManager.settings[species1.symbol].radius;
- const radius2 = this.viewer.atomManager.settings[species2.symbol].radius;
+ getDefaultSetting(symbol1, kind1, symbol2, kind2) {
+ /* Get the default bond setting for the kind1 and kind2 */
+ let color1 = this.viewer.atomManager.settings[symbol1].color;
+ let color2 = this.viewer.atomManager.settings[symbol2].color;
+ const radius1 = this.viewer.atomManager.settings[symbol1].radius;
+ const radius2 = this.viewer.atomManager.settings[symbol2].radius;
let min = 0.0;
let max = (radius1 + radius2) * 1.1;
- const symbol1 = species1.symbol;
- const symbol2 = species2.symbol;
- const type = default_bond_pairs[species1.element + "-" + species2.element][2];
+ const type = default_bond_pairs[kind1.element + "-" + kind2.element][2];
// if type is hydrogen bond, set the min as the max, and the max as the max + 1
if (type === 1) {
min = max + 0.4;
@@ -88,7 +86,7 @@ export class BondManager {
color1 = "#808080";
color2 = "#808080";
}
- const setting = new Setting({ species1: symbol1, species2: symbol2, min, max, color1, color2, type });
+ const setting = new Setting({ kind1: symbol1, kind2: symbol2, min, max, color1, color2, type });
return setting;
}
@@ -103,10 +101,10 @@ export class BondManager {
}
// Modify addSetting to accept a single object parameter
- addSetting({ species1, species2, radius, min = 0.0, max = 3.0, color1 = "#3d82ed", color2 = "#3d82ed", order = 1, type = 0 }) {
+ addSetting({ kind1, kind2, radius, min = 0.0, max = 3.0, color1 = "#3d82ed", color2 = "#3d82ed", order = 1, type = 0 }) {
/* Add a new setting to the bond */
- const setting = new Setting({ species1, species2, radius, min, max, color1, color2, order, type });
- const key = species1 + "-" + species2;
+ const setting = new Setting({ kind1, kind2, radius, min, max, color1, color2, order, type });
+ const key = kind1 + "-" + kind2;
this.settings[key] = setting;
}
@@ -114,9 +112,9 @@ export class BondManager {
/* Build a dictionary of cutoffs */
const cutoffDict = {};
Object.values(this.settings).forEach((setting) => {
- const species1 = setting.species1;
- const species2 = setting.species2;
- const key1 = species1 + "-" + species2;
+ const kind1 = setting.kind1;
+ const kind2 = setting.kind2;
+ const key1 = kind1 + "-" + kind2;
cutoffDict[key1] = setting.toDict();
});
this.viewer.logger.debug("cutoffDict: ", cutoffDict);
@@ -347,7 +345,7 @@ export function drawStick(atoms, bondList, bondIndices, settings, radius = 0.1,
var position2 = atoms.positions[index2].map((value, index) => value + calculateCartesianCoordinates(atoms.cell, offset2)[index]);
position2 = new THREE.Vector3(...position2);
// Setting color for each material
- const key = atoms.species[atoms.symbols[index1]].symbol + "-" + atoms.species[atoms.symbols[index2]].symbol;
+ const key = atoms.symbols[index1] + "-" + atoms.symbols[index2];
// if atomColors is not null, use the atomColors, otherwise use the settings
const color1 = atomColors ? atomColors[index1] : settings[key].color1;
const midpoint1 = new THREE.Vector3().lerpVectors(position1, position2, 0.25);
@@ -400,7 +398,7 @@ export function drawLine(atoms, bondList, bondIndices, settings, materialType =
vertices.push(position1.x, position1.y, position1.z);
vertices.push(position2.x, position2.y, position2.z);
// Setting color for each bond
- const key = atoms.species[atoms.symbols[index1]].symbol + "-" + atoms.species[atoms.symbols[index2]].symbol;
+ const key = atoms.symbols[index1] + "-" + atoms.symbols[index2];
const color1 = settings[key].color1;
const color2 = settings[key].color2;
@@ -671,7 +669,7 @@ export function findNeighbors(atoms, cutoffs, include_self = false, pbc = true)
/* Function to find neighbors within a certain cutoff
Args:
atoms: Atoms object
- cutoffs: Dictionary of cutoffs for each species pair, has min and max
+ cutoffs: Dictionary of cutoffs for each kind pair, has min and max
include_self: Include self in the neighbors list
pbc: Periodic boundary conditions
*/
@@ -726,8 +724,8 @@ export function findNeighbors(atoms, cutoffs, include_self = false, pbc = true)
offsets.forEach(([atomIndex1, offset1], idx1) => {
// skip the atoms not in the original cell
if (offset1[0] != 0 || offset1[1] != 0 || offset1[2] != 0) return;
- const species1 = atoms.species[atoms.symbols[atomIndex1]].symbol;
- const radius1 = covalentRadii[species1] * 1.1 || 1;
+ const kind1 = atoms.symbols[atomIndex1];
+ const radius1 = covalentRadii[kind1] * 1.1 || 1;
const pos1 = positions[idx1];
const point = { x: positions[idx1][0], y: positions[idx1][1], z: positions[idx1][2] };
@@ -741,7 +739,7 @@ export function findNeighbors(atoms, cutoffs, include_self = false, pbc = true)
if (idx1 == idx2) return;
const atomIndex2 = offsets[idx2][0];
if (!include_self && atomIndex1 == atomIndex2) return;
- const key = species1 + "-" + atoms.species[atoms.symbols[atomIndex2]].symbol;
+ const key = kind1 + "-" + atoms.symbols[atomIndex2];
// if key is not in cutoffs, skip
if (!cutoffs[key]) return;
const pos2 = positions[idx2];
diff --git a/src/atoms/plugins/boundary.js b/src/atoms/plugins/boundary.js
index a128098..3742da9 100644
--- a/src/atoms/plugins/boundary.js
+++ b/src/atoms/plugins/boundary.js
@@ -30,23 +30,20 @@ export class BoundaryManager {
}
init() {
- /* Initialize the species settings from the viewer.atoms
+ /* Initialize the settings from the viewer.atoms
*/
this.viewer.logger.debug("init atom settings");
this.settings = {};
- const speciesSet = new Set(this.viewer.originalAtoms.symbols);
- const speciesList = Array.from(speciesSet);
- for (let i = 0; i < speciesList.length; i++) {
- const species = speciesList[i];
- this.settings[species] = this.getDefaultSetting(species);
- }
+ Object.entries(this.viewer.originalAtoms.kinds).forEach(([symbol, kind]) => {
+ this.settings[symbol] = this.getDefaultSetting(symbol, kind);
+ });
}
- getDefaultSetting(species) {
- /* Get the default bond setting for the species1 and species2 */
- const color = elementColors[this.viewer.colorType][species];
- const radius = radiiData[this.viewer.radiusType][species];
- const setting = new Setting({ element: species, symbol: species, radius, color });
+ getDefaultSetting(symbol, kind) {
+ /* Get the default bond setting for the kind1 and kind2 */
+ const color = elementColors[this.viewer.colorType][kind.element];
+ const radius = radiiData[this.viewer.radiusType][kind.element];
+ const setting = new Setting({ element: kind.element, symbol: symbol, radius, color });
return setting;
}
@@ -60,10 +57,10 @@ export class BoundaryManager {
});
}
- addSetting({ species1, species2, radius, min = 0.0, max = 3.0, color1 = "#3d82ed", color2 = "#3d82ed", order = 1 }) {
+ addSetting({ kind1, kind2, radius, min = 0.0, max = 3.0, color1 = "#3d82ed", color2 = "#3d82ed", order = 1 }) {
/* Add a new setting to the bond */
- const setting = new Setting({ species1, species2, radius, min, max, color1, color2, order });
- const key = species1 + "-" + species2;
+ const setting = new Setting({ kind1, kind2, radius, min, max, color1, color2, order });
+ const key = kind1 + "-" + kind2;
this.settings[key] = setting;
}
@@ -80,7 +77,7 @@ export function getImageAtoms(atoms, offsets) {
// create a new atoms with the boundary atoms
const imageAtoms = new Atoms();
imageAtoms.cell = atoms.cell;
- imageAtoms.species = atoms.species;
+ imageAtoms.kinds = atoms.kinds;
const positions = offsets.map((offset) => {
// Get original position
const originalPosition = atoms.positions[offset[0]];
@@ -113,7 +110,7 @@ export function searchBoundary(
return [];
}
let positions = atoms.positions;
- let species = atoms.species; // Assuming species is a property of atoms
+ let kinds = atoms.kinds; // Assuming kinds is a property of atoms
if (typeof boundary === "number") {
boundary = [
@@ -136,7 +133,7 @@ export function searchBoundary(
let i0 = 0;
let offsets = [];
- let speciesExtended = [];
+ let kindsExtended = [];
for (let m0 = ib[0][0]; m0 < ib[1][0]; m0++) {
for (let m1 = ib[0][1]; m1 < ib[1][1]; m1++) {
@@ -149,7 +146,7 @@ export function searchBoundary(
npositions[i] = npositions[i].map((val, idx) => val + (idx === 0 ? m0 : idx === 1 ? m1 : m2));
offsets.push([i % n, [m0, m1, m2]]);
}
- speciesExtended = speciesExtended.concat(species);
+ kindsExtended = kindsExtended.concat(kinds);
i0 = i1;
}
}
diff --git a/src/atoms/plugins/highlight.js b/src/atoms/plugins/highlight.js
index 140618e..394447e 100644
--- a/src/atoms/plugins/highlight.js
+++ b/src/atoms/plugins/highlight.js
@@ -31,7 +31,7 @@ export class HighlightManager {
}
init() {
- /* Initialize the species settings from the viewer.atoms */
+ /* Initialize the kind settings from the viewer.atoms */
this.viewer.logger.debug("init highlight settings");
this.settings = {
selection: new Setting({ indices: [], scale: 1.1, color: "#ffff00" }),
diff --git a/src/atoms/plugins/polyhedra.js b/src/atoms/plugins/polyhedra.js
index 958a192..91532ad 100644
--- a/src/atoms/plugins/polyhedra.js
+++ b/src/atoms/plugins/polyhedra.js
@@ -8,15 +8,15 @@ import { convertColor } from "../utils.js";
const defaultColor = 0xffffff;
class Setting {
- constructor({ species, color = "#3d82ed", show_edge = false }) {
- this.species = species;
+ constructor({ symbol, color = "#3d82ed", show_edge = false }) {
+ this.symbol = symbol;
this.color = convertColor(color);
this.show_edge = show_edge;
}
toDict() {
return {
- species: this.species,
+ symbol: this.symbol,
color: this.color,
show_edge: this.show_edge,
};
@@ -35,24 +35,20 @@ export class PolyhedraManager {
init() {
/* Initialize the polyhedra settings from the viewer.atoms
- The default max is the sum of two radius of the species.
+ The default max is the sum of two radius of the kinds.
The default color is from the elementColors.
*/
this.viewer.logger.debug("init PolyhedraManager");
this.settings = [];
const atoms = this.viewer.atoms;
- const symbols = atoms.symbols;
- const speciesSet = new Set(symbols);
- const speciesList = Array.from(speciesSet);
- for (let i = 0; i < speciesList.length; i++) {
- if (!elementsWithPolyhedra.includes(speciesList[i])) {
- continue;
+ Object.entries(this.viewer.originalAtoms.kinds).forEach(([symbol, kind]) => {
+ if (!elementsWithPolyhedra.includes(kind.element)) {
+ return;
}
- const species = speciesList[i];
- const color = elementColors[this.viewer.colorType][species];
- const setting = new Setting({ species, color });
+ const color = elementColors[this.viewer.colorType][kind.element];
+ const setting = new Setting({ symbol, color });
this.settings.push(setting);
- }
+ });
}
fromSettings(settings) {
@@ -66,9 +62,9 @@ export class PolyhedraManager {
}
// Modify addSetting to accept a single object parameter
- addSetting({ species, color = "#3d82ed", show_edge = false }) {
+ addSetting({ symbol, color = "#3d82ed", show_edge = false }) {
/* Add a new setting to the polyhedra */
- const setting = new Setting({ species, color, show_edge });
+ const setting = new Setting({ symbol, color, show_edge });
this.settings.push(setting);
}
@@ -76,7 +72,7 @@ export class PolyhedraManager {
/* Build a dictionary of cutoffs */
const cutoffDict = {};
this.settings.forEach((setting) => {
- cutoffDict[setting.species] = setting.toDict();
+ cutoffDict[setting.symbol] = setting.toDict();
});
return cutoffDict;
}
@@ -174,7 +170,7 @@ export function drawPolyhedras(atoms, polyhedras, bondList, colorType = "CPK", m
export function filterBondMap(bondMap, symbols, elements, modelPolyhedras) {
/*
loop through bondMap and filter out only those atoms that have
- four or more bonds and whose species (retrieved from atoms.symbols[atomIndex])
+ four or more bonds and whose kind (retrieved from atoms.symbols[atomIndex])
are in a specified list of elements (elements)
*/
const filteredMap = {};
@@ -183,9 +179,9 @@ export function filterBondMap(bondMap, symbols, elements, modelPolyhedras) {
Object.keys(bondMap).forEach((key) => {
const atomIndex = bondMap[key]["atomIndex"];
const numBond = bondMap[key]["sticks"].length;
- const speciesName = symbols[atomIndex];
+ const kindName = symbols[atomIndex];
- if (modelPolyhedras[atomIndex] && numBond >= 4 && elements.includes(speciesName)) {
+ if (modelPolyhedras[atomIndex] && numBond >= 4 && elements.includes(kindName)) {
filteredMap[key] = bondMap[key];
}
});
diff --git a/src/index.js b/src/index.js
index 013a700..4bc7a49 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,6 +1,6 @@
// src/index.js
import { WEAS } from "./weas.js";
-import { Species, Atom, Atoms } from "./atoms/atoms.js";
+import { Kind, Atom, Atoms } from "./atoms/atoms.js";
import { AtomsViewer } from "./atoms/AtomsViewer.js";
import { parseXYZ } from "./io/parserXYZ.js";
import { parseCIF } from "./io/parserCif.js";
@@ -8,4 +8,4 @@ import { parseCube } from "./io/parserCube.js";
import { elementAtomicNumbers } from "./atoms/atoms_data.js";
// Export the modules to be publicly available
-export { WEAS, Species, Atom, Atoms, AtomsViewer, parseXYZ, parseCIF, parseCube, elementAtomicNumbers };
+export { WEAS, Kind, Atom, Atoms, AtomsViewer, parseXYZ, parseCIF, parseCube, elementAtomicNumbers };
diff --git a/src/io/parserCif.js b/src/io/parserCif.js
index 81b7d05..10b8a87 100644
--- a/src/io/parserCif.js
+++ b/src/io/parserCif.js
@@ -4,7 +4,7 @@ import { convertToMatrixFromABCAlphaBetaGamma, calculateCartesianCoordinates } f
export function parseCIF(cifString) {
const data = {
cell: [],
- species: {},
+ kinds: {},
positions: [],
symbols: [],
};
diff --git a/src/io/parserCube.js b/src/io/parserCube.js
index eeaec59..88537d2 100644
--- a/src/io/parserCube.js
+++ b/src/io/parserCube.js
@@ -24,7 +24,7 @@ export function parseCube(cubeContent) {
// Initialize data structure for Atoms
const data = {
- species: {},
+ kinds: {},
positions: [],
symbols: [],
};
@@ -37,12 +37,12 @@ export function parseCube(cubeContent) {
// Find the element symbol by atomic number
const elementSymbol = Object.keys(elementAtomicNumbers).find((key) => elementAtomicNumbers[key] === atomicNumber);
- // Update species data if it's a new element
- if (!data.species[elementSymbol]) {
- data.species[elementSymbol] = elementSymbol;
+ // Update kinds data if it's a new element
+ if (!data.kinds[elementSymbol]) {
+ data.kinds[elementSymbol] = elementSymbol;
}
- // Add species and position data for the current atom
+ // Add kinds and position data for the current atom
data.symbols.push(elementSymbol);
data.positions.push(position);
}
diff --git a/src/io/parserPOSCAR.js b/src/io/parserPOSCAR.js
index 904db08..3153a61 100644
--- a/src/io/parserPOSCAR.js
+++ b/src/io/parserPOSCAR.js
@@ -39,7 +39,7 @@ function parsePOSCAR(poscarString) {
// Create a data object for Atoms
const data = {
cell: latticeVectors.flat(),
- species: {},
+ kinds: {},
positions: positions,
symbols: atomTypes.flatMap((type, idx) => Array(atomCounts[idx]).fill(type)),
};
diff --git a/src/io/parserXYZ.js b/src/io/parserXYZ.js
index 693849c..d63face 100644
--- a/src/io/parserXYZ.js
+++ b/src/io/parserXYZ.js
@@ -21,7 +21,7 @@ function parseXYZ(xyzString) {
// Initialize data structure for the current frame
const data = {
- species: {},
+ kinds: {},
positions: [],
symbols: [],
};
@@ -35,12 +35,12 @@ function parseXYZ(xyzString) {
const [element, x, y, z] = parts;
- // Update species data if it's a new species
- if (!data.species[element]) {
- data.species[element] = element;
+ // Update kinds data if it's a new kinds
+ if (!data.kinds[element]) {
+ data.kinds[element] = element;
}
- // Add species and position data for the current atom
+ // Add kinds and position data for the current atom
data.symbols.push(element);
data.positions.push([parseFloat(x), parseFloat(y), parseFloat(z)]);
}
diff --git a/src/operation/atoms.js b/src/operation/atoms.js
index aaa0e7e..fb6d745 100644
--- a/src/operation/atoms.js
+++ b/src/operation/atoms.js
@@ -24,8 +24,8 @@ class ReplaceOperation extends BaseOperation {
}
adjust(newSymbol) {
- // if newSymbol not in elementAtomicNumbers, and newSymbol not in this.weas.avr.atoms.species, ship the adjustment
- if (!(newSymbol in elementAtomicNumbers || newSymbol in this.weas.avr.atoms.species)) {
+ // if newSymbol not in elementAtomicNumbers, and newSymbol not in this.weas.avr.atoms.kinds, ship the adjustment
+ if (!(newSymbol in elementAtomicNumbers || newSymbol in this.weas.avr.atoms.kinds)) {
return;
}
this.symbol = newSymbol;
@@ -68,7 +68,7 @@ class AddAtomOperation extends BaseOperation {
adjust(newSymbol, newPosition) {
// if newSymbol not in elementAtomicNumbers, ship the adjustment
- if (!(newSymbol in elementAtomicNumbers || newSymbol in this.weas.avr.atoms.species)) {
+ if (!(newSymbol in elementAtomicNumbers || newSymbol in this.weas.avr.atoms.kinds)) {
return;
}
this.weas.avr.atoms = this.initialAtoms.copy();
diff --git a/tests/atoms.test.mjs b/tests/atoms.test.mjs
index 510d63f..72b3e8f 100644
--- a/tests/atoms.test.mjs
+++ b/tests/atoms.test.mjs
@@ -39,7 +39,7 @@ describe("Atoms class", () => {
});
it("initializes an empty Atoms instance", () => {
- expect(atoms.species).toEqual({});
+ expect(atoms.kinds).toEqual({});
expect(atoms.symbols).toEqual([]);
expect(atoms.positions).toEqual([]);
expect(atoms.cell).toEqual([
@@ -51,9 +51,9 @@ describe("Atoms class", () => {
});
it("adds a species correctly", () => {
- atoms.addSpecies("H");
- expect(atoms.species).toHaveProperty("H");
- expect(atoms.species["H"]).toEqual(new Species("H"));
+ atoms.addKind("H");
+ expect(atoms.kinds).toHaveProperty("H");
+ expect(atoms.kinds["H"]).toEqual(new Species("H"));
});
// Add more tests for other methods like setCell, addAtom, removeAtom, etc.
diff --git a/tests/e2e/gui.spec.js b/tests/e2e/gui.spec.js
index 5df2ff3..dc5e4bb 100644
--- a/tests/e2e/gui.spec.js
+++ b/tests/e2e/gui.spec.js
@@ -51,7 +51,7 @@ test("VectorField", async ({ page }) => {
test("ColorBy", async ({ page }) => {
await page.goto("http://127.0.0.1:8080/tests/e2e/testColorBy.html");
await expect(page).toHaveScreenshot();
- // color by species
+ // color by kind
await page.evaluate(() => {
window.editor.avr.colorBy = "Element";
window.editor.avr.atomManager.settings["C"].color = "##eb4034";
@@ -60,7 +60,7 @@ test("ColorBy", async ({ page }) => {
window.editor.avr.atomManager.settings["S"].color = "#FFFF00";
window.editor.avr.drawModels();
});
- await expect(page).toHaveScreenshot("Color-species.png");
+ await expect(page).toHaveScreenshot("Color-kind.png");
});
test("Highlight Atoms", async ({ page }) => {
diff --git a/tests/e2e/gui.spec.js-snapshots/Color-species-chromium-linux.png b/tests/e2e/gui.spec.js-snapshots/Color-kind-chromium-linux.png
similarity index 100%
rename from tests/e2e/gui.spec.js-snapshots/Color-species-chromium-linux.png
rename to tests/e2e/gui.spec.js-snapshots/Color-kind-chromium-linux.png
diff --git a/tests/e2e/testSpecies.html b/tests/e2e/testSpecies.html
index 08c7343..4be62a0 100644
--- a/tests/e2e/testSpecies.html
+++ b/tests/e2e/testSpecies.html
@@ -24,7 +24,7 @@
const filename = "c2h6so.xyz";
fetchFile(filename).then((fileContent) => {
const atoms = weas.parseXYZ(fileContent);
- atoms[0].addSpecies("C1", "C");
+ atoms[0].addKind("C1", "C");
atoms[0].symbols[3] = "C1";
let editor = new weas.WEAS({ domElement });
editor.avr.atoms = atoms;
diff --git a/tests/parserXYZ.test.mjs b/tests/parserXYZ.test.mjs
index 32f53cd..61f5861 100644
--- a/tests/parserXYZ.test.mjs
+++ b/tests/parserXYZ.test.mjs
@@ -13,10 +13,10 @@ H 0.000000 0.757160 0.482080
console.log("atoms: ", atoms);
expect(atoms).toBeDefined();
- expect(atoms.species).toHaveProperty("H");
- expect(atoms.species).toHaveProperty("O");
- expect(atoms.species["H"]).toEqual(new Species("H"));
- expect(atoms.species["O"]).toEqual(new Species("O"));
+ expect(atoms.kinds).toHaveProperty("H");
+ expect(atoms.kinds).toHaveProperty("O");
+ expect(atoms.kinds["H"]).toEqual(new Species("H"));
+ expect(atoms.kinds["O"]).toEqual(new Species("O"));
expect(atoms.positions.length).toBe(3);
expect(atoms.symbols).toEqual(["O", "H", "H"]);
console.log(atoms.positions[0]);