Compare commits

...

10 Commits

Author SHA1 Message Date
dsehnal
2a83afa8c1 3.5.0 2022-03-25 13:49:33 +01:00
dsehnal
8891fa328b cif2bcif BCIF => CIF conversion support 2022-03-25 13:45:00 +01:00
David Sehnal
a23c06c456 Merge pull request #399 from MadCatX/dnatco-changeable-colors
Make Confal pyramids colors changeable
2022-03-22 13:25:32 +01:00
Michal Malý
34e87121e1 Make Confal pyramids colors changeable 2022-03-21 09:07:49 +01:00
Alexander Rose
6e5c20f442 improve surface bounding-sphere
- use exact max radius to expand structure/unit sphere
2022-03-19 12:21:55 -07:00
Alexander Rose
8ac3bec451 improve color-smoothing
- use padded box
2022-03-19 12:20:12 -07:00
Alexander Rose
5128d0f405 improve Sphere3D.expand & Box3D.fromSphere3D
- ensure extrema are within radius
- avoid degenerate box for low number of points
2022-03-19 12:19:39 -07:00
Alexander Rose
6ae2121391 guard against zero window.devicePixelRatio 2022-03-19 11:43:41 -07:00
David Sehnal
749e0c5a47 Merge pull request #396 from MadCatX/dnatco-off-by-one
DNATCO extension: Fix off-by-one error in element lookup
2022-03-17 09:21:11 +01:00
Michal Malý
7b55ef85e1 DNATCO extension: Fix missing Confal pyramids in some structures 2022-03-17 07:47:47 +01:00
25 changed files with 333 additions and 243 deletions

View File

@@ -6,6 +6,12 @@ Note that since we don't clearly distinguish between a public and private interf
## [Unreleased]
## [v3.5.0] - 2022-03-25
- Fix issues with bounding-sphere & color-smoothing (mostly for small geometries)
- Support BCIF => CIF conversion in ``cif2bcif`` CLI tool
## [v3.4.0] - 2022-03-13
- Fix handling of mmcif with empty ``label_*`` fields

View File

