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

Support modified residues in Sequence

parent a81db69e
No related branches found
No related tags found
No related merge requests found
......@@ -42,7 +42,8 @@ class EntitySequence extends React.Component<{ ctx: Context, seq: StructureSeque
const query = createQuery(this.props.seq.entityId, seqId);
const loci = Selection.toLoci(await query(this.props.structure, SyncRuntimeContext));
InteractivityEvents.HighlightElementLoci.dispatch(this.props.ctx, loci);
if (loci.elements.length === 0) InteractivityEvents.HighlightElementLoci.dispatch(this.props.ctx, void 0);
else InteractivityEvents.HighlightElementLoci.dispatch(this.props.ctx, loci);
}
......
......@@ -7,10 +7,12 @@
export type AminoAlphabet =
| 'H' | 'R' | 'K' | 'I' | 'F' | 'L' | 'W' | 'A' | 'M' | 'P' | 'C' | 'N' | 'V' | 'G' | 'S' | 'Q' | 'Y' | 'D' | 'E' | 'T' | 'U' | 'O'
| 'X' /** = Unknown */
| '-' /** = Gap */
export type NuclecicAlphabet =
| 'A' | 'C' | 'G' | 'T' | 'U'
| 'X' /** = Unknown */
| '-' /** = Gap */
// from NGL
const ProteinOneLetterCodes: { [name: string]: AminoAlphabet } = {
......
......@@ -29,7 +29,7 @@ namespace Sequence {
export interface Protein extends Base<Kind.Protein, AminoAlphabet> { }
export interface RNA extends Base<Kind.RNA, NuclecicAlphabet> { }
export interface DNA extends Base<Kind.DNA, NuclecicAlphabet> { }
export interface Generic extends Base<Kind.Generic, 'X'> { }
export interface Generic extends Base<Kind.Generic, 'X' | '-'> { }
export function create(kind: Kind, sequence: string, offset: number = 0): Sequence {
return { kind: kind as any, sequence: sequence as any, offset };
......@@ -49,11 +49,21 @@ namespace Sequence {
return { kind: Kind.Generic, code: (v: string) => 'X' };
}
export function ofResidueNames(residueName: Column<string>, seqId: Column<number>): Sequence {
function modCode(code: (name: string) => string, map: Map<string, string>): (name: string) => string {
return n => {
const ret = code(n);
if (ret !== 'X' || !map.has(n)) return ret;
return code(map.get(n)!);
}
}
export function ofResidueNames(residueName: Column<string>, seqId: Column<number>, modifiedMap?: Map<string, string>): Sequence {
if (seqId.rowCount === 0) throw new Error('cannot be empty');
const { kind, code } = determineKind(residueName);
return new Impl(kind, residueName, seqId, code) as Sequence;
if (!modifiedMap || modifiedMap.size === 0) return new Impl(kind, residueName, seqId, code) as Sequence;
return new Impl(kind, residueName, seqId, modCode(code, modifiedMap)) as Sequence;
}
class Impl implements Base<any, any> {
......@@ -83,7 +93,7 @@ namespace Sequence {
const count = maxSeqId - minSeqId + 1;
const sequenceArray = new Array(maxSeqId + 1);
for (let i = 0; i < count; i++) {
sequenceArray[i] = 'X';
sequenceArray[i] = '-';
}
for (let i = 0, _i = this.seqId.rowCount; i < _i; i++) {
......
......@@ -159,6 +159,8 @@ function createModel(format: mmCIF_Format, bounds: Interval, previous?: Model):
? format.data.entry.id.value(0)
: format.data._name;
const modifiedResidueNameMap = modResMap(format);
return {
id: UUID.create(),
label,
......@@ -166,13 +168,13 @@ function createModel(format: mmCIF_Format, bounds: Interval, previous?: Model):
modelNum: format.data.atom_site.pdbx_PDB_model_num.value(Interval.start(bounds)),
entities,
atomicHierarchy,
sequence: getSequence(format.data, entities, atomicHierarchy),
sequence: getSequence(format.data, entities, atomicHierarchy, modifiedResidueNameMap),
atomicConformation: getConformation(format, bounds),
coarseHierarchy: coarse.hierarchy,
coarseConformation: coarse.conformation,
properties: {
secondaryStructure: getSecondaryStructureMmCif(format.data, atomicHierarchy),
modifiedResidueNameMap: modResMap(format)
modifiedResidueNameMap
},
symmetry: getSymmetry(format)
};
......
......@@ -21,8 +21,8 @@ import { Sequence } from '../../../../sequence';
// corresponding ATOM_SITE entries should reflect this
// heterogeneity.
export function getSequence(cif: mmCIF, entities: Entities, hierarchy: AtomicHierarchy): StructureSequence {
if (!cif.entity_poly_seq._rowCount) return StructureSequence.fromAtomicHierarchy(entities, hierarchy);
export function getSequence(cif: mmCIF, entities: Entities, hierarchy: AtomicHierarchy, modResMap: Map<string, string>): StructureSequence {
if (!cif.entity_poly_seq._rowCount) return StructureSequence.fromAtomicHierarchy(entities, hierarchy, modResMap);
const { entity_id, num, mon_id } = cif.entity_poly_seq;
......@@ -45,7 +45,7 @@ export function getSequence(cif: mmCIF, entities: Entities, hierarchy: AtomicHie
entityId: id,
compId: _compId,
num: _num,
sequence: Sequence.ofResidueNames(_compId, _num)
sequence: Sequence.ofResidueNames(_compId, _num, modResMap)
};
sequences.push(byEntityKey[entityKey]);
......
......@@ -23,7 +23,7 @@ namespace StructureSequence {
readonly sequence: Sequence
}
export function fromAtomicHierarchy(entities: Entities, hierarchy: AtomicHierarchy): StructureSequence {
export function fromAtomicHierarchy(entities: Entities, hierarchy: AtomicHierarchy, modResMap?: Map<string, string>): StructureSequence {
const { label_comp_id, label_seq_id } = hierarchy.residues
const { chainSegments, residueSegments } = hierarchy
......@@ -52,7 +52,7 @@ namespace StructureSequence {
entityId: entities.data.id.value(entityKey),
compId,
num,
sequence: Sequence.ofResidueNames(compId, num)
sequence: Sequence.ofResidueNames(compId, num, modResMap)
};
sequences.push(byEntityKey[entityKey]);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment