Explorar o código

added ElementSequenceWrapper & ChainSequenceWrapper

Alexander Rose %!s(int64=5) %!d(string=hai) anos
pai
achega
4aecf4e0b4

+ 23 - 7
src/mol-plugin/ui/sequence.tsx

@@ -18,8 +18,10 @@ import { ParameterControls } from './controls/parameters';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { HeteroSequenceWrapper } from './sequence/hetero';
 import { State, StateSelection } from '../../mol-state';
+import { ChainSequenceWrapper } from './sequence/chain';
+import { ElementSequenceWrapper } from './sequence/element';
 
-const MaxDisplaySequenceLength = 10000
+const MaxDisplaySequenceLength = 5000
 
 function opKey(l: StructureElement.Location) {
     const ids = SP.unit.pdbx_struct_oper_list_ids(l)
@@ -45,19 +47,33 @@ function getSequenceWrapper(state: SequenceViewState, structureSelection: Struct
         if (unit.invariantId !== invariantUnitId) continue
         if (opKey(l) !== operatorKey) continue
 
+        const data = { structure, unit }
+
+        let sw: SequenceWrapper<any>
         if (unit.polymerElements.length) {
             const l = StructureElement.Location.create(unit, unit.elements[0])
             const entitySeq = unit.model.sequence.byEntityKey[SP.entity.key(l)]
             // check if entity sequence is available
-            if (!entitySeq) return 'No sequence available'
-            // check if sequence is too long
-            if (entitySeq.sequence.length > MaxDisplaySequenceLength) {
-                return `Sequence too long (${entitySeq.sequence.length} residues)`
+            if (entitySeq && entitySeq.sequence.length <= MaxDisplaySequenceLength) {
+                sw = new PolymerSequenceWrapper(data)
+            } else {
+                if (Unit.isAtomic(unit) || unit.polymerElements.length > MaxDisplaySequenceLength) {
+                    sw = new ChainSequenceWrapper(data)
+                } else {
+                    sw = new ElementSequenceWrapper(data)
+                }
+            }
+        } else if (Unit.isAtomic(unit)) {
+            if (unit.residueCount > MaxDisplaySequenceLength) {
+                sw = new ChainSequenceWrapper(data)
+            } else {
+                sw = new HeteroSequenceWrapper(data)
             }
+        } else {
+            console.warn('should not happen, expecting coarse units to be polymeric')
+            sw = new ChainSequenceWrapper(data)
         }
 
-        const Wrapper = unit.polymerElements.length ? PolymerSequenceWrapper : HeteroSequenceWrapper
-        const sw = new Wrapper({ structure, unit })
         sw.markResidue(structureSelection.get(structure), MarkerAction.Select)
         return sw
     }

+ 69 - 0
src/mol-plugin/ui/sequence/chain.ts

@@ -0,0 +1,69 @@
+/**
+ * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { Structure, StructureElement, StructureProperties } from '../../../mol-model/structure';
+import { SequenceWrapper, StructureUnit } from './wrapper';
+import { OrderedSet, Interval } from '../../../mol-data/int';
+import { Loci } from '../../../mol-model/loci';
+import { ColorNames } from '../../../mol-util/color/names';
+
+export class ChainSequenceWrapper extends SequenceWrapper<StructureUnit> {
+    private label: string
+    private indices: Interval<StructureElement.UnitIndex>
+    private loci: StructureElement.Loci
+
+    residueLabel(seqIdx: number) {
+        return this.label
+    }
+    residueColor(seqIdx: number) {
+        return ColorNames.black
+    }
+
+    eachResidue(loci: Loci, apply: (set: OrderedSet) => boolean) {
+        let changed = false
+        const { structure, unit } = this.data
+        if (StructureElement.Loci.is(loci)) {
+            if (!Structure.areRootsEquivalent(loci.structure, structure)) return false
+            loci = StructureElement.Loci.remap(loci, structure)
+
+            for (const e of loci.elements) {
+                if (e.unit.id === unit.id) {
+                    if (OrderedSet.isSubset(this.indices, e.indices)) {
+                        if (apply(Interval.ofSingleton(0))) changed = true
+                    }
+                }
+            }
+        } else if (Structure.isLoci(loci)) {
+            if (!Structure.areRootsEquivalent(loci.structure, structure)) return false
+
+            if (apply(Interval.ofSingleton(0))) changed = true
+        }
+        return changed
+    }
+
+    getLoci(seqIdx: number) {
+        return this.loci
+    }
+
+    constructor(data: StructureUnit) {
+        const counts: string[] = []
+        const l = StructureElement.Location.create(data.unit, data.unit.elements[0])
+        const entitySeq = data.unit.model.sequence.byEntityKey[StructureProperties.entity.key(l)]
+        if (entitySeq) counts.push(`${entitySeq.sequence.length} residues`)
+        counts.push(`${data.unit.elements.length} elements`)
+
+        const length = 1
+        const markerArray = new Uint8Array(length)
+
+        super(data, markerArray, length)
+
+        this.label = `Whole Unit (${counts.join(', ')})`
+        this.indices = Interval.ofBounds(0, data.unit.elements.length)
+        this.loci = StructureElement.Loci(this.data.structure, [{
+            unit: this.data.unit, indices: this.indices
+        }])
+    }
+}

+ 61 - 0
src/mol-plugin/ui/sequence/element.ts

@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { Structure, StructureElement } from '../../../mol-model/structure';
+import { SequenceWrapper, StructureUnit } from './wrapper';
+import { OrderedSet, Interval } from '../../../mol-data/int';
+import { Loci } from '../../../mol-model/loci';
+import { ColorNames } from '../../../mol-util/color/names';
+
+export class ElementSequenceWrapper extends SequenceWrapper<StructureUnit> {
+    private indices: Interval<StructureElement.UnitIndex>
+
+    residueLabel(seqIdx: number) {
+        return 'X'
+    }
+    residueColor(seqIdx: number) {
+        return ColorNames.black
+    }
+
+    eachResidue(loci: Loci, apply: (set: OrderedSet) => boolean) {
+        let changed = false
+        const { structure, unit } = this.data
+        if (StructureElement.Loci.is(loci)) {
+            if (!Structure.areRootsEquivalent(loci.structure, structure)) return false
+            loci = StructureElement.Loci.remap(loci, structure)
+
+            for (const e of loci.elements) {
+                if (e.unit.id === unit.id) {
+                    if (OrderedSet.isSubset(this.indices, e.indices)) {
+                        if (apply(e.indices)) changed = true
+                    }
+                }
+            }
+        } else if (Structure.isLoci(loci)) {
+            if (!Structure.areRootsEquivalent(loci.structure, structure)) return false
+
+            if (apply(this.indices)) changed = true
+        }
+        return changed
+    }
+
+    getLoci(seqIdx: number) {
+        const elements: StructureElement.Loci['elements'][0][] = [{
+            unit: this.data.unit,
+            indices: Interval.ofSingleton(seqIdx)
+        }]
+        return StructureElement.Loci(this.data.structure, elements)
+    }
+
+    constructor(data: StructureUnit) {
+        const length = data.unit.elements.length
+        const markerArray = new Uint8Array(length)
+
+        super(data, markerArray, length)
+
+        this.indices = Interval.ofBounds(0, length)
+    }
+}