Skip to content

Commit

Permalink
Merge pull request #152 from Exabyte-io/feat/SOF-7354
Browse files Browse the repository at this point in the history
SOF-7354: show labels with atomic symbols when present
  • Loading branch information
pranabdas authored May 23, 2024
2 parents fac1ab5 + 9e33e3e commit b36d662
Show file tree
Hide file tree
Showing 42 changed files with 1,148 additions and 163 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ jobs:

steps:
- name: Checkout this repository
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
lfs: true

- name: Checkout actions repository
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
repository: Exabyte-io/actions
token: ${{ secrets.BOT_GITHUB_TOKEN }}
path: actions

- name: Login to GitHub Container registry
uses: docker/login-action@v1
uses: docker/login-action@v3
env:
GITHUB_USER: ${{ github.actor }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down Expand Up @@ -60,12 +60,12 @@ jobs:

steps:
- name: Checkout this repository
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
lfs: true

- name: Checkout actions repository
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
repository: Exabyte-io/actions
token: ${{ secrets.BOT_GITHUB_TOKEN }}
Expand Down
2 changes: 0 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: "3.8"

services:
wave:
image: wave-${BASE_OS}:${IMAGE_TAG}
Expand Down
4 changes: 4 additions & 0 deletions dockerfiles/ubuntu/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
FROM ubuntu:latest
# TODO: with latest (24.04) version of ubuntu there are following errors
# MESA: error: ZINK: vkCreateInstance failed (VK_ERROR_INCOMPATIBLE_DRIVER)
# glx: failed to create drisw screen
# NOTE: however the snapshots on 24.04 are identical to the ones from 22.04

# Install base dependencies
RUN apt-get update && apt-get install -y -q --no-install-recommends \
Expand Down
1,145 changes: 1,017 additions & 128 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@
"@exabyte-io/eslint-config": "^2023.8.29-1",
"@mat3ra/tsconfig": "^2024.3.21-5",
"@mat3ra/code": "^2024.3.25-3",
"@mat3ra/esse": "^2024.3.25-6",
"@mat3ra/made": "^2024.3.26-0",
"@mat3ra/esse": "2024.4.19-1",
"@mat3ra/made": "2024.5.3-0",
"@exabyte-io/cove.js": "2024.2.21-1",
"@types/react": "^18.2.8",
"@types/react-dom": "^18.2.4",
Expand Down
2 changes: 1 addition & 1 deletion src/components/SquareIconButton.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import IconButton, { IconButtonProps } from "@mui/material/IconButton";
import Tooltip, { TooltipProps } from "@mui/material/Tooltip";
import React, { useState } from "react";
import React from "react";
import _ from "underscore";

interface SquareIconButtonProps extends IconButtonProps {
Expand Down
15 changes: 15 additions & 0 deletions src/mixins/atoms.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as THREE from "three";

import { ATOM_GROUP_NAME } from "../enums";
import { ApplyGlow } from "./utils";

/*
* Mixin containing the logic for dealing with atoms.
Expand Down Expand Up @@ -88,13 +89,27 @@ export const AtomsMixin = (superclass) =>
createAtomsGroup(basis, atomRadiiScale) {
const atomsGroup = new THREE.Group();
atomsGroup.name = ATOM_GROUP_NAME;
const { atomicLabelsArray, elementsWithLabelsArray } = basis;
basis.coordinates.forEach((atomicCoordinate, atomicIndex) => {
const element = basis.getElementByIndex(atomicIndex);
const sphereMesh = this.getSphereMeshObject({
...this._getDefaultSettingsForElement(element, atomRadiiScale),
coordinate: atomicCoordinate.value,
});
sphereMesh.name = `${element}-${atomicIndex}`;
// store any additional data in userData
// https://threejs.org/docs/#api/en/core/Object3D.userData
sphereMesh.userData = {
...sphereMesh.userData,
symbolWithLabel: elementsWithLabelsArray[atomicIndex],
};
const atomColor = this.getAtomColorByElement(element).toLowerCase();
const label = parseInt(atomicLabelsArray[atomicIndex], 10) || 0;
// set glow according to the label value as offset, currently
// only single digit numeric labels are allowed, in practice we
// expect only two different labels: 1 and 2 for up and down
// spin representations
ApplyGlow(sphereMesh, atomColor, label);
atomsGroup.add(sphereMesh);
});
return atomsGroup;
Expand Down
2 changes: 1 addition & 1 deletion src/mixins/bonds.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Made } from "@mat3ra/made";
import {
filterBondsDataByElementsAndOrder,
getElementsBondsData,
} from "@exabyte-io/periodic-table.js";
import { Made } from "@mat3ra/made";
import createKDTree from "static-kdtree";
import * as THREE from "three";

Expand Down
2 changes: 1 addition & 1 deletion src/mixins/labels.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export const LabelsMixin = (superclass) =>

group.children.forEach((atom) => {
if (atom instanceof THREE.Mesh) {
const text = atom.name.split("-")[0];
const text = atom.userData.symbolWithLabel;
const position = new THREE.Vector3().setFromMatrixPosition(
atom.matrixWorld,
);
Expand Down
38 changes: 38 additions & 0 deletions src/mixins/utils.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as THREE from "three";

export const UtilsMixin = (superclass) =>
class extends superclass {
// toggles a boolean variable and optionally sets all variables in the antagonists array to the opposite value
Expand Down Expand Up @@ -27,3 +29,39 @@ export const UtilsMixin = (superclass) =>
return resultingObject;
}
};

/**
* Applies glow to a THREE object.
* @param meshObjet {Object}: THREE mesh object.
* @param baseColor {String}: hex color string of the glow
* @param offset {Number}: can be a single digit number, 0 means no offset
*/
export const ApplyGlow = (meshObjet, baseColor, offset = 0) => {
const atomHSL = {};
new THREE.Color(baseColor).getHSL(atomHSL);
let hue, saturation;
if (offset !== 0) {
if (offset % 2 === 0) {
// even labels
hue = atomHSL.h + (offset * 0.1) / 2;
saturation = atomHSL.s + (offset * 0.1) / 2;
} else {
// odd labels
hue = atomHSL.h - ((offset + 1) * 0.1) / 2;
saturation = atomHSL.s + ((offset + 1) * 0.1) / 2;
}

// hue is cyclic
while (hue > 1) {
hue -= 1;
}

while (hue < 0) {
hue += 1;
}

saturation = Math.max(0, Math.min(1, saturation));
meshObjet.material.emissiveIntensity = 0.25;
meshObjet.material.emissive.setHSL(hue, saturation, atomHSL.l);
}
};
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions tests/__tests__/__snapshots__/ubuntu/toggleAxes.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions tests/__tests__/__snapshots__/ubuntu/vectorA.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions tests/__tests__/__snapshots__/ubuntu/vectorAB.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions tests/__tests__/__snapshots__/ubuntu/vectorABC.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions tests/__tests__/__snapshots__/ubuntu/vectorAC.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions tests/__tests__/__snapshots__/ubuntu/vectorB.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions tests/__tests__/__snapshots__/ubuntu/vectorBC.expected.png
4 changes: 2 additions & 2 deletions tests/__tests__/__snapshots__/ubuntu/vectorC.expected.png
5 changes: 2 additions & 3 deletions tests/__tests__/mixins/labels.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe("Atom labels", () => {
const basisAtomsNumber = wave.structure.basis.elements.length;

atoms.forEach((atom) => {
const atomName = atom.name.split("-")[0];
const atomName = atom.userData.symbolWithLabel;
const atomPosition = new THREE.Vector3().setFromMatrixPosition(atom.matrixWorld);

const offsetVector = wave.getLabelOffsetVector(atomPosition, atomName);
Expand All @@ -32,7 +32,6 @@ describe("Atom labels", () => {
label.position.distanceTo(expectedLabelPosition) < 0.00001
);
});

expect(labelSprite).toBeTruthy();
});

Expand All @@ -49,7 +48,7 @@ describe("Atom labels", () => {

const basisAtomsNumber = wave.structure.basis.elements.length;
const doAllAtomsHaveLabels = atoms.every((atom) => {
const atomName = atom.name.split("-")[0];
const atomName = atom.userData.symbolWithLabel;
const labelName = `labels-for-${atomName}`;
const labelPointsByAtomName = labels.find(
(labelPoints) => labelPoints.name === labelName,
Expand Down
2 changes: 1 addition & 1 deletion tests/__tests__/mixins/repetition.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe("Screen tests for repeats", () => {
const wave = getWaveInstance({ ...settings, repetitionsAlongLatticeVectorB: 3 });
return takeSnapshotAndAssertEqualityAsync(wave.renderer.getContext(), "vectorB");
});
test("Repeat along lattice vector С", () => {
test("Repeat along lattice vector C", () => {
const wave = getWaveInstance({ ...settings, repetitionsAlongLatticeVectorC: 3 });
return takeSnapshotAndAssertEqualityAsync(wave.renderer.getContext(), "vectorC");
});
Expand Down
16 changes: 15 additions & 1 deletion tests/__tests__/wave.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getWaveInstance } from "../enums";
import { getFeOWaveInstance, getWaveInstance } from "../enums";
import { takeSnapshotAndAssertEqualityAsync } from "../utils";

test("wave", async () => {
Expand All @@ -19,3 +19,17 @@ test("atomRepetitions", async () => {
wave.rebuildScene();
return takeSnapshotAndAssertEqualityAsync(wave.renderer.getContext(), "atomRepetitions");
});

test("colorsOfAtomsWithLabels", async () => {
const wave = getFeOWaveInstance();
// zoom-out to get full view of the cell
wave.toggleOrbitControls();
wave.renderer.domElement.dispatchEvent(new WheelEvent("wheel", { deltaY: 1 }));
wave.renderer.domElement.dispatchEvent(new WheelEvent("wheel", { deltaY: 1 }));
wave.renderer.domElement.dispatchEvent(new WheelEvent("wheel", { deltaY: 1 }));
wave.renderer.domElement.dispatchEvent(new WheelEvent("wheel", { deltaY: 1 }));
return takeSnapshotAndAssertEqualityAsync(
wave.renderer.getContext(),
"colorsOfAtomsWithLabels",
);
});
13 changes: 13 additions & 0 deletions tests/enums.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ export const ELEMENT_PROPERTIES = {
const materialJsonFilePath = path.resolve(__dirname, "fixtures/material.json");
export const MATERIAL_CONFIG = JSON.parse(fs.readFileSync(materialJsonFilePath));

// config for material with atomic labels
const FeOJsonFilePath = path.resolve(__dirname, "fixtures/FeO.json");
export const FeO_CONFIG = JSON.parse(fs.readFileSync(FeOJsonFilePath));

export const WAVE_SETTINGS = {
atomRadiiScale: 0.2,
repetitions: 1,
Expand All @@ -32,3 +36,12 @@ export function getWaveInstance(settings, material = new Made.Material(MATERIAL_
settings: settings || WAVE_SETTINGS,
});
}

export function getFeOWaveInstance(settings, material = new Made.Material(FeO_CONFIG)) {
return new Wave({
DOMElement: createElement("div", ELEMENT_PROPERTIES),
structure: material,
cell: material.Lattice.unitCell,
settings: settings || WAVE_SETTINGS,
});
}
3 changes: 3 additions & 0 deletions tests/fixtures/FeO.json
Git LFS file not shown

0 comments on commit b36d662

Please sign in to comment.