Skip to content

Commit

Permalink
Additional tests and refactoring.
Browse files Browse the repository at this point in the history
Added some tests to improve code coverage.  Identified errors in the
code as I did that.  Fix those problems and added new ones (most
likely).
  • Loading branch information
dkoes committed Dec 24, 2022
1 parent d1ebede commit 49c1631
Show file tree
Hide file tree
Showing 60 changed files with 411 additions and 451 deletions.
7 changes: 4 additions & 3 deletions packages/3Dmol/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,14 @@
"scripts": {
"build": "webpack --config webpack.dev.js --mode development && webpack --config webpack.prod.js --mode production && python3 tests/auto/generate_tests.py && npm run doc",
"prepare": "npm run build",
"jest": "npx jest",
"test": "npm run jest && npm run glcheck",
"jest": "npx jest --testPathIgnorePatterns=render.test.js",
"test": "npm run generate:jest && npm run jest && npm run glcheck",
"glcheck": "npm run clean:glcheck && npm run generate:glcheck && npm run test:glcheck",
"test:glcheck": "npx glcheck --config ./tests/glcheck/glcheck.config.json",
"clean:glcheck": "rm -rf ./tests/glcheck/render-failures",
"generate:glcheck": "python3 ./tests/glcheck/generate_glcheck_render_tests.py -min",
"cover": "python3 tests/jest/generate_jest_render_tests.py && npx jest --coverage",
"generate:jest": "python3 tests/jest/generate_jest_render_tests.py",
"cover": "npm run generate:jest && npx jest --coverage",
"doc": "npx jsdoc -c jsdoc.conf.json src doc.md"
}
}
25 changes: 12 additions & 13 deletions packages/3Dmol/src/GLModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
//atoms in the same model. An atom is uniquely specified by its model id and
//its serial number.
//A glmodel knows how to apply the styles on each atom to create a gl object
import { Geometry, CC, Material, StickImposterMaterial } from "./WebGL";
import { Geometry, Material, StickImposterMaterial } from "./WebGL";
import { Sphere, Cylinder } from "./WebGL/shapes";
import { Vector3, Matrix4, conversionMatrix3, Matrix3 } from "./WebGL/math";
import { Color } from "./WebGL";
import { Color, CC } from "./colors";
import { InstancedMaterial, SphereImposterMaterial, MeshLambertMaterial, Object3D, Mesh, LineBasicMaterial, Line, LineStyle } from "./WebGL";
import { GLDraw } from "./GLDraw"
import { drawCartoon } from "./glcartoon";
import { getColorFromStyle, elementColors } from "./colors";
import { deepCopy, extend, getExtent, getAtomProperty, makeFunction, getPropertyRange, specStringToObject, getbin } from "./utilities";
import { elementColors } from "./colors";
import { deepCopy, extend, getExtent, getAtomProperty, makeFunction, getPropertyRange, specStringToObject, getbin, getColorFromStyle } from "./utilities";
import { Gradient } from "./Gradient";
import { Parsers } from "./parsers";

Expand Down Expand Up @@ -486,7 +486,7 @@ export class GLModel {

};

private addLine(vertexArray, colorArray, offset, p1, p2, c1) {
private addLine(vertexArray, colorArray, offset, p1:Vector3, p2:Vector3, c1:Color) {
//make line from p1 to p2, does not incremeant counts
vertexArray[offset] = p1.x; vertexArray[offset + 1] = p1.y; vertexArray[offset + 2] = p1.z;
colorArray[offset] = c1.r; colorArray[offset + 1] = c1.g; colorArray[offset + 2] = c1.b;
Expand Down Expand Up @@ -570,10 +570,10 @@ export class GLModel {
}
if (bstyle.singleBond) singleBond = true;
if (typeof (bstyle.color1) != "undefined") {
c1 = CC.color(bstyle.color1);
c1 = CC.color(bstyle.color1) as Color;
}
if (typeof (bstyle.color2) != "undefined") {
c2 = CC.color(bstyle.color2);
c2 = CC.color(bstyle.color2) as Color;
}
}

Expand Down Expand Up @@ -724,7 +724,7 @@ export class GLModel {
}
};

