Browse Source

wip mol-model-parsers

David Sehnal 6 years ago
parent
commit
612910704c
28 changed files with 45 additions and 1603 deletions
  1. 4 2
      src/apps/structure-info/model.ts
  2. 1 1
      src/mol-io/reader/_spec/csv.spec.ts
  3. 0 0
      src/mol-model-parsers/structure/gro.ts
  4. 9 12
      src/mol-model-parsers/structure/mmcif.ts
  5. 1 2
      src/mol-model/structure/model.ts
  6. 0 25
      src/mol-model/structure/model/format.ts
  7. 0 311
      src/mol-model/structure/model/formats/mmcif.ts
  8. 0 151
      src/mol-model/structure/model/formats/mmcif/assembly.ts
  9. 0 107
      src/mol-model/structure/model/formats/mmcif/atomic.ts
  10. 0 9
      src/mol-model/structure/model/formats/mmcif/bonds.ts
  11. 0 164
      src/mol-model/structure/model/formats/mmcif/bonds/comp.ts
  12. 0 249
      src/mol-model/structure/model/formats/mmcif/bonds/struct_conn.ts
  13. 0 102
      src/mol-model/structure/model/formats/mmcif/ihm.ts
  14. 0 8
      src/mol-model/structure/model/formats/mmcif/pair-restraint.ts
  15. 0 107
      src/mol-model/structure/model/formats/mmcif/pair-restraints/cross-links.ts
  16. 0 26
      src/mol-model/structure/model/formats/mmcif/pair-restraints/predicted-contacts.ts
  17. 0 175
      src/mol-model/structure/model/formats/mmcif/secondary-structure.ts
  18. 0 55
      src/mol-model/structure/model/formats/mmcif/sequence.ts
  19. 0 43
      src/mol-model/structure/model/formats/mmcif/sort.ts
  20. 0 26
      src/mol-model/structure/model/formats/mmcif/util.ts
  21. 9 15
      src/mol-model/structure/model/model.ts
  22. 1 1
      src/mol-model/structure/structure/unit/links/inter-compute.ts
  23. 1 1
      src/mol-model/structure/structure/unit/links/intra-compute.ts
  24. 1 1
      src/mol-model/structure/structure/unit/pair-restraints/extract-cross-links.ts
  25. 4 2
      src/mol-plugin/state/transforms/model.ts
  26. 5 3
      src/perf-tests/lookup3d.ts
  27. 5 3
      src/perf-tests/structure.ts
  28. 4 2
      src/servers/model/server/structure-wrapper.ts

+ 4 - 2
src/apps/structure-info/model.ts

@@ -9,11 +9,13 @@ import * as argparse from 'argparse'
 require('util.promisify').shim();
 
 import { CifFrame } from 'mol-io/reader/cif'
-import { Model, Structure, StructureElement, Unit, Format, StructureProperties, UnitRing } from 'mol-model/structure'
+import { Model, Structure, StructureElement, Unit, StructureProperties, UnitRing } from 'mol-model/structure'
 // import { Run, Progress } from 'mol-task'
 import { OrderedSet } from 'mol-data/int';
 import { openCif, downloadCif } from './helpers';
 import { Vec3 } from 'mol-math/linear-algebra';
