diff --git a/src/apps/structure-info/model.ts b/src/apps/structure-info/model.ts
index b284d0422cd3886ca54532a2f028267649c75cbf..5abea8553fa240cbdf5dd88df4a8a9c3b7ee11d0 100644
--- a/src/apps/structure-info/model.ts
+++ b/src/apps/structure-info/model.ts
@@ -96,7 +96,7 @@ export function printUnits(structure: Structure) {
         if (Unit.isAtomic(l.unit)) {
             console.log(`Atomic unit ${unitId}: ${size} elements`);
         } else if (Unit.isCoarse(l.unit)) {
-            console.log(`Coarse unit ${unitId} (${Unit.isCoarseSpheres(l.unit) ? 'spheres' : 'gaussians'}): ${size} elements.`);
+            console.log(`Coarse unit ${unitId} (${Unit.isSpheres(l.unit) ? 'spheres' : 'gaussians'}): ${size} elements.`);
 
             const props = Queries.props.coarse_grained;
             const seq = l.unit.model.sequence;
diff --git a/src/mol-data/util/hash-functions.ts b/src/mol-data/util/hash-functions.ts
index 00cae92c4d6f16ba47ed7281b5a773d432198164..8584baa5946e9a06a4ef1ca8e07b8e43607028b9 100644
--- a/src/mol-data/util/hash-functions.ts
+++ b/src/mol-data/util/hash-functions.ts
@@ -45,6 +45,14 @@ export function hash4(i: number, j: number, k: number, l: number) {
     return a;
 }
 
+export function hashString(s: string) {
+    let h = 0;
+    for (let i = 0, l = s.length; i < l; i++) {
+        h = (h << 5) - h + s.charCodeAt(i++) | 0;
+    }
+    return h;
+}
+
 /**
  * A unique number for each pair of integers
  * Biggest representable pair is (67108863, 67108863) (limit imposed by Number.MAX_SAFE_INTEGER)
diff --git a/src/mol-model/structure/query/properties.ts b/src/mol-model/structure/query/properties.ts
index f358b3debf0db65a34b8a8743f4db115e7788ddf..e9a8140747807b675984efe5d2ae5e1e096d729a 100644
--- a/src/mol-model/structure/query/properties.ts
+++ b/src/mol-model/structure/query/properties.ts
@@ -60,6 +60,7 @@ const chain = {
 }
 
 const coarse_grained = {
+    key: atom.key,
     modelKey: Element.property(l => !Unit.isCoarse(l.unit) ? notCoarse() : l.unit.sites.modelKey[l.element]),
     entityKey: Element.property(l => !Unit.isCoarse(l.unit) ? notCoarse() : l.unit.sites.entityKey[l.element]),
 
@@ -71,11 +72,11 @@ const coarse_grained = {
     seq_id_begin: Element.property(l => !Unit.isCoarse(l.unit) ? notCoarse() : l.unit.sites.seq_id_begin.value(l.element)),
     seq_id_end: Element.property(l => !Unit.isCoarse(l.unit) ? notCoarse() : l.unit.sites.seq_id_end.value(l.element)),
 
-    sphere_radius: Element.property(l => !Unit.isCoarseSpheres(l.unit) ? notCoarse('spheres') : l.unit.sites.radius.value(l.element)),
-    sphere_rmsf: Element.property(l => !Unit.isCoarseSpheres(l.unit) ? notCoarse('spheres') : l.unit.sites.rmsf.value(l.element)),
+    sphere_radius: Element.property(l => !Unit.isSpheres(l.unit) ? notCoarse('spheres') : l.unit.sites.radius.value(l.element)),
+    sphere_rmsf: Element.property(l => !Unit.isSpheres(l.unit) ? notCoarse('spheres') : l.unit.sites.rmsf.value(l.element)),
 
-    gaussian_weight: Element.property(l => !Unit.isCoarseGaussians(l.unit) ? notCoarse('gaussians') : l.unit.sites.weight.value(l.element)),
-    gaussian_covariance_matrix: Element.property(l => !Unit.isCoarseGaussians(l.unit) ? notCoarse('gaussians') : l.unit.sites.covariance_matrix.value(l.element))
+    gaussian_weight: Element.property(l => !Unit.isGaussians(l.unit) ? notCoarse('gaussians') : l.unit.sites.weight.value(l.element)),
+    gaussian_covariance_matrix: Element.property(l => !Unit.isGaussians(l.unit) ? notCoarse('gaussians') : l.unit.sites.covariance_matrix.value(l.element))
 }
 
 function eK(l: Element.Location) { return !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.hierarchy.entityKey.value(l.unit.chainIndex[l.element]); }
diff --git a/src/mol-model/structure/structure/structure.ts b/src/mol-model/structure/structure/structure.ts
index 99ac010ade4da0cbdb50db65341a0b75e3446545..4447c1936c1b78c89043b000403207434cde3a3c 100644
--- a/src/mol-model/structure/structure/structure.ts
+++ b/src/mol-model/structure/structure/structure.ts
@@ -43,12 +43,12 @@ namespace Structure {
         if (cs.isDefined) {
             if (cs.spheres.count > 0) {
                 const group = ElementGroup.createNew(OrderedSet.ofBounds(0, cs.spheres.count));
-                const unit = Unit.create(Unit.Kind.CoarseSpheres, model, SymmetryOperator.Default, group);
+                const unit = Unit.create(Unit.Kind.Spheres, model, SymmetryOperator.Default, group);
                 builder.add(unit, unit.fullGroup);
             }
             if (cs.gaussians.count > 0) {
                 const group = ElementGroup.createNew(OrderedSet.ofBounds(0, cs.gaussians.count));
-                const unit = Unit.create(Unit.Kind.CoarseGaussians, model, SymmetryOperator.Default, group);
+                const unit = Unit.create(Unit.Kind.Gaussians, model, SymmetryOperator.Default, group);
                 builder.add(unit, unit.fullGroup);
             }
         }
diff --git a/src/mol-model/structure/structure/unit.ts b/src/mol-model/structure/structure/unit.ts
index 0ef49b456622299c93e65a89a2936e36f783dd77..3c82688a421d1aa5570778b92d753ace961d3b8c 100644
--- a/src/mol-model/structure/structure/unit.ts
+++ b/src/mol-model/structure/structure/unit.ts
@@ -13,15 +13,15 @@ import CoarseGrained from '../model/properties/coarse-grained';
 
 // A building block of a structure that corresponds to an atomic or a coarse grained representation
 // 'conveniently grouped together'.
-type Unit = Unit.Atomic | Unit.CoarseSpheres | Unit.CoarseGaussians
+type Unit = Unit.Atomic | Unit.Spheres | Unit.Gaussians
 
 namespace Unit {
-    export const enum Kind { Atomic, CoarseSpheres, CoarseGaussians }
+    export const enum Kind { Atomic, Spheres, Gaussians }
 
     export function isAtomic(u: Unit): u is Atomic { return u.kind === Kind.Atomic; }
-    export function isCoarse(u: Unit): u is CoarseSpheres | CoarseGaussians { return u.kind === Kind.CoarseSpheres || u.kind === Kind.CoarseGaussians; }
-    export function isCoarseSpheres(u: Unit): u is CoarseSpheres { return u.kind === Kind.CoarseSpheres; }
-    export function isCoarseGaussians(u: Unit): u is CoarseGaussians { return u.kind === Kind.CoarseGaussians; }
+    export function isCoarse(u: Unit): u is Spheres | Gaussians { return u.kind === Kind.Spheres || u.kind === Kind.Gaussians; }
+    export function isSpheres(u: Unit): u is Spheres { return u.kind === Kind.Spheres; }
+    export function isGaussians(u: Unit): u is Gaussians { return u.kind === Kind.Gaussians; }
 
     export interface Base extends SymmetryOperator.ArrayMapping {
         // Provides access to the underlying data.
@@ -58,14 +58,14 @@ namespace Unit {
         readonly sites: S
     }
 
-    export interface CoarseSpheres extends CoarseBase<Kind.CoarseSpheres, CoarseGrained.Spheres> { }
-    export interface CoarseGaussians extends CoarseBase<Kind.CoarseGaussians, CoarseGrained.Gaussians> { }
+    export interface Spheres extends CoarseBase<Kind.Spheres, CoarseGrained.Spheres> { }
+    export interface Gaussians extends CoarseBase<Kind.Gaussians, CoarseGrained.Gaussians> { }
 
     export function create(kind: Kind, model: Model, operator: SymmetryOperator, fullGroup: ElementGroup): Unit {
         switch (kind) {
             case Kind.Atomic: return createAtomic(model, operator, fullGroup);
-            case Kind.CoarseSpheres: return createCoarseSpheres(model, operator, fullGroup);
-            case Kind.CoarseGaussians: return createCoarseGaussians(model, operator, fullGroup);
+            case Kind.Spheres: return createSpheres(model, operator, fullGroup);
+            case Kind.Gaussians: return createGaussians(model, operator, fullGroup);
         }
     }
 
@@ -88,12 +88,12 @@ namespace Unit {
         };
     }
 
-    function createCoarseSpheres(model: Model, operator: SymmetryOperator, fullGroup: ElementGroup): Unit.CoarseSpheres {
+    function createSpheres(model: Model, operator: SymmetryOperator, fullGroup: ElementGroup): Unit.Spheres {
         const { invariantPosition, position, x, y, z } = SymmetryOperator.createMapping(operator, model.coarseGrained.spheres);
 
         return {
             model,
-            kind: Kind.CoarseSpheres,
+            kind: Kind.Spheres,
             sites: model.coarseGrained.spheres,
             operator,
             fullGroup,
@@ -103,12 +103,12 @@ namespace Unit {
         };
     }
 
-    function createCoarseGaussians(model: Model, operator: SymmetryOperator, fullGroup: ElementGroup): Unit.CoarseGaussians {
+    function createGaussians(model: Model, operator: SymmetryOperator, fullGroup: ElementGroup): Unit.Gaussians {
         const { invariantPosition, position, x, y, z } = SymmetryOperator.createMapping(operator, model.coarseGrained.gaussians);
 
         return {
             model,
-            kind: Kind.CoarseGaussians,
+            kind: Kind.Gaussians,
             sites: model.coarseGrained.gaussians,
             operator,
             fullGroup,