Skip to content
Snippets Groups Projects
Commit 4acc3662 authored by David Sehnal's avatar David Sehnal
Browse files

mol-plugin: show sequence offsets in UI (wip)

parent e5504137
No related branches found
No related tags found
No related merge requests found
...@@ -17,6 +17,7 @@ import { sortArray, hashFnv32a, hash2 } from '../../../../mol-data/util'; ...@@ -17,6 +17,7 @@ import { sortArray, hashFnv32a, hash2 } from '../../../../mol-data/util';
import Expression from '../../../../mol-script/language/expression'; import Expression from '../../../../mol-script/language/expression';
import { ElementIndex } from '../../model'; import { ElementIndex } from '../../model';
import { UnitIndex } from './element'; import { UnitIndex } from './element';
import { Location } from './location';
/** Represents multiple element index locations */ /** Represents multiple element index locations */
export interface Loci { export interface Loci {
...@@ -78,6 +79,18 @@ export namespace Loci { ...@@ -78,6 +79,18 @@ export namespace Loci {
return Loci(structure, []); return Loci(structure, []);
} }
export function getFirstLocation(loci: Loci, e?: Location): Location | undefined {
if (isEmpty(loci)) return void 0;
const unit = loci.elements[0].unit;
const element = unit.elements[OrderedSet.getAt(loci.elements[0].indices, 0)];
if (e) {
e.unit = loci.elements[0].unit;
e.element = element;
return e;
}
return Location.create(unit, element);
}
export function toStructure(loci: Loci): Structure { export function toStructure(loci: Loci): Structure {
const units: Unit[] = [] const units: Unit[] = []
for (const e of loci.elements) { for (const e of loci.elements) {
......
...@@ -30,4 +30,13 @@ ...@@ -30,4 +30,13 @@
span { span {
cursor: pointer; cursor: pointer;
} }
.msp-sequence-marker {
color: $sequence-marker-color;
// vertical-align: middle;
text-decoration: underline;
padding: 0 0 0 1ch;
word-break: keep-all;
cursor: default;
}
} }
\ No newline at end of file
...@@ -80,4 +80,5 @@ $entity-tag-color: color-lower-contrast($font-color, 20%); ...@@ -80,4 +80,5 @@ $entity-tag-color: color-lower-contrast($font-color, 20%);
// sequence // sequence
$sequence-background: $default-background; $sequence-background: $default-background;
$sequence-marker-color: $hover-font-color;
$sequence-select-width: 300px; $sequence-select-width: 300px;
\ No newline at end of file
...@@ -11,12 +11,14 @@ import { Interactivity } from '../../util/interactivity'; ...@@ -11,12 +11,14 @@ import { Interactivity } from '../../util/interactivity';
import { MarkerAction } from '../../../mol-util/marker-action'; import { 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 { SequenceWrapper } from './wrapper'; import { SequenceWrapper } from './wrapper';
import { StructureElement } from '../../../mol-model/structure'; import { StructureElement, StructureProperties } from '../../../mol-model/structure';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { debounceTime } from 'rxjs/operators'; import { debounceTime } from 'rxjs/operators';
import { Color } from '../../../mol-util/color'; import { Color } from '../../../mol-util/color';
type SequenceProps = { sequenceWrapper: SequenceWrapper.Any } type SequenceProps = { sequenceWrapper: SequenceWrapper.Any, hideMarkers?: boolean }
const SequenceMarkerPeriod = 50
// TODO: this is somewhat inefficient and should be done using a canvas. // TODO: this is somewhat inefficient and should be done using a canvas.
export class Sequence<P extends SequenceProps> extends PluginUIComponent<P> { export class Sequence<P extends SequenceProps> extends PluginUIComponent<P> {
...@@ -101,10 +103,16 @@ export class Sequence<P extends SequenceProps> extends PluginUIComponent<P> { ...@@ -101,10 +103,16 @@ export class Sequence<P extends SequenceProps> extends PluginUIComponent<P> {
if (!this.parentDiv.current) return; if (!this.parentDiv.current) return;
const xs = this.parentDiv.current.children; const xs = this.parentDiv.current.children;
const { markerArray } = this.props.sequenceWrapper; const { markerArray } = this.props.sequenceWrapper;
const markers = !this.props.hideMarkers;
let o = 0;
for (let i = 0, _i = markerArray.length; i < _i; i++) { for (let i = 0, _i = markerArray.length; i < _i; i++) {
const span = xs[i] as HTMLSpanElement; const span = xs[o] as HTMLSpanElement;
if (!span) continue; if (!span) return;
o++;
if (markers && i > 0 && i % SequenceMarkerPeriod === 0) {
o++;
}
const backgroundColor = this.getBackgroundColor(markerArray[i]); const backgroundColor = this.getBackgroundColor(markerArray[i]);
if (span.style.backgroundColor !== backgroundColor) span.style.backgroundColor = backgroundColor; if (span.style.backgroundColor !== backgroundColor) span.style.backgroundColor = backgroundColor;
...@@ -147,9 +155,21 @@ export class Sequence<P extends SequenceProps> extends PluginUIComponent<P> { ...@@ -147,9 +155,21 @@ export class Sequence<P extends SequenceProps> extends PluginUIComponent<P> {
const sw = this.props.sequenceWrapper const sw = this.props.sequenceWrapper
const elems: JSX.Element[] = []; const elems: JSX.Element[] = [];
const markers = !this.props.hideMarkers;
const location = StructureElement.Location.create();
for (let i = 0, il = sw.length; i < il; ++i) { for (let i = 0, il = sw.length; i < il; ++i) {
elems[elems.length] = this.residue(i, sw.residueLabel(i), sw.markerArray[i], sw.residueColor(i)); elems[elems.length] = this.residue(i, sw.residueLabel(i), sw.markerArray[i], sw.residueColor(i));
// TODO: add seq idx markers every N residues? Would need to modify "updateMarker" if (markers && i > 0 && i % SequenceMarkerPeriod === 0) {
if (i === sw.length - 1) break;
// TODO: is this correct way to show the offset?
const l = StructureElement.Loci.getFirstLocation(sw.getLoci(i + 1), location);
if (l) {
elems[elems.length] = <span key={`marker-${i}`} className='msp-sequence-marker'>{StructureProperties.residue.auth_seq_id(l)}</span>
} else {
// do not show the marker if the seq id is not known.
elems[elems.length] = <span key={`marker-${i}`} className='msp-sequence-marker'></span>
}
}
} }
// calling .updateMarker here is neccesary to ensure existing // calling .updateMarker here is neccesary to ensure existing
......
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