+import { parse_mmCIF } from 'mol-model-parsers/structure/mmcif';
+import { ModelFormat } from 'mol-model-parsers/structure/format';
 
 
 async function downloadFromPdb(pdb: string) {
@@ -198,7 +200,7 @@ export function printModelStats(models: ReadonlyArray<Model>) {
 }
 
 export async function getModelsAndStructure(frame: CifFrame) {
-    const models = await Model.create(Format.mmCIF(frame)).run();
+    const models = await parse_mmCIF(ModelFormat.mmCIF(frame)).run();
     const structure = Structure.ofModel(models[0]);
     return { models, structure };
 }

+ 1 - 1
src/mol-io/reader/_spec/csv.spec.ts

@@ -62,7 +62,7 @@ describe('csv reader', () => {
     });
 
     it('tabs', async () => {
-        const parsed = await Csv(tabString, { delimiter: '\t' }).run();;
+        const parsed = await Csv(tabString, { delimiter: '\t' }).run();
         if (parsed.isError) return;
         const csvFile = parsed.result;
 

+ 0 - 0
src/mol-model/structure/model/formats/gro.ts → src/mol-model-parsers/structure/gro.ts


+ 9 - 12
src/mol-model-parsers/structure/mmcif.ts

@@ -27,9 +27,16 @@ import { ChemicalComponent, ChemicalComponentMap } from 'mol-model/structure/mod
 import { ComponentType, getMoleculeType, MoleculeType } from 'mol-model/structure/model/types';
 import { ModelFormat } from './format';
 import { SaccharideComponentMap, SaccharideComponent, SaccharidesSnfgMap, SaccharideCompIdMap, UnknownSaccharideComponent } from 'mol-model/structure/structure/carbohydrates/constants';
-
 import mmCIF_Format = ModelFormat.mmCIF
 
+export function parse_mmCIF(format: mmCIF_Format): Task<Model.Trajectory> {
+    const formatData = getFormatData(format)
+    return Task.create('Create mmCIF Model', async ctx => {
+        const isIHM = format.data.ihm_model_list._rowCount > 0;
+        return isIHM ? await readIHM(ctx, format, formatData) : await readStandard(ctx, format, formatData);
+    });
+}
+
 type AtomSite = mmCIF_Database['atom_site']
 
 function getSymmetry(format: mmCIF_Format): ModelSymmetry {
@@ -298,14 +305,4 @@ async function readIHM(ctx: RuntimeContext, format: mmCIF_Format, formatData: Fo
     }
 
     return models;
-}
-
-function buildModels(format: mmCIF_Format): Task<ReadonlyArray<Model>> {
-    const formatData = getFormatData(format)
-    return Task.create('Create mmCIF Model', async ctx => {
-        const isIHM = format.data.ihm_model_list._rowCount > 0;
-        return isIHM ? await readIHM(ctx, format, formatData) : await readStandard(ctx, format, formatData);
-    });
-}
-
-export default buildModels;
+}

+ 1 - 2
src/mol-model/structure/model.ts

@@ -6,10 +6,9 @@
 
 import { Model } from './model/model'
 import * as Types from './model/types'
-import Format from './model/format'
 import { ModelSymmetry } from './model/properties/symmetry'
 import StructureSequence from './model/properties/sequence'
 
 export * from './model/properties/custom'
 export * from './model/indexing'
-export { Model, Types, Format, ModelSymmetry, StructureSequence }
+export { Model, Types, ModelSymmetry, StructureSequence }

+ 0 - 25
src/mol-model/structure/model/format.ts

@@ -1,25 +0,0 @@
-/**
- * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-// import { File as GroFile } from 'mol-io/reader/gro/schema'
-import { mmCIF_Database } from 'mol-io/reader/cif/schema/mmcif'
-import CIF, { CifFrame } from 'mol-io/reader/cif';
-import { PdbFile } from 'mol-io/reader/pdb/schema';
-
-type Format =
-    // | Format.gro
-    | Format.mmCIF
-
-namespace Format {
-    // export interface gro { kind: 'gro', data: GroFile }
-    export interface mmCIF { kind: 'mmCIF', data: mmCIF_Database, frame: CifFrame }
-    export function mmCIF(frame: CifFrame, data?: mmCIF_Database): mmCIF { return { kind: 'mmCIF', data: data || CIF.schema.mmCIF(frame), frame }; }
-
-    export interface PDB { kind: 'PDB', data: PdbFile }
-    export function PDB(data: PdbFile) { return { kind: 'PDB', data }; }
-}
-
-export default Format

+ 0 - 311
src/mol-model/structure/model/formats/mmcif.ts

@@ -1,311 +0,0 @@
-/**
- * Copyright (c) 2017-2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { Column, Table } from 'mol-data/db';
-import { mmCIF_Database, mmCIF_Schema } from 'mol-io/reader/cif/schema/mmcif';
-import { Spacegroup, SpacegroupCell, SymmetryOperator } from 'mol-math/geometry';
-import { Tensor, Vec3 } from 'mol-math/linear-algebra';
-import { Task, RuntimeContext } from 'mol-task';
-import UUID from 'mol-util/uuid';
-import Format from '../format';
-import { Model } from '../model';
-import { Entities } from '../properties/common';
-import { CustomProperties } from '../properties/custom';
-import { ModelSymmetry } from '../properties/symmetry';
-import { createAssemblies } from './mmcif/assembly';
-import { getAtomicHierarchyAndConformation } from './mmcif/atomic';
-import { ComponentBond } from './mmcif/bonds';
-import { getIHMCoarse, EmptyIHMCoarse, IHMData } from './mmcif/ihm';
-import { getSecondaryStructureMmCif } from './mmcif/secondary-structure';
-import { getSequence } from './mmcif/sequence';
-import { sortAtomSite } from './mmcif/sort';
-import { StructConn } from './mmcif/bonds/struct_conn';
-import { ChemicalComponent, ChemicalComponentMap } from '../properties/chemical-component';
-import { ComponentType, getMoleculeType, MoleculeType } from '../types';
-
-import mmCIF_Format = Format.mmCIF
-import { SaccharideComponentMap, SaccharideComponent, SaccharidesSnfgMap, SaccharideCompIdMap, UnknownSaccharideComponent } from 'mol-model/structure/structure/carbohydrates/constants';
-
-type AtomSite = mmCIF_Database['atom_site']
-
-function getSymmetry(format: mmCIF_Format): ModelSymmetry {
-    const assemblies = createAssemblies(format);
-    const spacegroup = getSpacegroup(format);
-    const isNonStandardCrytalFrame = checkNonStandardCrystalFrame(format, spacegroup);
-    return { assemblies, spacegroup, isNonStandardCrytalFrame, ncsOperators: getNcsOperators(format) };
-}
-
-function checkNonStandardCrystalFrame(format: mmCIF_Format, spacegroup: Spacegroup) {
-    const { atom_sites } = format.data;
-    if (atom_sites._rowCount === 0) return false;
-    // TODO: parse atom_sites transform and check if it corresponds to the toFractional matrix
-    return false;
-}
-
-function getSpacegroup(format: mmCIF_Format): Spacegroup {
-    const { symmetry, cell } = format.data;
-    if (symmetry._rowCount === 0 || cell._rowCount === 0) return Spacegroup.ZeroP1;
-    const groupName = symmetry['space_group_name_H-M'].value(0);
-    const spaceCell = SpacegroupCell.create(groupName,
-        Vec3.create(cell.length_a.value(0), cell.length_b.value(0), cell.length_c.value(0)),
-        Vec3.scale(Vec3.zero(), Vec3.create(cell.angle_alpha.value(0), cell.angle_beta.value(0), cell.angle_gamma.value(0)), Math.PI / 180));
-
-    return Spacegroup.create(spaceCell);
-}
-
-function getNcsOperators(format: mmCIF_Format) {
-    const { struct_ncs_oper } = format.data;
-    if (struct_ncs_oper._rowCount === 0) return void 0;
-    const { id, matrix, vector } = struct_ncs_oper;
-
-    const matrixSpace = mmCIF_Schema.struct_ncs_oper.matrix.space, vectorSpace = mmCIF_Schema.struct_ncs_oper.vector.space;
-
-    const opers: SymmetryOperator[] = [];
-    for (let i = 0; i < struct_ncs_oper._rowCount; i++) {
-        const m = Tensor.toMat3(matrixSpace, matrix.value(i));
-        const v = Tensor.toVec3(vectorSpace, vector.value(i));
-        if (!SymmetryOperator.checkIfRotationAndTranslation(m, v)) continue;
-        opers[opers.length] = SymmetryOperator.ofRotationAndOffset(`ncs_${id.value(i)}`, m, v);
-    }
-    return opers;
-}
-function getModifiedResidueNameMap(format: mmCIF_Format): Model['properties']['modifiedResidues'] {
-    const data = format.data.pdbx_struct_mod_residue;
-    const parentId = new Map<string, string>();
-    const details = new Map<string, string>();
-    const comp_id = data.label_comp_id.isDefined ? data.label_comp_id : data.auth_comp_id;
-    const parent_id = data.parent_comp_id, details_data = data.details;
-
-    for (let i = 0; i < data._rowCount; i++) {
-        const id = comp_id.value(i);
-        parentId.set(id, parent_id.value(i));
-        details.set(id, details_data.value(i));
-    }
-
-    return { parentId, details };
-}
-
-function getChemicalComponentMap(format: mmCIF_Format): ChemicalComponentMap {
-    const map = new Map<string, ChemicalComponent>();
-    const { id, type, name, pdbx_synonyms, formula, formula_weight } = format.data.chem_comp
-    for (let i = 0, il = id.rowCount; i < il; ++i) {
-        const _id = id.value(i)
-        const _type = type.value(i)
-        const cc: ChemicalComponent = {
-            id: _id,
-            type: ComponentType[_type],
-            moleculeType: getMoleculeType(_type, _id),
-            name: name.value(i),
-            synonyms: pdbx_synonyms.value(i),
-            formula: formula.value(i),
-            formulaWeight: formula_weight.value(i),
-        }
-        map.set(_id, cc)
-    }
-    return map
-}
-
-function getSaccharideComponentMap(format: mmCIF_Format): SaccharideComponentMap {
-    const map = new Map<string, SaccharideComponent>();
-    const { pdbx_chem_comp_identifier } = format.data
-    if (pdbx_chem_comp_identifier._rowCount > 0) {
-        const { comp_id, type, identifier } = pdbx_chem_comp_identifier
-        for (let i = 0, il = pdbx_chem_comp_identifier._rowCount; i < il; ++i) {
-            if (type.value(i) === 'SNFG CARB SYMBOL') {
-                const snfgName = identifier.value(i)
-                const saccharideComp = SaccharidesSnfgMap.get(snfgName)
-                if (saccharideComp) {
-                    map.set(comp_id.value(i), saccharideComp)
-                } else {
-                    console.warn(`Unknown SNFG name '${snfgName}'`)
-                }
-            }
-        }
-    } else if (format.data.chem_comp._rowCount > 0) {
-        const { id, type  } = format.data.chem_comp
-        for (let i = 0, il = id.rowCount; i < il; ++i) {
-            const _id = id.value(i)
-            const _type = type.value(i)
-            if (SaccharideCompIdMap.has(_id)) {
-                map.set(_id, SaccharideCompIdMap.get(_id)!)
-            } else if (!map.has(_id) && getMoleculeType(_type, _id) === MoleculeType.saccharide) {
-                map.set(_id, UnknownSaccharideComponent)
-            }
-        }
-    } else {
-        // TODO check if present in format.data.atom_site.label_comp_id
-        SaccharideCompIdMap.forEach((v, k) => map.set(k, v))
-    }
-    return map
-}
-
-export interface FormatData {
-    modifiedResidues: Model['properties']['modifiedResidues']
-    chemicalComponentMap: Model['properties']['chemicalComponentMap']
-    saccharideComponentMap: Model['properties']['saccharideComponentMap']
-}
-
-function getFormatData(format: mmCIF_Format): FormatData {
-    return {
-        modifiedResidues: getModifiedResidueNameMap(format),
-        chemicalComponentMap: getChemicalComponentMap(format),
-        saccharideComponentMap: getSaccharideComponentMap(format)
-    }
-}
-
-function createStandardModel(format: mmCIF_Format, atom_site: AtomSite, entities: Entities, formatData: FormatData, previous?: Model): Model {
-    const atomic = getAtomicHierarchyAndConformation(format, atom_site, entities, formatData, previous);
-    if (previous && atomic.sameAsPrevious) {
-        return {
-            ...previous,
-            id: UUID.create22(),
-            modelNum: atom_site.pdbx_PDB_model_num.value(0),
-            atomicConformation: atomic.conformation,
-            _dynamicPropertyData: Object.create(null)
-        };
-    }
-
-    const coarse = EmptyIHMCoarse;
-    const label = format.data.entry.id.valueKind(0) === Column.ValueKind.Present
-        ? format.data.entry.id.value(0)
-        : format.data._name;
-
-    return {
-        id: UUID.create22(),
-        label,
-        sourceData: format,
-        modelNum: atom_site.pdbx_PDB_model_num.value(0),
-        entities,
-        symmetry: getSymmetry(format),
-        sequence: getSequence(format.data, entities, atomic.hierarchy, formatData.modifiedResidues.parentId),
-        atomicHierarchy: atomic.hierarchy,
-        atomicConformation: atomic.conformation,
-        coarseHierarchy: coarse.hierarchy,
-        coarseConformation: coarse.conformation,
-        properties: {
-            secondaryStructure: getSecondaryStructureMmCif(format.data, atomic.hierarchy),
-            ...formatData
-        },
-        customProperties: new CustomProperties(),
-        _staticPropertyData: Object.create(null),
-        _dynamicPropertyData: Object.create(null)
-    };
-}
-
-function createModelIHM(format: mmCIF_Format, data: IHMData, formatData: FormatData): Model {
-    const atomic = getAtomicHierarchyAndConformation(format, data.atom_site, data.entities, formatData);
-    const coarse = getIHMCoarse(data, formatData);
-
-    return {
-        id: UUID.create22(),
-        label: data.model_name,
-        sourceData: format,
-        modelNum: data.model_id,
-        entities: data.entities,
-        symmetry: getSymmetry(format),
-        sequence: getSequence(format.data, data.entities, atomic.hierarchy, formatData.modifiedResidues.parentId),
-        atomicHierarchy: atomic.hierarchy,
-        atomicConformation: atomic.conformation,
-        coarseHierarchy: coarse.hierarchy,
-        coarseConformation: coarse.conformation,
-        properties: {
-            secondaryStructure: getSecondaryStructureMmCif(format.data, atomic.hierarchy),
-            ...formatData
-        },
-        customProperties: new CustomProperties(),
-        _staticPropertyData: Object.create(null),
-        _dynamicPropertyData: Object.create(null)
-    };
-}
-
-function attachProps(model: Model) {
-    ComponentBond.attachFromMmCif(model);
-    StructConn.attachFromMmCif(model);
-}
-
-function findModelEnd(num: Column<number>, startIndex: number) {
-    const rowCount = num.rowCount;
-    if (!num.isDefined) return rowCount;
-    let endIndex = startIndex + 1;
-    while (endIndex < rowCount && num.areValuesEqual(startIndex, endIndex)) endIndex++;
-    return endIndex;
-}
-
-async function readStandard(ctx: RuntimeContext, format: mmCIF_Format, formatData: FormatData) {
-    const atomCount = format.data.atom_site._rowCount;
-    const entities: Entities = { data: format.data.entity, getEntityIndex: Column.createIndexer(format.data.entity.id) };
-
-    const models: Model[] = [];
-    let modelStart = 0;
-    while (modelStart < atomCount) {
-        const modelEnd = findModelEnd(format.data.atom_site.pdbx_PDB_model_num, modelStart);
-        const atom_site = await sortAtomSite(ctx, format.data.atom_site, modelStart, modelEnd);
-        const model = createStandardModel(format, atom_site, entities, formatData, models.length > 0 ? models[models.length - 1] : void 0);
-        attachProps(model);
-        models.push(model);
-        modelStart = modelEnd;
-    }
-    return models;
-}
-
-function splitTable<T extends Table<any>>(table: T, col: Column<number>) {
-    const ret = new Map<number, T>()
-    const rowCount = table._rowCount;
-    let modelStart = 0;
-    while (modelStart < rowCount) {
-        const modelEnd = findModelEnd(col, modelStart);
-        const id = col.value(modelStart);
-        const window = Table.window(table, table._schema, modelStart, modelEnd) as T;
-        ret.set(id, window);
-        modelStart = modelEnd;
-    }
-    return ret;
-}
-
-async function readIHM(ctx: RuntimeContext, format: mmCIF_Format, formatData: FormatData) {
-    const { ihm_model_list } = format.data;
-    const entities: Entities = { data: format.data.entity, getEntityIndex: Column.createIndexer(format.data.entity.id) };
-
-    if (!format.data.atom_site.ihm_model_id.isDefined) {
-        throw new Error('expected _atom_site.ihm_model_id to be defined')
-    }
-
-    // TODO: will IHM require sorting or will we trust it?
-    const atom_sites = splitTable(format.data.atom_site, format.data.atom_site.ihm_model_id);
-    const sphere_sites = splitTable(format.data.ihm_sphere_obj_site, format.data.ihm_sphere_obj_site.model_id);
-    const gauss_sites = splitTable(format.data.ihm_gaussian_obj_site, format.data.ihm_gaussian_obj_site.model_id);
-
-    const models: Model[] = [];
-
-    const { model_id, model_name } = ihm_model_list;
-    for (let i = 0; i < ihm_model_list._rowCount; i++) {
-        const id = model_id.value(i);
-        const data: IHMData = {
-            model_id: id,
-            model_name: model_name.value(i),
-            entities: entities,
-            atom_site: atom_sites.has(id) ? atom_sites.get(id)! : Table.window(format.data.atom_site, format.data.atom_site._schema, 0, 0),
-            ihm_sphere_obj_site: sphere_sites.has(id) ? sphere_sites.get(id)! : Table.window(format.data.ihm_sphere_obj_site, format.data.ihm_sphere_obj_site._schema, 0, 0),
-            ihm_gaussian_obj_site: gauss_sites.has(id) ? gauss_sites.get(id)! : Table.window(format.data.ihm_gaussian_obj_site, format.data.ihm_gaussian_obj_site._schema, 0, 0)
-        };
-        const model = createModelIHM(format, data, formatData);
-        attachProps(model);
-        models.push(model);
-    }
-
-    return models;
-}
-
-function buildModels(format: mmCIF_Format): Task<ReadonlyArray<Model>> {
-    const formatData = getFormatData(format)
-    return Task.create('Create mmCIF Model', async ctx => {
-        const isIHM = format.data.ihm_model_list._rowCount > 0;
-        return isIHM ? await readIHM(ctx, format, formatData) : await readStandard(ctx, format, formatData);
-    });
-}
-
-export default buildModels;

+ 0 - 151
src/mol-model/structure/model/formats/mmcif/assembly.ts

@@ -1,151 +0,0 @@
-/**
- * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-import { Mat4, Tensor } from 'mol-math/linear-algebra'
-import { SymmetryOperator } from 'mol-math/geometry/symmetry-operator'
-import Format from '../../format'
-import { Assembly, OperatorGroup, OperatorGroups } from '../../properties/symmetry'
-import { Queries as Q } from '../../../query'
-
-import mmCIF_Format = Format.mmCIF
-import { StructureProperties } from '../../../structure';
-
-export function createAssemblies(format: mmCIF_Format): ReadonlyArray<Assembly> {
-    const { pdbx_struct_assembly } = format.data;
-    if (!pdbx_struct_assembly._rowCount) return [];
-
-    const matrices = getMatrices(format);
-    const assemblies: Assembly[] = [];
-    for (let i = 0; i < pdbx_struct_assembly._rowCount; i++) {
-        assemblies[assemblies.length] = createAssembly(format, i, matrices);
-    }
-    return assemblies;
-}
-
-type Matrices = Map<string, Mat4>
-type Generator = { assemblyId: string, expression: string, asymIds: string[] }
-
-function createAssembly(format: mmCIF_Format, index: number, matrices: Matrices): Assembly {
-    const { pdbx_struct_assembly, pdbx_struct_assembly_gen } = format.data;
-
-    const id = pdbx_struct_assembly.id.value(index);
-    const details = pdbx_struct_assembly.details.value(index);
-    const generators: Generator[] = [];
-
-    const { assembly_id, oper_expression, asym_id_list } = pdbx_struct_assembly_gen;
-
-    for (let i = 0, _i = pdbx_struct_assembly_gen._rowCount; i < _i; i++) {
-        if (assembly_id.value(i) !== id) continue;
-        generators[generators.length] = {
-            assemblyId: id,
-            expression: oper_expression.value(i),
-            asymIds: asym_id_list.value(i)
-        };
-    }
-
-    return Assembly.create(id, details, operatorGroupsProvider(generators, matrices));
-}
-
-function operatorGroupsProvider(generators: Generator[], matrices: Matrices): () => OperatorGroups {
-    return () => {
-        const groups: OperatorGroup[] = [];
-
-        let operatorOffset = 0;
-        for (let i = 0; i < generators.length; i++) {
-            const gen = generators[i];
-            const operatorList = parseOperatorList(gen.expression);
-            const operatorNames = expandOperators(operatorList);
-            const operators = getAssemblyOperators(matrices, operatorNames, operatorOffset, gen.assemblyId);
-            const selector = Q.generators.atoms({ chainTest: Q.pred.and(
-                Q.pred.eq(ctx => StructureProperties.unit.operator_name(ctx.element), SymmetryOperator.DefaultName),
-                Q.pred.inSet(ctx => StructureProperties.chain.label_asym_id(ctx.element), gen.asymIds)
-            )});
-            groups[groups.length] = { selector, operators };
-            operatorOffset += operators.length;
-        }
-
-        return groups;
-    }
-}
-
-function getMatrices({ data }: mmCIF_Format): Matrices {
-    const { pdbx_struct_oper_list } = data;
-    const { id, matrix, vector, _schema } = pdbx_struct_oper_list;
-    const matrices = new Map<string, Mat4>();
-
-    for (let i = 0, _i = pdbx_struct_oper_list._rowCount; i < _i; i++) {
-        const m = Tensor.toMat4(_schema.matrix.space, matrix.value(i));
-        const t = Tensor.toVec3(_schema.vector.space, vector.value(i));
-        Mat4.setTranslation(m, t);
-        Mat4.setValue(m, 3, 3, 1);
-        matrices.set(id.value(i), m);
-    }
-
-    return matrices;
-}
-
-function expandOperators(operatorList: string[][]) {
-    const ops: string[][] = [];
-    const currentOp: string[] = [];
-    for (let i = 0; i < operatorList.length; i++) currentOp[i] = '';
-    expandOperators1(operatorList, ops, operatorList.length - 1, currentOp);
-    return ops;
-}
-
-function expandOperators1(operatorNames: string[][], list: string[][], i: number, current: string[]) {
-    if (i < 0) {
-        list[list.length] = current.slice(0);
-        return;
-    }
-
-    let ops = operatorNames[i], len = ops.length;
-    for (let j = 0; j < len; j++) {
-        current[i] = ops[j];
-        expandOperators1(operatorNames, list, i - 1, current);
-    }
-}
-
-function getAssemblyOperators(matrices: Matrices, operatorNames: string[][], startIndex: number, assemblyId: string) {
-    const operators: SymmetryOperator[] = [];
-
-    let index = startIndex;
-    for (let op of operatorNames) {
-        let m = Mat4.identity();
-        for (let i = 0; i < op.length; i++) {
-            Mat4.mul(m, m, matrices.get(op[i])!);
-        }
-        index++
-        operators[operators.length] = SymmetryOperator.create(`A-${index}`, m, { id: assemblyId, operList: op });
-    }
-
-    return operators;
-}
-
-function parseOperatorList(value: string): string[][] {
-    // '(X0)(1-5)' becomes [['X0'], ['1', '2', '3', '4', '5']]
-    // kudos to Glen van Ginkel.
-
-    const oeRegex = /\(?([^\(\)]+)\)?]*/g, groups: string[] = [], ret: string[][] = [];
-
-    let g: any;
-    while (g = oeRegex.exec(value)) groups[groups.length] = g[1];
-
-    groups.forEach(g => {
-        const group: string[] = [];
-        g.split(',').forEach(e => {
-            const dashIndex = e.indexOf('-');
-            if (dashIndex > 0) {
-                const from = parseInt(e.substring(0, dashIndex)), to = parseInt(e.substr(dashIndex + 1));
-                for (let i = from; i <= to; i++) group[group.length] = i.toString();
-            } else {
-                group[group.length] = e.trim();
-            }
-        });
-        ret[ret.length] = group;
-    });
-
-    return ret;
-}

+ 0 - 107
src/mol-model/structure/model/formats/mmcif/atomic.ts

@@ -1,107 +0,0 @@
-/**
- * Copyright (c) 2017-2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-import { Column, Table } from 'mol-data/db';
-import { Interval, Segmentation } from 'mol-data/int';
-import { mmCIF_Database } from 'mol-io/reader/cif/schema/mmcif';
-import UUID from 'mol-util/uuid';
-import { ElementIndex } from '../../../../structure';
-import Format from '../../format';
-import { Model } from '../../model';
-import { AtomicConformation, AtomicData, AtomicHierarchy, AtomicSegments, AtomsSchema, ChainsSchema, ResiduesSchema } from '../../properties/atomic';
-import { getAtomicIndex } from '../../properties/utils/atomic-index';
-import { ElementSymbol } from '../../types';
-import { Entities } from '../../properties/common';
-
-import mmCIF_Format = Format.mmCIF
-import { getAtomicRanges } from '../../properties/utils/atomic-ranges';
-import { FormatData } from '../mmcif';
-import { getAtomicDerivedData } from '../../properties/utils/atomic-derived';
-
-type AtomSite = mmCIF_Database['atom_site']
-
-function findHierarchyOffsets(atom_site: AtomSite) {
-    if (atom_site._rowCount === 0) return { residues: [], chains: [] };
-
-    const start = 0, end = atom_site._rowCount;
-    const residues = [start as ElementIndex], chains = [start as ElementIndex];
-
-    const { label_entity_id, label_asym_id, label_seq_id, auth_seq_id, pdbx_PDB_ins_code, label_comp_id } = atom_site;
-
-    for (let i = start + 1 as ElementIndex; i < end; i++) {
-        const newChain = !label_entity_id.areValuesEqual(i - 1, i) || !label_asym_id.areValuesEqual(i - 1, i);
-        const newResidue = newChain
-            || !label_seq_id.areValuesEqual(i - 1, i)
-            || !auth_seq_id.areValuesEqual(i - 1, i)
-            || !pdbx_PDB_ins_code.areValuesEqual(i - 1, i)
-            || !label_comp_id.areValuesEqual(i - 1, i);
-
-        if (newResidue) residues[residues.length] = i as ElementIndex;
-        if (newChain) chains[chains.length] = i as ElementIndex;
-    }
-    return { residues, chains };
-}
-
-function createHierarchyData(atom_site: AtomSite, offsets: { residues: ArrayLike<number>, chains: ArrayLike<number> }): AtomicData {
-    const atoms = Table.ofColumns(AtomsSchema, {
-        type_symbol: Column.ofArray({ array: Column.mapToArray(atom_site.type_symbol, ElementSymbol), schema: Column.Schema.Aliased<ElementSymbol>(Column.Schema.str) }),
-        label_atom_id: atom_site.label_atom_id,
-        auth_atom_id: atom_site.auth_atom_id,
-        label_alt_id: atom_site.label_alt_id,
-        pdbx_formal_charge: atom_site.pdbx_formal_charge
-    });
-    const residues = Table.view(atom_site, ResiduesSchema, offsets.residues);
-    // Optimize the numeric columns
-    Table.columnToArray(residues, 'label_seq_id', Int32Array);
-    Table.columnToArray(residues, 'auth_seq_id', Int32Array);
-    const chains = Table.view(atom_site, ChainsSchema, offsets.chains);
-    return { atoms, residues, chains };
-}
-
-function getConformation(atom_site: AtomSite): AtomicConformation {
-    return {
-        id: UUID.create22(),
-        atomId: atom_site.id,
-        occupancy: atom_site.occupancy,
-        B_iso_or_equiv: atom_site.B_iso_or_equiv,
-        x: atom_site.Cartn_x.toArray({ array: Float32Array }),
-        y: atom_site.Cartn_y.toArray({ array: Float32Array }),
-        z: atom_site.Cartn_z.toArray({ array: Float32Array }),
-    }
-}
-
-function isHierarchyDataEqual(a: AtomicData, b: AtomicData) {
-    // TODO need to cast because of how TS handles type resolution for interfaces https://github.com/Microsoft/TypeScript/issues/15300
-    return Table.areEqual(a.chains as Table<ChainsSchema>, b.chains as Table<ChainsSchema>)
-        && Table.areEqual(a.residues as Table<ResiduesSchema>, b.residues as Table<ResiduesSchema>)
-        && Table.areEqual(a.atoms as Table<AtomsSchema>, b.atoms as Table<AtomsSchema>)
-}
-
-export function getAtomicHierarchyAndConformation(format: mmCIF_Format, atom_site: AtomSite, entities: Entities, formatData: FormatData, previous?: Model) {
-    const hierarchyOffsets = findHierarchyOffsets(atom_site);
-    const hierarchyData = createHierarchyData(atom_site, hierarchyOffsets);
-
-    if (previous && isHierarchyDataEqual(previous.atomicHierarchy, hierarchyData)) {
-        return {
-            sameAsPrevious: true,
-            hierarchy: previous.atomicHierarchy,
-            conformation: getConformation(atom_site)
-        };
-    }
-
-    const conformation = getConformation(atom_site)
-
-    const hierarchySegments: AtomicSegments = {
-        residueAtomSegments: Segmentation.ofOffsets(hierarchyOffsets.residues, Interval.ofBounds(0, atom_site._rowCount)),
-        chainAtomSegments: Segmentation.ofOffsets(hierarchyOffsets.chains, Interval.ofBounds(0, atom_site._rowCount)),
-    }
-
-    const index = getAtomicIndex(hierarchyData, entities, hierarchySegments);
-    const derived = getAtomicDerivedData(hierarchyData, index, formatData.chemicalComponentMap);
-    const hierarchyRanges = getAtomicRanges(hierarchyData, hierarchySegments, conformation, formatData.chemicalComponentMap);
-    const hierarchy: AtomicHierarchy = { ...hierarchyData, ...hierarchySegments, ...hierarchyRanges, index, derived };
-    return { sameAsPrevious: false, hierarchy, conformation };
-}

+ 0 - 9
src/mol-model/structure/model/formats/mmcif/bonds.ts

@@ -1,9 +0,0 @@
-/**
- * Copyright (c) 2017-2018 Mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-export * from './bonds/comp'
-export * from './bonds/struct_conn'

+ 0 - 164
src/mol-model/structure/model/formats/mmcif/bonds/comp.ts

@@ -1,164 +0,0 @@
-/**
- * Copyright (c) 2017-2018 Mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { Model } from '../../../model'
-import { LinkType } from '../../../types'
-import { ModelPropertyDescriptor } from '../../../properties/custom';
-import { mmCIF_Database } from 'mol-io/reader/cif/schema/mmcif';
-import { Structure, Unit, StructureProperties, StructureElement } from '../../../../structure';
-import { Segmentation } from 'mol-data/int';
-import { CifWriter } from 'mol-io/writer/cif'
-
-export interface ComponentBond {
-    entries: Map<string, ComponentBond.Entry>
-}
-
-export namespace ComponentBond {
-    export const Descriptor: ModelPropertyDescriptor = {
-        isStatic: true,
-        name: 'chem_comp_bond',
-        cifExport: {
-            prefix: '',
-            categories: [{
-                name: 'chem_comp_bond',
-                instance(ctx) {
-                    const chem_comp_bond = getChemCompBond(ctx.structures[0].model);
-                    if (!chem_comp_bond) return CifWriter.Category.Empty;
-
-                    const comp_names = getUniqueResidueNames(ctx.structures[0]);
-                    const { comp_id, _rowCount } = chem_comp_bond;
-                    const indices: number[] = [];
-                    for (let i = 0; i < _rowCount; i++) {
-                        if (comp_names.has(comp_id.value(i))) indices[indices.length] = i;
-                    }
-
-                    return CifWriter.Category.ofTable(chem_comp_bond, indices)
-                }
-            }]
-        }
-    }
-
-    export function attachFromMmCif(model: Model): boolean {
-        if (model.customProperties.has(Descriptor)) return true;
-        if (model.sourceData.kind !== 'mmCIF') return false;
-        const { chem_comp_bond } = model.sourceData.data;
-        if (chem_comp_bond._rowCount === 0) return false;
-
-        model.customProperties.add(Descriptor);
-        model._staticPropertyData.__ComponentBondData__ = chem_comp_bond;
-        return true;
-    }
-
-    export function attachFromExternalData(model: Model, bonds: ComponentBond, force = false) {
-        if (!force && model.customProperties.has(Descriptor)) return true;
-        if (model._staticPropertyData.__ComponentBondData__) delete model._staticPropertyData.__ComponentBondData__;
-        model.customProperties.add(Descriptor);
-        model._staticPropertyData[PropName] = bonds;
-        return true;
-    }
-
-    export class ComponentBondImpl implements ComponentBond {
-        entries: Map<string, ComponentBond.Entry> = new Map();
-
-        addEntry(id: string) {
-            let e = new Entry(id);
-            this.entries.set(id, e);
-            return e;
-        }
-    }
-
-    export class Entry {
-        map: Map<string, Map<string, { order: number, flags: number }>> = new Map();
-
-        add(a: string, b: string, order: number, flags: number, swap = true) {
-            let e = this.map.get(a);
-            if (e !== void 0) {
-                let f = e.get(b);
-                if (f === void 0) {
-                    e.set(b, { order, flags });
-                }
-            } else {
-                let map = new Map<string, { order: number, flags: number }>();
-                map.set(b, { order, flags });
-                this.map.set(a, map);
-            }
-
-            if (swap) this.add(b, a, order, flags, false);
-        }
-
-        constructor(public id: string) {
-        }
-    }
-
-    export function parseChemCompBond(data: mmCIF_Database['chem_comp_bond']): ComponentBond {
-        const { comp_id, atom_id_1, atom_id_2, value_order, pdbx_aromatic_flag, _rowCount: rowCount } = data;
-
-        const compBond = new ComponentBondImpl();
-        let entry = compBond.addEntry(comp_id.value(0)!);
-        for (let i = 0; i < rowCount; i++) {
-            const id = comp_id.value(i)!;
-            const nameA = atom_id_1.value(i)!;
-            const nameB = atom_id_2.value(i)!;
-            const order = value_order.value(i)!;
-            const aromatic = pdbx_aromatic_flag.value(i) === 'Y';
-
-            if (entry.id !== id) {
-                entry = compBond.addEntry(id);
-            }
-
-            let flags: number = LinkType.Flag.Covalent;
-            let ord = 1;
-            if (aromatic) flags |= LinkType.Flag.Aromatic;
-            switch (order.toLowerCase()) {
-                case 'doub':
-                case 'delo':
-                    ord = 2;
-                    break;
-                case 'trip': ord = 3; break;
-                case 'quad': ord = 4; break;
-            }
-
-            entry.add(nameA, nameB, ord, flags);
-        }
-
-        return compBond;
-    }
-
-    function getChemCompBond(model: Model) {
-        return model._staticPropertyData.__ComponentBondData__ as mmCIF_Database['chem_comp_bond'];
-    }
-
-    export const PropName = '__ComponentBond__';
-    export function get(model: Model): ComponentBond | undefined {
-        if (model._staticPropertyData[PropName]) return model._staticPropertyData[PropName];
-        if (!model.customProperties.has(Descriptor)) return void 0;
-
-        const chem_comp_bond = getChemCompBond(model);
-        if (!chem_comp_bond) return void 0;
-
-        const chemComp = parseChemCompBond(chem_comp_bond);
-        model._staticPropertyData[PropName] = chemComp;
-        return chemComp;
-    }
-
-    function getUniqueResidueNames(s: Structure) {
-        const prop = StructureProperties.residue.label_comp_id;
-        const names = new Set<string>();
-        const loc = StructureElement.create();
-        for (const unit of s.units) {
-            if (!Unit.isAtomic(unit)) continue;
-            const residues = Segmentation.transientSegments(unit.model.atomicHierarchy.residueAtomSegments, unit.elements);
-            loc.unit = unit;
-            while (residues.hasNext) {
-                const seg = residues.move();
-                loc.element = unit.elements[seg.start];
-                names.add(prop(loc));
-            }
-        }
-        return names;
-    }
-}

+ 0 - 249
src/mol-model/structure/model/formats/mmcif/bonds/struct_conn.ts

@@ -1,249 +0,0 @@
-/**
- * Copyright (c) 2017-2018 Mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { Model } from '../../../model'
-import { Structure } from '../../../../structure'
-import { LinkType } from '../../../types'
-import { findEntityIdByAsymId, findAtomIndexByLabelName } from '../util'
-import { Column } from 'mol-data/db'
-import { ModelPropertyDescriptor } from '../../../properties/custom';
-import { mmCIF_Database, mmCIF_Schema } from 'mol-io/reader/cif/schema/mmcif';
-import { SortedArray } from 'mol-data/int';
-import { CifWriter } from 'mol-io/writer/cif'
-import { ElementIndex, ResidueIndex } from '../../../indexing';
-
-export interface StructConn {
-    getResidueEntries(residueAIndex: ResidueIndex, residueBIndex: ResidueIndex): ReadonlyArray<StructConn.Entry>,
-    getAtomEntries(atomIndex: ElementIndex): ReadonlyArray<StructConn.Entry>,
-    readonly entries: ReadonlyArray<StructConn.Entry>
-}
-
-export namespace StructConn {
-    export const Descriptor: ModelPropertyDescriptor = {
-        isStatic: true,
-        name: 'struct_conn',
-        cifExport: {
-            prefix: '',
-            categories: [{
-                name: 'struct_conn',
-                instance(ctx) {
-                    const structure = ctx.structures[0], model = structure.model;
-                    const struct_conn = getStructConn(model);
-                    if (!struct_conn) return CifWriter.Category.Empty;
-
-                    const strConn = get(model);
-                    if (!strConn || strConn.entries.length === 0) return CifWriter.Category.Empty;
-
-                    const foundAtoms = new Set<ElementIndex>();
-                    const indices: number[] = [];
-                    for (const entry of strConn.entries) {
-                        const { partners } = entry;
-                        let hasAll = true;
-                        for (let i = 0, _i = partners.length; i < _i; i++) {
-                            const atom = partners[i].atomIndex;
-                            if (foundAtoms.has(atom)) continue;
-                            if (hasAtom(structure, atom)) {
-                                foundAtoms.add(atom);
-                            } else {
-                                hasAll = false;
-                                break;
-                            }
-                        }
-                        if (hasAll) {
-                            indices[indices.length] = entry.rowIndex;
-                        }
-                    }
-
-                    return CifWriter.Category.ofTable(struct_conn, indices);
-                }
-            }]
-        }
-    }
-
-    function hasAtom({ units }: Structure, element: ElementIndex) {
-        for (let i = 0, _i = units.length; i < _i; i++) {
-            if (SortedArray.indexOf(units[i].elements, element) >= 0) return true;
-        }
-        return false;
-    }
-
-    function _resKey(rA: number, rB: number) {
-        if (rA < rB) return `${rA}-${rB}`;
-        return `${rB}-${rA}`;
-    }
-    const _emptyEntry: Entry[] = [];
-
-    class StructConnImpl implements StructConn {
-        private _residuePairIndex: Map<string, StructConn.Entry[]> | undefined = void 0;
-        private _atomIndex: Map<number, StructConn.Entry[]> | undefined = void 0;
-
-        private getResiduePairIndex() {
-            if (this._residuePairIndex) return this._residuePairIndex;
-            this._residuePairIndex = new Map();
-            for (const e of this.entries) {
-                const ps = e.partners;
-                const l = ps.length;
-                for (let i = 0; i < l - 1; i++) {
-                    for (let j = i + i; j < l; j++) {
-                        const key = _resKey(ps[i].residueIndex, ps[j].residueIndex);
-                        if (this._residuePairIndex.has(key)) {
-                            this._residuePairIndex.get(key)!.push(e);
-                        } else {
-                            this._residuePairIndex.set(key, [e]);
-                        }
-                    }
-                }
-            }
-            return this._residuePairIndex;
-        }
-
-        private getAtomIndex() {
-            if (this._atomIndex) return this._atomIndex;
-            this._atomIndex = new Map();
-            for (const e of this.entries) {
-                for (const p of e.partners) {
-                    const key = p.atomIndex;
-                    if (this._atomIndex.has(key)) {
-                        this._atomIndex.get(key)!.push(e);
-                    } else {
-                        this._atomIndex.set(key, [e]);
-                    }
-                }
-            }
-            return this._atomIndex;
-        }
-
-
-        getResidueEntries(residueAIndex: ResidueIndex, residueBIndex: ResidueIndex): ReadonlyArray<StructConn.Entry> {
-            return this.getResiduePairIndex().get(_resKey(residueAIndex, residueBIndex)) || _emptyEntry;
-        }
-
-        getAtomEntries(atomIndex: ElementIndex): ReadonlyArray<StructConn.Entry> {
-            return this.getAtomIndex().get(atomIndex) || _emptyEntry;
-        }
-
-        constructor(public entries: StructConn.Entry[]) {
-        }
-    }
-
-    export interface Entry {
-        rowIndex: number,
-        distance: number,
-        order: number,
-        flags: number,
-        partners: { residueIndex: ResidueIndex, atomIndex: ElementIndex, symmetry: string }[]
-    }
-
-    type StructConnType = typeof mmCIF_Schema.struct_conn.conn_type_id.T
-
-    export function attachFromMmCif(model: Model): boolean {
-        if (model.customProperties.has(Descriptor)) return true;
-        if (model.sourceData.kind !== 'mmCIF') return false;
-        const { struct_conn } = model.sourceData.data;
-        if (struct_conn._rowCount === 0) return false;
-        model.customProperties.add(Descriptor);
-        model._staticPropertyData.__StructConnData__ = struct_conn;
-        return true;
-    }
-
-    function getStructConn(model: Model) {
-        return model._staticPropertyData.__StructConnData__ as mmCIF_Database['struct_conn'];
-    }
-
-    export const PropName = '__StructConn__';
-    export function get(model: Model): StructConn | undefined {
-        if (model._staticPropertyData[PropName]) return model._staticPropertyData[PropName];
-        if (!model.customProperties.has(Descriptor)) return void 0;
-
-        const struct_conn = getStructConn(model);
-
-        const { conn_type_id, pdbx_dist_value, pdbx_value_order } = struct_conn;
-        const p1 = {
-            label_asym_id: struct_conn.ptnr1_label_asym_id,
-            label_seq_id: struct_conn.ptnr1_label_seq_id,
-            auth_seq_id: struct_conn.ptnr1_auth_seq_id,
-            label_atom_id: struct_conn.ptnr1_label_atom_id,
-            label_alt_id: struct_conn.pdbx_ptnr1_label_alt_id,
-            ins_code: struct_conn.pdbx_ptnr1_PDB_ins_code,
-            symmetry: struct_conn.ptnr1_symmetry
-        };
-        const p2: typeof p1 = {
-            label_asym_id: struct_conn.ptnr2_label_asym_id,
-            label_seq_id: struct_conn.ptnr2_label_seq_id,
-            auth_seq_id: struct_conn.ptnr2_auth_seq_id,
-            label_atom_id: struct_conn.ptnr2_label_atom_id,
-            label_alt_id: struct_conn.pdbx_ptnr2_label_alt_id,
-            ins_code: struct_conn.pdbx_ptnr2_PDB_ins_code,
-            symmetry: struct_conn.ptnr2_symmetry
-        };
-
-        const _p = (row: number, ps: typeof p1) => {
-            if (ps.label_asym_id.valueKind(row) !== Column.ValueKind.Present) return void 0;
-            const asymId = ps.label_asym_id.value(row);
-            const residueIndex = model.atomicHierarchy.index.findResidue(
-                findEntityIdByAsymId(model, asymId),
-                asymId,
-                ps.auth_seq_id.value(row),
-                ps.ins_code.value(row)
-            );
-            if (residueIndex < 0) return void 0;
-            const atomName = ps.label_atom_id.value(row);
-            // turns out "mismat" records might not have atom name value
-            if (!atomName) return void 0;
-            const atomIndex = findAtomIndexByLabelName(model, residueIndex, atomName, ps.label_alt_id.value(row));
-            if (atomIndex < 0) return void 0;
-            return { residueIndex, atomIndex, symmetry: ps.symmetry.value(row) || '1_555' };
-        }
-
-        const _ps = (row: number) => {
-            const ret = [];
-            let p = _p(row, p1);
-            if (p) ret.push(p);
-            p = _p(row, p2);
-            if (p) ret.push(p);
-            return ret;
-        }
-
-        const entries: StructConn.Entry[] = [];
-        for (let i = 0; i < struct_conn._rowCount; i++) {
-            const partners = _ps(i);
-            if (partners.length < 2) continue;
-
-            const type = conn_type_id.value(i)! as StructConnType;
-            const orderType = (pdbx_value_order.value(i) || '').toLowerCase();
-            let flags = LinkType.Flag.None;
-            let order = 1;
-
-            switch (orderType) {
-                case 'sing': order = 1; break;
-                case 'doub': order = 2; break;
-                case 'trip': order = 3; break;
-                case 'quad': order = 4; break;
-            }
-
-            switch (type) {
-                case 'covale':
-                case 'covale_base':
-                case 'covale_phosphate':
-                case 'covale_sugar':
-                case 'modres':
-                    flags = LinkType.Flag.Covalent;
-                    break;
-                case 'disulf': flags = LinkType.Flag.Covalent | LinkType.Flag.Sulfide; break;
-                case 'hydrog': flags = LinkType.Flag.Hydrogen; break;
-                case 'metalc': flags = LinkType.Flag.MetallicCoordination; break;
-                case 'saltbr': flags = LinkType.Flag.Ionic; break;
-            }
-
-            entries.push({ rowIndex: i, flags, order, distance: pdbx_dist_value.value(i), partners });
-        }
-
-        const ret = new StructConnImpl(entries);
-        model._staticPropertyData[PropName] = ret;
-        return ret;
-    }
-}

+ 0 - 102
src/mol-model/structure/model/formats/mmcif/ihm.ts

@@ -1,102 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-import { mmCIF_Database as mmCIF, mmCIF_Schema } from 'mol-io/reader/cif/schema/mmcif'
-import { CoarseHierarchy, CoarseConformation, CoarseElementData, CoarseSphereConformation, CoarseGaussianConformation } from '../../properties/coarse'
-import { Entities } from '../../properties/common';
-import { Column } from 'mol-data/db';
-import { getCoarseKeys } from '../../properties/utils/coarse-keys';
-import { UUID } from 'mol-util';
-import { Segmentation, Interval } from 'mol-data/int';
-import { Mat3, Tensor } from 'mol-math/linear-algebra';
-import { ElementIndex, ChainIndex } from '../../indexing';
-import { getCoarseRanges } from '../../properties/utils/coarse-ranges';
-import { FormatData } from '../mmcif';
-
-export interface IHMData {
-    model_id: number,
-    model_name: string,
-    entities: Entities,
-    atom_site: mmCIF['atom_site'],
-    ihm_sphere_obj_site: mmCIF['ihm_sphere_obj_site'],
-    ihm_gaussian_obj_site: mmCIF['ihm_gaussian_obj_site']
-}
-
-export const EmptyIHMCoarse = { hierarchy: CoarseHierarchy.Empty, conformation: void 0 as any }
-
-export function getIHMCoarse(data: IHMData, formatData: FormatData): { hierarchy: CoarseHierarchy, conformation: CoarseConformation } {
-    const { ihm_sphere_obj_site, ihm_gaussian_obj_site } = data;
-
-    if (ihm_sphere_obj_site._rowCount === 0 && ihm_gaussian_obj_site._rowCount === 0) return EmptyIHMCoarse;
-
-    const sphereData = getData(ihm_sphere_obj_site);
-    const sphereConformation = getSphereConformation(ihm_sphere_obj_site);
-    const sphereKeys = getCoarseKeys(sphereData, data.entities);
-    const sphereRanges = getCoarseRanges(sphereData, formatData.chemicalComponentMap);
-
-    const gaussianData = getData(ihm_gaussian_obj_site);
-    const gaussianConformation = getGaussianConformation(ihm_gaussian_obj_site);
-    const gaussianKeys = getCoarseKeys(gaussianData, data.entities);
-    const gaussianRanges = getCoarseRanges(gaussianData, formatData.chemicalComponentMap);
-
-    return {
-        hierarchy: {
-            isDefined: true,
-            spheres: { ...sphereData, ...sphereKeys, ...sphereRanges },
-            gaussians: { ...gaussianData, ...gaussianKeys, ...gaussianRanges },
-        },
-        conformation: {
-            id: UUID.create22(),
-            spheres: sphereConformation,
-            gaussians: gaussianConformation
-        }
-    };
-}
-
-function getSphereConformation(data: mmCIF['ihm_sphere_obj_site']): CoarseSphereConformation {
-    return {
-        x: data.Cartn_x.toArray({ array: Float32Array }),
-        y: data.Cartn_y.toArray({ array: Float32Array }),
-        z: data.Cartn_z.toArray({ array: Float32Array }),
-        radius: data.object_radius.toArray({ array: Float32Array }),
-        rmsf: data.rmsf.toArray({ array: Float32Array })
-    };
-}
-
-function getGaussianConformation(data: mmCIF['ihm_gaussian_obj_site']): CoarseGaussianConformation {
-    const matrix_space = mmCIF_Schema.ihm_gaussian_obj_site.covariance_matrix.space;
-    const covariance_matrix: Mat3[] = [];
-    const { covariance_matrix: cm } = data;
-
-    for (let i = 0, _i = cm.rowCount; i < _i; i++) {
-        covariance_matrix[i] = Tensor.toMat3(matrix_space, cm.value(i));
-    }
-
-    return {
-        x: data.mean_Cartn_x.toArray({ array: Float32Array }),
-        y: data.mean_Cartn_y.toArray({ array: Float32Array }),
-        z: data.mean_Cartn_z.toArray({ array: Float32Array }),
-        weight: data.weight.toArray({ array: Float32Array }),
-        covariance_matrix
-    };
-}
-
-function getSegments(asym_id: Column<string>, seq_id_begin: Column<number>, seq_id_end: Column<number>) {
-    const chainOffsets = [0 as ElementIndex];
-    for (let i = 1, _i = asym_id.rowCount; i < _i; i++) {
-        const newChain = !asym_id.areValuesEqual(i - 1, i);
-        if (newChain) chainOffsets[chainOffsets.length] = i as ElementIndex;
-    }
-
-    return {
-        chainElementSegments: Segmentation.ofOffsets<ElementIndex, ChainIndex>(chainOffsets, Interval.ofBounds(0, asym_id.rowCount))
-    }
-}
-
-function getData(data: mmCIF['ihm_sphere_obj_site'] | mmCIF['ihm_gaussian_obj_site']): CoarseElementData {
-    const { entity_id, seq_id_begin, seq_id_end, asym_id } = data;
-    return { count: entity_id.rowCount, entity_id, asym_id, seq_id_begin, seq_id_end, ...getSegments(asym_id, seq_id_begin, seq_id_end) };
-}

+ 0 - 8
src/mol-model/structure/model/formats/mmcif/pair-restraint.ts

@@ -1,8 +0,0 @@
-/**
- * Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-export * from './pair-restraints/cross-links'
-// export * from './pair-restraints/predicted-contacts'

+ 0 - 107
src/mol-model/structure/model/formats/mmcif/pair-restraints/cross-links.ts

@@ -1,107 +0,0 @@
-/**
- * Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { Model } from '../../../model'
-import { Table } from 'mol-data/db'
-import { mmCIF_Schema } from 'mol-io/reader/cif/schema/mmcif';
-import { findAtomIndexByLabelName } from '../util';
-import { Unit } from '../../../../structure';
-import { ElementIndex } from '../../../indexing';
-
-function findAtomIndex(model: Model, entityId: string, asymId: string, seqId: number, atomId: string) {
-    if (!model.atomicHierarchy.atoms.auth_atom_id.isDefined) return -1
-    const residueIndex = model.atomicHierarchy.index.findResidue(entityId, asymId, seqId)
-    if (residueIndex < 0) return -1
-    return findAtomIndexByLabelName(model, residueIndex, atomId, '') as ElementIndex
-}
-
-export interface IHMCrossLinkRestraint {
-    getIndicesByElement: (element: ElementIndex, kind: Unit.Kind) => number[]
-    data: Table<mmCIF_Schema['ihm_cross_link_restraint']>
-}
-
-export namespace IHMCrossLinkRestraint {
-    export const PropName = '__CrossLinkRestraint__';
-    export function fromModel(model: Model): IHMCrossLinkRestraint | undefined {
-        if (model._staticPropertyData[PropName]) return model._staticPropertyData[PropName]
-
-        if (model.sourceData.kind !== 'mmCIF') return
-        const { ihm_cross_link_restraint } = model.sourceData.data;
-        if (!ihm_cross_link_restraint._rowCount) return
-
-        const p1 = {
-            entity_id: ihm_cross_link_restraint.entity_id_1,
-            asym_id: ihm_cross_link_restraint.asym_id_1,
-            seq_id: ihm_cross_link_restraint.seq_id_1,
-            atom_id: ihm_cross_link_restraint.atom_id_1,
-        }
-
-        const p2: typeof p1 = {
-            entity_id: ihm_cross_link_restraint.entity_id_2,
-            asym_id: ihm_cross_link_restraint.asym_id_2,
-            seq_id: ihm_cross_link_restraint.seq_id_2,
-            atom_id: ihm_cross_link_restraint.atom_id_2,
-        }
-
-        function _add(map: Map<ElementIndex, number[]>, element: ElementIndex, row: number) {
-            const indices = map.get(element)
-            if (indices) indices.push(row)
-            else map.set(element, [ row ])
-        }
-
-        function add(row: number, ps: typeof p1) {
-            const entityId = ps.entity_id.value(row)
-            const asymId = ps.asym_id.value(row)
-            const seqId = ps.seq_id.value(row)
-
-            if (ihm_cross_link_restraint.model_granularity.value(row) === 'by-atom') {
-                const atomicElement = findAtomIndex(model, entityId, asymId, seqId, ps.atom_id.value(row))
-                if (atomicElement >= 0) _add(atomicElementMap, atomicElement as ElementIndex, row)
-            } else if (model.coarseHierarchy.isDefined) {
-                const sphereElement = model.coarseHierarchy.spheres.findSequenceKey(entityId, asymId, seqId)
-                if (sphereElement >= 0) {
-                    _add(sphereElementMap, sphereElement, row)
-                } else {
-                    const gaussianElement = model.coarseHierarchy.gaussians.findSequenceKey(entityId, asymId, seqId)
-                    if (gaussianElement >= 0) _add(gaussianElementMap, gaussianElement, row)
-                }
-            }
-        }
-
-        function getMapByKind(kind: Unit.Kind) {
-            switch (kind) {
-                case Unit.Kind.Atomic: return atomicElementMap;
-                case Unit.Kind.Spheres: return sphereElementMap;
-                case Unit.Kind.Gaussians: return gaussianElementMap;
-            }
-        }
-
-        /** map from atomic element to cross link indices */
-        const atomicElementMap: Map<ElementIndex, number[]> = new Map()
-        /** map from sphere element to cross link indices */
-        const sphereElementMap: Map<ElementIndex, number[]> = new Map()
-        /** map from gaussian element to cross link indices */
-        const gaussianElementMap: Map<ElementIndex, number[]> = new Map()
-
-        const emptyIndexArray: number[] = [];
-
-        for (let i = 0; i < ihm_cross_link_restraint._rowCount; ++i) {
-            add(i, p1)
-            add(i, p2)
-        }
-
-        const crossLinkRestraint = {
-            getIndicesByElement: (element: ElementIndex, kind: Unit.Kind) => {
-                const map = getMapByKind(kind)
-                const idx = map.get(element)
-                return idx !== undefined ? idx : emptyIndexArray
-            },
-            data: ihm_cross_link_restraint
-        }
-        model._staticPropertyData[PropName] = crossLinkRestraint
-        return crossLinkRestraint
-    }
-}

