volume.ts 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /**
  2. * Copyright (c) 2018-2019 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 { parseDx } from '../../mol-io/reader/dx/parser';
  17. import { volumeFromDx } from '../../mol-model-formats/volume/dx';
  18. import { VolumeData } from '../../mol-model/volume';
  19. import { PluginContext } from '../../mol-plugin/context';
  20. import { StateSelection } from '../../mol-state';
  21. export { VolumeFromCcp4 };
  22. export { VolumeFromDsn6 };
  23. export { VolumeFromCube };
  24. export { VolumeFromDx };
  25. export { AssignColorVolume };
  26. export { VolumeFromDensityServerCif };
  27. type VolumeFromCcp4 = typeof VolumeFromCcp4
  28. const VolumeFromCcp4 = PluginStateTransform.BuiltIn({
  29. name: 'volume-from-ccp4',
  30. display: { name: 'Volume from CCP4/MRC/MAP', description: 'Create Volume from CCP4/MRC/MAP data' },
  31. from: SO.Format.Ccp4,
  32. to: SO.Volume.Data,
  33. params(a) {
  34. return {
  35. voxelSize: PD.Vec3(Vec3.create(1, 1, 1)),
  36. offset: PD.Vec3(Vec3.create(0, 0, 0))
  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.label }).runInContext(ctx);
  43. const props = { label: volume.label || 'Volume', description: 'Volume' };
  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. };
  58. }
  59. })({
  60. apply({ a, params }) {
  61. return Task.create('Create volume from DSN6/BRIX', async ctx => {
  62. const volume = await volumeFromDsn6(a.data, { ...params, label: a.label }).runInContext(ctx);
  63. const props = { label: volume.label || 'Volume', description: 'Volume' };
  64. return new SO.Volume.Data(volume, props);
  65. });
  66. }
  67. });
  68. type VolumeFromCube = typeof VolumeFromCube
  69. const VolumeFromCube = PluginStateTransform.BuiltIn({
  70. name: 'volume-from-cube',
  71. display: { name: 'Volume from Cube', description: 'Create Volume from Cube data' },
  72. from: SO.Format.Cube,
  73. to: SO.Volume.Data,
  74. params(a) {
  75. if (!a) return { dataIndex: PD.Numeric(0) };
  76. return {
  77. dataIndex: PD.Select(0, a.data.header.dataSetIds.map((id, i) => [i, `${id}`] as const))
  78. };
  79. }
  80. })({
  81. apply({ a, params }) {
  82. return Task.create('Create volume from Cube', async ctx => {
  83. const volume = await volumeFromCube(a.data, { ...params, label: a.label }).runInContext(ctx);
  84. const props = { label: volume.label || 'Volume', description: 'Volume' };
  85. return new SO.Volume.Data(volume, props);
  86. });
  87. }
  88. });
  89. type VolumeFromDx = typeof VolumeFromDx
  90. const VolumeFromDx = PluginStateTransform.BuiltIn({
  91. name: 'volume-from-dx',
  92. display: { name: 'Parse PX', description: 'Parse DX string/binary and create volume.' },
  93. from: [SO.Data.String, SO.Data.Binary],
  94. to: SO.Volume.Data
  95. })({
  96. apply({ a }) {
  97. return Task.create('Parse DX', async ctx => {
  98. const parsed = await parseDx(a.data).runInContext(ctx);
  99. if (parsed.isError) throw new Error(parsed.message);
  100. const volume = await volumeFromDx(parsed.result, { label: a.label }).runInContext(ctx);
  101. const props = { label: volume.label || 'Volume', description: 'Volume' };
  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. };
  117. }
  118. const blocks = a.data.blocks.slice(1); // zero block contains query meta-data
  119. return {
  120. 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' }))
  121. };
  122. }
  123. })({
  124. isApplicable: a => a.data.blocks.length > 0,
  125. apply({ a, params }) {
  126. return Task.create('Parse density-server CIF', async ctx => {
  127. const header = params.blockHeader || a.data.blocks[1].header; // zero block contains query meta-data
  128. const block = a.data.blocks.find(b => b.header === header);
  129. if (!block) throw new Error(`Data block '${[header]}' not found.`);
  130. const densityServerCif = CIF.schema.densityServer(block);
  131. const volume = await volumeFromDensityServerData(densityServerCif).runInContext(ctx);
  132. const props = { label: densityServerCif.volume_data_3d_info.name.value(0), description: `${densityServerCif.volume_data_3d_info.name.value(0)}` };
  133. return new SO.Volume.Data(volume, props);
  134. });
  135. }
  136. });
  137. type AssignColorVolume = typeof AssignColorVolume
  138. const AssignColorVolume = PluginStateTransform.BuiltIn({
  139. name: 'assign-color-volume',
  140. display: { name: 'Assign Color Volume', description: 'Assigns another volume to be available for coloring.' },
  141. from: SO.Volume.Data,
  142. to: SO.Volume.Data,
  143. isDecorator: true,
  144. params(a, plugin: PluginContext) {
  145. if (!a) return { ref: PD.Text() };
  146. 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));
  147. if (cells.length === 0) return { ref: PD.Text('', { isHidden: true }) };
  148. return { ref: PD.Select(cells[0].transform.ref, cells.map(c => [c.transform.ref, c.obj!.label])) };
  149. }
  150. })({
  151. apply({ a, params, dependencies }) {
  152. return Task.create('Assign Color Volume', async ctx => {
  153. if (!dependencies || !dependencies[params.ref]) {
  154. throw new Error('Dependency not available.');
  155. }
  156. const colorVolume = dependencies[params.ref].data as VolumeData;
  157. const volume: VolumeData = {
  158. ...a.data,
  159. colorVolume
  160. };
  161. const props = { label: a.label, description: 'Volume + Colors' };
  162. return new SO.Volume.Data(volume, props);
  163. });
  164. }
  165. });