model.ts 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /**
  2. * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { Column, Table } from '../../mol-data/db';
  7. import { OrderedSet } from '../../mol-data/int';
  8. import { Vec3 } from '../../mol-math/linear-algebra';
  9. import { createModels } from '../../mol-model-formats/structure/basic/parser';
  10. import { BasicSchema, createBasic } from '../../mol-model-formats/structure/basic/schema';
  11. import { EntityBuilder } from '../../mol-model-formats/structure/common/entity';
  12. import { Loci } from '../../mol-model/loci';
  13. import { Model, Trajectory, Unit } from '../../mol-model/structure';
  14. import { MoleculeType } from '../../mol-model/structure/model/types';
  15. import { LociLabelProvider } from '../../mol-plugin-state/manager/loci-label';
  16. import { MolScriptBuilder as MS } from '../../mol-script/language/builder';
  17. import { CustomPropSymbol } from '../../mol-script/language/symbol';
  18. import Type from '../../mol-script/language/type';
  19. import { QuerySymbolRuntime } from '../../mol-script/runtime/query/base';
  20. import { RuntimeContext, Task } from '../../mol-task';
  21. import { objectForEach } from '../../mol-util/object';
  22. import { G3dDataBlock } from './data';
  23. interface NormalizedData {
  24. entity_id: string[],
  25. chromosome: string[],
  26. seq_id_begin: Int32Array,
  27. seq_id_end: Int32Array,
  28. start: Int32Array,
  29. x: Float32Array,
  30. y: Float32Array,
  31. z: Float32Array,
  32. r: Float32Array,
  33. haplotype: string[]
  34. }
  35. function getColumns(block: G3dDataBlock) {
  36. const { data } = block;
  37. let size = 0;
  38. objectForEach(data, h => objectForEach(h, g => size += g.start.length));
  39. const normalized: NormalizedData = {
  40. entity_id: new Array(size),
  41. chromosome: new Array(size),
  42. seq_id_begin: new Int32Array(size),
  43. seq_id_end: new Int32Array(size),
  44. start: new Int32Array(size),
  45. x: new Float32Array(size),
  46. y: new Float32Array(size),
  47. z: new Float32Array(size),
  48. r: new Float32Array(size),
  49. haplotype: new Array(size)
  50. };
  51. const p = [Vec3(), Vec3(), Vec3()];
  52. let o = 0;
  53. objectForEach(data, (hs, h) => {
  54. objectForEach(hs, (chs, ch) => {
  55. const entity_id = `${ch}-${h}`;
  56. const l = chs.start.length;
  57. if (l === 0) return;
  58. let x = chs.x[0];
  59. let y = chs.y[0];
  60. let z = chs.z[0];
  61. Vec3.set(p[0], x, y, z);
  62. Vec3.set(p[2], x, y, z);
  63. for (let i = 0; i < l; i++) {
  64. normalized.entity_id[o] = entity_id;
  65. normalized.chromosome[o] = ch;
  66. normalized.start[o] = chs.start[i];
  67. normalized.seq_id_begin[o] = o;
  68. normalized.seq_id_end[o] = o;
  69. x = chs.x[i];
  70. y = chs.y[i];
  71. z = chs.z[i];
  72. Vec3.set(p[1], x, y, z);
  73. if (i + 1 < l) Vec3.set(p[2], chs.x[i + 1], chs.y[i + 1], chs.z[i + 1]);
  74. else Vec3.set(p[2], x, y, z);
  75. normalized.x[o] = x;
  76. normalized.y[o] = y;
  77. normalized.z[o] = z;
  78. normalized.r[o] = 2 / 3 * Math.min(Vec3.distance(p[0], p[1]), Vec3.distance(p[1], p[2]));
  79. normalized.haplotype[o] = h;
  80. const _p = p[0];
  81. p[0] = p[1];
  82. p[1] = _p;
  83. o++;
  84. }
  85. if (l === 1) {
  86. normalized.r[o - 1] = 1;
  87. }
  88. });
  89. });
  90. return normalized;
  91. }
  92. async function getTraj(ctx: RuntimeContext, data: G3dDataBlock) {
  93. const normalized = getColumns(data);
  94. const rowCount = normalized.seq_id_begin.length;
  95. const entityIds = new Array<string>(rowCount);
  96. const entityBuilder = new EntityBuilder();
  97. const eName = { customName: '' };
  98. for (let i = 0; i < rowCount; ++i) {
  99. const e = normalized.entity_id[i];
  100. eName.customName = e;
  101. const entityId = entityBuilder.getEntityId(e, MoleculeType.DNA, e, eName);
  102. entityIds[i] = entityId;
  103. }
  104. const ihm_sphere_obj_site = Table.ofPartialColumns(BasicSchema.ihm_sphere_obj_site, {
  105. id: Column.range(0, rowCount),
  106. entity_id: Column.ofStringArray(entityIds),
  107. seq_id_begin: Column.ofIntArray(normalized.seq_id_begin),
  108. seq_id_end: Column.ofIntArray(normalized.seq_id_end),
  109. asym_id: Column.ofStringArray(normalized.chromosome),
  110. Cartn_x: Column.ofFloatArray(normalized.x),
  111. Cartn_y: Column.ofFloatArray(normalized.y),
  112. Cartn_z: Column.ofFloatArray(normalized.z),
  113. object_radius: Column.ofFloatArray(normalized.r),
  114. rmsf: Column.ofConst(0, rowCount, Column.Schema.float),
  115. model_id: Column.ofConst(1, rowCount, Column.Schema.int),
  116. }, rowCount);
  117. const basic = createBasic({
  118. entity: entityBuilder.getEntityTable(),
  119. ihm_model_list: Table.ofPartialColumns(BasicSchema.ihm_model_list, {
  120. model_id: Column.ofIntArray([1]),
  121. model_name: Column.ofStringArray(['3DG Model']),
  122. }, 1),
  123. ihm_sphere_obj_site
  124. });
  125. const models = await createModels(basic, { kind: 'g3d', name: 'G3D', data }, ctx);
  126. models.representative.customData.g3dInfo = {
  127. haplotypes: Object.keys(data.data),
  128. haplotype: normalized.haplotype,
  129. resolution: data.resolution,
  130. start: normalized.start
  131. } as G3dInfoData;
  132. return models;
  133. }
  134. export function trajectoryFromG3D(data: G3dDataBlock): Task<Trajectory> {
  135. return Task.create('Parse G3D', async ctx => {
  136. return getTraj(ctx, data);
  137. });
  138. }
  139. export const G3dSymbols = {
  140. haplotype: QuerySymbolRuntime.Dynamic(CustomPropSymbol('g3d', 'haplotype', Type.Str),
  141. ctx => {
  142. if (Unit.isAtomic(ctx.element.unit)) return '';
  143. const info = getG3dInfoData(ctx.element.unit.model);
  144. if (!info) return '';
  145. const seqId = ctx.element.unit.model.coarseHierarchy.spheres.seq_id_begin.value(ctx.element.element);
  146. return info.haplotype[seqId] || '';
  147. }
  148. )
  149. };
  150. export function g3dHaplotypeQuery(haplotype: string) {
  151. return MS.struct.generator.atomGroups({
  152. 'chain-test': MS.core.rel.eq([G3dSymbols.haplotype.symbol(), haplotype]),
  153. });
  154. }
  155. export interface G3dInfoData {
  156. haplotypes: string[],
  157. haplotype: string[],
  158. start: Int32Array,
  159. resolution: number
  160. };
  161. export function setG3dInfoData(model: Model, data: G3dInfoData) {
  162. model.customData.g3dInfo = data;
  163. }
  164. export function getG3dInfoData(model: Model): G3dInfoData | undefined {
  165. return model.customData.g3dInfo;
  166. }
  167. export const G3dLabelProvider: LociLabelProvider = {
  168. label: (e: Loci): string | undefined => {
  169. if (e.kind !== 'element-loci' || Loci.isEmpty(e)) return;
  170. const first = e.elements[0];
  171. if (e.elements.length !== 1 || Unit.isAtomic(first.unit)) return;
  172. const info = getG3dInfoData(first.unit.model);
  173. if (!info) return;
  174. const eI = first.unit.elements[OrderedSet.getAt(first.indices, 0)];
  175. const seqId = first.unit.model.coarseHierarchy.spheres.seq_id_begin.value(eI);
  176. return `<b>Start:</b> ${info.start[seqId]} <small>| resolution ${info.resolution}<small>`;
  177. }
  178. };