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