UNPKG

molstar

Version:

A comprehensive macromolecular library.

115 lines (114 loc) 4.31 kB
/** * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ import { Color } from '../../mol-util/color'; import { StructureElement, Bond } from '../../mol-model/structure'; import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { getPaletteParams, getPalette } from '../../mol-util/color/palette'; import { Vec3 } from '../../mol-math/linear-algebra'; import { integerDigitCount } from '../../mol-util/number'; import { ColorLists, getColorListFromName } from '../../mol-util/color/lists'; import { ColorThemeCategory } from './categories'; const DefaultList = 'dark-2'; const DefaultColor = Color(0xCCCCCC); const Description = `Assigns a color based on the operator HKL value of a transformed chain.`; export const OperatorHklColorThemeParams = { ...getPaletteParams({ type: 'colors', colorList: DefaultList }), }; export function getOperatorHklColorThemeParams(ctx) { const params = PD.clone(OperatorHklColorThemeParams); if (ctx.structure) { if (getOperatorHklSerialMap(ctx.structure.root).map.size > ColorLists[DefaultList].list.length) { params.palette.defaultValue.name = 'colors'; params.palette.defaultValue.params = { ...params.palette.defaultValue.params, list: { kind: 'interpolate', colors: getColorListFromName(DefaultList).list } }; } } return params; } const hklOffset = 10000; function hklKey(hkl) { return hkl.map(v => `${v + hklOffset}`.padStart(5, '0')).join(''); } function hklKeySplit(key) { const len = integerDigitCount(hklOffset, 0); const h = parseInt(key.substr(0, len)); const k = parseInt(key.substr(len, len)); const l = parseInt(key.substr(len + len, len)); return Vec3.create(h - hklOffset, k - hklOffset, l - hklOffset); } function formatHkl(hkl) { return hkl.map(v => v + 5).join(''); } function getOperatorHklSerialMap(structure) { const map = new Map(); const set = new Set(); for (let i = 0, il = structure.units.length; i < il; ++i) { const k = hklKey(structure.units[i].conformation.operator.hkl); set.add(k); } const arr = Array.from(set.values()).sort(); arr.forEach(k => map.set(k, map.size)); const min = hklKeySplit(arr[0]); const max = hklKeySplit(arr[arr.length - 1]); return { min, max, map }; } export function OperatorHklColorTheme(ctx, props) { let color; let legend; if (ctx.structure) { const { min, max, map } = getOperatorHklSerialMap(ctx.structure.root); const labelTable = []; map.forEach((v, k) => { const i = v % map.size; const label = formatHkl(hklKeySplit(k)); if (labelTable[i] === undefined) labelTable[i] = label; else labelTable[i] += `, ${label}`; }); const labelOptions = { minLabel: formatHkl(min), maxLabel: formatHkl(max), valueLabel: (i) => labelTable[i] }; const palette = getPalette(map.size, props, labelOptions); legend = palette.legend; color = (location) => { let serial = undefined; if (StructureElement.Location.is(location)) { const k = hklKey(location.unit.conformation.operator.hkl); serial = map.get(k); } else if (Bond.isLocation(location)) { const k = hklKey(location.aUnit.conformation.operator.hkl); serial = map.get(k); } return serial === undefined ? DefaultColor : palette.color(serial); }; } else { color = () => DefaultColor; } return { factory: OperatorHklColorTheme, granularity: 'instance', color, props, description: Description, legend }; } export const OperatorHklColorThemeProvider = { name: 'operator-hkl', label: 'Operator HKL', category: ColorThemeCategory.Symmetry, factory: OperatorHklColorTheme, getParams: getOperatorHklColorThemeParams, defaultValues: PD.getDefaultValues(OperatorHklColorThemeParams), isApplicable: (ctx) => !!ctx.structure };