Skip to content

Commit

Permalink
implement packed cell
Browse files Browse the repository at this point in the history
  • Loading branch information
eimrek committed Mar 19, 2024
1 parent 777471f commit af61128
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 16 deletions.
86 changes: 82 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"preview": "vite preview"
},
"dependencies": {
"3dmol": "^2.1.0"
"3dmol": "^2.1.0",
"mathjs": "^12.4.1"
},
"peerDependencies": {
"bootstrap": "^5.2.3",
Expand Down
13 changes: 6 additions & 7 deletions src/StructureVisualizer/ControlBox/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,16 @@ class ControlBox extends React.Component {
<Form.Check
className="option-checkbox"
type="checkbox"
checked={this.props.viewerParams.atomLabels}
onChange={() => this.handleOptionChange("atomLabels")}
label="Atom labels"
checked={this.props.viewerParams.packedCell}
onChange={() => this.handleOptionChange("packedCell")}
label="Packed cell"
/>
<Form.Check
className="option-checkbox"
type="checkbox"
checked={this.props.viewerParams.packedCell}
onChange={() => this.handleOptionChange("packedCell")}
disabled={true}
label="Packed cell"
checked={this.props.viewerParams.atomLabels}
onChange={() => this.handleOptionChange("atomLabels")}
label="Atom labels"
/>
<Form.Check
className="option-checkbox"
Expand Down
129 changes: 126 additions & 3 deletions src/StructureVisualizer/StructureWindow/3dmol/Visualizer3dmol.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@ import React from "react";

import * as $3Dmol from "3dmol";

import * as math from "mathjs";

import { covalentRadii } from "./bondLengths";

import "./Visualizer3dmol.css";

function mod(n, m) {
return ((n % m) + m) % m;
}

// override the covalent bond detection based on examples in MC3D
const overrideBondLengths = {
// uuid = "aaea1e0f-337c-453f-a23a-acc06ddc93c9"; // BaTiO3 mc3d-46554/pbe
Expand Down Expand Up @@ -64,9 +70,126 @@ class Visualizer3dmol extends React.Component {
}
}

custom3dmolSetup() {
this.model = this.viewer.addModel();

if (this.props.cifText) {
let loadedCif = $3Dmol.Parsers.CIF(this.props.cifText);
let loadedAtoms = loadedCif[0];
let cellData = loadedCif["modelData"][0]["cryst"];

this.model.setCrystData(
cellData.a,
cellData.b,
cellData.c,
cellData.alpha,
cellData.beta,
cellData.gamma,
);

let cellMatrix = this.model.modelData.cryst.matrix;

let fracConversionMatrix = new $3Dmol.Matrix3().getInverse3(cellMatrix);

let final_atoms = [];

// console.log("loadedAtoms", loadedAtoms);
// loadedAtoms = [
// {
// elem: "C",
// x: 0.1,
// y: 0.1,
// z: 50.0,
// },
// ];

// in case of packed cell, make sure all the initially specified atoms
// are folded back to the unit cell
let atoms = [];
loadedAtoms.forEach((atom) => {
let cart = new $3Dmol.Vector3(atom.x, atom.y, atom.z);
if (this.props.viewerParams.packedCell) {
let frac = cart.clone().applyMatrix3(fracConversionMatrix);
let folded_frac = new $3Dmol.Vector3(
mod(frac.x, 1),
mod(frac.y, 1),
mod(frac.z, 1),
);
// convert back to cartesian
cart = folded_frac.applyMatrix3(cellMatrix);
}
atoms.push({
elem: atom.elem,
x: cart.x,
y: cart.y,
z: cart.z,
});
});

// Build the supercell

let sc = this.props.viewerParams.supercell;
for (let i = -1; i < sc[0] + 1; i++) {
for (let j = -1; j < sc[1] + 1; j++) {
for (let k = -1; k < sc[2] + 1; k++) {
let offset = new $3Dmol.Vector3(i, j, k);
offset.applyMatrix3(cellMatrix);

// prettier-ignore
if (
i == -1 || i == sc[0] ||
j == -1 || j == sc[1] ||
k == -1 || k == sc[2]
) {
// we are outside the specified supercell.
// in case of packed cell, add all atoms from the
// neighboring cells that are exactly on edges
if (this.props.viewerParams.packedCell) {
atoms.forEach((atom) => {
let cart = new $3Dmol.Vector3(atom.x, atom.y, atom.z);
cart.add(offset);
let frac = cart.clone().applyMatrix3(fracConversionMatrix);

// prettier-ignore
if (
frac.x > -0.0001 && frac.x < sc[0] + 0.0001 &&
frac.y > -0.0001 && frac.y < sc[1] + 0.0001 &&
frac.z > -0.0001 && frac.z < sc[2] + 0.0001
) {
final_atoms.push({
elem: atom.elem,
x: cart.x,
y: cart.y,
z: cart.z,
});
}
});
} else {
// in "non-packed" case, skip these edge cells
continue
}
} else {
atoms.forEach((atom) => {
final_atoms.push({
elem: atom.elem,
x: atom.x + offset.x,
y: atom.y + offset.y,
z: atom.z + offset.z,
});
});
}
}
}
}

this.model.addAtoms(final_atoms);
}
}

updateView() {
this.viewer.removeAllModels();
this.model = this.viewer.addModel(this.props.cifText, "cif");
// this.model = this.viewer.addModel(this.props.cifText, "cif");
this.custom3dmolSetup();

let style = {
sphere: { scale: 0.3, colorscheme: "Jmol" },
Expand All @@ -81,8 +204,8 @@ class Visualizer3dmol extends React.Component {
this.viewer.setStyle(style);

this.viewer.addUnitCell(this.model);
let sc = this.props.viewerParams.supercell;
this.viewer.replicateUnitCell(sc[0], sc[1], sc[2], this.model);
//let sc = this.props.viewerParams.supercell;
//this.viewer.replicateUnitCell(sc[0], sc[1], sc[2], this.model);

this.model.assignBonds();

Expand Down
2 changes: 1 addition & 1 deletion src/StructureVisualizer/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ const StructureVisualizer = (props) => {
const [viewerParams, setViewerParams] = useState({
supercell: props.initSupercell || [2, 2, 2],
bonds: true,
packedCell: true,
atomLabels: false,
packedCell: false,
vdwRadius: false,
});
const [mouseEnabled, setMouseEnabled] = useState(false);
Expand Down

0 comments on commit af61128

Please sign in to comment.