sequence.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /**
  2. * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. * @author David Sehnal <david.sehnal@gmail.com>
  6. */
  7. import * as React from 'react'
  8. import { PluginUIComponent } from './base';
  9. import { StateTreeSpine } from '../../mol-state/tree/spine';
  10. import { PluginStateObject as SO } from '../state/objects';
  11. import { Sequence } from './sequence/sequence';
  12. import { Structure, StructureElement, StructureProperties as SP } from '../../mol-model/structure';
  13. import { SequenceWrapper } from './sequence/util';
  14. import { PolymerSequenceWrapper } from './sequence/polymer';
  15. import { StructureElementSelectionManager } from '../util/structure-element-selection';
  16. import { MarkerAction } from '../../mol-util/marker-action';
  17. import { ParameterControls } from './controls/parameters';
  18. import { ParamDefinition as PD } from '../../mol-util/param-definition';
  19. function getSequenceWrapperForStructure(index: number, structure: Structure, structureSelection: StructureElementSelectionManager): SequenceWrapper.Any | undefined {
  20. let j = 0
  21. for (let i = 0, il = structure.units.length; i < il; ++i) {
  22. const unit = structure.units[i]
  23. if (unit.polymerElements.length === 0) continue
  24. if (j === index) {
  25. const sw = new PolymerSequenceWrapper({ structure, unit })
  26. sw.markResidue(structureSelection.get(structure), MarkerAction.Select)
  27. return sw
  28. }
  29. j += 1
  30. }
  31. }
  32. function getPolymerOptionsForStructure(structure: Structure) {
  33. const options: [number, string][] = []
  34. let i = 0
  35. structure.units.forEach(unit => {
  36. if (unit.polymerElements.length === 0) return
  37. const l = StructureElement.create(unit, unit.elements[0])
  38. const entityDescription = SP.entity.pdbx_description(l)
  39. const label_asym_id = SP.chain.label_asym_id(l)
  40. const label = `${label_asym_id}: ${entityDescription}`
  41. options.push([ i, label ])
  42. i += 1
  43. })
  44. return options
  45. }
  46. export class SequenceView extends PluginUIComponent<{ }, { polymer: number }> {
  47. private spine: StateTreeSpine.Impl
  48. state = { polymer: 0 }
  49. componentDidMount() {
  50. this.spine = new StateTreeSpine.Impl(this.plugin.state.dataState.cells);
  51. this.subscribe(this.plugin.state.behavior.currentObject, o => {
  52. const current = this.plugin.state.dataState.cells.get(o.ref)!;
  53. this.spine.current = current
  54. this.forceUpdate();
  55. });
  56. this.subscribe(this.plugin.events.state.object.updated, ({ ref, state }) => {
  57. const current = this.spine.current;
  58. if (!current || current.sourceRef !== ref || current.state !== state) return;
  59. this.forceUpdate();
  60. });
  61. }
  62. private getStructure() {
  63. const so = this.spine && this.spine.getRootOfType(SO.Molecule.Structure)
  64. return so && so.data
  65. }
  66. private getParams(structure: Structure) {
  67. return {
  68. polymer: PD.Select(0, getPolymerOptionsForStructure(structure))
  69. }
  70. }
  71. private setParamProps = (p: { param: PD.Base<any>, name: string, value: any }) => {
  72. if (p.name === 'polymer') {
  73. this.setState({ polymer: p.value })
  74. }
  75. }
  76. render() {
  77. const structure = this.getStructure();
  78. if (!structure) return <div className='msp-sequence'>
  79. <div className='msp-sequence-entity'>No structure available</div>
  80. </div>;
  81. const { structureSelection } = this.plugin.helpers
  82. const params = this.getParams(structure)
  83. const sequenceWrapper = getSequenceWrapperForStructure(this.state.polymer, structure, structureSelection)
  84. return <div className='msp-sequence'>
  85. <ParameterControls params={params} values={this.state} onChange={this.setParamProps} />
  86. {sequenceWrapper !== undefined
  87. ? <Sequence sequenceWrapper={sequenceWrapper} />
  88. : <div className='msp-sequence-entity'>No sequence available</div>}
  89. </div>;
  90. }
  91. }