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

sequence view, better handling of missing residues, full structure loci

parent f300e524
No related branches found
No related tags found
No related merge requests found
......@@ -37,6 +37,7 @@ namespace OrderedSet {
export const union: <T extends number = number>(a: OrderedSet<T>, b: OrderedSet<T>) => OrderedSet<T> = Base.union as any;
export const intersect: <T extends number = number>(a: OrderedSet<T>, b: OrderedSet<T>) => OrderedSet<T> = Base.intersect as any;
/** Returns elements of `a` that are not in `b`, i.e `a` - `b` */
export const subtract: <T extends number = number>(a: OrderedSet<T>, b: OrderedSet<T>) => OrderedSet<T> = Base.subtract as any;
export const findPredecessorIndex: <T extends number = number>(set: OrderedSet<T>, x: number) => number = Base.findPredecessorIndex as any;
......
......@@ -12,9 +12,9 @@ namespace SortedArray {
export const ofUnsortedArray: <T extends number = number>(xs: ArrayLike<number>) => SortedArray<T> = Impl.ofUnsortedArray as any;
export const ofSingleton: <T extends number = number>(v: number) => SortedArray<T> = Impl.ofSingleton as any;
export const ofSortedArray: <T extends number = number>(xs: ArrayLike<number>) => SortedArray<T> = Impl.ofSortedArray as any;
// create sorted array [min, max] (it DOES contain the max value)
/** create sorted array [min, max] (it DOES contain the max value) */
export const ofRange: <T extends number = number>(min: T, max: T) => SortedArray<T> = Impl.ofRange as any;
// create sorted array [min, max) (it does NOT contain the max value)
/** create sorted array [min, max) (it does NOT contain the max value) */
export const ofBounds: <T extends number = number>(min: T, max: T) => SortedArray<T> = (min, max) => Impl.ofRange(min, max - 1) as any;
export const is: <T extends number = number>(v: any) => v is SortedArray<T> = Impl.is as any;
......@@ -23,9 +23,9 @@ namespace SortedArray {
export const indexOf: <T extends number = number>(array: SortedArray<T>, x: T) => number = Impl.indexOf as any;
export const indexOfInInterval: <T extends number = number>(array: SortedArray<T>, x: number, bounds: Interval) => number = Impl.indexOfInInterval as any;
// array[0]
/** Returns `array[0]` */
export const start: <T extends number = number>(array: SortedArray<T>) => T = Impl.start as any;
// array[array.length - 1] + 1
/** Returns `array[array.length - 1] + 1` */
export const end: <T extends number = number>(array: SortedArray<T>) => T = Impl.end as any;
export const min: <T extends number = number>(array: SortedArray<T>) => T = Impl.min as any;
export const max: <T extends number = number>(array: SortedArray<T>) => T = Impl.max as any;
......
......@@ -6,7 +6,7 @@
import { StructureSelection, StructureQuery, Structure, Queries, StructureProperties as SP, StructureElement, Unit } from '../../../mol-model/structure';
import { SequenceWrapper } from './util';
import { OrderedSet, Interval } from '../../../mol-data/int';
import { OrderedSet, Interval, SortedArray } from '../../../mol-data/int';
import { Loci } from '../../../mol-model/loci';
import { Sequence } from '../../../mol-model/sequence';
import { MissingResidues } from '../../../mol-model/structure/model/properties/common';
......@@ -18,27 +18,28 @@ export class PolymerSequenceWrapper extends SequenceWrapper<StructureUnit> {
private readonly location: StructureElement
private readonly sequence: Sequence
private readonly missing: MissingResidues
private readonly observed: OrderedSet // sequences indices
private readonly modelNum: number
private readonly asymId: string
seqId(i: number) {
return this.sequence.offset + i + 1
seqId(seqIdx: number) {
return this.sequence.offset + seqIdx + 1
}
residueLabel(i: number) {
return this.sequence.sequence[i]
residueLabel(seqIdx: number) {
return this.sequence.sequence[seqIdx]
}
residueColor(i: number) {
return this.missing.has(this.modelNum, this.asymId, this.seqId(i))
residueColor(seqIdx: number) {
return this.missing.has(this.modelNum, this.asymId, this.seqId(seqIdx))
? ColorNames.grey
: ColorNames.black
}
eachResidue(loci: Loci, apply: (interval: Interval) => boolean) {
eachResidue(loci: Loci, apply: (set: OrderedSet) => boolean) {
let changed = false
const { structure, unit } = this.data
if (!StructureElement.isLoci(loci)) return false
if (!Structure.areParentsEquivalent(loci.structure, structure)) return false
if (StructureElement.isLoci(loci)) {
if (!Structure.areParentsEqual(loci.structure, structure)) return false
const { location } = this
for (const e of loci.elements) {
......@@ -54,11 +55,16 @@ export class PolymerSequenceWrapper extends SequenceWrapper<StructureUnit> {
if (rI !== rIprev) {
if (SP.unit.id(location) !== unit.id) return
if (apply(getSeqIdInterval(location))) changed = true
if (apply(getSeqIndices(location))) changed = true
rIprev = rI
}
})
}
} else if (Structure.isLoci(loci)) {
if (!Structure.areParentsEqual(loci.structure, structure)) return false
if (apply(this.observed)) changed = true
}
return changed
}
......@@ -70,7 +76,8 @@ export class PolymerSequenceWrapper extends SequenceWrapper<StructureUnit> {
constructor(data: StructureUnit) {
const l = StructureElement.create(data.unit, data.unit.elements[0])
const sequence = data.unit.model.sequence.byEntityKey[SP.entity.key(l)].sequence
const markerArray = new Uint8Array(sequence.sequence.length)
const length = sequence.sequence.length
const markerArray = new Uint8Array(length)
super(data, markerArray, sequence.sequence.length)
......@@ -80,6 +87,12 @@ export class PolymerSequenceWrapper extends SequenceWrapper<StructureUnit> {
this.modelNum = data.unit.model.modelNum
this.asymId = SP.chain.label_asym_id(l)
const missing: number[] = []
for (let i = 0; i < length; ++i) {
if (this.missing.has(this.modelNum, this.asymId, this.seqId(i))) missing.push(i)
}
this.observed = OrderedSet.subtract(Interval.ofBounds(0, length), SortedArray.ofSortedArray(missing))
}
}
......@@ -101,8 +114,7 @@ function createResidueQuery(unitId: number, label_seq_id: number) {
});
}
/** Zero-indexed */
function getSeqIdInterval(location: StructureElement): Interval {
function getSeqIndices(location: StructureElement): Interval {
const { unit, element } = location
const { model } = unit
switch (unit.kind) {
......
......@@ -4,7 +4,7 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { Interval } from '../../../mol-data/int';
import { OrderedSet } from '../../../mol-data/int';
import { Loci } from '../../../mol-model/loci';
import { MarkerAction, applyMarkerAction } from '../../../mol-util/marker-action';
import { StructureElement } from '../../../mol-model/structure';
......@@ -13,16 +13,16 @@ import { Color } from '../../../mol-util/color';
export { SequenceWrapper }
abstract class SequenceWrapper<D> {
abstract seqId(i: number): number
abstract residueLabel(i: number): string
abstract residueColor(i: number): Color
abstract seqId(seqIdx: number): number
abstract residueLabel(seqIdx: number): string
abstract residueColor(seqIdx: number): Color
abstract eachResidue(loci: Loci, apply: (interval: Interval) => boolean): boolean
abstract eachResidue(loci: Loci, apply: (set: OrderedSet) => boolean): boolean
abstract getLoci(seqId: number): StructureElement.Loci
markResidue(loci: Loci, action: MarkerAction) {
return this.eachResidue(loci, (i: Interval) => {
return applyMarkerAction(this.markerArray, i, action)
return this.eachResidue(loci, (set: OrderedSet) => {
return applyMarkerAction(this.markerArray, set, action)
})
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment