molecular-surface.ts 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /**
  2. * Copyright (c) 2019-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { Unit, Structure } from '../../../../mol-model/structure';
  7. import { Task, RuntimeContext } from '../../../../mol-task';
  8. import { getUnitConformationAndRadius, CommonSurfaceProps, ensureReasonableResolution, getStructureConformationAndRadius } from './common';
  9. import { PositionData, DensityData, Box3D } from '../../../../mol-math/geometry';
  10. import { MolecularSurfaceCalculationProps, calcMolecularSurface } from '../../../../mol-math/geometry/molecular-surface';
  11. import { OrderedSet } from '../../../../mol-data/int';
  12. import { Boundary } from '../../../../mol-math/geometry/boundary';
  13. import { SizeTheme } from '../../../../mol-theme/size';
  14. export type MolecularSurfaceProps = MolecularSurfaceCalculationProps & CommonSurfaceProps
  15. function getUnitPositionDataAndMaxRadius(structure: Structure, unit: Unit, sizeTheme: SizeTheme<any>, props: MolecularSurfaceProps) {
  16. const { probeRadius } = props;
  17. const { position, boundary, radius } = getUnitConformationAndRadius(structure, unit, sizeTheme, props);
  18. const { indices } = position;
  19. const n = OrderedSet.size(indices);
  20. const radii = new Float32Array(OrderedSet.end(indices));
  21. let maxRadius = 0;
  22. for (let i = 0; i < n; ++i) {
  23. const j = OrderedSet.getAt(indices, i);
  24. const r = radius(j);
  25. if (maxRadius < r) maxRadius = r;
  26. radii[j] = r + probeRadius;
  27. }
  28. return { position: { ...position, radius: radii }, boundary, maxRadius };
  29. }
  30. export function computeUnitMolecularSurface(structure: Structure, unit: Unit, sizeTheme: SizeTheme<any>, props: MolecularSurfaceProps) {
  31. const { position, boundary, maxRadius } = getUnitPositionDataAndMaxRadius(structure, unit, sizeTheme, props);
  32. const p = ensureReasonableResolution(boundary.box, props);
  33. return Task.create('Molecular Surface', async ctx => {
  34. return await MolecularSurface(ctx, position, boundary, maxRadius, boundary.box, p);
  35. });
  36. }
  37. //
  38. function getStructurePositionDataAndMaxRadius(structure: Structure, sizeTheme: SizeTheme<any>, props: MolecularSurfaceProps) {
  39. const { probeRadius } = props;
  40. const { position, boundary, radius } = getStructureConformationAndRadius(structure, sizeTheme, props);
  41. const { indices } = position;
  42. const n = OrderedSet.size(indices);
  43. const radii = new Float32Array(OrderedSet.end(indices));
  44. let maxRadius = 0;
  45. for (let i = 0; i < n; ++i) {
  46. const j = OrderedSet.getAt(indices, i);
  47. const r = radius(j);
  48. if (maxRadius < r) maxRadius = r;
  49. radii[j] = r + probeRadius;
  50. }
  51. return { position: { ...position, radius: radii }, boundary, maxRadius };
  52. }
  53. export function computeStructureMolecularSurface(structure: Structure, sizeTheme: SizeTheme<any>, props: MolecularSurfaceProps) {
  54. const { position, boundary, maxRadius } = getStructurePositionDataAndMaxRadius(structure, sizeTheme, props);
  55. const p = ensureReasonableResolution(boundary.box, props);
  56. return Task.create('Molecular Surface', async ctx => {
  57. return await MolecularSurface(ctx, position, boundary, maxRadius, boundary.box, p);
  58. });
  59. }
  60. //
  61. async function MolecularSurface(ctx: RuntimeContext, position: Required<PositionData>, boundary: Boundary, maxRadius: number, box: Box3D | null, props: MolecularSurfaceCalculationProps): Promise<DensityData> {
  62. return calcMolecularSurface(ctx, position, boundary, maxRadius, box, props);
  63. }