Skip to content
Snippets Groups Projects
Commit f740ba95 authored by Michal Malý's avatar Michal Malý
Browse files

ReDNATCO plugin stage 5

parent c9d8235a
No related branches found
No related tags found
No related merge requests found
export namespace Commands {
export type Type = 'select-step'|'switch-model';
export type SelectStep = {
type: 'select-step';
stepName: string;
referenceNtC: string;
references: ('sel'|'prev'|'next')[];
}
export function SelectStep(stepName: string, referenceNtC = '', references = ['sel', 'prev', 'next']): SelectStep {
return {
type: 'select-step',
stepName,
referenceNtC,
references: references as ('sel'|'prev'|'next')[],
};
}
export type SwitchModel = { type: 'switch-model', model: number };
export function SwitchModel(model: number): SwitchModel { return { type: 'switch-model', model }; }
export type Cmd = SelectStep|SwitchModel;
}
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<script type="text/javascript" src="./molstar.js"></script> <script type="text/javascript" src="./molstar.js"></script>
<script> <script>
async function loadStructure() { async function loadStructure() {
const resp = await fetch('./3vok_v32C35A23.cif'); const resp = await fetch('./1bna_v41C35A23.cif');
const data = await resp.text(); const data = await resp.text();
molstar.ReDNATCOMspApi.loadStructure(data); molstar.ReDNATCOMspApi.loadStructure(data);
......
This diff is collapsed.
...@@ -21,6 +21,25 @@ export namespace Step { ...@@ -21,6 +21,25 @@ export namespace Step {
return `${compId}${altId ? `.${altId}` : ''}_${seqId}${insCode ? `.${insCode}` : '' }`; return `${compId}${altId ? `.${altId}` : ''}_${seqId}${insCode ? `.${insCode}` : '' }`;
} }
function residueDescription(a: string, b: string): { comp: string, altId?: string, resNo: number, insCode?: string }|undefined {
const toksA = a.split('.');
const toksB = b.split('.');
if (toksA.length > 2 || toksB.length > 2)
return void 0;
const resNo = parseInt(toksB[0]);
if (isNaN(resNo))
return void 0;
return {
comp: toksA[0],
altId: toksA.length === 2 ? toksA[1] : void 0,
resNo,
insCode: toksB.length === 2 ? toksB[1] : void 0,
};
}
export function describe(loci: StructureElement.Loci) { export function describe(loci: StructureElement.Loci) {
const es = loci.elements[0]; // Ignore multiple selections const es = loci.elements[0]; // Ignore multiple selections
...@@ -62,6 +81,96 @@ export namespace Step { ...@@ -62,6 +81,96 @@ export namespace Step {
return description; return description;
} }
export function fromName(name: string) {
const description: Description = {
model: -1,
entryId: '',
chain: '',
resNo1: -1,
comp1: '',
altId1: void 0,
insCode1: void 0,
resNo2: -1,
comp2: '',
altId2: void 0,
insCode2: void 0,
};
const toks = name.split('_');
if (toks.length !== 6) {
console.error(`String ${name} is not valid step name`);
return void 0;
}
const entryTok = toks[0];
const chain = toks[1];
const res1TokA = toks[2];
const res1TokB = toks[3];
const res2TokA = toks[4];
const res2TokB = toks[5];
const ets = entryTok.split('-');
if (ets.length === 1) {
description.entryId = ets[0];
description.model = 1;
} else if (ets.length === 2) {
description.entryId = ets[0];
const m = parseInt(ets[1].slice(1));
if (isNaN(m)) {
console.error(`String ${name} is not valid step name`);
return void 0;
}
description.model = m;
} else {
console.error(`String ${name} is not valid step name`);
return void 0;
}
if (chain.length !== 1) {
console.error(`String ${name} is not valid step name`);
return void 0;
} else
description.chain = chain;
const res1 = residueDescription(res1TokA, res1TokB);
const res2 = residueDescription(res2TokA, res2TokB);
if (!res1 || !res2) {
console.error(`String ${name} is not valid step name`);
return void 0;
}
description.resNo1 = res1.resNo;
description.comp1 = res1.comp;
description.altId1 = res1.altId;
description.insCode1 = res1.insCode;
description.resNo2 = res2.resNo;
description.comp2 = res2.comp;
description.altId2 = res2.altId;
description.insCode2 = res2.insCode;
return description;
}
export function is(loci: StructureElement.Loci) {
const e = loci.elements[0];
const loc = Location.create(loci.structure, e.unit, e.unit.elements[OrderedSet.getAt(e.indices, 0)]);
const resNo1 = StructureProperties.residue.label_seq_id(loc);
const asymId = StructureProperties.chain.label_asym_id(loc);
for (let idx = 1; idx < OrderedSet.size(e.indices); idx++) {
loc.element = e.unit.elements[OrderedSet.getAt(e.indices, idx)];
const resNo = StructureProperties.residue.label_seq_id(loc);
if (resNo !== resNo1 + 1)
continue;
const _asymId = StructureProperties.chain.label_asym_id(loc);
if (_asymId === asymId)
return true;
}
return false;
}
export function name(description: Description, multipleModels: boolean) { export function name(description: Description, multipleModels: boolean) {
const res1 = nameResidue(description.resNo1, description.comp1, description.altId1, description.insCode1); const res1 = nameResidue(description.resNo1, description.comp1, description.altId1, description.insCode1);
const res2 = nameResidue(description.resNo2, description.comp2, description.altId2, description.insCode2); const res2 = nameResidue(description.resNo2, description.comp2, description.altId2, description.insCode2);
......
import { Segmentation } from '../../mol-data/int';
import { OrderedSet } from '../../mol-data/int/ordered-set';
import { EmptyLoci, Loci } from '../../mol-model/loci';
import { ResidueIndex, Structure, StructureElement, StructureProperties, Unit } from '../../mol-model/structure';
import { Location } from '../../mol-model/structure/structure/element/location';
export namespace Traverse {
type Residue = Segmentation.Segment<ResidueIndex>;
export function residueAltId(structure: Structure, unit: Unit, residue: Residue) {
const loc = Location.create(structure, unit);
for (let rI = residue.start; rI < residue.end; rI++) {
loc.element = OrderedSet.getAt(unit.elements, rI);
const altId = StructureProperties.atom.label_alt_id(loc);
if (altId !== '')
return altId;
}
return void 0;
}
export function findResidue(asymId: string, seqId: number, altId: string|undefined, loci: StructureElement.Loci, source: 'label'|'auth') {
for (const e of loci.elements) {
const loc = Location.create(loci.structure, e.unit);
const getAsymId = source === 'label' ? StructureProperties.chain.label_asym_id : StructureProperties.chain.auth_asym_id;
const getSeqId = source === 'label' ? StructureProperties.residue.label_seq_id : StructureProperties.residue.auth_seq_id;
// Walk the entire unit and look for the requested residue
const chainIt = Segmentation.transientSegments(e.unit.model.atomicHierarchy.chainAtomSegments, e.unit.elements);
const residueIt = Segmentation.transientSegments(e.unit.model.atomicHierarchy.residueAtomSegments, e.unit.elements);
const elemIndex = (idx: number) => OrderedSet.getAt(e.unit.elements, idx);
while (chainIt.hasNext) {
const chain = chainIt.move();
loc.element = elemIndex(chain.start);
const _asymId = getAsymId(loc);
if (_asymId !== asymId)
continue; // Wrong chain, skip it
residueIt.setSegment(chain);
while (residueIt.hasNext) {
const residue = residueIt.move();
loc.element = elemIndex(residue.start);
const _seqId = getSeqId(loc);
if (_seqId === seqId) {
if (altId) {
const _altId = residueAltId(loci.structure, e.unit, residue);
if (_altId && _altId !== altId)
continue;
}
const start = residue.start as StructureElement.UnitIndex;
const end = residue.end as StructureElement.UnitIndex;
return StructureElement.Loci(
loci.structure,
[{ unit: e.unit, indices: OrderedSet.ofBounds(start, end) }]
);
}
}
}
}
return EmptyLoci;
}
export function residue(shift: number, altId: string|undefined, cursor: StructureElement.Loci) {
for (const e of cursor.elements) {
const entireUnit = cursor.structure.units[e.unit.id];
const loc = Location.create(cursor.structure, e.unit);
loc.element = e.unit.elements[OrderedSet.getAt(e.indices, 0)];
const asymId = StructureProperties.chain.label_asym_id(loc);
const seqId = StructureProperties.residue.label_seq_id(loc);
const from = 0 as StructureElement.UnitIndex;
const to = entireUnit.elements.length as StructureElement.UnitIndex;
const loci = findResidue(
asymId,
seqId + shift,
altId,
StructureElement.Loci(cursor.structure, [{ unit: entireUnit, indices: OrderedSet.ofBounds(from, to) }]),
'label'
);
if (!Loci.isEmpty(loci))
return loci;
}
return EmptyLoci;
}
}
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