private drawAtomInstanced(atom, geo) {
private drawAtomInstanced(atom, geo:Geometry) {

if (!atom.style.sphere)
return;
Expand Down Expand Up @@ -962,10 +962,10 @@ export class GLModel {
if (bstyle.radius) bondR = bstyle.radius;
if (bstyle.singleBond) singleBond = true;
if (typeof (bstyle.color1) != "undefined") {
C1 = CC.color(bstyle.color1);
C1 = CC.color(bstyle.color1) as Color;
}
if (typeof (bstyle.color2) != "undefined") {
C2 = CC.color(bstyle.color2);
C2 = CC.color(bstyle.color2) as Color;
}
}
var p1 = new Vector3(atom.x, atom.y, atom.z);
Expand Down Expand Up @@ -2108,10 +2108,9 @@ export class GLModel {
viewer.render();
});
*/
public selectedAtoms(sel, from) {
public selectedAtoms(sel, from?) {
var ret = [];


// make a copy of the selection to allow caching results without
// the possibility for the user to change the selection and this
// code not noticing the changes
Expand Down Expand Up @@ -2595,7 +2594,7 @@ export class GLModel {
* @param {boolean} whether or not to include style information. Defaults to false.
* @return {Object}
*/
public toCDObject(includeStyles) {
public toCDObject(includeStyles:boolean=false) {
var out: any = { a: [], b: [] };
if (includeStyles) {
out.s = [];
Expand Down
4 changes: 2 additions & 2 deletions packages/3Dmol/src/GLShape.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Geometry, CC, Material } from "./WebGL";
import { Geometry, Material } from "./WebGL";
import { Sphere, Cylinder, Triangle } from "./WebGL/shapes";
import { Vector3 } from "./WebGL/math";
import { clamp } from "./WebGL/math";
import { DoubleSide } from "./WebGL";
import { Color } from "./WebGL";
import { Color, CC } from "./colors";
import { MarchingCube } from "./ProteinSurface4";
import { VolumeData } from "./VolumeData";
import { MeshDoubleLambertMaterial, MeshLambertMaterial, Object3D, Coloring, Mesh, LineBasicMaterial, Line, LineStyle } from "./WebGL";
Expand Down
115 changes: 46 additions & 69 deletions packages/3Dmol/src/GLViewer.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
//a molecular viewer based on GLMol

import { Geometry, CC, Renderer, Camera, Raycaster, Projector, Light, Fog, Scene, Coloring, FrontSide } from "./WebGL";
import { Geometry, Renderer, Camera, Raycaster, Projector, Light, Fog, Scene, Coloring, FrontSide } from "./WebGL";
import { Vector3, Matrix4, Matrix3, Quaternion } from "./WebGL/math";
import { MeshLambertMaterial, Object3D, Mesh, LineBasicMaterial, Line } from "./WebGL";
import { getColorFromStyle, elementColors } from "./colors";
import { extend, getExtent, makeFunction, getPropertyRange, isEmptyObject, adjustVolumeStyle, mergeGeos, PausableTimer } from "./utilities";
import { elementColors, CC } from "./colors";
import { extend, getExtent, makeFunction, getPropertyRange, isEmptyObject, adjustVolumeStyle, mergeGeos, PausableTimer, getColorFromStyle } from "./utilities";
import { Gradient } from "./Gradient";
import { GLModel } from "./GLModel";
import { Label } from "./Label";
Expand Down Expand Up @@ -37,7 +37,7 @@ export class GLViewer {
private glDOM: any = null;
private ui: any = null;

private models = []; // atomistic molecular models
private models: GLModel[] = []; // atomistic molecular models
private surfaces: any = {};
private shapes = []; // Generic shapes
private labels = [];
Expand Down Expand Up @@ -293,7 +293,7 @@ export class GLViewer {
this.contextMenuEnabledAtoms.splice(0, this.contextMenuEnabledAtoms.length);

for (let i = 0, il = this.models.length; i < il; i++) {
var model = this.models[i];
let model = this.models[i];
if (model) {
let atoms = model.selectedAtoms({
clickable: true
Expand Down Expand Up @@ -472,12 +472,12 @@ export class GLViewer {
private adjustZoomToLimits(z) {
//a lower limit of 0 is at CAMERA_Z
if (this.config.lowerZoomLimit && this.config.lowerZoomLimit > 0) {
var lower = this.CAMERA_Z - this.config.lowerZoomLimit;
let lower = this.CAMERA_Z - this.config.lowerZoomLimit;
if (z > lower) z = lower;
}

if (this.config.upperZoomLimit && this.config.upperZoomLimit > 0) {
var upper = this.CAMERA_Z - this.config.upperZoomLimit;
let upper = this.CAMERA_Z - this.config.upperZoomLimit;
if (z < upper) z = upper;
}

Expand All @@ -488,16 +488,16 @@ export class GLViewer {
};
//interpolate between two normalized quaternions (t between 0 and 1)
//https://en.wikipedia.org/wiki/Slerp
private static slerp(v0, v1, t) {
private static slerp(v0: Quaternion, v1: Quaternion, t: number) {
// Compute the cosine of the angle between the two vectors.
//dot product
if (t == 1) return v1;
else if (t == 0) return v0;
var dot = v0.x * v1.x + v0.y * v1.y + v0.z * v1.z + v0.w * v1.w;
if (t == 1) return v1.clone();
else if (t == 0) return v0.clone();
let dot = v0.x * v1.x + v0.y * v1.y + v0.z * v1.z + v0.w * v1.w;
if (dot > 0.9995) {
// If the inputs are too close for comfort, linearly interpolate
// and normalize the result.
var result = new Quaternion(
let result = new Quaternion(
v0.x + t * (v1.x - v0.x),
v0.y + t * (v1.y - v0.y),
v0.z + t * (v1.z - v0.z),
Expand Down Expand Up @@ -1370,7 +1370,7 @@ export class GLViewer {
* value reverses the direction of the spin.
*
*/
public spin(axis, speed) {
public spin(axis, speed: number = 1) {
clearInterval(this.spinInterval);
if (typeof axis == 'undefined')
axis = 'y';
Expand All @@ -1380,9 +1380,6 @@ export class GLViewer {
else
axis = 'y';
}
if (typeof speed != 'number') {
speed = 1;
}

if (Array.isArray(axis)) {
axis = { x: axis[0], y: axis[1], z: axis[2] };
Expand All @@ -1409,10 +1406,10 @@ export class GLViewer {
//and rotationgroup quaternion
//return array includes final position, but not current
//the returned array includes an animate method
private animateMotion(duration, fixed, mpos, rz, rot, cam) {
private animateMotion(duration: number, fixed: boolean, mpos: Vector3, rz: number, rot: Quaternion, cam: Vector3) {
var interval = 20;
var steps: any = Math.ceil(duration / interval);
if (steps < 1) steps = 1;
var nsteps: number = Math.ceil(duration / interval);
if (nsteps < 1) nsteps = 1;
this.incAnim();

var curr = {
Expand All @@ -1423,24 +1420,14 @@ export class GLViewer {
};

if (fixed) { //precompute path and stick to it
steps = new Array(steps);
var n = steps.length;
for (var i = 0; i < n; i++) {
let frac = (i + 1) / n;
let steps = new Array(nsteps);
for (let i = 0; i < nsteps; i++) {
let frac = (i + 1) / nsteps;
let next: any = { mpos: curr.mpos, rz: curr.rz, rot: curr.rot };
if (mpos) {
next.mpos = mpos.clone().sub(curr.mpos).multiplyScalar(frac).add(curr.mpos);
}
if (typeof (rz) != 'undefined' && rz != null) {
next.rz = curr.rz + frac * (rz - curr.rz);
}
if (rot) {
next.rot = GLViewer.slerp(curr.rot, rot, frac);
}
if (cam) {
next.cam = cam.clone().sub(curr.cam).multiplyScalar(frac).add(curr.cam);
}

next.mpos = mpos.clone().sub(curr.mpos).multiplyScalar(frac).add(curr.mpos);
next.rz = curr.rz + frac * (rz - curr.rz);
next.rot = GLViewer.slerp(curr.rot, rot, frac);
next.cam = cam.clone().sub(curr.cam).multiplyScalar(frac).add(curr.cam);
steps[i] = next;
}

Expand All @@ -1449,18 +1436,10 @@ export class GLViewer {
let callback = function () {
var p = steps[step];
step += 1;
if (p.mpos) {
self.modelGroup.position = p.mpos;
}
if (p.rz) {
self.rotationGroup.position.z = p.rz;
}
if (p.rot) {
self.rotationGroup.quaternion = p.rot;
}
if (p.cam) {
self.camera.lookAt(p.cam);
}
self.modelGroup.position = p.mpos;
self.rotationGroup.position.z = p.rz;
self.rotationGroup.quaternion = p.rot;
self.camera.lookAt(p.cam);

if (step < steps.length) {
setTimeout(callback, interval);
Expand All @@ -1473,7 +1452,7 @@ export class GLViewer {

} else { //relative update
var delta: any = {};
let frac = 1.0 / steps;
let frac = 1.0 / nsteps;
if (mpos) {
delta.mpos = mpos.clone().sub(curr.mpos).multiplyScalar(frac);
}
Expand Down Expand Up @@ -1506,7 +1485,7 @@ export class GLViewer {
self.camera.lookAt(self.lookingAt);
}

if (step < steps) {
if (step < nsteps) {
setTimeout(callback, interval);
} else {
self.decAnim();
Expand Down Expand Up @@ -1541,7 +1520,7 @@ export class GLViewer {
*
*/
public rotate(angle, axis: any = "y", animationDuration = 0, fixedPath?) {
public rotate(angle, axis: any = "y", animationDuration: number = 0, fixedPath: boolean = false) {

if (axis == "x") {
axis = { x: 1, y: 0, z: 0 };
Expand Down Expand Up @@ -1769,25 +1748,27 @@ export class GLViewer {
/** @param {AtomSelectionSpec} sel
* @return list of models specified by sel
*/
private getModelList(sel) {
var ms = [];
private getModelList(sel): GLModel[] {
let ms: GLModel[] = [];
if (typeof sel === 'undefined' || typeof sel.model === "undefined") {
for (let i = 0; i < this.models.length; i++) {
if (this.models[i])
ms.push(this.models[i]);
}
} else { // specific to some models
ms = sel.model;
if (!Array.isArray(ms))
ms = [ms];
let selm:any = sel.model;
if (!Array.isArray(selm))
selm = [selm];

for (let i = 0; i < ms.length; i++) {
for (let i = 0; i < selm.length; i++) {
//allow referencing models by order of creation
if (typeof ms[i] === 'number') {
var index = ms[i];
if (typeof selm[i] === 'number') {
var index = selm[i];
//support python backward indexing
if (index < 0) index += this.models.length;
ms[i] = this.models[index];
ms.push(this.models[index]);
} else {
ms.push(selm[i]);
}
}
}
Expand All @@ -1807,7 +1788,7 @@ export class GLViewer {

var ms = this.getModelList(sel);

for (var i = 0; i < ms.length; i++) {
for (let i = 0; i < ms.length; i++) {
atoms = atoms.concat(ms[i].selectedAtoms(sel));
}

Expand Down Expand Up @@ -1910,9 +1891,8 @@ export class GLViewer {
});
*/
public zoom(factor, animationDuration, fixedPath) {
public zoom(factor?, animationDuration: number = 0, fixedPath: boolean = false) {
factor = factor || 2;
animationDuration = animationDuration !== undefined ? animationDuration : 0;
var scale = (this.CAMERA_Z - this.rotationGroup.position.z) / factor;
var final_z = this.CAMERA_Z - scale;

Expand Down Expand Up @@ -1950,8 +1930,7 @@ export class GLViewer {
viewer.render(callback);
});
*/
public translate(x, y, animationDuration, fixedPath) {
animationDuration = animationDuration !== undefined ? animationDuration : 0;
public translate(x, y, animationDuration: number = 0, fixedPath: boolean = false) {
var dx = x / this.WIDTH;
var dy = y / this.HEIGHT;
var v = new Vector3(0, 0, -this.CAMERA_Z);
Expand Down Expand Up @@ -1999,8 +1978,7 @@ export class GLViewer {
viewer.render(callback);
});
*/
public translateScene(x, y, animationDuration, fixedPath) {
animationDuration = animationDuration !== undefined ? animationDuration : 0;
public translateScene(x, y, animationDuration: number = 0, fixedPath = false) {

var t = this.screenOffsetToModel(x, y);
var final_position = this.modelGroup.position.clone().add(t);
Expand Down Expand Up @@ -2072,8 +2050,7 @@ export class GLViewer {
viewer.render(callback);
});
*/
public center(sel, animationDuration, fixedPath) {
animationDuration = animationDuration !== undefined ? animationDuration : 0;
public center(sel, animationDuration: number = 0, fixedPath: boolean = false) {
var allatoms, alltmp;
sel = sel || {};
var atoms = this.getAtomsFromSel(sel);
Expand Down
6 changes: 2 additions & 4 deletions packages/3Dmol/src/Gradient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,6 @@ export class Gradient extends GradientType {
static builtinGradients = builtinGradients;
static normalizeValue = normalizeValue;
static getGradient = getGradient;
// @ts-ignore
valueToHex(_value: number, _range: number): number { }
// @ts-ignore
range(): [number, number] { }
valueToHex(_value: number, _range: number): number { return 0; }
range(): [number, number]|null { return null; }
}
Loading

0 comments on commit 49c1631

Please sign in to comment.