representation.ts 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /**
  2. * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Michal Malý <michal.maly@ibt.cas.cz>
  5. * @author Jiří Černý <jiri.cerny@ibt.cas.cz>
  6. */
  7. import { ConfalPyramids, ConfalPyramidsProvider } from './property';
  8. import { ConfalPyramidsUtil } from './util';
  9. import { ConfalPyramidsTypes as CPT } from './types';
  10. import { Interval } from '../../../mol-data/int';
  11. import { Mesh } from '../../../mol-geo/geometry/mesh/mesh';
  12. import { MeshBuilder } from '../../../mol-geo/geometry/mesh/mesh-builder';
  13. import { PickingId } from '../../../mol-geo/geometry/picking';
  14. import { PrimitiveBuilder } from '../../../mol-geo/primitive/primitive';
  15. import { LocationIterator } from '../../../mol-geo/util/location-iterator';
  16. import { Mat4, Vec3 } from '../../../mol-math/linear-algebra';
  17. import { EmptyLoci, Loci } from '../../../mol-model/loci';
  18. import { Structure, Unit } from '../../../mol-model/structure';
  19. import { CustomProperty } from '../../../mol-model-props/common/custom-property';
  20. import { Representation, RepresentationContext, RepresentationParamsGetter } from '../../../mol-repr/representation';
  21. import { StructureRepresentation, StructureRepresentationProvider, StructureRepresentationStateBuilder, UnitsRepresentation } from '../../../mol-repr/structure/representation';
  22. import { UnitsMeshParams, UnitsMeshVisual, UnitsVisual } from '../../../mol-repr/structure/units-visual';
  23. import { VisualUpdateState } from '../../../mol-repr/util';
  24. import { VisualContext } from '../../../mol-repr/visual';
  25. import { StructureGroup } from '../../../mol-repr/structure/visual/util/common';
  26. import { ParamDefinition as PD } from '../../../mol-util/param-definition';
  27. import { Theme, ThemeRegistryContext } from '../../../mol-theme/theme';
  28. import { NullLocation } from '../../../mol-model/location';
  29. const t = Mat4.identity();
  30. const w = Vec3.zero();
  31. const mp = Vec3.zero();
  32. function calcMidpoint(mp: Vec3, v: Vec3, w: Vec3) {
  33. Vec3.sub(mp, v, w);
  34. Vec3.scale(mp, mp, 0.5);
  35. Vec3.add(mp, mp, w);
  36. }
  37. function shiftVertex(vec: Vec3, ref: Vec3, scale: number) {
  38. Vec3.sub(w, vec, ref);
  39. Vec3.scale(w, w, scale);
  40. Vec3.add(vec, vec, w);
  41. }
  42. const ConfalPyramidsMeshParams = {
  43. ...UnitsMeshParams
  44. };
  45. type ConfalPyramidsMeshParams = typeof ConfalPyramidsMeshParams;
  46. function createConfalPyramidsIterator(structureGroup: StructureGroup): LocationIterator {
  47. const { structure, group } = structureGroup;
  48. const instanceCount = group.units.length;
  49. const prop = ConfalPyramidsProvider.get(structure.model).value;
  50. if (prop === undefined || prop.data === undefined) {
  51. return LocationIterator(0, 1, 1, () => NullLocation);
  52. }
  53. const { halfPyramids } = prop.data;
  54. const getLocation = (groupIndex: number, instanceIndex: number) => {
  55. if (halfPyramids.length <= groupIndex) return NullLocation;
  56. return CPT.Location(halfPyramids[groupIndex]);
  57. };
  58. return LocationIterator(halfPyramids.length, instanceCount, 1, getLocation);
  59. }
  60. function createConfalPyramidsMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PD.Values<ConfalPyramidsMeshParams>, mesh?: Mesh) {
  61. if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh);
  62. const prop = ConfalPyramidsProvider.get(structure.model).value;
  63. if (prop === undefined || prop.data === undefined) return Mesh.createEmpty(mesh);
  64. const { steps } = prop.data;
  65. if (steps.length === 0) return Mesh.createEmpty(mesh);
  66. const mb = MeshBuilder.createState(512, 512, mesh);
  67. const handler = (step: CPT.Step, first: ConfalPyramidsUtil.FirstResidueAtoms, second: ConfalPyramidsUtil.SecondResidueAtoms, firsLocIndex: number, secondLocIndex: number) => {
  68. if (firsLocIndex === -1 || secondLocIndex === -1)
  69. throw new Error('Invalid location index');
  70. const scale = (step.confal_score - 20.0) / 100.0;
  71. const O3 = first.O3.pos;
  72. const OP1 = second.OP1.pos; const OP2 = second.OP2.pos; const O5 = second.O5.pos; const P = second.P.pos;
  73. shiftVertex(O3, P, scale);
  74. shiftVertex(OP1, P, scale);
  75. shiftVertex(OP2, P, scale);
  76. shiftVertex(O5, P, scale);
  77. calcMidpoint(mp, O3, O5);
  78. mb.currentGroup = firsLocIndex;
  79. let pb = PrimitiveBuilder(3);
  80. /* Upper part (for first residue in step) */
  81. pb.add(O3, OP1, OP2);
  82. pb.add(O3, mp, OP1);
  83. pb.add(O3, OP2, mp);
  84. MeshBuilder.addPrimitive(mb, t, pb.getPrimitive());
  85. /* Lower part (for second residue in step */
  86. mb.currentGroup = secondLocIndex;
  87. pb = PrimitiveBuilder(3);
  88. pb.add(mp, O5, OP1);
  89. pb.add(mp, OP2, O5);
  90. pb.add(O5, OP2, OP1);
  91. MeshBuilder.addPrimitive(mb, t, pb.getPrimitive());
  92. };
  93. const walker = new ConfalPyramidsUtil.UnitWalker(structure, unit, handler);
  94. walker.walk();
  95. return MeshBuilder.getMesh(mb);
  96. }
  97. function getConfalPyramidLoci(pickingId: PickingId, structureGroup: StructureGroup, id: number) {
  98. const { groupId, objectId, instanceId } = pickingId;
  99. if (objectId !== id) return EmptyLoci;
  100. const { structure } = structureGroup;
  101. const unit = structureGroup.group.units[instanceId];
  102. if (!Unit.isAtomic(unit)) return EmptyLoci;
  103. const prop = ConfalPyramidsProvider.get(structure.model).value;
  104. if (prop === undefined || prop.data === undefined) return EmptyLoci;
  105. const { halfPyramids } = prop.data;
  106. if (halfPyramids.length <= groupId) return EmptyLoci;
  107. const hp = halfPyramids[groupId];
  108. return CPT.Loci(hp, [{}]);
  109. }
  110. function eachConfalPyramid(loci: Loci, structureGroup: StructureGroup, apply: (interval: Interval) => boolean) {
  111. return false; // TODO: Implement me
  112. }
  113. function ConfalPyramidsVisual(materialId: number): UnitsVisual<ConfalPyramidsMeshParams> {
  114. return UnitsMeshVisual<ConfalPyramidsMeshParams>({
  115. defaultProps: PD.getDefaultValues(ConfalPyramidsMeshParams),
  116. createGeometry: createConfalPyramidsMesh,
  117. createLocationIterator: createConfalPyramidsIterator,
  118. getLoci: getConfalPyramidLoci,
  119. eachLocation: eachConfalPyramid,
  120. setUpdateState: (state: VisualUpdateState, newProps: PD.Values<ConfalPyramidsMeshParams>, currentProps: PD.Values<ConfalPyramidsMeshParams>) => {
  121. }
  122. }, materialId);
  123. }
  124. const ConfalPyramidsVisuals = {
  125. 'confal-pyramids-symbol': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, UnitsMeshParams>) => UnitsRepresentation('Confal Pyramids Symbol Mesh', ctx, getParams, ConfalPyramidsVisual),
  126. };
  127. export const ConfalPyramidsParams = {
  128. ...UnitsMeshParams
  129. };
  130. export type ConfalPyramidsParams = typeof ConfalPyramidsParams;
  131. export function getConfalPyramidsParams(ctx: ThemeRegistryContext, structure: Structure) {
  132. return PD.clone(ConfalPyramidsParams);
  133. }
  134. export type ConfalPyramidsRepresentation = StructureRepresentation<ConfalPyramidsParams>;
  135. export function ConfalPyramidsRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, ConfalPyramidsParams>): ConfalPyramidsRepresentation {
  136. const repr = Representation.createMulti('Confal Pyramids', ctx, getParams, StructureRepresentationStateBuilder, ConfalPyramidsVisuals as unknown as Representation.Def<Structure, ConfalPyramidsParams>);
  137. return repr;
  138. }
  139. export const ConfalPyramidsRepresentationProvider = StructureRepresentationProvider({
  140. name: 'confal-pyramids',
  141. label: 'Confal Pyramids',
  142. description: 'Displays schematic depiction of conformer classes and confal values',
  143. factory: ConfalPyramidsRepresentation,
  144. getParams: getConfalPyramidsParams,
  145. defaultValues: PD.getDefaultValues(ConfalPyramidsParams),
  146. defaultColorTheme: { name: 'confal-pyramids' },
  147. defaultSizeTheme: { name: 'uniform' },
  148. isApplicable: (structure: Structure) => structure.models.some(m => ConfalPyramids.isApplicable(m)),
  149. ensureCustomProperties: {
  150. attach: (ctx: CustomProperty.Context, structure: Structure) => ConfalPyramidsProvider.attach(ctx, structure.model, void 0, true),
  151. detach: (data) => ConfalPyramidsProvider.ref(data.model, false),
  152. }
  153. });