+ 0 - 26
src/mol-model/structure/model/formats/mmcif/pair-restraints/predicted-contacts.ts

@@ -1,26 +0,0 @@
-/**
- * Copyright (c) 2018 Mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-// TODO
-// ihm_predicted_contact_restraint: {
-//     id: int,
-//     entity_id_1: str,
-//     entity_id_2: str,
-//     asym_id_1: str,
-//     asym_id_2: str,
-//     comp_id_1: str,
-//     comp_id_2: str,
-//     seq_id_1: int,
-//     seq_id_2: int,
-//     atom_id_1: str,
-//     atom_id_2: str,
-//     distance_upper_limit: float,
-//     probability: float,
-//     restraint_type: Aliased<'lower bound' | 'upper bound' | 'lower and upper bound'>(str),
-//     model_granularity: Aliased<'by-residue' | 'by-feature' | 'by-atom'>(str),
-//     dataset_list_id: int,
-//     software_id: int,
-// },

+ 0 - 175
src/mol-model/structure/model/formats/mmcif/secondary-structure.ts

@@ -1,175 +0,0 @@
-
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-import { mmCIF_Database as mmCIF, mmCIF_Database } from 'mol-io/reader/cif/schema/mmcif'
-import { SecondaryStructureType } from '../../types';
-import { AtomicHierarchy } from '../../properties/atomic';
-import { SecondaryStructure } from '../../properties/seconday-structure';
-import { Column } from 'mol-data/db';
-import { ChainIndex, ResidueIndex } from '../../indexing';
-
-export function getSecondaryStructureMmCif(data: mmCIF_Database, hierarchy: AtomicHierarchy): SecondaryStructure {
-    const map: SecondaryStructureMap = new Map();
-    const elements: SecondaryStructure.Element[] = [{ kind: 'none' }];
-    addHelices(data.struct_conf, map, elements);
-    // must add Helices 1st because of 'key' value assignment.
-    addSheets(data.struct_sheet_range, map, data.struct_conf._rowCount, elements);
-
-    const secStruct: SecondaryStructureData = {
-        type: new Int32Array(hierarchy.residues._rowCount) as any,
-        key: new Int32Array(hierarchy.residues._rowCount) as any,
-        elements
-    };
-
-    if (map.size > 0) assignSecondaryStructureRanges(hierarchy, map, secStruct);
-    return secStruct;
-}
-
-type SecondaryStructureEntry = {
-    startSeqNumber: number,
-    startInsCode: string | null,
-    endSeqNumber: number,
-    endInsCode: string | null,
-    type: SecondaryStructureType,
-    key: number
-}
-type SecondaryStructureMap = Map<string, Map<number, SecondaryStructureEntry>>
-type SecondaryStructureData = { type: SecondaryStructureType[], key: number[], elements: SecondaryStructure.Element[] }
-
-function addHelices(cat: mmCIF['struct_conf'], map: SecondaryStructureMap, elements: SecondaryStructure.Element[]) {
-    if (!cat._rowCount) return;
-
-    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 { pdbx_PDB_helix_class, conf_type_id, details } = cat;
-
-    for (let i = 0, _i = cat._rowCount; i < _i; i++) {
-        const type = SecondaryStructureType.create(pdbx_PDB_helix_class.valueKind(i) === Column.ValueKind.Present
-            ? SecondaryStructureType.SecondaryStructurePdb[pdbx_PDB_helix_class.value(i)]
-            : conf_type_id.valueKind(i) === Column.ValueKind.Present
-                ? SecondaryStructureType.SecondaryStructureMmcif[conf_type_id.value(i)]
-                : SecondaryStructureType.Flag.NA);
-
-        const element: SecondaryStructure.Helix = {
-            kind: 'helix',
-            flags: type,
-            type_id: 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 = {
-            startSeqNumber: beg_label_seq_id.value(i),
-            startInsCode: pdbx_beg_PDB_ins_code.value(i),
-            endSeqNumber: end_label_seq_id.value(i),
-            endInsCode: pdbx_end_PDB_ins_code.value(i),
-            type,
-            key: elements.length
-        };
-
-
-        elements[elements.length] = element;
-
-        const asymId = beg_label_asym_id.value(i)!;
-        if (map.has(asymId)) {
-            map.get(asymId)!.set(entry.startSeqNumber, entry);
-        } else {
-            map.set(asymId, new Map([[entry.startSeqNumber, entry]]));
-        }
-    }
-}
-
-function addSheets(cat: mmCIF['struct_sheet_range'], map: SecondaryStructureMap, sheetCount: number, elements: SecondaryStructure.Element[]) {
-    if (!cat._rowCount) return;
-
-    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 { sheet_id } = cat;
-
-    const sheet_id_key = new Map<string, number>();
-    let currentKey = sheetCount + 1;
-
-    for (let i = 0, _i = cat._rowCount; i < _i; i++) {
-        const id = sheet_id.value(i);
-        let key: number;
-        if (sheet_id_key.has(id)) key = sheet_id_key.get(id)!;
-        else {
-            key = currentKey++;
-            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 = {
-            startSeqNumber: beg_label_seq_id.value(i),
-            startInsCode: pdbx_beg_PDB_ins_code.value(i),
-            endSeqNumber: end_label_seq_id.value(i),
-            endInsCode: pdbx_end_PDB_ins_code.value(i),
-            type,
-            key: elements.length
-        };
-
-        elements[elements.length] = element;
-
-
-        const asymId = beg_label_asym_id.value(i)!;
-        if (map.has(asymId)) {
-            map.get(asymId)!.set(entry.startSeqNumber, entry);
-        } else {
-            map.set(asymId, new Map([[entry.startSeqNumber, entry]]));
-        }
-    }
-
-    return;
-}
-
-function assignSecondaryStructureEntry(hierarchy: AtomicHierarchy, entry: SecondaryStructureEntry, resStart: ResidueIndex, resEnd: ResidueIndex, data: SecondaryStructureData) {
-    const { label_seq_id, pdbx_PDB_ins_code } = hierarchy.residues;
-    const { endSeqNumber, endInsCode, key, type } = entry;
-
-    let rI = resStart;
-    while (rI < resEnd) {
-        const seqNumber = label_seq_id.value(rI);
-        data.type[rI] = type;
-        data.key[rI] = key;
-
-        if ((seqNumber > endSeqNumber) ||
-            (seqNumber === endSeqNumber && pdbx_PDB_ins_code.value(rI) === endInsCode)) {
-            break;
-        }
-
-        rI++;
-    }
-}
-
-function assignSecondaryStructureRanges(hierarchy: AtomicHierarchy, map: SecondaryStructureMap, data: SecondaryStructureData) {
-    const { count: chainCount } = hierarchy.chainAtomSegments;
-    const { label_asym_id } = hierarchy.chains;
-    const { label_seq_id, pdbx_PDB_ins_code } = hierarchy.residues;
-
-    for (let cI = 0 as ChainIndex; cI < chainCount; cI++) {
-        const resStart = AtomicHierarchy.chainStartResidueIndex(hierarchy, cI), resEnd = AtomicHierarchy.chainEndResidueIndexExcl(hierarchy, cI);
-        const asymId = label_asym_id.value(cI);
-        if (map.has(asymId)) {
-            const entries = map.get(asymId)!;
-
-            for (let rI = resStart; rI < resEnd; rI++) {
-                const seqNumber = label_seq_id.value(rI);
-                if (entries.has(seqNumber)) {
-                    const entry = entries.get(seqNumber)!;
-                    const insCode = pdbx_PDB_ins_code.value(rI);
-                    if (entry.startInsCode !== insCode) continue;
-                    assignSecondaryStructureEntry(hierarchy, entry, rI, resEnd, data);
-                }
-            }
-        }
-    }
-}

+ 0 - 55
src/mol-model/structure/model/formats/mmcif/sequence.ts

@@ -1,55 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-import { mmCIF_Database as mmCIF } from 'mol-io/reader/cif/schema/mmcif'
-import StructureSequence from '../../properties/sequence'
-import { Column } from 'mol-data/db';
-import { AtomicHierarchy } from '../../properties/atomic';
-import { Entities } from '../../properties/common';
-import { Sequence } from '../../../../sequence';
-
-// TODO how to handle microheterogeneity
-//    see http://mmcif.wwpdb.org/dictionaries/mmcif_pdbx_v50.dic/Categories/entity_poly_seq.html
-//
-// Data items in the ENTITY_POLY_SEQ category specify the sequence
-// of monomers in a polymer. Allowance is made for the possibility
-// of microheterogeneity in a sample by allowing a given sequence
-// number to be correlated with more than one monomer ID. The
-// corresponding ATOM_SITE entries should reflect this
-// heterogeneity.
-
-export function getSequence(cif: mmCIF, entities: Entities, hierarchy: AtomicHierarchy, modResMap: ReadonlyMap<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;
-
-    const byEntityKey: StructureSequence['byEntityKey'] = {};
-    const sequences: StructureSequence.Entity[] = [];
-    const count = entity_id.rowCount;
-
-    let i = 0;
-    while (i < count) {
-        const start = i;
-        while (i < count - 1 && entity_id.areValuesEqual(i, i + 1)) i++;
-        i++;
-
-        const id = entity_id.value(start);
-        const _compId = Column.window(mon_id, start, i);
-        const _num = Column.window(num, start, i);
-        const entityKey = entities.getEntityIndex(id);
-
-        byEntityKey[entityKey] = {
-            entityId: id,
-            compId: _compId,
-            num: _num,
-            sequence: Sequence.ofResidueNames(_compId, _num, modResMap)
-        };
-
-        sequences.push(byEntityKey[entityKey]);
-    }
-
-    return { byEntityKey, sequences };
-}

+ 0 - 43
src/mol-model/structure/model/formats/mmcif/sort.ts

@@ -1,43 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author David Sehnal <david.sehnal@gmail.com>
- */
-
-import { mmCIF_Database } from 'mol-io/reader/cif/schema/mmcif';
-import { createRangeArray, makeBuckets } from 'mol-data/util';
-import { Column, Table } from 'mol-data/db';
-import { RuntimeContext } from 'mol-task';
-
-function isIdentity(xs: ArrayLike<number>) {
-    for (let i = 0, _i = xs.length; i < _i; i++) {
-        if (xs[i] !== i) return false;
-    }
-    return true;
-}
-
-export async function sortAtomSite(ctx: RuntimeContext, atom_site: mmCIF_Database['atom_site'], start: number, end: number) {
-    const indices = createRangeArray(start, end - 1);
-
-    const { label_entity_id, label_asym_id, label_seq_id } = atom_site;
-    const entityBuckets = makeBuckets(indices, label_entity_id.value);
-    if (ctx.shouldUpdate) await ctx.update();
-    for (let ei = 0, _eI = entityBuckets.length - 1; ei < _eI; ei++) {
-        const chainBuckets = makeBuckets(indices, label_asym_id.value, { start: entityBuckets[ei], end: entityBuckets[ei + 1] });
-        for (let cI = 0, _cI = chainBuckets.length - 1; cI < _cI; cI++) {
-            const aI = chainBuckets[cI];
-            // are we in HETATM territory?
-            if (label_seq_id.valueKind(aI) !== Column.ValueKind.Present) continue;
-
-            makeBuckets(indices, label_seq_id.value, { sort: true, start: aI, end: chainBuckets[cI + 1] });
-            if (ctx.shouldUpdate) await ctx.update();
-        }
-        if (ctx.shouldUpdate) await ctx.update();
-    }
-
-    if (isIdentity(indices) && indices.length === atom_site._rowCount) {
-        return atom_site;
-    }
-
-    return Table.view(atom_site, atom_site._schema, indices) as mmCIF_Database['atom_site'];
-}

