Skip to content

Commit af61128

Browse files
committed
implement packed cell
1 parent 777471f commit af61128

File tree

5 files changed

+217
-16
lines changed

5 files changed

+217
-16
lines changed

package-lock.json

Lines changed: 82 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
"preview": "vite preview"
1515
},
1616
"dependencies": {
17-
"3dmol": "^2.1.0"
17+
"3dmol": "^2.1.0",
18+
"mathjs": "^12.4.1"
1819
},
1920
"peerDependencies": {
2021
"bootstrap": "^5.2.3",

src/StructureVisualizer/ControlBox/index.jsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,17 +73,16 @@ class ControlBox extends React.Component {
7373
<Form.Check
7474
className="option-checkbox"
7575
type="checkbox"
76-
checked={this.props.viewerParams.atomLabels}
77-
onChange={() => this.handleOptionChange("atomLabels")}
78-
label="Atom labels"
76+
checked={this.props.viewerParams.packedCell}
77+
onChange={() => this.handleOptionChange("packedCell")}
78+
label="Packed cell"
7979
/>
8080
<Form.Check
8181
className="option-checkbox"
8282
type="checkbox"
83-
checked={this.props.viewerParams.packedCell}
84-
onChange={() => this.handleOptionChange("packedCell")}
85-
disabled={true}
86-
label="Packed cell"
83+
checked={this.props.viewerParams.atomLabels}
84+
onChange={() => this.handleOptionChange("atomLabels")}
85+
label="Atom labels"
8786
/>
8887
<Form.Check
8988
className="option-checkbox"

src/StructureVisualizer/StructureWindow/3dmol/Visualizer3dmol.jsx

Lines changed: 126 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@ import React from "react";
22

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

5+
import * as math from "mathjs";
6+
57
import { covalentRadii } from "./bondLengths";
68

79
import "./Visualizer3dmol.css";
810

11+
function mod(n, m) {
12+
return ((n % m) + m) % m;
13+
}
14+
915
// override the covalent bond detection based on examples in MC3D
1016
const overrideBondLengths = {
1117
// uuid = "aaea1e0f-337c-453f-a23a-acc06ddc93c9"; // BaTiO3 mc3d-46554/pbe
@@ -64,9 +70,126 @@ class Visualizer3dmol extends React.Component {
6470
}
6571
}
6672

73+
custom3dmolSetup() {
74+
this.model = this.viewer.addModel();
75+
76+
if (this.props.cifText) {
77+
let loadedCif = $3Dmol.Parsers.CIF(this.props.cifText);
78+
let loadedAtoms = loadedCif[0];
79+
let cellData = loadedCif["modelData"][0]["cryst"];
80+
81+
this.model.setCrystData(
82+
cellData.a,
83+
cellData.b,
84+
cellData.c,
85+
cellData.alpha,
86+
cellData.beta,
87+
cellData.gamma,
88+
);
89+
90+
let cellMatrix = this.model.modelData.cryst.matrix;
91+
92+
let fracConversionMatrix = new $3Dmol.Matrix3().getInverse3(cellMatrix);
93+
94+
let final_atoms = [];
95+
96+
// console.log("loadedAtoms", loadedAtoms);
97+
// loadedAtoms = [
98+
// {
99+
// elem: "C",
100+
// x: 0.1,
101+
// y: 0.1,
102+
// z: 50.0,
103+
// },
104+
// ];
105+
106+
// in case of packed cell, make sure all the initially specified atoms
107+
// are folded back to the unit cell
108+
let atoms = [];
109+
loadedAtoms.forEach((atom) => {
110+
let cart = new $3Dmol.Vector3(atom.x, atom.y, atom.z);
111+
if (this.props.viewerParams.packedCell) {
112+
let frac = cart.clone().applyMatrix3(fracConversionMatrix);
113+
let folded_frac = new $3Dmol.Vector3(
114+
mod(frac.x, 1),
115+
mod(frac.y, 1),
116+
mod(frac.z, 1),
117+
);
118+
// convert back to cartesian
119+
cart = folded_frac.applyMatrix3(cellMatrix);
120+
}
121+
atoms.push({
122+
elem: atom.elem,
123+
x: cart.x,
124+
y: cart.y,
125+
z: cart.z,
126+
});
127+
});
128+
129+
// Build the supercell
130+
131+
let sc = this.props.viewerParams.supercell;
132+
for (let i = -1; i < sc[0] + 1; i++) {
133+
for (let j = -1; j < sc[1] + 1; j++) {
134+
for (let k = -1; k < sc[2] + 1; k++) {
135+
let offset = new $3Dmol.Vector3(i, j, k);
136+
offset.applyMatrix3(cellMatrix);
137+
138+
// prettier-ignore
139+
if (
140+
i == -1 || i == sc[0] ||
141+
j == -1 || j == sc[1] ||
142+
k == -1 || k == sc[2]
143+
) {
144+
// we are outside the specified supercell.
145+
// in case of packed cell, add all atoms from the
146+
// neighboring cells that are exactly on edges
147+
if (this.props.viewerParams.packedCell) {
148+
atoms.forEach((atom) => {
149+
let cart = new $3Dmol.Vector3(atom.x, atom.y, atom.z);
150+
cart.add(offset);
151+
let frac = cart.clone().applyMatrix3(fracConversionMatrix);
152+
153+
// prettier-ignore
154+
if (
155+
frac.x > -0.0001 && frac.x < sc[0] + 0.0001 &&
156+
frac.y > -0.0001 && frac.y < sc[1] + 0.0001 &&
157+
frac.z > -0.0001 && frac.z < sc[2] + 0.0001
158+
) {
159+
final_atoms.push({
160+
elem: atom.elem,
161+
x: cart.x,
162+
y: cart.y,
163+
z: cart.z,
164+
});
165+
}
166+
});
167+
} else {
168+
// in "non-packed" case, skip these edge cells
169+
continue
170+
}
171+
} else {
172+
atoms.forEach((atom) => {
173+
final_atoms.push({
174+
elem: atom.elem,
175+
x: atom.x + offset.x,
176+
y: atom.y + offset.y,
177+
z: atom.z + offset.z,
178+
});
179+
});
180+
}
181+
}
182+
}
183+
}
184+
185+
this.model.addAtoms(final_atoms);
186+
}
187+
}
188+
67189
updateView() {
68190
this.viewer.removeAllModels();
69-
this.model = this.viewer.addModel(this.props.cifText, "cif");
191+
// this.model = this.viewer.addModel(this.props.cifText, "cif");
192+
this.custom3dmolSetup();
70193

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

83206
this.viewer.addUnitCell(this.model);
84-
let sc = this.props.viewerParams.supercell;
85-
this.viewer.replicateUnitCell(sc[0], sc[1], sc[2], this.model);
207+
//let sc = this.props.viewerParams.supercell;
208+
//this.viewer.replicateUnitCell(sc[0], sc[1], sc[2], this.model);
86209

87210
this.model.assignBonds();
88211

src/StructureVisualizer/index.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ const StructureVisualizer = (props) => {
77
const [viewerParams, setViewerParams] = useState({
88
supercell: props.initSupercell || [2, 2, 2],
99
bonds: true,
10+
packedCell: true,
1011
atomLabels: false,
11-
packedCell: false,
1212
vdwRadius: false,
1313
});
1414
const [mouseEnabled, setMouseEnabled] = useState(false);

0 commit comments

Comments
 (0)