@@ -141,7 +141,7 @@ and navigate to `build/viewer`
export NODE_PATH="lib"; node build/state-docs
**Convert any CIF to BinaryCIF**
**Convert any CIF to BinaryCIF (or vice versa)**
node lib/commonjs/servers/model/preprocess -i file.cif -ob file.bcif
@@ -151,6 +151,11 @@ Or
node lib/commonjs/cli/cif2bcif
E.g.
node lib/commonjs/cli/cif2bcif src.cif out.bcif.gz
node lib/commonjs/cli/cif2bcif src.bcif.gz out.cif
## Development
### Installation

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "molstar",
"version": "3.4.0",
"version": "3.5.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "molstar",
"version": "3.4.0",
"version": "3.5.0",
"license": "MIT",
"dependencies": {
"@types/argparse": "^2.0.10",

View File

@@ -1,6 +1,6 @@
{
"name": "molstar",
"version": "3.4.0",
"version": "3.5.0",
"description": "A comprehensive macromolecular library.",
"homepage": "https://github.com/molstar/molstar#readme",
"repository": {

View File

@@ -71,7 +71,7 @@ function classify(name: string, field: CifField): CifWriter.Field {
}
export function convert(path: string, asText = false, hints?: EncodingStrategyHint[], filter?: string) {
return Task.create<Uint8Array>('BinaryCIF', async ctx => {
return Task.create<Uint8Array>('Convert CIF', async ctx => {
const encodingProvider: BinaryEncodingProvider = hints
? CifWriter.createEncodingProviderFromJsonConfig(hints)
: { get: (c, f) => void 0 };

View File

@@ -18,7 +18,7 @@ async function process(srcPath: string, outPath: string, configPath?: string, fi
const config = configPath ? JSON.parse(fs.readFileSync(configPath, 'utf8')) : void 0;
const filter = filterPath ? fs.readFileSync(filterPath, 'utf8') : void 0;
const res = await convert(srcPath, false, config, filter);
const res = await convert(srcPath, srcPath.toLowerCase().indexOf('.bcif') > 0, config, filter);
await write(outPath, res);
}
@@ -38,13 +38,13 @@ function run(args: Args) {
const parser = new argparse.ArgumentParser({
add_help: true,
description: 'Convert any CIF file to a BCIF file'
description: 'Convert any BCIF file to a CIF file or vice versa'
});
parser.add_argument('src', {
help: 'Source CIF path'
help: 'Source file path'
});
parser.add_argument('out', {
help: 'Output BCIF path'
help: 'Output file path'
});
parser.add_argument('-c', '--config', {
help: 'Optional encoding strategy/precision config path',

View File

@@ -11,149 +11,248 @@ import { Location } from '../../../mol-model/location';
import { CustomProperty } from '../../../mol-model-props/common/custom-property';
import { ColorTheme } from '../../../mol-theme/color';
import { ThemeDataContext } from '../../../mol-theme/theme';
import { Color } from '../../../mol-util/color';
import { Color, ColorMap } from '../../../mol-util/color';
import { getColorMapParams } from '../../../mol-util/color/params';
import { ParamDefinition as PD } from '../../../mol-util/param-definition';
import { TableLegend } from '../../../mol-util/legend';
import { iterableToArray } from '../../../mol-data/util';
import { ObjectKeys } from '../../../mol-util/type-helpers';
const DefaultColor = Color(0xCCCCCC);
const Description = 'Assigns colors to confal pyramids';
const DefaultClassColors = {
A: 0xFFC1C1,
B: 0xC8CFFF,
BII: 0x0059DA,
miB: 0x3BE8FB,
Z: 0x01F60E,
IC: 0xFA5CFB,
OPN: 0xE90000,
SYN: 0xFFFF01,
N: 0xF2F2F2,
};
const ErrorColor = Color(0xFFA10A);
type ConformerClasses = 'A' | 'B' | 'BII' | 'miB' | 'Z' | 'IC' | 'OPN' | 'SYN' | 'N';
const PyramidsColors = ColorMap({
NANT_Upr: DefaultClassColors.N,
NANT_Lwr: DefaultClassColors.N,
AA00_Upr: DefaultClassColors.A,
AA00_Lwr: DefaultClassColors.A,
AA02_Upr: DefaultClassColors.A,
AA02_Lwr: DefaultClassColors.A,
AA03_Upr: DefaultClassColors.A,
AA03_Lwr: DefaultClassColors.A,
AA04_Upr: DefaultClassColors.A,
AA04_Lwr: DefaultClassColors.A,
AA08_Upr: DefaultClassColors.A,
AA08_Lwr: DefaultClassColors.A,
AA09_Upr: DefaultClassColors.A,
AA09_Lwr: DefaultClassColors.A,
AA01_Upr: DefaultClassColors.A,
AA01_Lwr: DefaultClassColors.A,
AA05_Upr: DefaultClassColors.A,
AA05_Lwr: DefaultClassColors.A,
AA06_Upr: DefaultClassColors.A,
AA06_Lwr: DefaultClassColors.A,
AA10_Upr: DefaultClassColors.A,
AA10_Lwr: DefaultClassColors.A,
AA11_Upr: DefaultClassColors.A,
AA11_Lwr: DefaultClassColors.A,
AA07_Upr: DefaultClassColors.A,
AA07_Lwr: DefaultClassColors.A,
AA12_Upr: DefaultClassColors.A,
AA12_Lwr: DefaultClassColors.A,
AA13_Upr: DefaultClassColors.A,
AA13_Lwr: DefaultClassColors.A,
AB01_Upr: DefaultClassColors.A,
AB01_Lwr: DefaultClassColors.B,
AB02_Upr: DefaultClassColors.A,
AB02_Lwr: DefaultClassColors.B,
AB03_Upr: DefaultClassColors.A,
AB03_Lwr: DefaultClassColors.B,
AB04_Upr: DefaultClassColors.A,
AB04_Lwr: DefaultClassColors.B,
AB05_Upr: DefaultClassColors.A,
AB05_Lwr: DefaultClassColors.B,
BA01_Upr: DefaultClassColors.B,
BA01_Lwr: DefaultClassColors.A,
BA05_Upr: DefaultClassColors.B,
BA05_Lwr: DefaultClassColors.A,
BA09_Upr: DefaultClassColors.B,
BA09_Lwr: DefaultClassColors.A,
BA08_Upr: DefaultClassColors.BII,
BA08_Lwr: DefaultClassColors.A,
BA10_Upr: DefaultClassColors.B,
BA10_Lwr: DefaultClassColors.A,
BA13_Upr: DefaultClassColors.BII,
BA13_Lwr: DefaultClassColors.A,
BA16_Upr: DefaultClassColors.BII,
BA16_Lwr: DefaultClassColors.A,
BA17_Upr: DefaultClassColors.BII,
BA17_Lwr: DefaultClassColors.A,
BB00_Upr: DefaultClassColors.B,
BB00_Lwr: DefaultClassColors.B,
BB01_Upr: DefaultClassColors.B,
BB01_Lwr: DefaultClassColors.B,
BB17_Upr: DefaultClassColors.B,
BB17_Lwr: DefaultClassColors.B,
BB02_Upr: DefaultClassColors.B,
BB02_Lwr: DefaultClassColors.B,
BB03_Upr: DefaultClassColors.B,
BB03_Lwr: DefaultClassColors.B,
BB11_Upr: DefaultClassColors.B,
BB11_Lwr: DefaultClassColors.B,
BB16_Upr: DefaultClassColors.B,
BB16_Lwr: DefaultClassColors.B,
BB04_Upr: DefaultClassColors.B,
BB04_Lwr: DefaultClassColors.BII,
BB05_Upr: DefaultClassColors.B,
BB05_Lwr: DefaultClassColors.BII,
BB07_Upr: DefaultClassColors.BII,
BB07_Lwr: DefaultClassColors.BII,
BB08_Upr: DefaultClassColors.BII,
BB08_Lwr: DefaultClassColors.BII,
BB10_Upr: DefaultClassColors.miB,
BB10_Lwr: DefaultClassColors.miB,
BB12_Upr: DefaultClassColors.miB,
BB12_Lwr: DefaultClassColors.miB,
BB13_Upr: DefaultClassColors.miB,
BB13_Lwr: DefaultClassColors.miB,
BB14_Upr: DefaultClassColors.miB,
BB14_Lwr: DefaultClassColors.miB,
BB15_Upr: DefaultClassColors.miB,
BB15_Lwr: DefaultClassColors.miB,
BB20_Upr: DefaultClassColors.miB,
BB20_Lwr: DefaultClassColors.miB,
IC01_Upr: DefaultClassColors.IC,
IC01_Lwr: DefaultClassColors.IC,
IC02_Upr: DefaultClassColors.IC,
IC02_Lwr: DefaultClassColors.IC,
IC03_Upr: DefaultClassColors.IC,
IC03_Lwr: DefaultClassColors.IC,
IC04_Upr: DefaultClassColors.IC,
IC04_Lwr: DefaultClassColors.IC,
IC05_Upr: DefaultClassColors.IC,
IC05_Lwr: DefaultClassColors.IC,
IC06_Upr: DefaultClassColors.IC,
IC06_Lwr: DefaultClassColors.IC,
IC07_Upr: DefaultClassColors.IC,
IC07_Lwr: DefaultClassColors.IC,
OP01_Upr: DefaultClassColors.OPN,
OP01_Lwr: DefaultClassColors.OPN,
OP02_Upr: DefaultClassColors.OPN,
OP02_Lwr: DefaultClassColors.OPN,
OP03_Upr: DefaultClassColors.OPN,
OP03_Lwr: DefaultClassColors.OPN,
OP04_Upr: DefaultClassColors.OPN,
OP04_Lwr: DefaultClassColors.OPN,
OP05_Upr: DefaultClassColors.OPN,
OP05_Lwr: DefaultClassColors.OPN,
OP06_Upr: DefaultClassColors.OPN,
OP06_Lwr: DefaultClassColors.OPN,
OP07_Upr: DefaultClassColors.OPN,
OP07_Lwr: DefaultClassColors.OPN,
OP08_Upr: DefaultClassColors.OPN,
OP08_Lwr: DefaultClassColors.OPN,
OP09_Upr: DefaultClassColors.OPN,
OP09_Lwr: DefaultClassColors.OPN,
OP10_Upr: DefaultClassColors.OPN,
OP10_Lwr: DefaultClassColors.OPN,
OP11_Upr: DefaultClassColors.OPN,
OP11_Lwr: DefaultClassColors.OPN,
OP12_Upr: DefaultClassColors.OPN,
OP12_Lwr: DefaultClassColors.OPN,
OP13_Upr: DefaultClassColors.OPN,
OP13_Lwr: DefaultClassColors.OPN,
OP14_Upr: DefaultClassColors.OPN,
OP14_Lwr: DefaultClassColors.OPN,
OP15_Upr: DefaultClassColors.OPN,
OP15_Lwr: DefaultClassColors.OPN,
OP16_Upr: DefaultClassColors.OPN,
OP16_Lwr: DefaultClassColors.OPN,
OP17_Upr: DefaultClassColors.OPN,
OP17_Lwr: DefaultClassColors.OPN,
OP18_Upr: DefaultClassColors.OPN,
OP18_Lwr: DefaultClassColors.OPN,
OP19_Upr: DefaultClassColors.OPN,
OP19_Lwr: DefaultClassColors.OPN,
OP20_Upr: DefaultClassColors.OPN,
OP20_Lwr: DefaultClassColors.OPN,
OP21_Upr: DefaultClassColors.OPN,
OP21_Lwr: DefaultClassColors.OPN,
OP22_Upr: DefaultClassColors.OPN,
OP22_Lwr: DefaultClassColors.OPN,
OP23_Upr: DefaultClassColors.OPN,
OP23_Lwr: DefaultClassColors.OPN,
OP24_Upr: DefaultClassColors.OPN,
OP24_Lwr: DefaultClassColors.OPN,
OP25_Upr: DefaultClassColors.OPN,
OP25_Lwr: DefaultClassColors.OPN,
OP26_Upr: DefaultClassColors.OPN,
OP26_Lwr: DefaultClassColors.OPN,
OP27_Upr: DefaultClassColors.OPN,
OP27_Lwr: DefaultClassColors.OPN,
OP28_Upr: DefaultClassColors.OPN,
OP28_Lwr: DefaultClassColors.OPN,
OP29_Upr: DefaultClassColors.OPN,
OP29_Lwr: DefaultClassColors.OPN,
OP30_Upr: DefaultClassColors.OPN,
OP30_Lwr: DefaultClassColors.OPN,
OP31_Upr: DefaultClassColors.OPN,
OP31_Lwr: DefaultClassColors.OPN,
OPS1_Upr: DefaultClassColors.OPN,
OPS1_Lwr: DefaultClassColors.OPN,
OP1S_Upr: DefaultClassColors.OPN,
OP1S_Lwr: DefaultClassColors.SYN,
AAS1_Upr: DefaultClassColors.SYN,
AAS1_Lwr: DefaultClassColors.A,
AB1S_Upr: DefaultClassColors.A,
AB1S_Lwr: DefaultClassColors.SYN,
AB2S_Upr: DefaultClassColors.A,
AB2S_Lwr: DefaultClassColors.SYN,
BB1S_Upr: DefaultClassColors.B,
BB1S_Lwr: DefaultClassColors.SYN,
BB2S_Upr: DefaultClassColors.B,
BB2S_Lwr: DefaultClassColors.SYN,
BBS1_Upr: DefaultClassColors.SYN,
BBS1_Lwr: DefaultClassColors.B,
ZZ01_Upr: DefaultClassColors.Z,
ZZ01_Lwr: DefaultClassColors.Z,
ZZ02_Upr: DefaultClassColors.Z,
ZZ02_Lwr: DefaultClassColors.Z,
ZZ1S_Upr: DefaultClassColors.Z,
ZZ1S_Lwr: DefaultClassColors.SYN,
ZZ2S_Upr: DefaultClassColors.Z,
ZZ2S_Lwr: DefaultClassColors.SYN,
ZZS1_Upr: DefaultClassColors.SYN,
ZZS1_Lwr: DefaultClassColors.Z,
ZZS2_Upr: DefaultClassColors.SYN,
ZZS2_Lwr: DefaultClassColors.Z,
});
type PyramidsColors = typeof PyramidsColors;
const ColorMapping: ReadonlyMap<ConformerClasses, Color> = new Map([
['A', Color(0xFFC1C1)],
['B', Color(0xC8CFFF)],
['BII', Color(0x0059DA)],
['miB', Color(0x3BE8FB)],
['Z', Color(0x01F60E)],
['IC', Color(0xFA5CFB)],
['OPN', Color(0xE90000)],
['SYN', Color(0xFFFF01)],
['N', Color(0xF2F2F2)],
]);
export const ConfalPyramidsColorThemeParams = {
colors: PD.MappedStatic('default', {
'default': PD.EmptyGroup(),
'custom': PD.Group(getColorMapParams(PyramidsColors))
}),
};
export type ConfalPyramidsColorThemeParams = typeof ConfalPyramidsColorThemeParams;
const NtCToClasses: ReadonlyMap<string, [ConformerClasses, ConformerClasses]> = new Map([
['NANT', ['N', 'N']],
['AA00', ['A', 'A']],
['AA02', ['A', 'A']],
['AA03', ['A', 'A']],
['AA04', ['A', 'A']],
['AA08', ['A', 'A']],
['AA09', ['A', 'A']],
['AA01', ['A', 'A']],
['AA05', ['A', 'A']],
['AA06', ['A', 'A']],
['AA10', ['A', 'A']],
['AA11', ['A', 'A']],
['AA07', ['A', 'A']],
['AA12', ['A', 'A']],
['AA13', ['A', 'A']],
['AB01', ['A', 'B']],
['AB02', ['A', 'B']],
['AB03', ['A', 'B']],
['AB04', ['A', 'B']],
['AB05', ['A', 'B']],
['BA01', ['B', 'A']],
['BA05', ['B', 'A']],
['BA09', ['B', 'A']],
['BA08', ['BII', 'A']],
['BA10', ['B', 'A']],
['BA13', ['BII', 'A']],
['BA16', ['BII', 'A']],
['BA17', ['BII', 'A']],
['BB00', ['B', 'B']],
['BB01', ['B', 'B']],
['BB17', ['B', 'B']],
['BB02', ['B', 'B']],
['BB03', ['B', 'B']],
['BB11', ['B', 'B']],
['BB16', ['B', 'B']],
['BB04', ['B', 'BII']],
['BB05', ['B', 'BII']],
['BB07', ['BII', 'BII']],
['BB08', ['BII', 'BII']],
['BB10', ['miB', 'miB']],
['BB12', ['miB', 'miB']],
['BB13', ['miB', 'miB']],
['BB14', ['miB', 'miB']],
['BB15', ['miB', 'miB']],
['BB20', ['miB', 'miB']],
['IC01', ['IC', 'IC']],
['IC02', ['IC', 'IC']],
['IC03', ['IC', 'IC']],
['IC04', ['IC', 'IC']],
['IC05', ['IC', 'IC']],
['IC06', ['IC', 'IC']],
['IC07', ['IC', 'IC']],
['OP01', ['OPN', 'OPN']],
['OP02', ['OPN', 'OPN']],
['OP03', ['OPN', 'OPN']],
['OP04', ['OPN', 'OPN']],
['OP05', ['OPN', 'OPN']],
['OP06', ['OPN', 'OPN']],
['OP07', ['OPN', 'OPN']],
['OP08', ['OPN', 'OPN']],
['OP09', ['OPN', 'OPN']],
['OP10', ['OPN', 'OPN']],
['OP11', ['OPN', 'OPN']],
['OP12', ['OPN', 'OPN']],
['OP13', ['OPN', 'OPN']],
['OP14', ['OPN', 'OPN']],
['OP15', ['OPN', 'OPN']],
['OP16', ['OPN', 'OPN']],
['OP17', ['OPN', 'OPN']],
['OP18', ['OPN', 'OPN']],
['OP19', ['OPN', 'OPN']],
['OP20', ['OPN', 'OPN']],
['OP21', ['OPN', 'OPN']],
['OP22', ['OPN', 'OPN']],
['OP23', ['OPN', 'OPN']],
['OP24', ['OPN', 'OPN']],
['OP25', ['OPN', 'OPN']],
['OP26', ['OPN', 'OPN']],
['OP27', ['OPN', 'OPN']],
['OP28', ['OPN', 'OPN']],
['OP29', ['OPN', 'OPN']],
['OP30', ['OPN', 'OPN']],
['OP31', ['OPN', 'OPN']],
['OPS1', ['OPN', 'OPN']],
['OP1S', ['OPN', 'SYN']],
['AAS1', ['SYN', 'A']],
['AB1S', ['A', 'SYN']],
['AB2S', ['A', 'SYN']],
['BB1S', ['B', 'SYN']],
['BB2S', ['B', 'SYN']],
['BBS1', ['SYN', 'B']],
['ZZ01', ['Z', 'Z']],
['ZZ02', ['Z', 'Z']],
['ZZ1S', ['Z', 'SYN']],
['ZZ2S', ['Z', 'SYN']],
['ZZS1', ['SYN', 'Z']],
['ZZS2', ['SYN', 'Z']],
]);
function getConformerColor(ntc: string, useLower: boolean): Color {
const item = NtCToClasses.get(ntc);
if (!item) return ErrorColor;
return ColorMapping.get(useLower ? item[1] : item[0]) ?? ErrorColor;
}
export const ConfalPyramidsColorThemeParams = {};
export type ConfalPyramidsColorThemeParams = typeof ConfalPyramidsColorThemeParams
export function getConfalPyramidsColorThemeParams(ctx: ThemeDataContext) {
return ConfalPyramidsColorThemeParams; // TODO return copy
return PD.clone(ConfalPyramidsColorThemeParams);
}
export function ConfalPyramidsColorTheme(ctx: ThemeDataContext, props: PD.Values<ConfalPyramidsColorThemeParams>): ColorTheme<ConfalPyramidsColorThemeParams> {
const colorMap = props.colors.name === 'default' ? PyramidsColors : props.colors.params;
function color(location: Location, isSecondary: boolean): Color {
if (CPT.isLocation(location)) {
const { pyramid, isLower } = location.data;
return getConformerColor(pyramid.NtC, isLower);
const key = pyramid.NtC + `_${isLower ? 'Lwr' : 'Upr'}` as keyof PyramidsColors;
return colorMap[key] ?? ErrorColor;
}
return DefaultColor;
return ErrorColor;
}
return {
@@ -162,12 +261,7 @@ export function ConfalPyramidsColorTheme(ctx: ThemeDataContext, props: PD.Values
color,
props,
description: Description,
legend: TableLegend(iterableToArray(ColorMapping.entries()).map(([conformer, color]) => {
return [conformer, color] as [string, Color];
}).concat([
['Error', ErrorColor],
['Unknown', DefaultColor]
]))
legend: TableLegend(ObjectKeys(colorMap).map(k => [k.replace('_', ' '), colorMap[k]] as [string, Color]).concat([['Error', ErrorColor]])),
};
}

View File

@@ -123,10 +123,8 @@ function createPyramidsFromCif(model: Model,
for (let i = 0; i < _rowCount; i++) {
const model_num = PDB_model_number.value(i);
if (model_num !== model.modelNum) {
if (model_num !== model.modelNum)
hasMultipleModels = true;
continue; // We are only interested in data for the current model
}
const { _NtC, _confal_score } = getNtCAndConfalScore(id.value(i), i, stepsSummary);

View File

@@ -7,7 +7,7 @@
import { ConfalPyramidsProvider } from './property';
import { ConfalPyramidsTypes as CPT } from './types';
import { OrderedSet, Segmentation } from '../../../mol-data/int';
import { Segmentation } from '../../../mol-data/int';
import { Vec3 } from '../../../mol-math/linear-algebra';
import { ChainIndex, ElementIndex, ResidueIndex, Structure, StructureElement, StructureProperties, Unit } from '../../../mol-model/structure';
@@ -63,15 +63,12 @@ export namespace ConfalPyramidsUtil {
return prop.data.hasMultipleModels;
}
function getPossibleAltIdsIndices(eIFirst: ElementIndex, eILast: ElementIndex, structure: Structure, unit: Unit.Atomic): string[] {
const loc = StructureElement.Location.create(structure, unit, -1 as ElementIndex);
const uIFirst = OrderedSet.indexOf(unit.elements, eIFirst);
const uILast = OrderedSet.indexOf(unit.elements, eILast);
function getPossibleAltIds(residue: Residue, structure: Structure, unit: Unit.Atomic): string[] {
const possibleAltIds: string[] = [];
for (let uI = uIFirst; uI <= uILast; uI++) {
loc.element = unit.elements[uI];
const loc = StructureElement.Location.create(structure, unit, -1 as ElementIndex);
for (let rI = residue.start; rI <= residue.end - 1; rI++) {
loc.element = unit.elements[rI];
const altId = StructureProperties.atom.label_alt_id(loc);
if (altId !== '' && !possibleAltIds.includes(altId)) possibleAltIds.push(altId);
}
@@ -79,10 +76,6 @@ export namespace ConfalPyramidsUtil {
return possibleAltIds;
}
function getPossibleAltIdsResidue(residue: Residue, structure: Structure, unit: Unit.Atomic): string[] {
return getPossibleAltIdsIndices(unit.elements[residue.start], unit.elements[residue.end - 1], structure, unit);
}
class Utility {
protected getPyramidByName(name: string): { pyramid: CPT.Pyramid | undefined, index: number } {
const index = this.data.names.get(name);
@@ -122,19 +115,22 @@ export namespace ConfalPyramidsUtil {
export class UnitWalker extends Utility {
private getAtomIndices(names: string[], residue: Residue): ElementIndex[] {
let rI = residue.start;
const rILast = residue.end - 1;
const indices: ElementIndex[] = [];
for (; rI !== rILast; rI++) {
const eI = this.unit.elements[rI];
const loc = StructureElement.Location.create(this.structure, this.unit, eI);
const loc = StructureElement.Location.create(this.structure, this.unit, -1 as ElementIndex);
for (let rI = residue.start; rI <= residue.end - 1; rI++) {
loc.element = this.unit.elements[rI];
const thisName = StructureProperties.atom.label_atom_id(loc);
if (names.includes(thisName)) indices.push(eI);
if (names.includes(thisName)) indices.push(loc.element);
}
if (indices.length === 0)
throw new Error(`Element ${name} not found on residue ${residue.index}`);
if (indices.length === 0) {
let namesStr = '';
for (const n of names)
namesStr += `${n} `;
throw new Error(`Element [${namesStr}] not found on residue ${residue.index}`);
}
return indices;
}
@@ -257,12 +253,12 @@ export namespace ConfalPyramidsUtil {
}
private step(residue: Residue): { firstAtoms: FirstResidueAtoms[], secondAtoms: SecondResidueAtoms[] } {
const firstPossibleAltIds = getPossibleAltIdsResidue(residue, this.structure, this.unit);
const firstPossibleAltIds = getPossibleAltIds(residue, this.structure, this.unit);
const firstAtoms = this.processFirstResidue(residue, firstPossibleAltIds);
residue = this.residueIt.move();
const secondPossibleAltIds = getPossibleAltIdsResidue(residue, this.structure, this.unit);
const secondPossibleAltIds = getPossibleAltIds(residue, this.structure, this.unit);
const secondAtoms = this.processSecondResidue(residue, secondPossibleAltIds);
return { firstAtoms, secondAtoms };

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2021-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -34,13 +34,15 @@ export function calcMeshColorSmoothing(input: ColorSmoothingInput, resolution: n
const isInstanceType = colorType.endsWith('Instance');
const box = Box3D.fromSphere3D(Box3D(), isInstanceType ? input.boundingSphere : input.invariantBoundingSphere);
const pad = 1 + resolution;
const expandedBox = Box3D.expand(Box3D(), box, Vec3.create(pad, pad, pad));
const scaleFactor = 1 / resolution;
const scaledBox = Box3D.scale(Box3D(), box, scaleFactor);
const scaledBox = Box3D.scale(Box3D(), expandedBox, scaleFactor);
const gridDim = Box3D.size(Vec3(), scaledBox);
Vec3.ceil(gridDim, gridDim);
Vec3.add(gridDim, gridDim, Vec3.create(2, 2, 2));
const { min } = box;
const { min } = expandedBox;
const [xn, yn] = gridDim;
const { width, height } = getVolumeTexture2dLayout(gridDim);

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2021-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -259,13 +259,15 @@ export function calcTextureMeshColorSmoothing(input: ColorSmoothingInput, resolu
const isInstanceType = input.colorType.endsWith('Instance');
const box = Box3D.fromSphere3D(Box3D(), isInstanceType ? input.boundingSphere : input.invariantBoundingSphere);
const pad = 1 + resolution;
const expandedBox = Box3D.expand(Box3D(), box, Vec3.create(pad, pad, pad));
const scaleFactor = 1 / resolution;
const scaledBox = Box3D.scale(Box3D(), box, scaleFactor);
const scaledBox = Box3D.scale(Box3D(), expandedBox, scaleFactor);
const gridDim = Box3D.size(Vec3(), scaledBox);
Vec3.ceil(gridDim, gridDim);
Vec3.add(gridDim, gridDim, Vec3.create(2, 2, 2));
const { min } = box;
const { min } = expandedBox;
const [dx, dy, dz] = gridDim;
const { texDimX: width, texDimY: height, texCols } = getTexture2dSize(gridDim);
@@ -308,7 +310,7 @@ export function calcTextureMeshColorSmoothing(input: ColorSmoothingInput, resolu
accumulateTexture.attachFramebuffer(framebuffer, 0);
countTexture.attachFramebuffer(framebuffer, 1);
const accumulateRenderable = getAccumulateRenderable(webgl, input, box, resolution, stride);
const accumulateRenderable = getAccumulateRenderable(webgl, input, expandedBox, resolution, stride);
state.currentRenderItemId = -1;
framebuffer.bind();

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -281,7 +281,7 @@ export function createContext(gl: GLRenderingContext, props: Partial<{ pixelScal
gl,
isWebGL2: isWebGL2(gl),
get pixelRatio() {
const dpr = (typeof window !== 'undefined') ? window.devicePixelRatio : 1;
const dpr = (typeof window !== 'undefined') ? (window.devicePixelRatio || 1) : 1;
return dpr * (props.pixelScale || 1);
},

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -26,7 +26,8 @@ export type DensityData = {
transform: Mat4,
field: Tensor,
idField: Tensor,
resolution: number
resolution: number,
maxRadius: number,
}
export type DensityTextureData = {

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -21,12 +21,12 @@ export type GaussianDensityProps = typeof DefaultGaussianDensityProps
export type GaussianDensityData = {
radiusFactor: number
resolution: number
} & DensityData
export type GaussianDensityTextureData = {
radiusFactor: number
resolution: number
maxRadius: number
} & DensityTextureData
export function computeGaussianDensity(position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityProps) {

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -129,5 +129,5 @@ export async function GaussianDensityCPU(ctx: RuntimeContext, position: Position
Mat4.fromScaling(transform, Vec3.create(resolution, resolution, resolution));
Mat4.setTranslation(transform, expandedBox.min);
return { field, idField, transform, radiusFactor: 1, resolution };
return { field, idField, transform, radiusFactor: 1, resolution, maxRadius };
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Michael Krone <michael.krone@uni-tuebingen.de>
@@ -70,12 +70,12 @@ export function GaussianDensityGPU(position: PositionData, box: Box3D, radius: (
// it's faster than texture3d
// console.time('GaussianDensityTexture2d')
const tmpTexture = getTexture('tmp', webgl, 'image-uint8', 'rgba', 'ubyte', 'linear');
const { scale, bbox, texture, gridDim, gridTexDim, radiusFactor, resolution } = calcGaussianDensityTexture2d(webgl, position, box, radius, false, props, tmpTexture);
const { scale, bbox, texture, gridDim, gridTexDim, radiusFactor, resolution, maxRadius } = calcGaussianDensityTexture2d(webgl, position, box, radius, false, props, tmpTexture);
// webgl.waitForGpuCommandsCompleteSync()
// console.timeEnd('GaussianDensityTexture2d')
const { field, idField } = fieldFromTexture2d(webgl, texture, gridDim, gridTexDim);
return { field, idField, transform: getTransform(scale, bbox), radiusFactor, resolution };
return { field, idField, transform: getTransform(scale, bbox), radiusFactor, resolution, maxRadius };
}
export function GaussianDensityTexture(webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityProps, oldTexture?: Texture): GaussianDensityTextureData {
@@ -92,8 +92,8 @@ export function GaussianDensityTexture3d(webgl: WebGLContext, position: Position
return finalizeGaussianDensityTexture(calcGaussianDensityTexture3d(webgl, position, box, radius, props, oldTexture));
}
function finalizeGaussianDensityTexture({ texture, scale, bbox, gridDim, gridTexDim, gridTexScale, radiusFactor, resolution }: _GaussianDensityTextureData): GaussianDensityTextureData {
return { transform: getTransform(scale, bbox), texture, bbox, gridDim, gridTexDim, gridTexScale, radiusFactor, resolution };
function finalizeGaussianDensityTexture({ texture, scale, bbox, gridDim, gridTexDim, gridTexScale, radiusFactor, resolution, maxRadius }: _GaussianDensityTextureData): GaussianDensityTextureData {
return { transform: getTransform(scale, bbox), texture, bbox, gridDim, gridTexDim, gridTexScale, radiusFactor, resolution, maxRadius };
}
function getTransform(scale: Vec3, bbox: Box3D) {
@@ -114,6 +114,7 @@ type _GaussianDensityTextureData = {
gridTexScale: Vec2
radiusFactor: number
resolution: number
maxRadius: number
}
function calcGaussianDensityTexture2d(webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, powerOfTwo: boolean, props: GaussianDensityProps, texture?: Texture): _GaussianDensityTextureData {
@@ -198,7 +199,7 @@ function calcGaussianDensityTexture2d(webgl: WebGLContext, position: PositionDat
// printTexture(webgl, minDistTex, 0.75);
return { texture, scale, bbox: expandedBox, gridDim: dim, gridTexDim, gridTexScale, radiusFactor, resolution };
return { texture, scale, bbox: expandedBox, gridDim: dim, gridTexDim, gridTexScale, radiusFactor, resolution, maxRadius };
}
function calcGaussianDensityTexture3d(webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityProps, texture?: Texture): _GaussianDensityTextureData {
@@ -254,7 +255,7 @@ function calcGaussianDensityTexture3d(webgl: WebGLContext, position: PositionDat
setupGroupIdRendering(webgl, renderable);
render(texture, false);
return { texture, scale, bbox: expandedBox, gridDim: dim, gridTexDim: dim, gridTexScale, radiusFactor, resolution };
return { texture, scale, bbox: expandedBox, gridDim: dim, gridTexDim: dim, gridTexScale, radiusFactor, resolution, maxRadius };
}
//

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Fred Ludlow <fred.ludlow@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
@@ -370,5 +370,5 @@ export async function calcMolecularSurface(ctx: RuntimeContext, position: Requir
Mat4.fromScaling(transform, Vec3.create(resolution, resolution, resolution));
Mat4.setTranslation(transform, expandedBox.min);
// console.log({ field, idField, transform, updateChunk })
return { field, idField, transform, resolution };
return { field, idField, transform, resolution, maxRadius };
}

View File

@@ -32,7 +32,9 @@ namespace Box3D {
/** Get box from sphere, uses extrema if available */
export function fromSphere3D(out: Box3D, sphere: Sphere3D): Box3D {
if (Sphere3D.hasExtrema(sphere)) return fromVec3Array(out, sphere.extrema);
if (Sphere3D.hasExtrema(sphere) && sphere.extrema.length >= 14) { // 14 extrema with coarse boundary helper
return fromVec3Array(out, sphere.extrema);
}
const r = Vec3.create(sphere.radius, sphere.radius, sphere.radius);
Vec3.sub(out.min, sphere.center, r);
Vec3.add(out.max, sphere.center, r);

View File

@@ -212,19 +212,26 @@ namespace Sphere3D {
Axes3D.scale(axes, Axes3D.normalize(axes, axes), delta);
setExtrema(out, sphere.extrema.map(e => {
Vec3.sub(tmpDir, e, sphere.center);
const out = Vec3.clone(e);
Vec3.normalize(tmpDir, Vec3.sub(tmpDir, e, sphere.center));
const o = Vec3.clone(e);
const sA = Vec3.dot(tmpDir, axes.dirA) < 0 ? -1 : 1;
Vec3.scaleAndAdd(out, out, axes.dirA, sA);
Vec3.scaleAndAdd(o, o, axes.dirA, sA);
const sB = Vec3.dot(tmpDir, axes.dirB) < 0 ? -1 : 1;
Vec3.scaleAndAdd(out, out, axes.dirB, sB);
Vec3.scaleAndAdd(o, o, axes.dirB, sB);
const sC = Vec3.dot(tmpDir, axes.dirC) < 0 ? -1 : 1;
Vec3.scaleAndAdd(out, out, axes.dirC, sC);
Vec3.scaleAndAdd(o, o, axes.dirC, sC);
return out;
if (Vec3.distance(out.center, o) > out.radius) {
if (sphere.extrema.length >= 14) { // 14 extrema with coarse boundary helper
Vec3.normalize(tmpDir, Vec3.sub(tmpDir, o, sphere.center));
}
Vec3.scaleAndAdd(o, out.center, tmpDir, out.radius);
}
return o;
}));
}
return out;

View File

@@ -16,7 +16,6 @@ import { Mat4, Vec3 } from '../../../mol-math/linear-algebra';
import { eachElement, eachSerialElement, ElementIterator, getElementLoci, getSerialElementLoci } from './util/element';
import { Sphere3D } from '../../../mol-math/geometry';
import { UnitsDirectVolumeParams, UnitsVisual, UnitsDirectVolumeVisual } from '../units-visual';
import { getStructureExtraRadius, getUnitExtraRadius } from './util/common';
async function createGaussianDensityVolume(ctx: VisualContext, structure: Structure, theme: Theme, props: GaussianDensityProps, directVolume?: DirectVolume): Promise<DirectVolume> {
const { runtime, webgl } = ctx;
@@ -34,7 +33,7 @@ async function createGaussianDensityVolume(ctx: VisualContext, structure: Struct
const axisOrder = Vec3.create(0, 1, 2);
const vol = DirectVolume.create(bbox, gridDim, transform, unitToCartn, cellDim, texture, stats, true, axisOrder, directVolume);
const sphere = Sphere3D.expand(Sphere3D(), structure.boundary.sphere, props.radiusOffset + getStructureExtraRadius(structure));
const sphere = Sphere3D.expand(Sphere3D(), structure.boundary.sphere, densityTextureData.maxRadius);
vol.setBoundingSphere(sphere);
return vol;
@@ -90,7 +89,7 @@ async function createUnitsGaussianDensityVolume(ctx: VisualContext, unit: Unit,
const axisOrder = Vec3.create(0, 1, 2);
const vol = DirectVolume.create(bbox, gridDim, transform, unitToCartn, cellDim, texture, stats, true, axisOrder, directVolume);
const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, props.radiusOffset + getUnitExtraRadius(unit));
const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, densityTextureData.maxRadius);
vol.setBoundingSphere(sphere);
return vol;

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -18,7 +18,7 @@ import { TextureMesh } from '../../../mol-geo/geometry/texture-mesh/texture-mesh
import { extractIsosurface } from '../../../mol-gl/compute/marching-cubes/isosurface';
import { Sphere3D } from '../../../mol-math/geometry';
import { ComplexVisual, ComplexMeshParams, ComplexMeshVisual, ComplexTextureMeshVisual, ComplexTextureMeshParams } from '../complex-visual';
import { getUnitExtraRadius, getStructureExtraRadius, getVolumeSliceInfo, StructureGroup } from './util/common';
import { getVolumeSliceInfo, StructureGroup } from './util/common';
import { WebGLContext } from '../../../mol-gl/webgl/context';
import { MeshValues } from '../../../mol-gl/renderable/mesh';
import { TextureMeshValues } from '../../../mol-gl/renderable/texture-mesh';
@@ -89,7 +89,7 @@ type GaussianSurfaceMeta = {
async function createGaussianSurfaceMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: GaussianDensityProps, mesh?: Mesh): Promise<Mesh> {
const { smoothness } = props;
const { transform, field, idField, radiusFactor, resolution } = await computeUnitGaussianDensity(structure, unit, theme.size, props).runInContext(ctx.runtime);
const { transform, field, idField, radiusFactor, resolution, maxRadius } = await computeUnitGaussianDensity(structure, unit, theme.size, props).runInContext(ctx.runtime);
const params = {
isoLevel: Math.exp(-smoothness) / radiusFactor,
@@ -102,7 +102,7 @@ async function createGaussianSurfaceMesh(ctx: VisualContext, unit: Unit, structu
Mesh.transform(surface, transform);
if (ctx.webgl && !ctx.webgl.isWebGL2) Mesh.uniformTriangleGroup(surface);
const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, props.radiusOffset + getUnitExtraRadius(unit));
const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, maxRadius);
surface.setBoundingSphere(sphere);
return surface;
@@ -150,7 +150,7 @@ export function GaussianSurfaceMeshVisual(materialId: number): UnitsVisual<Gauss
async function createStructureGaussianSurfaceMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: GaussianDensityProps, mesh?: Mesh): Promise<Mesh> {
const { smoothness } = props;
const { transform, field, idField, radiusFactor, resolution } = await computeStructureGaussianDensity(structure, theme.size, props).runInContext(ctx.runtime);
const { transform, field, idField, radiusFactor, resolution, maxRadius } = await computeStructureGaussianDensity(structure, theme.size, props).runInContext(ctx.runtime);
const params = {
isoLevel: Math.exp(-smoothness) / radiusFactor,
@@ -163,7 +163,7 @@ async function createStructureGaussianSurfaceMesh(ctx: VisualContext, structure:
Mesh.transform(surface, transform);
if (ctx.webgl && !ctx.webgl.isWebGL2) Mesh.uniformTriangleGroup(surface);
const sphere = Sphere3D.expand(Sphere3D(), structure.boundary.sphere, props.radiusOffset + getStructureExtraRadius(structure));
const sphere = Sphere3D.expand(Sphere3D(), structure.boundary.sphere, maxRadius);
surface.setBoundingSphere(sphere);
return surface;
@@ -235,7 +235,7 @@ async function createGaussianSurfaceTextureMesh(ctx: VisualContext, unit: Unit,
const buffer = textureMesh?.doubleBuffer.get();
const gv = extractIsosurface(ctx.webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.gridTexScale, densityTextureData.transform, isoLevel, false, true, axisOrder, buffer?.vertex, buffer?.group, buffer?.normal);
const boundingSphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, props.radiusOffset + getStructureExtraRadius(structure));
const boundingSphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, densityTextureData.maxRadius);
const surface = TextureMesh.create(gv.vertexCount, 1, gv.vertexTexture, gv.groupTexture, gv.normalTexture, boundingSphere, textureMesh);
(surface.meta as GaussianSurfaceMeta).resolution = densityTextureData.resolution;
@@ -312,7 +312,7 @@ async function createStructureGaussianSurfaceTextureMesh(ctx: VisualContext, str
const buffer = textureMesh?.doubleBuffer.get();
const gv = extractIsosurface(ctx.webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.gridTexScale, densityTextureData.transform, isoLevel, false, true, axisOrder, buffer?.vertex, buffer?.group, buffer?.normal);
const boundingSphere = Sphere3D.expand(Sphere3D(), structure.boundary.sphere, props.radiusOffset + getStructureExtraRadius(structure));
const boundingSphere = Sphere3D.expand(Sphere3D(), structure.boundary.sphere, densityTextureData.maxRadius);
const surface = TextureMesh.create(gv.vertexCount, 1, gv.vertexTexture, gv.groupTexture, gv.normalTexture, boundingSphere, textureMesh);
(surface.meta as GaussianSurfaceMeta).resolution = densityTextureData.resolution;

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -15,11 +15,10 @@ import { UnitsLinesParams, UnitsVisual, UnitsLinesVisual } from '../units-visual
import { ElementIterator, getElementLoci, eachElement } from './util/element';
import { VisualUpdateState } from '../../util';
import { Sphere3D } from '../../../mol-math/geometry';
import { getUnitExtraRadius } from './util/common';
async function createGaussianWireframe(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: GaussianDensityProps, lines?: Lines): Promise<Lines> {
const { smoothness } = props;
const { transform, field, idField } = await computeUnitGaussianDensity(structure, unit, theme.size, props).runInContext(ctx.runtime);
const { transform, field, idField, maxRadius } = await computeUnitGaussianDensity(structure, unit, theme.size, props).runInContext(ctx.runtime);
const params = {
isoLevel: Math.exp(-smoothness),
@@ -30,7 +29,7 @@ async function createGaussianWireframe(ctx: VisualContext, unit: Unit, structure
Lines.transform(wireframe, transform);
const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, props.radiusOffset + getUnitExtraRadius(unit));
const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, maxRadius);
wireframe.setBoundingSphere(sphere);
return wireframe;

View File

@@ -15,7 +15,7 @@ import { computeUnitMolecularSurface } from './util/molecular-surface';
import { computeMarchingCubesMesh } from '../../../mol-geo/util/marching-cubes/algorithm';
import { ElementIterator, getElementLoci, eachElement } from './util/element';
import { VisualUpdateState } from '../../util';
import { CommonSurfaceParams, getUnitExtraRadius } from './util/common';
import { CommonSurfaceParams } from './util/common';
import { Sphere3D } from '../../../mol-math/geometry';
import { MeshValues } from '../../../mol-gl/renderable/mesh';
import { Texture } from '../../../mol-gl/webgl/texture';
@@ -40,7 +40,7 @@ type MolecularSurfaceMeta = {
//
async function createMolecularSurfaceMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: MolecularSurfaceMeshProps, mesh?: Mesh): Promise<Mesh> {
const { transform, field, idField, resolution } = await computeUnitMolecularSurface(structure, unit, theme.size, props).runInContext(ctx.runtime);
const { transform, field, idField, resolution, maxRadius } = await computeUnitMolecularSurface(structure, unit, theme.size, props).runInContext(ctx.runtime);
const params = {
isoLevel: props.probeRadius,
@@ -57,7 +57,7 @@ async function createMolecularSurfaceMesh(ctx: VisualContext, unit: Unit, struct
Mesh.transform(surface, transform);
if (ctx.webgl && !ctx.webgl.isWebGL2) Mesh.uniformTriangleGroup(surface);
const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, getUnitExtraRadius(unit));
const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, maxRadius);
surface.setBoundingSphere(sphere);
(surface.meta as MolecularSurfaceMeta).resolution = resolution;

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -15,7 +15,7 @@ import { computeUnitMolecularSurface, MolecularSurfaceProps } from './util/molec
import { computeMarchingCubesLines } from '../../../mol-geo/util/marching-cubes/algorithm';
import { ElementIterator, getElementLoci, eachElement } from './util/element';
import { VisualUpdateState } from '../../util';
import { CommonSurfaceParams, getUnitExtraRadius } from './util/common';
import { CommonSurfaceParams } from './util/common';
import { Sphere3D } from '../../../mol-math/geometry';
export const MolecularSurfaceWireframeParams = {
@@ -29,7 +29,7 @@ export type MolecularSurfaceWireframeParams = typeof MolecularSurfaceWireframePa
//
async function createMolecularSurfaceWireframe(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: MolecularSurfaceProps, lines?: Lines): Promise<Lines> {
const { transform, field, idField } = await computeUnitMolecularSurface(structure, unit, theme.size, props).runInContext(ctx.runtime);
const { transform, field, idField, maxRadius } = await computeUnitMolecularSurface(structure, unit, theme.size, props).runInContext(ctx.runtime);
const params = {
isoLevel: props.probeRadius,
scalarField: field,
@@ -39,7 +39,7 @@ async function createMolecularSurfaceWireframe(ctx: VisualContext, unit: Unit, s
Lines.transform(wireframe, transform);
const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, props.probeRadius + getUnitExtraRadius(unit));
const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, maxRadius);
wireframe.setBoundingSphere(sphere);
return wireframe;

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
* Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
@@ -298,25 +298,3 @@ export function isTrace(unit: Unit, element: ElementIndex) {
if (atomId === 'CA' || atomId === 'BB' || atomId === 'P') return true;
return false;
}
export function getUnitExtraRadius(unit: Unit) {
if (Unit.isAtomic(unit)) return 4;
let max = 0;
const { elements } = unit;
const { r } = unit.conformation;
for (let i = 0, _i = elements.length; i < _i; i++) {
const _r = r(elements[i]);
if (_r > max) max = _r;
}
return max + 1;
}
export function getStructureExtraRadius(structure: Structure) {
let max = 0;
for (const ug of structure.unitSymmetryGroups) {
const r = getUnitExtraRadius(ug.units[0]);
if (r > max) max = r;
}
return max;
}