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

wip, seconadry structure export, updated sec. struct data model

parent 53c12b74
No related branches found
No related tags found
No related merge requests found
...@@ -13,8 +13,6 @@ import { Model, Structure, Element, Unit, Format, StructureProperties } from 'mo ...@@ -13,8 +13,6 @@ import { Model, Structure, Element, Unit, Format, StructureProperties } from 'mo
// import { Run, Progress } from 'mol-task' // import { Run, Progress } from 'mol-task'
import { OrderedSet } from 'mol-data/int'; import { OrderedSet } from 'mol-data/int';
import { openCif, downloadCif } from './helpers'; import { openCif, downloadCif } from './helpers';
import { BitFlags } from 'mol-util';
import { SecondaryStructureType } from 'mol-model/structure/model/types';
import { UnitRings } from 'mol-model/structure/structure/unit/rings'; import { UnitRings } from 'mol-model/structure/structure/unit/rings';
import { Vec3 } from 'mol-math/linear-algebra'; import { Vec3 } from 'mol-math/linear-algebra';
...@@ -51,21 +49,17 @@ export function residueLabel(model: Model, rI: number) { ...@@ -51,21 +49,17 @@ export function residueLabel(model: Model, rI: number) {
export function printSecStructure(model: Model) { export function printSecStructure(model: Model) {
console.log('\nSecondary Structure\n============='); console.log('\nSecondary Structure\n=============');
const { residues } = model.atomicHierarchy; const { residues } = model.atomicHierarchy;
const { type, key } = model.properties.secondaryStructure; const { index, elements } = model.properties.secondaryStructure;
const count = residues._rowCount; const count = residues._rowCount;
let rI = 0; let rI = 0;
while (rI < count) { while (rI < count) {
let start = rI; let start = rI;
while (rI < count && key[start] === key[rI]) rI++; while (rI < count && index[start] === index[rI]) rI++;
rI--; rI--;
if (BitFlags.has(type[start], SecondaryStructureType.Flag.Beta)) { const e = elements[index[start]];
console.log(`Sheet: ${residueLabel(model, start)} - ${residueLabel(model, rI)} (key ${key[start]})`); if (e.kind !== 'none') console.log(`${e.kind}: ${residueLabel(model, start)} - ${residueLabel(model, rI)}`);
} else if (BitFlags.has(type[start], SecondaryStructureType.Flag.Helix)) {
console.log(`Helix: ${residueLabel(model, start)} - ${residueLabel(model, rI)} (key ${key[start]})`);
}
rI++; rI++;
} }
} }
......
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
...@@ -33,17 +33,29 @@ function _entity({ model, structure }: CifExportContext): CifCategory { ...@@ -33,17 +33,29 @@ function _entity({ model, structure }: CifExportContext): CifCategory {
} }
const Categories = [ const Categories = [
// Basics
copy_mmCif_category('entry'), copy_mmCif_category('entry'),
copy_mmCif_category('exptl'), copy_mmCif_category('exptl'),
_entity, _entity,
// Symmetry
copy_mmCif_category('cell'), copy_mmCif_category('cell'),
copy_mmCif_category('symmetry'), copy_mmCif_category('symmetry'),
// Assemblies
copy_mmCif_category('pdbx_struct_assembly'), copy_mmCif_category('pdbx_struct_assembly'),
copy_mmCif_category('pdbx_struct_assembly_gen'), copy_mmCif_category('pdbx_struct_assembly_gen'),
copy_mmCif_category('pdbx_struct_oper_list'), copy_mmCif_category('pdbx_struct_oper_list'),
// Secondary structure
// TODO
// Misc
// TODO: filter for actual present residues? // TODO: filter for actual present residues?
copy_mmCif_category('chem_comp'), copy_mmCif_category('chem_comp'),
copy_mmCif_category('atom_sites'), copy_mmCif_category('atom_sites'),
// Atoms
_atom_site _atom_site
]; ];
......
...@@ -13,13 +13,15 @@ import { Column } from 'mol-data/db'; ...@@ -13,13 +13,15 @@ import { Column } from 'mol-data/db';
export function getSecondaryStructureMmCif(data: mmCIF_Database, hierarchy: AtomicHierarchy): SecondaryStructure { export function getSecondaryStructureMmCif(data: mmCIF_Database, hierarchy: AtomicHierarchy): SecondaryStructure {
const map: SecondaryStructureMap = new Map(); const map: SecondaryStructureMap = new Map();
addHelices(data.struct_conf, map); const elements: SecondaryStructure.Element[] = [{ kind: 'none' }];
addHelices(data.struct_conf, map, elements);
// must add Helices 1st because of 'key' value assignment. // must add Helices 1st because of 'key' value assignment.
addSheets(data.struct_sheet_range, map, data.struct_conf._rowCount); addSheets(data.struct_sheet_range, map, data.struct_conf._rowCount, elements);
const secStruct: SecondaryStructureData = { const secStruct: SecondaryStructureData = {
type: new Int32Array(hierarchy.residues._rowCount) as any, type: new Int32Array(hierarchy.residues._rowCount) as any,
key: new Int32Array(hierarchy.residues._rowCount) as any index: new Int32Array(hierarchy.residues._rowCount) as any,
elements
}; };
if (map.size > 0) assignSecondaryStructureRanges(hierarchy, map, secStruct); if (map.size > 0) assignSecondaryStructureRanges(hierarchy, map, secStruct);
...@@ -32,34 +34,45 @@ type SecondaryStructureEntry = { ...@@ -32,34 +34,45 @@ type SecondaryStructureEntry = {
endSeqNumber: number, endSeqNumber: number,
endInsCode: string | null, endInsCode: string | null,
type: SecondaryStructureType, type: SecondaryStructureType,
key: number index: number
} }
type SecondaryStructureMap = Map<string, Map<number, SecondaryStructureEntry>> type SecondaryStructureMap = Map<string, Map<number, SecondaryStructureEntry>>
type SecondaryStructureData = { type: SecondaryStructureType[], key: number[] } type SecondaryStructureData = { type: SecondaryStructureType[], index: number[], elements: SecondaryStructure.Element[] }
function addHelices(cat: mmCIF['struct_conf'], map: SecondaryStructureMap) { function addHelices(cat: mmCIF['struct_conf'], map: SecondaryStructureMap, elements: SecondaryStructure.Element[]) {
if (!cat._rowCount) return; if (!cat._rowCount) return;
const { beg_label_asym_id, beg_label_seq_id, pdbx_beg_PDB_ins_code } = cat; const { beg_label_asym_id, beg_label_seq_id, pdbx_beg_PDB_ins_code } = cat;
const { end_label_seq_id, pdbx_end_PDB_ins_code } = cat; const { end_label_seq_id, pdbx_end_PDB_ins_code } = cat;
const { pdbx_PDB_helix_class, conf_type_id } = cat; const { pdbx_PDB_helix_class, conf_type_id, details } = cat;
for (let i = 0, _i = cat._rowCount; i < _i; i++) { for (let i = 0, _i = cat._rowCount; i < _i; i++) {
const type = pdbx_PDB_helix_class.valueKind(i) === Column.ValueKind.Present const type = SecondaryStructureType.create(pdbx_PDB_helix_class.valueKind(i) === Column.ValueKind.Present
? SecondaryStructureType.SecondaryStructurePdb[pdbx_PDB_helix_class.value(i)] ? SecondaryStructureType.SecondaryStructurePdb[pdbx_PDB_helix_class.value(i)]
: conf_type_id.valueKind(i) === Column.ValueKind.Present : conf_type_id.valueKind(i) === Column.ValueKind.Present
? SecondaryStructureType.SecondaryStructureMmcif[conf_type_id.value(i)] ? SecondaryStructureType.SecondaryStructureMmcif[conf_type_id.value(i)]
: SecondaryStructureType.Flag.NA : SecondaryStructureType.Flag.NA);
const element: SecondaryStructure.Helix = {
kind: 'helix',
flags: type,
type_id: pdbx_PDB_helix_class.valueKind(i) === Column.ValueKind.Present
? pdbx_PDB_helix_class.value(i) : conf_type_id.valueKind(i) === Column.ValueKind.Present
? conf_type_id.value(i) : 'HELIX_P',
helix_class: pdbx_PDB_helix_class.value(i),
details: details.valueKind(i) === Column.ValueKind.Present ? details.value(i) : void 0
};
const entry: SecondaryStructureEntry = { const entry: SecondaryStructureEntry = {
startSeqNumber: beg_label_seq_id.value(i), startSeqNumber: beg_label_seq_id.value(i),
startInsCode: pdbx_beg_PDB_ins_code.value(i), startInsCode: pdbx_beg_PDB_ins_code.value(i),
endSeqNumber: end_label_seq_id.value(i), endSeqNumber: end_label_seq_id.value(i),
endInsCode: pdbx_end_PDB_ins_code.value(i), endInsCode: pdbx_end_PDB_ins_code.value(i),
type: SecondaryStructureType.create(type), type,
key: i + 1 index: elements.length
}; };
elements[elements.length] = element;
const asymId = beg_label_asym_id.value(i)!; const asymId = beg_label_asym_id.value(i)!;
if (map.has(asymId)) { if (map.has(asymId)) {
map.get(asymId)!.set(entry.startSeqNumber, entry); map.get(asymId)!.set(entry.startSeqNumber, entry);
...@@ -69,7 +82,7 @@ function addHelices(cat: mmCIF['struct_conf'], map: SecondaryStructureMap) { ...@@ -69,7 +82,7 @@ function addHelices(cat: mmCIF['struct_conf'], map: SecondaryStructureMap) {
} }
} }
function addSheets(cat: mmCIF['struct_sheet_range'], map: SecondaryStructureMap, sheetCount: number) { function addSheets(cat: mmCIF['struct_sheet_range'], map: SecondaryStructureMap, sheetCount: number, elements: SecondaryStructure.Element[]) {
if (!cat._rowCount) return; if (!cat._rowCount) return;
const { beg_label_asym_id, beg_label_seq_id, pdbx_beg_PDB_ins_code } = cat; const { beg_label_asym_id, beg_label_seq_id, pdbx_beg_PDB_ins_code } = cat;
...@@ -88,15 +101,25 @@ function addSheets(cat: mmCIF['struct_sheet_range'], map: SecondaryStructureMap, ...@@ -88,15 +101,25 @@ function addSheets(cat: mmCIF['struct_sheet_range'], map: SecondaryStructureMap,
sheet_id_key.set(id, key); sheet_id_key.set(id, key);
} }
const type = SecondaryStructureType.create(SecondaryStructureType.Flag.Beta | SecondaryStructureType.Flag.BetaSheet);
const element: SecondaryStructure.Sheet = {
kind: 'sheet',
flags: type,
sheet_id: id,
symmetry: void 0
}
const entry: SecondaryStructureEntry = { const entry: SecondaryStructureEntry = {
startSeqNumber: beg_label_seq_id.value(i), startSeqNumber: beg_label_seq_id.value(i),
startInsCode: pdbx_beg_PDB_ins_code.value(i), startInsCode: pdbx_beg_PDB_ins_code.value(i),
endSeqNumber: end_label_seq_id.value(i), endSeqNumber: end_label_seq_id.value(i),
endInsCode: pdbx_end_PDB_ins_code.value(i), endInsCode: pdbx_end_PDB_ins_code.value(i),
type: SecondaryStructureType.create(SecondaryStructureType.Flag.Beta | SecondaryStructureType.Flag.BetaSheet), type,
key index: elements.length
}; };
elements[elements.length] = element;
const asymId = beg_label_asym_id.value(i)!; const asymId = beg_label_asym_id.value(i)!;
if (map.has(asymId)) { if (map.has(asymId)) {
map.get(asymId)!.set(entry.startSeqNumber, entry); map.get(asymId)!.set(entry.startSeqNumber, entry);
...@@ -110,14 +133,13 @@ function addSheets(cat: mmCIF['struct_sheet_range'], map: SecondaryStructureMap, ...@@ -110,14 +133,13 @@ function addSheets(cat: mmCIF['struct_sheet_range'], map: SecondaryStructureMap,
function assignSecondaryStructureEntry(hierarchy: AtomicHierarchy, entry: SecondaryStructureEntry, resStart: number, resEnd: number, data: SecondaryStructureData) { function assignSecondaryStructureEntry(hierarchy: AtomicHierarchy, entry: SecondaryStructureEntry, resStart: number, resEnd: number, data: SecondaryStructureData) {
const { label_seq_id, pdbx_PDB_ins_code } = hierarchy.residues; const { label_seq_id, pdbx_PDB_ins_code } = hierarchy.residues;
const { endSeqNumber, endInsCode, type, key } = entry; const { endSeqNumber, endInsCode, index, type } = entry;
let rI = resStart; let rI = resStart;
while (rI < resEnd) { while (rI < resEnd) {
const seqNumber = label_seq_id.value(rI); const seqNumber = label_seq_id.value(rI);
data.type[rI] = type; data.type[rI] = type;
data.key[rI] = key; data.index[rI] = index;
if ((seqNumber > endSeqNumber) || if ((seqNumber > endSeqNumber) ||
(seqNumber === endSeqNumber && pdbx_PDB_ins_code.value(rI) === endInsCode)) { (seqNumber === endSeqNumber && pdbx_PDB_ins_code.value(rI) === endInsCode)) {
......
...@@ -8,10 +8,35 @@ import { SecondaryStructureType } from '../types'; ...@@ -8,10 +8,35 @@ import { SecondaryStructureType } from '../types';
/** Secondary structure "indexed" by residues. */ /** Secondary structure "indexed" by residues. */
interface SecondaryStructure { interface SecondaryStructure {
// assign flags to each residue
readonly type: ArrayLike<SecondaryStructureType>, readonly type: ArrayLike<SecondaryStructureType>,
/** unique value for each "element". This is because single sheet is speficied by multiple records. */
readonly key: ArrayLike<number> /** index into the elements array */
readonly index: ArrayLike<number>,
/** indexed by key */
readonly elements: ReadonlyArray<SecondaryStructure.Element>
}
namespace SecondaryStructure {
export type Element = None | Helix | Sheet
export interface None {
kind: 'none'
}
export interface Helix {
kind: 'helix',
flags: SecondaryStructureType,
type_id: string, // TODO: use aliased type?
helix_class: string,
details?: string
}
export interface Sheet {
kind: 'sheet',
flags: SecondaryStructureType,
sheet_id: string,
symmetry?: string
}
} }
export { SecondaryStructure } export { SecondaryStructure }
\ No newline at end of file
...@@ -59,7 +59,7 @@ const residue = { ...@@ -59,7 +59,7 @@ const residue = {
// Properties // Properties
secondary_structure_type: Element.property(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.properties.secondaryStructure.type[l.unit.residueIndex[l.element]]), secondary_structure_type: Element.property(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.properties.secondaryStructure.type[l.unit.residueIndex[l.element]]),
secondary_structure_key: Element.property(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.properties.secondaryStructure.key[l.unit.residueIndex[l.element]]), secondary_structure_key: Element.property(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.properties.secondaryStructure.index[l.unit.residueIndex[l.element]]),
} }
const chain = { const chain = {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment