UNPKG

molstar

Version:

A comprehensive macromolecular library.

154 lines (153 loc) 6.89 kB
import { ParamDefinition as PD } from '../../../mol-util/param-definition'; import { MmcifFormat } from '../../../mol-model-formats/structure/mmcif'; import { CustomPropertyDescriptor } from '../../../mol-model/custom-property'; import { CustomModelProperty } from '../../../mol-model-props/common/custom-model-property'; import { arrayMinMax } from '../../../mol-util/array'; import { Column } from '../../../mol-data/db'; const PartialChargesPropertyParams = { typeId: PD.Select(0, [[0, '0']]), }; const DefaultPartialChargesPropertyParams = PD.clone(PartialChargesPropertyParams); function getParams(model) { var _a, _b; return (_b = (_a = getData(model).value) === null || _a === void 0 ? void 0 : _a.params) !== null && _b !== void 0 ? _b : DefaultPartialChargesPropertyParams; } const PropertyKey = 'sb-ncbr-partial-charges-property-data'; function getData(model) { if (PropertyKey in model._staticPropertyData) { return model._staticPropertyData[PropertyKey]; } let data; if (!SbNcbrPartialChargesPropertyProvider.isApplicable(model)) { data = { value: undefined }; } else { const typeIdToMethod = getTypeIdToMethod(model); const typeIdToAtomIdToCharge = getTypeIdToAtomIdToCharge(model); const typeIdToResidueToCharge = getTypeIdToResidueIdToCharge(model, typeIdToAtomIdToCharge); const maxAbsoluteAtomCharges = getMaxAbsoluteCharges(typeIdToAtomIdToCharge); const maxAbsoluteResidueCharges = getMaxAbsoluteCharges(typeIdToResidueToCharge); const maxAbsoluteAtomChargeAll = getMaxAbsoluteAtomChargeAll(maxAbsoluteAtomCharges, maxAbsoluteResidueCharges); const options = Array.from(typeIdToMethod.entries()).map(([typeId, method]) => [typeId, method]); const params = { typeId: PD.Select(1, options), }; data = { value: { typeIdToMethod, typeIdToAtomIdToCharge, typeIdToResidueToCharge, maxAbsoluteAtomCharges, maxAbsoluteResidueCharges, maxAbsoluteAtomChargeAll, params, }, }; } model._staticPropertyData[PropertyKey] = data; return data; } function getTypeIdToMethod(model) { const typeIdToMethod = new Map(); const sourceData = model.sourceData; const rowCount = sourceData.data.frame.categories.sb_ncbr_partial_atomic_charges_meta.rowCount; const typeIds = sourceData.data.frame.categories.sb_ncbr_partial_atomic_charges_meta.getField('id'); const methods = sourceData.data.frame.categories.sb_ncbr_partial_atomic_charges_meta.getField('method'); if (!typeIds || !methods) { return typeIdToMethod; } for (let i = 0; i < rowCount; ++i) { const typeId = typeIds.int(i); const method = methods.str(i); typeIdToMethod.set(typeId, method); } return typeIdToMethod; } function getTypeIdToAtomIdToCharge(model) { var _a; const atomIdToCharge = new Map(); const sourceData = model.sourceData; const rowCount = sourceData.data.frame.categories.sb_ncbr_partial_atomic_charges.rowCount; const typeIds = sourceData.data.frame.categories.sb_ncbr_partial_atomic_charges.getField('type_id'); const atomIds = sourceData.data.frame.categories.sb_ncbr_partial_atomic_charges.getField('atom_id'); const charges = sourceData.data.frame.categories.sb_ncbr_partial_atomic_charges.getField('charge'); if (!typeIds || !atomIds || !charges) return atomIdToCharge; for (let i = 0; i < rowCount; ++i) { const typeId = typeIds.int(i); const atomId = atomIds.int(i); const isPresent = charges.valueKind(i) === Column.ValueKind.Present; if (!isPresent) continue; const charge = charges.float(i); if (!atomIdToCharge.has(typeId)) atomIdToCharge.set(typeId, new Map()); (_a = atomIdToCharge.get(typeId)) === null || _a === void 0 ? void 0 : _a.set(atomId, charge); } return atomIdToCharge; } function getTypeIdToResidueIdToCharge(model, typeIdToAtomIdToCharge) { const { offsets, count } = model.atomicHierarchy.residueAtomSegments; const { atomId: atomIds } = model.atomicConformation; const residueToCharge = new Map(); typeIdToAtomIdToCharge.forEach((atomIdToCharge, typeId) => { if (!residueToCharge.has(typeId)) residueToCharge.set(typeId, new Map()); const residueCharges = residueToCharge.get(typeId); for (let rI = 0; rI < count; rI++) { let charge = 0; for (let aI = offsets[rI], _aI = offsets[rI + 1]; aI < _aI; aI++) { const atom_id = atomIds.value(aI); charge += atomIdToCharge.get(atom_id) || 0; } for (let aI = offsets[rI], _aI = offsets[rI + 1]; aI < _aI; aI++) { const atom_id = atomIds.value(aI); residueCharges.set(atom_id, charge); } } }); return residueToCharge; } function getMaxAbsoluteCharges(typeIdToCharge) { const maxAbsoluteCharges = new Map(); typeIdToCharge.forEach((idToCharge, typeId) => { const charges = Array.from(idToCharge.values()); const [min, max] = arrayMinMax(charges); const bound = Math.max(Math.abs(min), max); maxAbsoluteCharges.set(typeId, bound); }); return maxAbsoluteCharges; } function getMaxAbsoluteAtomChargeAll(maxAbsoluteAtomCharges, maxAbsoluteResidueCharges) { let maxAbsoluteCharge = 0; maxAbsoluteAtomCharges.forEach((_, typeId) => { const maxCharge = maxAbsoluteAtomCharges.get(typeId) || 0; if (maxCharge > maxAbsoluteCharge) maxAbsoluteCharge = maxCharge; }); maxAbsoluteResidueCharges.forEach((_, typeId) => { const maxCharge = maxAbsoluteResidueCharges.get(typeId) || 0; if (maxCharge > maxAbsoluteCharge) maxAbsoluteCharge = maxCharge; }); return maxAbsoluteCharge; } export function hasPartialChargesCategories(model) { if (!model || !MmcifFormat.is(model.sourceData)) return false; const { categories } = model.sourceData.data.frame; return ('atom_site' in categories && 'sb_ncbr_partial_atomic_charges' in categories && 'sb_ncbr_partial_atomic_charges_meta' in categories); } export const SbNcbrPartialChargesPropertyProvider = CustomModelProperty.createProvider({ label: 'SB NCBR Partial Charges Property Provider', descriptor: CustomPropertyDescriptor({ name: 'sb-ncbr-partial-charges-property-provider', }), type: 'static', defaultParams: DefaultPartialChargesPropertyParams, getParams: (data) => getParams(data), isApplicable: (model) => hasPartialChargesCategories(model), obtain: (_ctx, model) => Promise.resolve(getData(model)), });