Browse Source

change comp_id to be atom property to support micro heterogeneity

Alexander Rose 4 years ago
parent
commit
bb7d3e075c
27 changed files with 85 additions and 74 deletions
  1. 5 4
      src/cli/structure-info/model.ts
  2. 1 1
      src/examples/proteopedia-wrapper/helpers.ts
  3. 4 2
      src/mol-model-formats/structure/basic/atomic.ts
  4. 1 0
      src/mol-model-formats/structure/property/symmetry.ts
  5. 1 1
      src/mol-model-props/computed/accessible-surface-area/shrake-rupley.ts
  6. 2 2
      src/mol-model-props/computed/accessible-surface-area/shrake-rupley/radii.ts
  7. 1 1
      src/mol-model-props/computed/chemistry/util.ts
  8. 2 2
      src/mol-model-props/computed/interactions/charged.ts
  9. 6 6
      src/mol-model/structure/export/categories/atom_site.ts
  10. 12 10
      src/mol-model/structure/model/properties/atomic/hierarchy.ts
  11. 10 4
      src/mol-model/structure/model/properties/sequence.ts
  12. 6 4
      src/mol-model/structure/model/properties/utils/atomic-derived.ts
  13. 2 2
      src/mol-model/structure/structure/carbohydrates/compute.ts
  14. 3 8
      src/mol-model/structure/structure/properties.ts
  15. 2 1
      src/mol-model/structure/structure/structure.ts
  16. 4 4
      src/mol-model/structure/structure/unit/bonds/inter-compute.ts
  17. 2 2
      src/mol-model/structure/structure/unit/bonds/intra-compute.ts
  18. 1 2
      src/mol-model/structure/structure/unit/rings.ts
  19. 5 4
      src/mol-model/structure/util.ts
  20. 2 2
      src/mol-plugin-ui/sequence/hetero.ts
  21. 2 1
      src/mol-repr/structure/visual/label-text.ts
  22. 2 2
      src/mol-repr/structure/visual/nucleotide-block-mesh.ts
  23. 2 2
      src/mol-repr/structure/visual/nucleotide-ring-mesh.ts
  24. 4 4
      src/mol-script/runtime/query/table.ts
  25. 1 1
      src/mol-theme/color/hydrophobicity.ts
  26. 1 1
      src/mol-theme/color/residue-name.ts
  27. 1 1
      src/mol-theme/label.ts

+ 5 - 4
src/cli/structure-info/model.ts