+ 0 - 26
src/mol-model/structure/model/formats/mmcif/util.ts

@@ -1,26 +0,0 @@
-/**
- * Copyright (c) 2017-2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { Model } from '../../model'
-import { ElementIndex } from '../../indexing';
-
-export function findEntityIdByAsymId(model: Model, asymId: string) {
-    if (model.sourceData.kind !== 'mmCIF') return ''
-    const { struct_asym } = model.sourceData.data
-    for (let i = 0, n = struct_asym._rowCount; i < n; ++i) {
-        if (struct_asym.id.value(i) === asymId) return struct_asym.entity_id.value(i)
-    }
-    return ''
-}
-
-export function findAtomIndexByLabelName(model: Model, residueIndex: number, atomName: string, altLoc: string | null): ElementIndex {
-    const { offsets } = model.atomicHierarchy.residueAtomSegments;
-    const { label_atom_id, label_alt_id } = model.atomicHierarchy.atoms;
-    for (let i = offsets[residueIndex], n = offsets[residueIndex + 1]; i < n; ++i) {
-        if (label_atom_id.value(i) === atomName && (!altLoc || label_alt_id.value(i) === altLoc)) return i as ElementIndex;
-    }
-    return -1 as ElementIndex;
-}

+ 9 - 15
src/mol-model/structure/model/model.ts

@@ -4,19 +4,17 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import UUID from 'mol-util/uuid'
-import Format from './format'
-import StructureSequence from './properties/sequence'
-import { AtomicHierarchy, AtomicConformation } from './properties/atomic'
-import { ModelSymmetry } from './properties/symmetry'
-import { CoarseHierarchy, CoarseConformation } from './properties/coarse'
+import UUID from 'mol-util/uuid';
+import StructureSequence from './properties/sequence';
+import { AtomicHierarchy, AtomicConformation } from './properties/atomic';
+import { ModelSymmetry } from './properties/symmetry';
+import { CoarseHierarchy, CoarseConformation } from './properties/coarse';
 import { Entities } from './properties/common';
 import { CustomProperties } from './properties/custom';
 import { SecondaryStructure } from './properties/seconday-structure';
-
-import from_mmCIF from './formats/mmcif'
 import { ChemicalComponentMap } from './properties/chemical-component';
 import { SaccharideComponentMap } from '../structure/carbohydrates/constants';
+import { ModelFormat } from 'mol-model-parsers/structure/format';
 
 /**
  * Interface to the "source data" of the molecule.
@@ -30,7 +28,7 @@ export interface Model extends Readonly<{
     // for IHM, corresponds to ihm_model_list.model_id
     modelNum: number,
 
-    sourceData: Format,
+    sourceData: ModelFormat,
 
     symmetry: ModelSymmetry,
     entities: Entities,
@@ -69,10 +67,6 @@ export interface Model extends Readonly<{
 } { }
 
 export namespace Model {
-    export function create(format: Format) {
-        switch (format.kind) {
-            // case 'gro': return from_gro(format);
-            case 'mmCIF': return from_mmCIF(format);
-        }
-    }
+    // TODO: is this enough?
+    export type Trajectory = ReadonlyArray<Model>
 }

+ 1 - 1
src/mol-model/structure/structure/unit/links/inter-compute.ts

@@ -4,7 +4,6 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import { StructConn } from '../../../model/formats/mmcif/bonds';
 import { LinkType } from '../../../model/types';
 import Structure from '../../structure';
 import Unit from '../../unit';
@@ -14,6 +13,7 @@ import { UniqueArray } from 'mol-data/generic';
 import { SortedArray } from 'mol-data/int';
 import { Vec3, Mat4 } from 'mol-math/linear-algebra';
 import StructureElement from '../../element';
+import { StructConn } from 'mol-model-parsers/structure/mmcif/bonds';
 
 const MAX_RADIUS = 4;
 

+ 1 - 1
src/mol-model/structure/structure/unit/links/intra-compute.ts

@@ -6,11 +6,11 @@
 
 import { LinkType } from '../../../model/types'
 import { IntraUnitLinks } from './data'
-import { StructConn, ComponentBond } from '../../../model/formats/mmcif/bonds'
 import Unit from '../../unit'
 import { IntAdjacencyGraph } from 'mol-math/graph';
 import { LinkComputationParameters, getElementIdx, MetalsSet, getElementThreshold, isHydrogen, getElementPairThreshold } from './common';
 import { SortedArray } from 'mol-data/int';
+import { StructConn, ComponentBond } from 'mol-model-parsers/structure/mmcif/bonds';
 
 function getGraph(atomA: number[], atomB: number[], _order: number[], _flags: number[], atomCount: number): IntraUnitLinks {
     const builder = new IntAdjacencyGraph.EdgeBuilder(atomCount, atomA, atomB);

+ 1 - 1
src/mol-model/structure/structure/unit/pair-restraints/extract-cross-links.ts

@@ -6,9 +6,9 @@
 
 import Unit from '../../unit';
 import Structure from '../../structure';
-import { IHMCrossLinkRestraint } from '../../../model/formats/mmcif/pair-restraint';
 import { PairRestraints, CrossLinkRestraint } from './data';
 import { StructureElement } from '../../../structure';
+import { IHMCrossLinkRestraint } from 'mol-model-parsers/structure/mmcif/pair-restraint';
 
 function _addRestraints(map: Map<number, number>, unit: Unit, restraints: IHMCrossLinkRestraint) {
     const { elements } = unit;

+ 4 - 2
src/mol-plugin/state/transforms/model.ts

@@ -8,7 +8,7 @@
 import { PluginStateTransform } from '../objects';
 import { PluginStateObject as SO } from '../objects';
 import { Task, RuntimeContext } from 'mol-task';
-import { Model, Format, Structure, ModelSymmetry, StructureSymmetry, QueryContext, StructureSelection as Sel, StructureQuery, Queries } from 'mol-model/structure';
+import { Model, Structure, ModelSymmetry, StructureSymmetry, QueryContext, StructureSelection as Sel, StructureQuery, Queries } from 'mol-model/structure';
 import { ParamDefinition as PD } from 'mol-util/param-definition';
 import Expression from 'mol-script/language/expression';
 import { compile } from 'mol-script/runtime/query/compiler';
@@ -19,6 +19,8 @@ import { stringToWords } from 'mol-util/string';
 import { volumeFromCcp4 } from 'mol-model/volume/formats/ccp4';
 import { Vec3 } from 'mol-math/linear-algebra';
 import { volumeFromDsn6 } from 'mol-model/volume/formats/dsn6';
+import { parse_mmCIF } from 'mol-model-parsers/structure/mmcif';
+import { ModelFormat } from 'mol-model-parsers/structure/format';
 
 export { TrajectoryFromMmCif }
 type TrajectoryFromMmCif = typeof TrajectoryFromMmCif
@@ -45,7 +47,7 @@ const TrajectoryFromMmCif = PluginStateTransform.BuiltIn({
             const header = params.blockHeader || a.data.blocks[0].header;
             const block = a.data.blocks.find(b => b.header === header);
             if (!block) throw new Error(`Data block '${[header]}' not found.`);
-            const models = await Model.create(Format.mmCIF(block)).runInContext(ctx);
+            const models = await parse_mmCIF(ModelFormat.mmCIF(block)).runInContext(ctx);
             if (models.length === 0) throw new Error('No models found.');
             const props = { label: models[0].label, description: `${models.length} model${models.length === 1 ? '' : 's'}` };
             return new SO.Molecule.Trajectory(models, props);

+ 5 - 3
src/perf-tests/lookup3d.ts

@@ -2,11 +2,13 @@ import * as util from 'util'
 import * as fs from 'fs'
 import CIF from 'mol-io/reader/cif'
 
-import { Structure, Model, Format } from 'mol-model/structure'
+import { Structure } from 'mol-model/structure'
 
 import { GridLookup3D } from 'mol-math/geometry';
 // import { sortArray } from 'mol-data/util';
 import { OrderedSet } from 'mol-data/int';
+import { ModelFormat } from 'mol-model-parsers/structure/format';
+import { parse_mmCIF } from 'mol-model-parsers/structure/mmcif';
 
 require('util.promisify').shim();
 const readFileAsync = util.promisify(fs.readFile);
@@ -31,8 +33,8 @@ export async function readCIF(path: string) {
         throw parsed;
     }
 
-    const mmcif = Format.mmCIF(parsed.result.blocks[0]);
-    const models = await Model.create(mmcif).run();
+    const mmcif = ModelFormat.mmCIF(parsed.result.blocks[0]);
+    const models = await parse_mmCIF(mmcif).run();
     const structures = models.map(Structure.ofModel);
 
     return { mmcif: mmcif.data, models, structures };

+ 5 - 3
src/perf-tests/structure.ts

@@ -11,11 +11,13 @@ import * as fs from 'fs'
 import fetch from 'node-fetch'
 import CIF from 'mol-io/reader/cif'
 
-import { Structure, Model, Queries as Q, StructureElement, StructureSelection, StructureSymmetry, StructureQuery, Format, StructureProperties as SP } from 'mol-model/structure'
+import { Structure, Model, Queries as Q, StructureElement, StructureSelection, StructureSymmetry, StructureQuery, StructureProperties as SP } from 'mol-model/structure'
 // import { Segmentation, OrderedSet } from 'mol-data/int'
 
 import to_mmCIF from 'mol-model/structure/export/mmcif'
 import { Vec3 } from 'mol-math/linear-algebra';
+import { ModelFormat } from 'mol-model-parsers/structure/format';
+import { parse_mmCIF } from 'mol-model-parsers/structure/mmcif';
 // import { printUnits } from 'apps/structure-info/model';
 // import { EquivalenceClasses } from 'mol-data/util';
 
@@ -70,11 +72,11 @@ export async function readCIF(path: string) {
 
     const data = parsed.result.blocks[0];
     console.time('schema')
-    const mmcif = Format.mmCIF(data);
+    const mmcif = ModelFormat.mmCIF(data);
 
     console.timeEnd('schema')
     console.time('buildModels')
-    const models = await Model.create(mmcif).run();
+    const models = await parse_mmCIF(mmcif).run();
     console.timeEnd('buildModels')
     const structures = models.map(Structure.ofModel);
 

+ 4 - 2
src/servers/model/server/structure-wrapper.ts

@@ -4,7 +4,7 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import { Structure, Model, Format } from 'mol-model/structure';
+import { Structure, Model } from 'mol-model/structure';
 import { PerformanceMonitor } from 'mol-util/performance-monitor';
 import { Cache } from './cache';
 import Config from '../config';
@@ -15,6 +15,8 @@ import * as zlib from 'zlib'
 import { Job } from './jobs';
 import { ConsoleLogger } from 'mol-util/console-logger';
 import { ModelPropertiesProvider } from '../property-provider';
+import { parse_mmCIF } from 'mol-model-parsers/structure/mmcif';
+import { ModelFormat } from 'mol-model-parsers/structure/format';
 
 require('util.promisify').shim();
 
@@ -108,7 +110,7 @@ export async function readStructureWrapper(key: string, sourceId: string | '_loc
     const frame = (await parseCif(data)).blocks[0];
     perf.end('parse');
     perf.start('createModel');
-    const models = await Model.create(Format.mmCIF(frame)).run();
+    const models = await parse_mmCIF(ModelFormat.mmCIF(frame)).run();
     perf.end('createModel');
 
     const modelMap = new Map<number, Model>();