Skip to content
Snippets Groups Projects
Commit bcb8419f authored by Alexander Rose's avatar Alexander Rose
Browse files

init repr3d and seq view marker with global selection

parent 7d24bcf1
No related branches found
No related tags found
No related merge requests found
...@@ -7,9 +7,11 @@ ...@@ -7,9 +7,11 @@
import { MarkerAction } from '../../../mol-util/marker-action'; import { MarkerAction } from '../../../mol-util/marker-action';
import { PluginContext } from '../../../mol-plugin/context'; import { PluginContext } from '../../../mol-plugin/context';
import { PluginStateObject as SO } from '../../state/objects';
import { labelFirst } from '../../../mol-theme/label'; import { labelFirst } from '../../../mol-theme/label';
import { PluginBehavior } from '../behavior'; import { PluginBehavior } from '../behavior';
import { Interaction } from '../../util/interaction'; import { Interaction } from '../../util/interaction';
import { StateTreeSpine } from '../../../mol-state/tree/spine';
export const HighlightLoci = PluginBehavior.create({ export const HighlightLoci = PluginBehavior.create({
name: 'representation-highlight-loci', name: 'representation-highlight-loci',
...@@ -17,7 +19,7 @@ export const HighlightLoci = PluginBehavior.create({ ...@@ -17,7 +19,7 @@ export const HighlightLoci = PluginBehavior.create({
ctor: class extends PluginBehavior.Handler { ctor: class extends PluginBehavior.Handler {
private lociMarkProvider = (loci: Interaction.Loci, action: MarkerAction) => { private lociMarkProvider = (loci: Interaction.Loci, action: MarkerAction) => {
if (!this.ctx.canvas3d) return; if (!this.ctx.canvas3d) return;
this.ctx.canvas3d.mark(loci, action) this.ctx.canvas3d.mark({ ...loci, repr: undefined }, action)
} }
register() { register() {
this.ctx.lociHighlights.addProvider(this.lociMarkProvider) this.ctx.lociHighlights.addProvider(this.lociMarkProvider)
...@@ -33,16 +35,33 @@ export const SelectLoci = PluginBehavior.create({ ...@@ -33,16 +35,33 @@ export const SelectLoci = PluginBehavior.create({
name: 'representation-select-loci', name: 'representation-select-loci',
category: 'interaction', category: 'interaction',
ctor: class extends PluginBehavior.Handler { ctor: class extends PluginBehavior.Handler {
private spine: StateTreeSpine.Impl
private lociMarkProvider = (loci: Interaction.Loci, action: MarkerAction) => { private lociMarkProvider = (loci: Interaction.Loci, action: MarkerAction) => {
if (!this.ctx.canvas3d) return; if (!this.ctx.canvas3d) return;
this.ctx.canvas3d.mark(loci, action) this.ctx.canvas3d.mark({ ...loci, repr: undefined }, action)
} }
register() { register() {
this.ctx.lociSelections.addProvider(this.lociMarkProvider) this.ctx.lociSelections.addProvider(this.lociMarkProvider)
this.subscribeObservable(this.ctx.events.state.object.created, ({ ref, state }) => {
const cell = this.ctx.state.dataState.cells.get(ref)
if (cell && SO.isRepresentation3D(cell.obj)) {
this.spine.current = cell
const so = this.spine.getRootOfType(SO.Molecule.Structure)
if (so) {
const loci = this.ctx.helpers.structureSelection.get(so.data)
this.lociMarkProvider({ loci }, MarkerAction.Select)
}
}
});
} }
unregister() { unregister() {
this.ctx.lociSelections.removeProvider(this.lociMarkProvider) this.ctx.lociSelections.removeProvider(this.lociMarkProvider)
} }
constructor(ctx: PluginContext, params: {}) {
super(ctx, params)
this.spine = new StateTreeSpine.Impl(ctx.state.dataState.cells)
}
}, },
display: { name: 'Select Loci on Canvas' } display: { name: 'Select Loci on Canvas' }
}); });
......
...@@ -15,6 +15,7 @@ import { OrderedSet, Interval } from '../../mol-data/int'; ...@@ -15,6 +15,7 @@ import { OrderedSet, Interval } from '../../mol-data/int';
import { Loci } from '../../mol-model/loci'; import { Loci } from '../../mol-model/loci';
import { applyMarkerAction, MarkerAction } from '../../mol-util/marker-action'; import { applyMarkerAction, MarkerAction } from '../../mol-util/marker-action';
import { ButtonsType, ModifiersKeys, getButtons, getModifiers } from '../../mol-util/input/input-observer'; import { ButtonsType, ModifiersKeys, getButtons, getModifiers } from '../../mol-util/input/input-observer';
import { ValueBox } from '../../mol-util';
function getStructureSeqKey(structureSeq: StructureSeq) { function getStructureSeqKey(structureSeq: StructureSeq) {
const { structure, seq } = structureSeq const { structure, seq } = structureSeq
...@@ -42,6 +43,20 @@ export class SequenceView extends PluginUIComponent<{ }, { }> { ...@@ -42,6 +43,20 @@ export class SequenceView extends PluginUIComponent<{ }, { }> {
}); });
} }
private getMarkerArray(structureSeq: StructureSeq): Uint8Array {
const { structure, seq } = structureSeq
const key = getStructureSeqKey(structureSeq)
let markerArray = this.markerArrays.get(key)
if (!markerArray) {
markerArray = new Uint8Array(seq.sequence.sequence.length)
this.markerArrays.set(key, markerArray)
}
const loci = this.plugin.helpers.structureSelection.get(structure)
markerArray.fill(0)
markResidue(loci, structureSeq, markerArray, MarkerAction.Select)
return markerArray
}
private getStructure() { private getStructure() {
const so = this.spine && this.spine.getRootOfType(SO.Molecule.Structure) const so = this.spine && this.spine.getRootOfType(SO.Molecule.Structure)
return so && so.data return so && so.data
...@@ -57,12 +72,7 @@ export class SequenceView extends PluginUIComponent<{ }, { }> { ...@@ -57,12 +72,7 @@ export class SequenceView extends PluginUIComponent<{ }, { }> {
return <div className='msp-sequence'> return <div className='msp-sequence'>
{seqs.map((seq, i) => { {seqs.map((seq, i) => {
const structureSeq = { structure, seq } const structureSeq = { structure, seq }
const key = getStructureSeqKey(structureSeq) const markerArray = this.getMarkerArray(structureSeq)
let markerArray = this.markerArrays.get(key)
if (!markerArray) {
markerArray = new Uint8Array(seq.sequence.sequence.length)
this.markerArrays.set(key, markerArray)
}
return <EntitySequence key={i} structureSeq={structureSeq} markerArray={markerArray} /> return <EntitySequence key={i} structureSeq={structureSeq} markerArray={markerArray} />
})} })}
</div>; </div>;
...@@ -138,31 +148,29 @@ function markResidue(loci: Loci, structureSeq: StructureSeq, array: Uint8Array, ...@@ -138,31 +148,29 @@ function markResidue(loci: Loci, structureSeq: StructureSeq, array: Uint8Array,
} }
type EntitySequenceProps = { structureSeq: StructureSeq, markerArray: Uint8Array } type EntitySequenceProps = { structureSeq: StructureSeq, markerArray: Uint8Array }
type EntitySequenceState = { markerData: { array: Uint8Array } } type EntitySequenceState = { markerData: ValueBox<Uint8Array> }
// TODO: this is really inefficient and should be done using a canvas. // TODO: this is really inefficient and should be done using a canvas.
class EntitySequence extends PluginUIComponent<EntitySequenceProps, EntitySequenceState> { class EntitySequence extends PluginUIComponent<EntitySequenceProps, EntitySequenceState> {
state = { state = {
markerData: { array: new Uint8Array(this.props.markerArray) } markerData: ValueBox.create(new Uint8Array(this.props.markerArray))
} }
private lociHighlightProvider = (loci: Interaction.Loci, action: MarkerAction) => { private lociHighlightProvider = (loci: Interaction.Loci, action: MarkerAction) => {
const { array } = this.state.markerData; const { markerData } = this.state;
const { structureSeq } = this.props const changed = markResidue(loci.loci, this.props.structureSeq, markerData.value, action)
const changed = markResidue(loci.loci, structureSeq, array, action) if (changed) this.setState({ markerData: ValueBox.withValue(markerData, markerData.value) })
if (changed) this.setState({ markerData: { array } })
} }
private lociSelectionProvider = (loci: Interaction.Loci, action: MarkerAction) => { private lociSelectionProvider = (loci: Interaction.Loci, action: MarkerAction) => {
const { array } = this.state.markerData; const { markerData } = this.state;
const { structureSeq } = this.props const changed = markResidue(loci.loci, this.props.structureSeq, markerData.value, action)
const changed = markResidue(loci.loci, structureSeq, array, action) if (changed) this.setState({ markerData: ValueBox.withValue(markerData, markerData.value) })
if (changed) this.setState({ markerData: { array } })
} }
static getDerivedStateFromProps(nextProps: EntitySequenceProps, prevState: EntitySequenceState) { static getDerivedStateFromProps(nextProps: EntitySequenceProps, prevState: EntitySequenceState): EntitySequenceState | null {
if (prevState.markerData.array !== nextProps.markerArray) { if (prevState.markerData.value !== nextProps.markerArray) {
return { markerData: { array: nextProps.markerArray } } return { markerData: ValueBox.create(nextProps.markerArray) }
} }
return null return null
} }
...@@ -218,7 +226,7 @@ class EntitySequence extends PluginUIComponent<EntitySequenceProps, EntitySequen ...@@ -218,7 +226,7 @@ class EntitySequence extends PluginUIComponent<EntitySequenceProps, EntitySequen
const elems: JSX.Element[] = []; const elems: JSX.Element[] = [];
for (let i = 0, _i = sequence.length; i < _i; i++) { for (let i = 0, _i = sequence.length; i < _i; i++) {
elems[elems.length] = <Residue seqId={offset + i + 1} letter={sequence[i]} parent={this} marker={markerData.array[i]} key={i} />; elems[elems.length] = <Residue seqId={offset + i + 1} letter={sequence[i]} parent={this} marker={markerData.value[i]} key={i} />;
} }
return <div return <div
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment