volume.ts 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /**
  2. * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  6. */
  7. import { CIF } from '../../mol-io/reader/cif';
  8. import { Vec3 } from '../../mol-math/linear-algebra';
  9. import { volumeFromCcp4 } from '../../mol-model-formats/volume/ccp4';
  10. import { volumeFromDensityServerData } from '../../mol-model-formats/volume/density-server';
  11. import { volumeFromDsn6 } from '../../mol-model-formats/volume/dsn6';
  12. import { Task } from '../../mol-task';
  13. import { ParamDefinition as PD } from '../../mol-util/param-definition';
  14. import { PluginStateObject as SO, PluginStateTransform } from '../objects';
  15. import { volumeFromCube } from '../../mol-model-formats/volume/cube';
  16. import { volumeFromDx } from '../../mol-model-formats/volume/dx';
  17. import { Volume } from '../../mol-model/volume';
  18. import { PluginContext } from '../../mol-plugin/context';
  19. import { StateSelection } from '../../mol-state';
  20. export { VolumeFromCcp4 };
  21. export { VolumeFromDsn6 };
  22. export { VolumeFromCube };
  23. export { VolumeFromDx };
  24. export { AssignColorVolume };
  25. export { VolumeFromDensityServerCif };
  26. type VolumeFromCcp4 = typeof VolumeFromCcp4
  27. const VolumeFromCcp4 = PluginStateTransform.BuiltIn({
  28. name: 'volume-from-ccp4',
  29. display: { name: 'Volume from CCP4/MRC/MAP', description: 'Create Volume from CCP4/MRC/MAP data' },
  30. from: SO.Format.Ccp4,
  31. to: SO.Volume.Data,
  32. params(a) {
  33. return {
  34. voxelSize: PD.Vec3(Vec3.create(1, 1, 1)),
  35. offset: PD.Vec3(Vec3.create(0, 0, 0)),
  36. entryId: PD.Text(''),
  37. };
  38. }
  39. })({
  40. apply({ a, params }) {
  41. return Task.create('Create volume from CCP4/MRC/MAP', async ctx => {
  42. const volume = await volumeFromCcp4(a.data, { ...params, label: a.data.name || a.label }).runInContext(ctx);
  43. const props = { label: volume.label || 'Volume', description: `Volume ${a.data.header.NX}\u00D7${a.data.header.NX}\u00D7${a.data.header.NX}` };
  44. return new SO.Volume.Data(volume, props);
  45. });
  46. }
  47. });
  48. type VolumeFromDsn6 = typeof VolumeFromDsn6
  49. const VolumeFromDsn6 = PluginStateTransform.BuiltIn({
  50. name: 'volume-from-dsn6',
  51. display: { name: 'Volume from DSN6/BRIX', description: 'Create Volume from DSN6/BRIX data' },
  52. from: SO.Format.Dsn6,
  53. to: SO.Volume.Data,
  54. params(a) {
  55. return {
  56. voxelSize: PD.Vec3(Vec3.create(1, 1, 1)),
  57. entryId: PD.Text(''),
  58. };
  59. }
  60. })({
  61. apply({ a, params }) {
  62. return Task.create('Create volume from DSN6/BRIX', async ctx => {
  63. const volume = await volumeFromDsn6(a.data, { ...params, label: a.data.name || a.label }).runInContext(ctx);
  64. const props = { label: volume.label || 'Volume', description: `Volume ${a.data.header.xExtent}\u00D7${a.data.header.yExtent}\u00D7${a.data.header.zExtent}` };
  65. return new SO.Volume.Data(volume, props);
  66. });
  67. }
  68. });
  69. type VolumeFromCube = typeof VolumeFromCube
  70. const VolumeFromCube = PluginStateTransform.BuiltIn({
  71. name: 'volume-from-cube',
  72. display: { name: 'Volume from Cube', description: 'Create Volume from Cube data' },
  73. from: SO.Format.Cube,
  74. to: SO.Volume.Data,
  75. params(a) {
  76. const dataIndex = a ? PD.Select(0, a.data.header.dataSetIds.map((id, i) => [i, `${id}`] as const)) : PD.Numeric(0);
  77. return {
  78. dataIndex,
  79. entryId: PD.Text(''),
  80. };
  81. }
  82. })({
  83. apply({ a, params }) {
  84. return Task.create('Create volume from Cube', async ctx => {
  85. const volume = await volumeFromCube(a.data, { ...params, label: a.data.name || a.label }).runInContext(ctx);
  86. const props = { label: volume.label || 'Volume', description: `Volume ${a.data.header.dim[0]}\u00D7${a.data.header.dim[1]}\u00D7${a.data.header.dim[2]}` };
  87. return new SO.Volume.Data(volume, props);
  88. });
  89. }
  90. });
  91. type VolumeFromDx = typeof VolumeFromDx
  92. const VolumeFromDx = PluginStateTransform.BuiltIn({
  93. name: 'volume-from-dx',
  94. display: { name: 'Parse DX', description: 'Create volume from DX data.' },
  95. from: SO.Format.Dx,
  96. to: SO.Volume.Data
  97. })({
  98. apply({ a }) {
  99. return Task.create('Parse DX', async ctx => {
  100. const volume = await volumeFromDx(a.data, { label: a.data.name || a.label }).runInContext(ctx);
  101. const props = { label: volume.label || 'Volume', description: `Volume ${a.data.header.dim[0]}\u00D7${a.data.header.dim[1]}\u00D7${a.data.header.dim[2]}` };
  102. return new SO.Volume.Data(volume, props);
  103. });
  104. }
  105. });
  106. type VolumeFromDensityServerCif = typeof VolumeFromDensityServerCif
  107. const VolumeFromDensityServerCif = PluginStateTransform.BuiltIn({
  108. name: 'volume-from-density-server-cif',
  109. display: { name: 'Volume from density-server CIF', description: 'Identify and create all separate models in the specified CIF data block' },
  110. from: SO.Format.Cif,
  111. to: SO.Volume.Data,
  112. params(a) {
  113. if (!a) {
  114. return {
  115. blockHeader: PD.Optional(PD.Text(void 0, { description: 'Header of the block to parse. If none is specifed, the 1st data block in the file is used.' })),
  116. entryId: PD.Text(''),
  117. };
  118. }
  119. const blocks = a.data.blocks.slice(1); // zero block contains query meta-data
  120. return {
  121. blockHeader: PD.Optional(PD.Select(blocks[0] && blocks[0].header, blocks.map(b => [b.header, b.header] as [string, string]), { description: 'Header of the block to parse' })),
  122. entryId: PD.Text(''),
  123. };
  124. }
  125. })({
  126. isApplicable: a => a.data.blocks.length > 0,
  127. apply({ a, params }) {
  128. return Task.create('Parse density-server CIF', async ctx => {
  129. const header = params.blockHeader || a.data.blocks[1].header; // zero block contains query meta-data
  130. const block = a.data.blocks.find(b => b.header === header);
  131. if (!block) throw new Error(`Data block '${[header]}' not found.`);
  132. const densityServerCif = CIF.schema.densityServer(block);
  133. const volume = await volumeFromDensityServerData(densityServerCif, { entryId: params.entryId }).runInContext(ctx);
  134. const [x, y, z] = volume.grid.cells.space.dimensions;
  135. const props = { label: densityServerCif.volume_data_3d_info.name.value(0), description: `Volume ${x}\u00D7${y}\u00D7${z}` };
  136. return new SO.Volume.Data(volume, props);
  137. });
  138. }
  139. });
  140. type AssignColorVolume = typeof AssignColorVolume
  141. const AssignColorVolume = PluginStateTransform.BuiltIn({
  142. name: 'assign-color-volume',
  143. display: { name: 'Assign Color Volume', description: 'Assigns another volume to be available for coloring.' },
  144. from: SO.Volume.Data,
  145. to: SO.Volume.Data,
  146. isDecorator: true,
  147. params(a, plugin: PluginContext) {
  148. if (!a) return { ref: PD.Text() };
  149. const cells = plugin.state.data.select(StateSelection.Generators.root.subtree().ofType(SO.Volume.Data).filter(cell => !!cell.obj && !cell.obj?.data.colorVolume && cell.obj !== a));
  150. if (cells.length === 0) return { ref: PD.Text('', { isHidden: true }) };
  151. return { ref: PD.Select(cells[0].transform.ref, cells.map(c => [c.transform.ref, c.obj!.label])) };
  152. }
  153. })({
  154. apply({ a, params, dependencies }) {
  155. return Task.create('Assign Color Volume', async ctx => {
  156. if (!dependencies || !dependencies[params.ref]) {
  157. throw new Error('Dependency not available.');
  158. }
  159. const colorVolume = dependencies[params.ref].data as Volume;
  160. const volume: Volume = {
  161. ...a.data,
  162. colorVolume
  163. };
  164. const props = { label: a.label, description: 'Volume + Colors' };
  165. return new SO.Volume.Data(volume, props);
  166. });
  167. }
  168. });