volume.ts 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /**
  2. * Copyright (c) 2018-2022 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 { PluginContext } from '../../mol-plugin/context';
  8. import { StateAction, StateTransformer, StateSelection } from '../../mol-state';
  9. import { Task } from '../../mol-task';
  10. import { getFileInfo } from '../../mol-util/file-info';
  11. import { ParamDefinition as PD } from '../../mol-util/param-definition';
  12. import { PluginStateObject } from '../objects';
  13. import { Download } from '../transforms/data';
  14. import { DataFormatProvider } from '../formats/provider';
  15. import { Asset } from '../../mol-util/assets';
  16. import { StateTransforms } from '../transforms';
  17. import { assertUnreachable } from '../../mol-util/type-helpers';
  18. export type EmdbDownloadProvider = 'pdbe' | 'rcsb'
  19. export { DownloadDensity };
  20. type DownloadDensity = typeof DownloadDensity
  21. const DownloadDensity = StateAction.build({
  22. from: PluginStateObject.Root,
  23. display: { name: 'Download Density', description: 'Load a density from the provided source and create its default visual.' },
  24. params: (a, ctx: PluginContext) => {
  25. const { options } = ctx.dataFormats;
  26. return {
  27. source: PD.MappedStatic('pdb-xray', {
  28. 'pdb-xray': PD.Group({
  29. provider: PD.Group({
  30. id: PD.Text('1tqn', { label: 'Id' }),
  31. server: PD.Select('rcsb', [['pdbe', 'PDBe'], ['rcsb', 'RCSB PDB']]),
  32. }, { pivot: 'id' }),
  33. type: PD.Select('2fofc', [['2fofc', '2Fo-Fc'], ['fofc', 'Fo-Fc']]),
  34. }, { isFlat: true }),
  35. 'pdb-xray-ds': PD.Group({
  36. provider: PD.Group({
  37. id: PD.Text('1tqn', { label: 'Id' }),
  38. server: PD.Select('pdbe', [['pdbe', 'PDBe'], ['rcsb', 'RCSB PDB']]),
  39. }, { pivot: 'id' }),
  40. detail: PD.Numeric(3, { min: 0, max: 6, step: 1 }, { label: 'Detail' }),
  41. }, { isFlat: true }),
  42. 'pdb-emd-ds': PD.Group({
  43. provider: PD.Group({
  44. id: PD.Text('emd-8004', { label: 'Id' }),
  45. server: PD.Select<EmdbDownloadProvider>('pdbe', [['pdbe', 'PDBe'], ['rcsb', 'RCSB PDB']]),
  46. }, { pivot: 'id' }),
  47. detail: PD.Numeric(3, { min: 0, max: 6, step: 1 }, { label: 'Detail' }),
  48. }, { isFlat: true }),
  49. 'url': PD.Group({
  50. url: PD.Url(''),
  51. isBinary: PD.Boolean(false),
  52. format: PD.Select('auto', options),
  53. }, { isFlat: true })
  54. }, {
  55. options: [
  56. ['pdb-xray', 'PDB X-ray maps'],
  57. ['pdb-emd-ds', 'PDB EMD Density Server'],
  58. ['pdb-xray-ds', 'PDB X-ray Density Server'],
  59. ['url', 'URL']
  60. ]
  61. })
  62. };
  63. }
  64. })(({ params }, plugin: PluginContext) => Task.create('Download Density', async taskCtx => {
  65. const src = params.source;
  66. let downloadParams: StateTransformer.Params<Download>;
  67. let provider: DataFormatProvider | undefined;
  68. switch (src.name) {
  69. case 'url':
  70. downloadParams = src.params;
  71. break;
  72. case 'pdb-xray':
  73. downloadParams = src.params.provider.server === 'pdbe' ? {
  74. url: Asset.Url(src.params.type === '2fofc'
  75. ? `https://www.ebi.ac.uk/pdbe/coordinates/files/${src.params.provider.id.toLowerCase()}.ccp4`
  76. : `https://www.ebi.ac.uk/pdbe/coordinates/files/${src.params.provider.id.toLowerCase()}_diff.ccp4`),
  77. isBinary: true,
  78. label: `PDBe X-ray map: ${src.params.provider.id}`
  79. } : {
  80. url: Asset.Url(src.params.type === '2fofc'
  81. ? `https://edmaps.rcsb.org/maps/${src.params.provider.id.toLowerCase()}_2fofc.dsn6`
  82. : `https://edmaps.rcsb.org/maps/${src.params.provider.id.toLowerCase()}_fofc.dsn6`),
  83. isBinary: true,
  84. label: `RCSB X-ray map: ${src.params.provider.id}`
  85. };
  86. break;
  87. case 'pdb-emd-ds':
  88. downloadParams = src.params.provider.server === 'pdbe' ? {
  89. url: Asset.Url(`https://www.ebi.ac.uk/pdbe/densities/emd/${src.params.provider.id.toLowerCase()}/cell?detail=${src.params.detail}`),
  90. isBinary: true,
  91. label: `PDBe EMD Density Server: ${src.params.provider.id}`
  92. } : {
  93. url: Asset.Url(`https://maps.rcsb.org/em/${src.params.provider.id.toLowerCase()}/cell?detail=${src.params.detail}`),
  94. isBinary: true,
  95. label: `RCSB PDB EMD Density Server: ${src.params.provider.id}`
  96. };
  97. break;
  98. case 'pdb-xray-ds':
  99. downloadParams = src.params.provider.server === 'pdbe' ? {
  100. url: Asset.Url(`https://www.ebi.ac.uk/pdbe/densities/x-ray/${src.params.provider.id.toLowerCase()}/cell?detail=${src.params.detail}`),
  101. isBinary: true,
  102. label: `PDBe X-ray Density Server: ${src.params.provider.id}`
  103. } : {
  104. url: Asset.Url(`https://maps.rcsb.org/x-ray/${src.params.provider.id.toLowerCase()}/cell?detail=${src.params.detail}`),
  105. isBinary: true,
  106. label: `RCSB PDB X-ray Density Server: ${src.params.provider.id}`
  107. };
  108. break;
  109. default: assertUnreachable(src);
  110. }
  111. const data = await plugin.builders.data.download(downloadParams);
  112. let entryId: string | undefined = undefined;
  113. switch (src.name) {
  114. case 'url':
  115. downloadParams = src.params;
  116. provider = src.params.format === 'auto' ? plugin.dataFormats.auto(getFileInfo(Asset.getUrl(downloadParams.url)), data.cell?.obj!) : plugin.dataFormats.get(src.params.format);
  117. break;
  118. case 'pdb-xray':
  119. entryId = src.params.provider.id;
  120. provider = src.params.provider.server === 'pdbe'
  121. ? plugin.dataFormats.get('ccp4')
  122. : plugin.dataFormats.get('dsn6');
  123. break;
  124. case 'pdb-emd-ds':
  125. case 'pdb-xray-ds':
  126. entryId = src.params.provider.id;
  127. provider = plugin.dataFormats.get('dscif');
  128. break;
  129. default: assertUnreachable(src);
  130. }
  131. if (!provider) {
  132. plugin.log.warn('DownloadDensity: Format provider not found.');
  133. return;
  134. }
  135. const volumes = await provider.parse(plugin, data, { entryId });
  136. await provider.visuals?.(plugin, volumes);
  137. }));
  138. export const AssignColorVolume = StateAction.build({
  139. display: { name: 'Assign Volume Colors', description: 'Assigns another volume to be available for coloring.' },
  140. from: PluginStateObject.Volume.Data,
  141. isApplicable(a) { return !a.data.colorVolume; },
  142. params(a, plugin: PluginContext) {
  143. const cells = plugin.state.data.select(StateSelection.Generators.root.subtree().ofType(PluginStateObject.Volume.Data).filter(cell => !!cell.obj && !cell.obj?.data.colorVolume && cell.obj !== a));
  144. if (cells.length === 0) return { ref: PD.Text('', { isHidden: true, label: 'Volume' }) };
  145. return { ref: PD.Select(cells[0].transform.ref, cells.map(c => [c.transform.ref, c.obj!.label]), { label: 'Volume' }) };
  146. }
  147. })(({ ref, params, state }, plugin: PluginContext) => {
  148. return plugin.build().to(ref).apply(StateTransforms.Volume.AssignColorVolume, { ref: params.ref }, { dependsOn: [params.ref] }).commit();
  149. });