Skip to content

Commit

Permalink
Fixed a bug in shape coloring, and fixed colorscales (#325)
Browse files Browse the repository at this point in the history
For some reasons, 3dmol seems to misunderstand gradient interpolation if
it's very coarsely discretized. Maybe we should file a bug upstream, but
for the moment I just defined more finely the two color scales that were
mishbehaving.
  • Loading branch information
ceriottm authored Dec 23, 2023
1 parent df83b53 commit 179e8f7
Show file tree
Hide file tree
Showing 2 changed files with 162 additions and 25 deletions.
131 changes: 130 additions & 1 deletion src/map/colorscales.ts
Original file line number Diff line number Diff line change
Expand Up @@ -616,10 +616,138 @@ const SEISMIC: RGBColorMap = [

const BWR: RGBColorMap = [
[0.0, [0, 0, 255]],
[0.5, [255, 255, 255]],
[0.01587, [8, 8, 255]],
[0.03175, [16, 16, 255]],
[0.04762, [24, 24, 255]],
[0.06349, [32, 32, 255]],
[0.07937, [40, 40, 255]],
[0.09524, [48, 48, 255]],
[0.1111, [56, 56, 255]],
[0.127, [64, 64, 255]],
[0.1429, [72, 72, 255]],
[0.1587, [80, 80, 255]],
[0.1746, [89, 89, 255]],
[0.1905, [97, 97, 255]],
[0.2063, [105, 105, 255]],
[0.2222, [113, 113, 255]],
[0.2381, [121, 121, 255]],
[0.254, [129, 129, 255]],
[0.2698, [137, 137, 255]],
[0.2857, [145, 145, 255]],
[0.3016, [153, 153, 255]],
[0.3175, [161, 161, 255]],
[0.3333, [170, 170, 255]],
[0.3492, [178, 178, 255]],
[0.3651, [186, 186, 255]],
[0.381, [194, 194, 255]],
[0.3968, [202, 202, 255]],
[0.4127, [210, 210, 255]],
[0.4286, [218, 218, 255]],
[0.4444, [226, 226, 255]],
[0.4603, [234, 234, 255]],
[0.4762, [242, 242, 255]],
[0.4921, [250, 250, 255]],
[0.5079, [255, 250, 250]],
[0.5238, [254, 242, 242]],
[0.5397, [255, 234, 234]],
[0.5556, [255, 226, 226]],
[0.5714, [255, 218, 218]],
[0.5873, [254, 210, 210]],
[0.6032, [255, 202, 202]],
[0.619, [255, 194, 194]],
[0.6349, [255, 186, 186]],
[0.6508, [254, 178, 178]],
[0.6667, [255, 170, 170]],
[0.6825, [255, 161, 161]],
[0.6984, [255, 153, 153]],
[0.7143, [254, 145, 145]],
[0.7302, [255, 137, 137]],
[0.746, [255, 129, 129]],
[0.7619, [255, 121, 121]],
[0.7778, [255, 113, 113]],
[0.7937, [255, 105, 105]],
[0.8095, [255, 97, 97]],
[0.8254, [255, 89, 89]],
[0.8413, [255, 80, 80]],
[0.8571, [255, 72, 72]],
[0.873, [255, 64, 64]],
[0.8889, [255, 56, 56]],
[0.9048, [255, 48, 48]],
[0.9206, [255, 40, 40]],
[0.9365, [255, 32, 32]],
[0.9524, [255, 24, 24]],
[0.9683, [255, 16, 16]],
[0.9841, [255, 8, 8]],
[1.0, [255, 0, 0]],
];

const RWG: RGBColorMap = [
[0.0, [200, 0, 0]],
[0.01587, [201, 8, 8]],
[0.03175, [203, 16, 16]],
[0.04762, [205, 24, 24]],
[0.06349, [206, 32, 32]],
[0.07937, [208, 40, 40]],
[0.09524, [210, 48, 48]],
[0.1111, [212, 56, 56]],
[0.127, [213, 64, 64]],
[0.1429, [215, 72, 72]],
[0.1587, [217, 80, 80]],
[0.1746, [219, 89, 89]],
[0.1905, [220, 97, 97]],
[0.2063, [222, 105, 105]],
[0.2222, [224, 113, 113]],
[0.2381, [226, 121, 121]],
[0.254, [227, 129, 129]],
[0.2698, [229, 137, 137]],
[0.2857, [231, 145, 145]],
[0.3016, [233, 153, 153]],
[0.3175, [234, 161, 161]],
[0.3333, [236, 170, 170]],
[0.3492, [238, 178, 178]],
[0.3651, [240, 186, 186]],
[0.381, [241, 194, 194]],
[0.3968, [243, 202, 202]],
[0.4127, [245, 210, 210]],
[0.4286, [247, 218, 218]],
[0.4444, [248, 226, 226]],
[0.4603, [250, 234, 234]],
[0.4762, [252, 242, 242]],
[0.4921, [254, 250, 250]],
[0.5079, [250, 252, 250]],
[0.5238, [242, 248, 242]],
[0.5397, [234, 244, 234]],
[0.5556, [226, 240, 226]],
[0.5714, [218, 236, 218]],
[0.5873, [210, 232, 210]],
[0.6032, [202, 228, 202]],
[0.619, [194, 224, 194]],
[0.6349, [186, 220, 186]],
[0.6508, [178, 216, 178]],
[0.6667, [170, 212, 170]],
[0.6825, [161, 208, 161]],
[0.6984, [153, 204, 153]],
[0.7143, [145, 200, 145]],
[0.7302, [137, 196, 137]],
[0.746, [129, 192, 129]],
[0.7619, [121, 188, 121]],
[0.7778, [113, 184, 113]],
[0.7937, [105, 180, 105]],
[0.8095, [97, 176, 97]],
[0.8254, [89, 172, 89]],
[0.8413, [80, 168, 80]],
[0.8571, [72, 164, 72]],
[0.873, [64, 160, 64]],
[0.8889, [56, 156, 56]],
[0.9048, [48, 152, 48]],
[0.9206, [40, 148, 40]],
[0.9365, [32, 144, 32]],
[0.9524, [24, 140, 24]],
[0.9683, [16, 136, 16]],
[0.9841, [8, 132, 8]],
[1.0, [0, 128, 0]],
];

const BRG: RGBColorMap = [
[0.0, [0, 0, 255]],
[0.0159, [8, 0, 248]],
Expand Down Expand Up @@ -702,6 +830,7 @@ export const COLOR_MAPS: ColorMaps = {
seismic: rgb_to_plotly(SEISMIC),
brg: rgb_to_plotly(BRG),
bwr: rgb_to_plotly(BWR),
rwg: rgb_to_plotly(RWG),
'twilight (periodic)': rgb_to_plotly(TWILIGHT),
'twilight dark (periodic)': rgb_to_plotly(TWILIGHT_SHIFTED),
'hsv (periodic)': rgb_to_plotly(HSV),
Expand Down
56 changes: 32 additions & 24 deletions src/structure/viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { Arrow, CustomShape, Cylinder, Ellipsoid, ShapeData, Sphere, add_shapes
import { StructureOptions } from './options';

import { COLOR_MAPS } from '../map/colorscales';
import { sensitiveHeaders } from 'http2';

Check warning on line 20 in src/structure/viewer.ts

View workflow job for this annotation

GitHub Actions / npm-test (16.x)

'sensitiveHeaders' is defined but never used

Check warning on line 20 in src/structure/viewer.ts

View workflow job for this annotation

GitHub Actions / npm-test (18.x)

'sensitiveHeaders' is defined but never used

Check warning on line 20 in src/structure/viewer.ts

View workflow job for this annotation

GitHub Actions / npm-test (20.x)

'sensitiveHeaders' is defined but never used

const IS_SAFARI =
navigator.vendor !== undefined &&
Expand Down Expand Up @@ -314,6 +315,10 @@ export class MoleculeViewer {
);

window.addEventListener('resize', () => this.resize());
// waits for loading of widget, then triggers a redraw. fixes some glitches on the Jupyter side
window.requestAnimationFrame(() => {
window.dispatchEvent(new Event('resize'));
});
}

/**
Expand Down Expand Up @@ -823,7 +828,6 @@ export class MoleculeViewer {
// setup state when the property changes
const colorPropertyChanged = () => {
const property = this._options.color.property.value;
this._deleteColorBar();

if (property !== 'element') {
this._options.color.transform.enable();
Expand Down Expand Up @@ -853,7 +857,6 @@ export class MoleculeViewer {
this._options.color.max.value = max;
this._options.color.min.value = min;
this._setScaleStep([min, max]);
this._updateColorBar();
} else {
this._options.color.transform.disable();
this._options.color.min.disable();
Expand All @@ -865,6 +868,8 @@ export class MoleculeViewer {

this._viewer.setColorByElement({}, $3Dmol.elementColors.Jmol);
}

this._updateColorBar();
restyleAndRender();
};
this._options.color.property.onchange.push(colorPropertyChanged);
Expand All @@ -885,6 +890,7 @@ export class MoleculeViewer {
}
this._setScaleStep([min, max]);
this._updateColorBar();
restyleAndRender();
};

// ======= color transform
Expand All @@ -904,7 +910,6 @@ export class MoleculeViewer {
this._options.color.min.value = min;
this._setScaleStep([min, max]);
this._updateColorBar();

restyleAndRender();
});

Expand Down Expand Up @@ -937,7 +942,6 @@ export class MoleculeViewer {
this._options.color.max.value = max;
this._setScaleStep([min, max]);
this._updateColorBar();

restyleAndRender();
});

Expand Down Expand Up @@ -1170,8 +1174,10 @@ export class MoleculeViewer {
for (let i = 0; i < structure.size; i++) {
const name = structure.names[i];
assert(i < current_shape.parameters.atom.length);
const atom_pars = current_shape.parameters.atom[i];
shape_data = { ...shape_data, ...atom_pars };
const atom_pars = {
...shape_data,
...current_shape.parameters.atom[i],
};

let position: [number, number, number] = [
structure.x[i],
Expand All @@ -1186,55 +1192,57 @@ export class MoleculeViewer {
position[1] += a * cell[1] + b * cell[4] + c * cell[7];
position[2] += a * cell[2] + b * cell[5] + c * cell[8];

shape_data.position = position;
if (atom_pars.color) {
shape_data.color = atom_pars.color;
} else if (colorfunc) {
atomspec.serial = i;
shape_data.color = colorfunc(atomspec);
} else {
shape_data.color = $3Dmol.elementColors.Jmol[name];
atom_pars.position = position;
// obey explicit color specification if given,
// otherwise color as the corresponding atom
if (!atom_pars.color) {
if (colorfunc) {
atomspec.serial = i;
atom_pars.color = colorfunc(atomspec);
} else {
atom_pars.color = $3Dmol.elementColors.Jmol[name];
}
}

if (current_shape.kind === 'sphere') {
const shape = new Sphere(shape_data);
const shape = new Sphere(atom_pars);
//this._viewer.addCustom(
add_shapes(
all_shapes,
shape.outputTo3Dmol(shape_data.color || 0xffffff),
shape.outputTo3Dmol(atom_pars.color || 0xffffff),
this._viewer,
32768
);
} else if (current_shape.kind === 'ellipsoid') {
const shape = new Ellipsoid(shape_data);
const shape = new Ellipsoid(atom_pars);
add_shapes(
all_shapes,
shape.outputTo3Dmol(shape_data.color || 0xffffff),
shape.outputTo3Dmol(atom_pars.color || 0xffffff),
this._viewer,
32768
);
} else if (current_shape.kind === 'cylinder') {
const shape = new Cylinder(shape_data);
const shape = new Cylinder(atom_pars);
add_shapes(
all_shapes,
shape.outputTo3Dmol(shape_data.color || 0xffffff),
shape.outputTo3Dmol(atom_pars.color || 0xffffff),
this._viewer,
32768
);
} else if (current_shape.kind === 'arrow') {
const shape = new Arrow(shape_data);
const shape = new Arrow(atom_pars);
add_shapes(
all_shapes,
shape.outputTo3Dmol(shape_data.color || 0xffffff),
shape.outputTo3Dmol(atom_pars.color || 0xffffff),
this._viewer,
32768
);
} else {
assert(current_shape.kind === 'custom');
const shape = new CustomShape(shape_data);
const shape = new CustomShape(atom_pars);
add_shapes(
all_shapes,
shape.outputTo3Dmol(shape_data.color || 0xffffff),
shape.outputTo3Dmol(atom_pars.color || 0xffffff),
this._viewer,
32768
);
Expand Down

0 comments on commit 179e8f7

Please sign in to comment.