@@ -34,8 +34,8 @@ export async function readCifFile(path: string) {
 
 export function atomLabel(model: Model, aI: number) {
     const { atoms, residues, chains, residueAtomSegments, chainAtomSegments } = model.atomicHierarchy;
-    const { label_atom_id } = atoms;
-    const { label_comp_id, label_seq_id } = residues;
+    const { label_atom_id, label_comp_id } = atoms;
+    const { label_seq_id } = residues;
     const { label_asym_id } = chains;
     const rI = residueAtomSegments.index[aI];
     const cI = chainAtomSegments.index[aI];
@@ -43,8 +43,9 @@ export function atomLabel(model: Model, aI: number) {
 }
 
 export function residueLabel(model: Model, rI: number) {
-    const { residues, chains, residueAtomSegments, chainAtomSegments } = model.atomicHierarchy;
-    const { label_comp_id, label_seq_id } = residues;
+    const { atoms, residues, chains, residueAtomSegments, chainAtomSegments } = model.atomicHierarchy;
+    const { label_comp_id } = atoms;
+    const { label_seq_id } = residues;
     const { label_asym_id } = chains;
     const cI = chainAtomSegments.index[residueAtomSegments.offsets[rI]];
     return `${label_asym_id.value(cI)} ${label_comp_id.value(rI)} ${label_seq_id.value(rI)}`;

+ 1 - 1
src/examples/proteopedia-wrapper/helpers.ts

@@ -58,7 +58,7 @@ export namespace ModelInfo {
             const entityType = model.entities.data.type.value(eI);
             if (entityType !== 'non-polymer' && entityType !== 'branched') continue;
 
-            const comp_id = model.atomicHierarchy.residues.label_comp_id.value(rI);
+            const comp_id = model.atomicHierarchy.atoms.label_comp_id.value(rI);
 
             let lig = hetMap.get(comp_id);
             if (!lig) {

+ 4 - 2
src/mol-model-formats/structure/basic/atomic.ts

@@ -60,6 +60,8 @@ function createHierarchyData(atom_site: AtomSite, sourceIndex: Column<number>, o
         label_atom_id: atom_site.label_atom_id,
         auth_atom_id: atom_site.auth_atom_id,
         label_alt_id: atom_site.label_alt_id,
+        label_comp_id: atom_site.label_comp_id,
+        auth_comp_id: atom_site.auth_comp_id,
         pdbx_formal_charge: atom_site.pdbx_formal_charge,
         sourceIndex
     });
@@ -74,8 +76,8 @@ function createHierarchyData(atom_site: AtomSite, sourceIndex: Column<number>, o
 
     // Fix possibly missing auth_/label_ columns
     substUndefinedColumn(atoms, 'label_atom_id', 'auth_atom_id');
+    substUndefinedColumn(atoms, 'label_comp_id', 'auth_comp_id');
     substUndefinedColumn(residues, 'label_seq_id', 'auth_seq_id');
-    substUndefinedColumn(residues, 'label_comp_id', 'auth_comp_id');
     substUndefinedColumn(chains, 'label_asym_id', 'auth_asym_id');
 
     return { atoms, residues, chains };
@@ -174,7 +176,7 @@ function getAtomicHierarchy(atom_site: AtomSite, sourceIndex: Column<number>, en
     };
 
     const index = getAtomicIndex(hierarchyData, entities, hierarchySegments);
-    const derived = getAtomicDerivedData(hierarchyData, index, chemicalComponentMap);
+    const derived = getAtomicDerivedData(hierarchyData, hierarchySegments, index, chemicalComponentMap);
     const hierarchy: AtomicHierarchy = { ...hierarchyData, ...hierarchySegments, index, derived };
     return { sameAsPrevious: false, hierarchy, chainOperatorMapping };
 }

+ 1 - 0
src/mol-model-formats/structure/property/symmetry.ts

@@ -36,6 +36,7 @@ namespace ModelSymmetry {
     export function fromData(data: Data): Symmetry {
         const assemblies = createAssemblies(data.pdbx_struct_assembly, data.pdbx_struct_assembly_gen, data.pdbx_struct_oper_list);
         const spacegroup = getSpacegroup(data.symmetry, data.cell);
+        // TODO fix name
         const isNonStandardCrytalFrame = checkNonStandardCrystalFrame(data.atom_sites, spacegroup);
         return { assemblies, spacegroup, isNonStandardCrytalFrame, ncsOperators: getNcsOperators(data.struct_ncs_oper) };
     }

+ 1 - 1
src/mol-model-props/computed/accessible-surface-area/shrake-rupley.ts

@@ -108,7 +108,7 @@ namespace AccessibleSurfaceArea {
 
     export function getNormalizedValue(location: StructureElement.Location, accessibleSurfaceArea: AccessibleSurfaceArea) {
         const value = getValue(location, accessibleSurfaceArea);
-        return value === -1 ? -1 : normalize(StructureProperties.residue.label_comp_id(location), value);
+        return value === -1 ? -1 : normalize(StructureProperties.atom.label_comp_id(location), value);
     }
 
     export function getFlag(location: StructureElement.Location, accessibleSurfaceArea: AccessibleSurfaceArea) {

+ 2 - 2
src/mol-model-props/computed/accessible-surface-area/shrake-rupley/radii.ts

@@ -15,8 +15,8 @@ import { getElementMoleculeType } from '../../../../mol-model/structure/util';
 const l = StructureElement.Location.create(void 0);
 
 export function assignRadiusForHeavyAtoms(ctx: ShrakeRupleyContext) {
-    const { label_comp_id, key } = StructureProperties.residue;
-    const { type_symbol, label_atom_id } = StructureProperties.atom;
+    const { key } = StructureProperties.residue;
+    const { type_symbol, label_atom_id, label_comp_id } = StructureProperties.atom;
     const { structure, atomRadiusType, serialResidueIndex } = ctx;
 
     let prevResidueIdx = 0;

+ 1 - 1
src/mol-model-props/computed/chemistry/util.ts

@@ -27,7 +27,7 @@ export function altLoc(unit: Unit.Atomic, index: StructureElement.UnitIndex) {
 }
 
 export function compId(unit: Unit.Atomic, index: StructureElement.UnitIndex) {
-    return unit.model.atomicHierarchy.residues.label_comp_id.value(unit.getResidueIndex(index));
+    return unit.model.atomicHierarchy.atoms.label_comp_id.value(unit.getResidueIndex(index));
 }
 
 //

+ 2 - 2
src/mol-model-props/computed/interactions/charged.ts

@@ -62,7 +62,7 @@ function addUnitPositiveCharges(structure: Structure, unit: Unit.Atomic, builder
 
     const addedElements = new Set<StructureElement.UnitIndex>();
 
-    const { label_comp_id } = unit.model.atomicHierarchy.residues;
+    const { label_comp_id } = unit.model.atomicHierarchy.atoms;
     const residueIt = Segmentation.transientSegments(unit.model.atomicHierarchy.residueAtomSegments, elements);
 
     while (residueIt.hasNext) {
@@ -115,7 +115,7 @@ function addUnitNegativeCharges(structure: Structure, unit: Unit.Atomic, builder
 
     const addedElements = new Set<StructureElement.UnitIndex>();
 
-    const { label_comp_id } = unit.model.atomicHierarchy.residues;
+    const { label_comp_id } = unit.model.atomicHierarchy.atoms;
     const residueIt = Segmentation.transientSegments(unit.model.atomicHierarchy.residueAtomSegments, elements);
 
     while (residueIt.hasNext) {

+ 6 - 6
src/mol-model/structure/export/categories/atom_site.ts

@@ -34,7 +34,7 @@ const atom_site_fields = CifWriter.fields<StructureElement.Location, Structure>(
     .str('type_symbol', P.atom.type_symbol as any)
     .str('label_atom_id', P.atom.label_atom_id)
 
-    .str('label_comp_id', P.residue.label_comp_id)
+    .str('label_comp_id', P.atom.label_comp_id)
     .int('label_seq_id', P.residue.label_seq_id, {
         encoder: E.deltaRLE,
         valueKind: (k, d) => {
@@ -58,7 +58,7 @@ const atom_site_fields = CifWriter.fields<StructureElement.Location, Structure>(
     })
 
     .str('auth_atom_id', P.atom.auth_atom_id)
-    .str('auth_comp_id', P.residue.auth_comp_id)
+    .str('auth_comp_id', P.atom.auth_comp_id)
     .int('auth_seq_id', P.residue.auth_seq_id, { encoder: E.deltaRLE })
     .str('auth_asym_id', atom_site_auth_asym_id)
 
@@ -108,7 +108,7 @@ export interface IdFieldsOptions {
 export function residueIdFields<K, D>(getLocation: (key: K, data: D) => StructureElement.Location, options?: IdFieldsOptions): CifField<K, D>[] {
     const prefix = options && options.prefix, postfix = options && options.postfix;
     const ret = CifWriter.fields<K, D>()
-        .str(prepostfixed(prefix, postfix, `label_comp_id`), mappedProp(getLocation, P.residue.label_comp_id))
+        .str(prepostfixed(prefix, postfix, `label_comp_id`), mappedProp(getLocation, P.atom.label_comp_id))
         .int(prepostfixed(prefix, postfix, `label_seq_id`), mappedProp(getLocation, P.residue.label_seq_id), {
             encoder: E.deltaRLE,
             valueKind: (k, d) => {
@@ -122,7 +122,7 @@ export function residueIdFields<K, D>(getLocation: (key: K, data: D) => Structur
         .str(prepostfixed(prefix, postfix, `label_asym_id`), mappedProp(getLocation, P.chain.label_asym_id))
         .str(prepostfixed(prefix, postfix, `label_entity_id`), mappedProp(getLocation, P.chain.label_entity_id))
 
-        .str(prepostfixed(prefix, postfix, `auth_comp_id`), mappedProp(getLocation, P.residue.auth_comp_id))
+        .str(prepostfixed(prefix, postfix, `auth_comp_id`), mappedProp(getLocation, P.atom.auth_comp_id))
         .int(prepostfixed(prefix, postfix, `auth_seq_id`), mappedProp(getLocation, P.residue.auth_seq_id), { encoder: E.deltaRLE })
         .str(prepostfixed(prefix, postfix, `auth_asym_id`), mappedProp(getLocation, P.chain.auth_asym_id));
 
@@ -154,7 +154,7 @@ export function atomIdFields<K, D>(getLocation: (key: K, data: D) => StructureEl
     const prefix = options && options.prefix, postfix = options && options.postfix;
     const ret = CifWriter.fields<K, D>()
         .str(prepostfixed(prefix, postfix, `label_atom_id`), mappedProp(getLocation, P.atom.label_atom_id))
-        .str(prepostfixed(prefix, postfix, `label_comp_id`), mappedProp(getLocation, P.residue.label_comp_id))
+        .str(prepostfixed(prefix, postfix, `label_comp_id`), mappedProp(getLocation, P.atom.label_comp_id))
         .int(prepostfixed(prefix, postfix, `label_seq_id`), mappedProp(getLocation, P.residue.label_seq_id), {
             encoder: E.deltaRLE,
             valueKind: (k, d) => {
@@ -170,7 +170,7 @@ export function atomIdFields<K, D>(getLocation: (key: K, data: D) => StructureEl
         .str(prepostfixed(prefix, postfix, `label_entity_id`), mappedProp(getLocation, P.chain.label_entity_id))
 
         .str(prepostfixed(prefix, postfix, `auth_atom_id`), mappedProp(getLocation, P.atom.auth_atom_id))
-        .str(prepostfixed(prefix, postfix, `auth_comp_id`), mappedProp(getLocation, P.residue.auth_comp_id))
+        .str(prepostfixed(prefix, postfix, `auth_comp_id`), mappedProp(getLocation, P.atom.auth_comp_id))
         .int(prepostfixed(prefix, postfix, `auth_seq_id`), mappedProp(getLocation, P.residue.auth_seq_id), { encoder: E.deltaRLE })
         .str(prepostfixed(prefix, postfix, `auth_asym_id`), mappedProp(getLocation, P.chain.auth_asym_id));
 

+ 12 - 10
src/mol-model/structure/model/properties/atomic/hierarchy.ts

@@ -34,6 +34,16 @@ export const AtomsSchema = {
      * Identifies an alternative conformation for this atom site.
      */
     label_alt_id: mmCIF.atom_site.label_alt_id,
+    /**
+     * A component of the identifier for this atom site.
+     * For mmCIF files, this points to chem_comp.id in the CHEM_COMP category.
+     */
+    label_comp_id: mmCIF.atom_site.label_comp_id,
+    /**
+     * An alternative identifier for atom_site.label_comp_id that may be provided by an author
+     * in order to match the identification used in the publication that describes the structure.
+     */
+    auth_comp_id: mmCIF.atom_site.auth_comp_id,
     /**
      * The net integer charge assigned to this atom.
      * This is the formal charge assignment normally found in chemical diagrams.
@@ -58,16 +68,6 @@ export const ResiduesSchema = {
      * compatibility with the original Protein Data Bank format, and only for that purpose.
      */
     group_PDB: mmCIF.atom_site.group_PDB,
-    /**
-     * A component of the identifier for this atom site.
-     * For mmCIF files, this points to chem_comp.id in the CHEM_COMP category.
-     */
-    label_comp_id: mmCIF.atom_site.label_comp_id,
-    /**
-     * An alternative identifier for atom_site.label_comp_id that may be provided by an author
-     * in order to match the identification used in the publication that describes the structure.
-     */
-    auth_comp_id: mmCIF.atom_site.auth_comp_id,
     /**
      * For mmCIF files, this points to entity_poly_seq.num in the ENTITY_POLY_SEQ category.
      */
@@ -81,6 +81,8 @@ export const ResiduesSchema = {
      * PDB insertion code.
      */
     pdbx_PDB_ins_code: mmCIF.atom_site.pdbx_PDB_ins_code,
+
+    // comp_id is part of atoms because of microheterogeneity
 };
 export type ResiduesSchema = typeof ResiduesSchema
 export type Residues = Table<ResiduesSchema>

+ 10 - 4
src/mol-model/structure/model/properties/sequence.ts

@@ -44,7 +44,8 @@ namespace StructureSequence {
     }
 
     export function fromAtomicHierarchy(entities: Entities, hierarchy: AtomicHierarchy): StructureSequence {
-        const { label_comp_id, label_seq_id } = hierarchy.residues;
+        const { label_comp_id } = hierarchy.atoms;
+        const { label_seq_id } = hierarchy.residues;
         const { chainAtomSegments, residueAtomSegments } = hierarchy;
         const { count, offsets } = chainAtomSegments;
 
@@ -70,12 +71,17 @@ namespace StructureSequence {
 
             const rStart = residueAtomSegments.index[offsets[start]];
             const rEnd = residueAtomSegments.index[offsets[cI + 1] - 1] + 1;
+            const seqId = Column.window(label_seq_id, rStart, rEnd);
+
+            const _compId: string[] = [];
+            for (let rI = rStart; rI < rEnd; ++rI) {
+                _compId.push(label_comp_id.value(residueAtomSegments.offsets[rI]));
+            }
+            const compId = Column.ofStringArray(_compId);
 
-            const compId = Column.window(label_comp_id, rStart, rEnd);
-            const num = Column.window(label_seq_id, rStart, rEnd);
             byEntityKey[entityKey] = {
                 entityId: entities.data.id.value(entityKey),
-                sequence: Sequence.ofResidueNames(compId, num)
+                sequence: Sequence.ofResidueNames(compId, seqId)
             };
 
             sequences.push(byEntityKey[entityKey]);

+ 6 - 4
src/mol-model/structure/model/properties/utils/atomic-derived.ts

@@ -5,15 +5,17 @@
  */
 
 import { AtomicData } from '../atomic';
-import { AtomicIndex, AtomicDerivedData } from '../atomic/hierarchy';
+import { AtomicIndex, AtomicDerivedData, AtomicSegments } from '../atomic/hierarchy';
 import { ElementIndex, ResidueIndex } from '../../indexing';
 import { MoleculeType, getMoleculeType, getComponentType, PolymerType, getPolymerType } from '../../types';
 import { getAtomIdForAtomRole } from '../../../../../mol-model/structure/util';
 import { ChemicalComponentMap } from '../common';
 import { isProductionMode } from '../../../../../mol-util/debug';
 
-export function getAtomicDerivedData(data: AtomicData, index: AtomicIndex, chemicalComponentMap: ChemicalComponentMap): AtomicDerivedData {
-    const { label_comp_id, _rowCount: n } = data.residues;
+export function getAtomicDerivedData(data: AtomicData, segments: AtomicSegments, index: AtomicIndex, chemicalComponentMap: ChemicalComponentMap): AtomicDerivedData {
+    const { label_comp_id } = data.atoms;
+    const { _rowCount: n } = data.residues;
+    const { offsets } = segments.residueAtomSegments;
 
     const traceElementIndex = new Int32Array(n);
     const directionFromElementIndex = new Int32Array(n);
@@ -25,7 +27,7 @@ export function getAtomicDerivedData(data: AtomicData, index: AtomicIndex, chemi
     const polymerTypeMap = new Map<string, PolymerType>();
 
     for (let i = 0 as ResidueIndex; i < n; ++i) {
-        const compId = label_comp_id.value(i);
+        const compId = label_comp_id.value(offsets[i]);
         const chemCompMap = chemicalComponentMap;
 
         let molType: MoleculeType;

+ 2 - 2
src/mol-model/structure/structure/carbohydrates/compute.ts

@@ -154,8 +154,8 @@ export function computeCarbohydrates(structure: Structure): Carbohydrates {
         if (!Unit.isAtomic(unit)) continue;
 
         const { model, rings } = unit;
-        const { chainAtomSegments, residueAtomSegments, residues } = model.atomicHierarchy;
-        const { label_comp_id } = residues;
+        const { chainAtomSegments, residueAtomSegments, atoms } = model.atomicHierarchy;
+        const { label_comp_id } = atoms;
 
         const chainIt = Segmentation.transientSegments(chainAtomSegments, unit.elements);
         const residueIt = Segmentation.transientSegments(residueAtomSegments, unit.elements);

+ 3 - 8
src/mol-model/structure/structure/properties.ts

@@ -51,20 +51,17 @@ const atom = {
     label_atom_id: p(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.atomicHierarchy.atoms.label_atom_id.value(l.element)),
     auth_atom_id: p(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.atomicHierarchy.atoms.auth_atom_id.value(l.element)),
     label_alt_id: p(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.atomicHierarchy.atoms.label_alt_id.value(l.element)),
+    label_comp_id: p(compId),
+    auth_comp_id: p(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.atomicHierarchy.atoms.auth_comp_id.value(l.unit.residueIndex[l.element])),
     pdbx_formal_charge: p(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.atomicHierarchy.atoms.pdbx_formal_charge.value(l.element)),
 
     // Derived
     vdw_radius: p(l => !Unit.isAtomic(l.unit) ? notAtomic() : VdwRadius(l.unit.model.atomicHierarchy.atoms.type_symbol.value(l.element))),
 };
 
-function _compId(l: StructureElement.Location) {
-    return !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.atomicHierarchy.residues.label_comp_id.value(l.unit.residueIndex[l.element]);
-}
-
 function compId(l: StructureElement.Location) {
     if (!Unit.isAtomic(l.unit)) notAtomic();
-    if (!hasMicroheterogeneity(l)) return _compId(l);
-    return l.unit.model.atomicHierarchy.residues.label_comp_id.value(l.unit.residueIndex[l.element]);
+    return l.unit.model.atomicHierarchy.atoms.label_comp_id.value(l.element);
 }
 
 function seqId(l: StructureElement.Location) {
@@ -91,8 +88,6 @@ const residue = {
     key: p(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.residueIndex[l.element]),
 
     group_PDB: p(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.atomicHierarchy.residues.group_PDB.value(l.unit.residueIndex[l.element])),
-    label_comp_id: p(compId),
-    auth_comp_id: p(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.atomicHierarchy.residues.auth_comp_id.value(l.unit.residueIndex[l.element])),
     label_seq_id: p(seqId),
     auth_seq_id: p(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.atomicHierarchy.residues.auth_seq_id.value(l.unit.residueIndex[l.element])),
     pdbx_PDB_ins_code: p(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.atomicHierarchy.residues.pdbx_PDB_ins_code.value(l.unit.residueIndex[l.element])),

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

@@ -408,7 +408,7 @@ function getModels(s: Structure) {
 }
 
 function getUniqueResidueNames(s: Structure) {
-    const prop = StructureProperties.residue.label_comp_id;
+    const prop = StructureProperties.atom.label_comp_id;
     const names = new Set<string>();
     const loc = StructureElement.Location.create(s);
     for (const unitGroup of s.unitSymmetryGroups) {
@@ -420,6 +420,7 @@ function getUniqueResidueNames(s: Structure) {
         while (residues.hasNext) {
             const seg = residues.move();
             loc.element = unit.elements[seg.start];
+            // TODO check for microhet
             names.add(prop(loc));
         }
     }

+ 4 - 4
src/mol-model/structure/structure/unit/bonds/inter-compute.ts

@@ -38,10 +38,10 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput
     const { elements: atomsB, residueIndex: residueIndexB } = unitB;
     const atomCount = unitA.elements.length;
 
-    const { type_symbol: type_symbolA, label_alt_id: label_alt_idA, label_atom_id: label_atom_idA } = unitA.model.atomicHierarchy.atoms;
-    const { type_symbol: type_symbolB, label_alt_id: label_alt_idB, label_atom_id: label_atom_idB } = unitB.model.atomicHierarchy.atoms;
-    const { label_comp_id: label_comp_idA, auth_seq_id: auth_seq_idA } = unitA.model.atomicHierarchy.residues;
-    const { label_comp_id: label_comp_idB, auth_seq_id: auth_seq_idB } = unitB.model.atomicHierarchy.residues;
+    const { type_symbol: type_symbolA, label_alt_id: label_alt_idA, label_atom_id: label_atom_idA, label_comp_id: label_comp_idA } = unitA.model.atomicHierarchy.atoms;
+    const { type_symbol: type_symbolB, label_alt_id: label_alt_idB, label_atom_id: label_atom_idB, label_comp_id: label_comp_idB } = unitB.model.atomicHierarchy.atoms;
+    const { auth_seq_id: auth_seq_idA } = unitA.model.atomicHierarchy.residues;
+    const { auth_seq_id: auth_seq_idB } = unitB.model.atomicHierarchy.residues;
     const { occupancy: occupancyA } = unitA.model.atomicConformation;
     const { occupancy: occupancyB } = unitB.model.atomicConformation;
     const hasOccupancy = occupancyA.isDefined && occupancyB.isDefined;

+ 2 - 2
src/mol-model/structure/structure/unit/bonds/intra-compute.ts

@@ -38,8 +38,8 @@ function _computeBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUni
     const { x, y, z } = unit.model.atomicConformation;
     const atomCount = unit.elements.length;
     const { elements: atoms, residueIndex, chainIndex } = unit;
-    const { type_symbol, label_atom_id, label_alt_id } = unit.model.atomicHierarchy.atoms;
-    const { label_comp_id, label_seq_id } = unit.model.atomicHierarchy.residues;
+    const { type_symbol, label_atom_id, label_alt_id, label_comp_id } = unit.model.atomicHierarchy.atoms;
+    const { label_seq_id } = unit.model.atomicHierarchy.residues;
     const { index } = unit.model.atomicHierarchy;
     const { byEntityKey } = unit.model.sequence;
     const query3d = unit.lookup3d;

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

@@ -99,8 +99,7 @@ namespace UnitRing {
 
     export function isAromatic(unit: Unit.Atomic, ring: UnitRing): boolean {
         const { elements, bonds: { b, offset, edgeProps: { flags } } } = unit;
-        const { type_symbol } = unit.model.atomicHierarchy.atoms;
-        const { label_comp_id } = unit.model.atomicHierarchy.residues;
+        const { type_symbol, label_comp_id } = unit.model.atomicHierarchy.atoms;
 
         // ignore Proline (can be flat because of bad geometry)
         if (label_comp_id.value(unit.getResidueIndex(ring[0])) === 'PRO') return false;

+ 5 - 4
src/mol-model/structure/util.ts

@@ -46,8 +46,9 @@ export function getAtomIdForAtomRole(polymerType: PolymerType, atomRole: AtomRol
 }
 
 export function residueLabel(model: Model, rI: number) {
-    const { residues, chains, residueAtomSegments, chainAtomSegments } = model.atomicHierarchy;
-    const { label_comp_id, label_seq_id } = residues;
+    const { atoms, residues, chains, residueAtomSegments, chainAtomSegments } = model.atomicHierarchy;
+    const { label_comp_id } = atoms;
+    const { label_seq_id } = residues;
     const { label_asym_id } = chains;
     const cI = chainAtomSegments.index[residueAtomSegments.offsets[rI]];
     return `${label_asym_id.value(cI)} ${label_comp_id.value(rI)} ${label_seq_id.value(rI)}`;
@@ -55,8 +56,8 @@ export function residueLabel(model: Model, rI: number) {
 
 export function elementLabel(model: Model, index: ElementIndex) {
     const { atoms, residues, chains, residueAtomSegments, chainAtomSegments } = model.atomicHierarchy;
-    const { label_atom_id } = atoms;
-    const { auth_seq_id, label_comp_id } = residues;
+    const { label_atom_id, label_comp_id } = atoms;
+    const { auth_seq_id } = residues;
     const { auth_asym_id } = chains;
 
     const residueIndex = residueAtomSegments.index[index];

+ 2 - 2
src/mol-plugin-ui/sequence/hetero.ts

@@ -74,14 +74,14 @@ export class HeteroSequenceWrapper extends SequenceWrapper<StructureUnit> {
 
         for (let i = 0, il = data.units.length; i < il; ++i) {
             const unit = data.units[i];
-            const { residueAtomSegments, residues } = unit.model.atomicHierarchy;
+            const { residueAtomSegments, atoms } = unit.model.atomicHierarchy;
             const residueIt = Segmentation.transientSegments(residueAtomSegments, unit.elements);
             while (residueIt.hasNext) {
                 const { index } = residueIt.move();
                 sequenceIndices.set(index, sequence.length);
                 residueIndices.set(sequence.length, index);
                 seqToUnit.set(sequence.length, unit);
-                sequence.push(residues.label_comp_id.value(index));
+                sequence.push(atoms.label_comp_id.value(index));
             }
         }
 

+ 2 - 1
src/mol-repr/structure/visual/label-text.ts

@@ -94,7 +94,8 @@ function createChainText(ctx: VisualContext, structure: Structure, theme: Theme,
 function createResidueText(ctx: VisualContext, structure: Structure, theme: Theme, props: LabelTextProps, text?: Text): Text {
     const l = StructureElement.Location.create(structure);
     const { units, serialMapping } = structure;
-    const { auth_seq_id, label_comp_id } = StructureProperties.residue;
+    const { label_comp_id } = StructureProperties.atom;
+    const { auth_seq_id } = StructureProperties.residue;
     const { cumulativeUnitElementCount } = serialMapping;
 
     const count = structure.polymerResidueCount * 2;

+ 2 - 2
src/mol-repr/structure/visual/nucleotide-block-mesh.ts

@@ -55,9 +55,9 @@ function createNucleotideBlockMesh(ctx: VisualContext, unit: Unit, structure: St
     const builderState = MeshBuilder.createState(vertexCount, vertexCount / 4, mesh);
 
     const { elements, model } = unit;
-    const { chainAtomSegments, residueAtomSegments, residues, index: atomicIndex } = model.atomicHierarchy;
+    const { chainAtomSegments, residueAtomSegments, atoms, index: atomicIndex } = model.atomicHierarchy;
     const { moleculeType, traceElementIndex } = model.atomicHierarchy.derived.residue;
-    const { label_comp_id } = residues;
+    const { label_comp_id } = atoms;
     const pos = unit.conformation.invariantPosition;
 
     const chainIt = Segmentation.transientSegments(chainAtomSegments, elements);

+ 2 - 2
src/mol-repr/structure/visual/nucleotide-ring-mesh.ts

@@ -74,9 +74,9 @@ function createNucleotideRingMesh(ctx: VisualContext, unit: Unit, structure: Str
     const builderState = MeshBuilder.createState(vertexCount, vertexCount / 4, mesh);
 
     const { elements, model } = unit;
-    const { chainAtomSegments, residueAtomSegments, residues, index: atomicIndex } = model.atomicHierarchy;
+    const { chainAtomSegments, residueAtomSegments, atoms, index: atomicIndex } = model.atomicHierarchy;
     const { moleculeType, traceElementIndex } = model.atomicHierarchy.derived.residue;
-    const { label_comp_id } = residues;
+    const { label_comp_id } = atoms;
     const pos = unit.conformation.invariantPosition;
 
     const chainIt = Segmentation.transientSegments(chainAtomSegments, elements);

+ 4 - 4
src/mol-script/runtime/query/table.ts

@@ -319,15 +319,15 @@ const symbols = [
 
     D(MolScript.structureQuery.atomProperty.macromolecular.label_atom_id, atomProp(StructureProperties.atom.label_atom_id)),
     D(MolScript.structureQuery.atomProperty.macromolecular.label_alt_id, atomProp(StructureProperties.atom.label_alt_id)),
-    D(MolScript.structureQuery.atomProperty.macromolecular.label_asym_id, atomProp(StructureProperties.chain.label_asym_id)),
-    D(MolScript.structureQuery.atomProperty.macromolecular.label_comp_id, atomProp(StructureProperties.residue.label_comp_id)),
+    D(MolScript.structureQuery.atomProperty.macromolecular.label_comp_id, atomProp(StructureProperties.atom.label_comp_id)),
     D(MolScript.structureQuery.atomProperty.macromolecular.label_seq_id, atomProp(StructureProperties.residue.label_seq_id)),
+    D(MolScript.structureQuery.atomProperty.macromolecular.label_asym_id, atomProp(StructureProperties.chain.label_asym_id)),
     D(MolScript.structureQuery.atomProperty.macromolecular.label_entity_id, atomProp(StructureProperties.entity.id)),
 
     D(MolScript.structureQuery.atomProperty.macromolecular.auth_atom_id, atomProp(StructureProperties.atom.auth_atom_id)),
-    D(MolScript.structureQuery.atomProperty.macromolecular.auth_asym_id, atomProp(StructureProperties.chain.auth_asym_id)),
-    D(MolScript.structureQuery.atomProperty.macromolecular.auth_comp_id, atomProp(StructureProperties.residue.auth_comp_id)),
+    D(MolScript.structureQuery.atomProperty.macromolecular.auth_comp_id, atomProp(StructureProperties.atom.auth_comp_id)),
     D(MolScript.structureQuery.atomProperty.macromolecular.auth_seq_id, atomProp(StructureProperties.residue.auth_seq_id)),
+    D(MolScript.structureQuery.atomProperty.macromolecular.auth_asym_id, atomProp(StructureProperties.chain.auth_asym_id)),
 
     D(MolScript.structureQuery.atomProperty.macromolecular.pdbx_PDB_ins_code, atomProp(StructureProperties.residue.pdbx_PDB_ins_code)),
     D(MolScript.structureQuery.atomProperty.macromolecular.pdbx_formal_charge, atomProp(StructureProperties.atom.pdbx_formal_charge)),

+ 1 - 1
src/mol-theme/color/hydrophobicity.ts

@@ -31,7 +31,7 @@ export function hydrophobicity(compId: string, scaleIndex: number): number {
 }
 
 function getAtomicCompId(unit: Unit.Atomic, element: ElementIndex) {
-    return unit.model.atomicHierarchy.residues.label_comp_id.value(unit.residueIndex[element]);
+    return unit.model.atomicHierarchy.atoms.label_comp_id.value(unit.residueIndex[element]);
 }
 
 function getCoarseCompId(unit: Unit.Spheres | Unit.Gaussians, element: ElementIndex) {

+ 1 - 1
src/mol-theme/color/residue-name.ts

@@ -74,7 +74,7 @@ export function getResidueNameColorThemeParams(ctx: ThemeDataContext) {
 }
 
 function getAtomicCompId(unit: Unit.Atomic, element: ElementIndex) {
-    return unit.model.atomicHierarchy.residues.label_comp_id.value(unit.residueIndex[element]);
+    return unit.model.atomicHierarchy.atoms.label_comp_id.value(unit.residueIndex[element]);
 }
 
 function getCoarseCompId(unit: Unit.Spheres | Unit.Gaussians, element: ElementIndex) {

+ 1 - 1
src/mol-theme/label.ts

@@ -239,7 +239,7 @@ function _atomicElementLabel(location: StructureElement.Location<Unit.Atomic>, g
     const label_seq_id = Props.residue.label_seq_id(location);
     const auth_seq_id = Props.residue.auth_seq_id(location);
     const ins_code = Props.residue.pdbx_PDB_ins_code(location);
-    const comp_id = Props.residue.label_comp_id(location);
+    const comp_id = Props.atom.label_comp_id(location);
     const atom_id = Props.atom.label_atom_id(location);
     const alt_id = Props.atom.label_alt_id(location);
     const occupancy = Props.atom.occupancy(location);