diff --git a/src/mol-math/geometry/symmetry-operator.ts b/src/mol-math/geometry/symmetry-operator.ts
index 053113865b69a758645180e5d0fe3d11372a5939..d0065a740df3b01a91989834aa12e017e0a9fe7c 100644
--- a/src/mol-math/geometry/symmetry-operator.ts
+++ b/src/mol-math/geometry/symmetry-operator.ts
@@ -23,13 +23,19 @@ namespace SymmetryOperator {
 
     const RotationEpsilon = 0.0001;
 
-    export function create(name: string, matrix: Mat4, hkl?: number[]): SymmetryOperator {
-        const _hkl = hkl ? Vec3.create(hkl[0], hkl[1], hkl[2]) : Vec3.zero();
+    export function create(name: string, matrix: Mat4, hkl?: Vec3): SymmetryOperator {
+        const _hkl = hkl ? Vec3.copy(Vec3.zero(), hkl) : Vec3.zero();
         if (Mat4.isIdentity(matrix)) return { name, matrix, inverse: Mat4.identity(), isIdentity: true, hkl: _hkl };
         if (!Mat4.isRotationAndTranslation(matrix, RotationEpsilon)) throw new Error(`Symmetry operator (${name}) must be a composition of rotation and translation.`);
         return { name, matrix, inverse: Mat4.invert(Mat4.zero(), matrix), isIdentity: false, hkl: _hkl };
     }
 
+    // Apply the 1st and then 2nd operator. ( = second.matrix * first.matrix)
+    export function compose(first: SymmetryOperator, second: SymmetryOperator) {
+        const matrix = Mat4.mul(Mat4.zero(), second.matrix, first.matrix);
+        return create(second.name, matrix, second.hkl);
+    }
+
     export interface CoordinateMapper { (index: number, slot: Vec3): Vec3 }
     export interface ArrayMapping {
         readonly invariantPosition: CoordinateMapper,
diff --git a/src/mol-model/structure/structure/structure.ts b/src/mol-model/structure/structure/structure.ts
index 9d25590e4cd1cf317f31cace6c0dc0e29905ee57..da8546c2cf24c4d8d6ec76ac2cdc9d0bd60cd88e 100644
--- a/src/mol-model/structure/structure/structure.ts
+++ b/src/mol-model/structure/structure/structure.ts
@@ -37,7 +37,7 @@ namespace Structure {
 
         for (let c = 0; c < chains.count; c++) {
             const group = AtomGroup.createNew(OrderedSet.ofBounds(chains.segments[c], chains.segments[c + 1]));
-            const unit = Unit.create(c, model, SymmetryOperator.Default, group);
+            const unit = Unit.create(model, SymmetryOperator.Default, group);
             builder.add(unit, OrderedSet.ofBounds(chains.segments[c], chains.segments[c + 1]));
         }
 
@@ -53,12 +53,13 @@ namespace Structure {
     }
 
     class BuilderImpl implements Builder {
+        private _unitId = 0;
         private units = IntMap.Mutable<Unit>();
         private atoms = AtomSet.Generator();
         atomCount = 0;
 
-        add(unit: Unit, atoms: OrderedSet) { this.addUnit(unit); this.setAtoms(unit.id, atoms); }
-        addUnit(unit: Unit) { this.units.set(unit.id, unit); }
+        add(unit: Unit, atoms: OrderedSet) { const id = this.addUnit(unit); this.setAtoms(id, atoms); }
+        addUnit(unit: Unit) { const id = this._unitId++; this.units.set(id, unit); return id; }
         setAtoms(unitId: number, atoms: OrderedSet) { this.atoms.add(unitId, atoms); this.atomCount += OrderedSet.size(atoms); }
         getStructure(): Structure { return this.atomCount > 0 ? Structure.create(this.units, this.atoms.getSet()) : Empty; }
     }
diff --git a/src/mol-model/structure/structure/symmetry.ts b/src/mol-model/structure/structure/symmetry.ts
index daa45f3fb6bf01fd034d057ac489af7d7962f4f0..a0348b6745dc02f4ba01c20542fdaa30d6cabf86 100644
--- a/src/mol-model/structure/structure/symmetry.ts
+++ b/src/mol-model/structure/structure/symmetry.ts
@@ -25,7 +25,6 @@ function buildAssemblyImpl(structure: Structure, name: string) {
 
     const assembler = Structure.Builder();
 
-    let unitId = 0;
     for (const g of assembly.operatorGroups) {
         const selection = g.selector(structure);
         if (Selection.structureCount(selection) === 0) continue;
@@ -36,7 +35,7 @@ function buildAssemblyImpl(structure: Structure, name: string) {
         for (const oper of g.operators) {
             for (let uI = 0, _uI = unitIds.length; uI < _uI; uI++) {
                 const unit = units.get(unitIds[uI]);
-                assembler.add(Unit.create(unitId++, unit.model, oper, unit.naturalGroup), AtomSet.unitGetByIndex(atoms, uI));
+                assembler.add(Unit.withOperator(unit, oper), AtomSet.unitGetByIndex(atoms, uI));
             }
         }
     }
diff --git a/src/mol-model/structure/structure/unit.ts b/src/mol-model/structure/structure/unit.ts
index e8edaa4c4f0e2a4964daa9c1bb6529a0a19e05dc..05bc6315c26f0448be4c9cf568e5cdf478a4b243 100644
--- a/src/mol-model/structure/structure/unit.ts
+++ b/src/mol-model/structure/structure/unit.ts
@@ -9,9 +9,6 @@ import AtomGroup from './atom/group'
 import { Model } from '../model'
 
 interface Unit extends SymmetryOperator.ArrayMapping {
-    // Structure-level unique identifier of the unit.
-    readonly id: number,
-
     // Provides access to the underlying data.
     readonly model: Model,
 
@@ -32,12 +29,11 @@ interface Unit extends SymmetryOperator.ArrayMapping {
 }
 
 namespace Unit {
-    export function create(id: number, model: Model, operator: SymmetryOperator, naturalGroup: AtomGroup): Unit {
+    export function create(model: Model, operator: SymmetryOperator, naturalGroup: AtomGroup): Unit {
         const h = model.hierarchy;
         const { invariantPosition, position, x, y, z } = SymmetryOperator.createMapping(operator, model.conformation);
 
         return {
-            id,
             model,
             operator,
             naturalGroup,
@@ -50,6 +46,10 @@ namespace Unit {
             x, y, z
         };
     }
+
+    export function withOperator(unit: Unit, operator: SymmetryOperator) {
+        return create(unit.model, SymmetryOperator.compose(unit.operator, operator), unit.naturalGroup);
+    }
 }
 
 export default Unit;
\ No newline at end of file