diff --git a/src/apps/render-test/components/detail.tsx b/src/apps/render-test/components/detail.tsx
index a53c64f826c6b77a33af5aeb258d90e00d53ab7c..9bbd84a6de3b6f208ece2c5d52f959f463a9b9d9 100644
--- a/src/apps/render-test/components/detail.tsx
+++ b/src/apps/render-test/components/detail.tsx
@@ -38,7 +38,7 @@ export default class Detail extends Observer<{ state: State } & WithStyles, Deta
     render() {
         const { classes } = this.props;
 
-        const items = [0, 1, 2].map((value, idx) => {
+        const items = [0, 1, 2, 3].map((value, idx) => {
             return <MenuItem key={idx} value={value}>{value.toString()}</MenuItem>
         })
 
diff --git a/src/mol-geo/primitive/icosahedron.ts b/src/mol-geo/primitive/icosahedron.ts
index 7e73afb419daeef55278241fafe2cfef5f7dbeaf..07e544e07fcfdd7cddb36940173f2841c58da169 100644
--- a/src/mol-geo/primitive/icosahedron.ts
+++ b/src/mol-geo/primitive/icosahedron.ts
@@ -23,6 +23,10 @@ const indices = [
      4, 9, 5, 	2, 4, 11,	6, 2, 10,	8, 6, 7,	9, 8, 1
 ];
 
+export function icosahedronVertexCount(detail: number) {
+    return 10 * Math.pow(Math.pow(2, detail), 2) + 2
+}
+
 export const DefaultIcosahedronProps = {
     radius: 1,
     detail: 0
diff --git a/src/mol-geo/representation/structure/point.ts b/src/mol-geo/representation/structure/point.ts
index b95347fb17e7035214d95963c38d896bf2002262..73884615d0dbaf21f78d746862c4d42b89cbc86e 100644
--- a/src/mol-geo/representation/structure/point.ts
+++ b/src/mol-geo/representation/structure/point.ts
@@ -7,7 +7,7 @@
 import { ValueCell } from 'mol-util/value-cell'
 import { createPointRenderObject, RenderObject, PointRenderObject } from 'mol-gl/scene'
 import { OrderedSet } from 'mol-data/int'
-import { Unit, ElementGroup } from 'mol-model/structure';
+import { Unit, ElementGroup, Element } from 'mol-model/structure';
 import { Task } from 'mol-task'
 import { fillSerial } from 'mol-gl/renderable/util';
 
@@ -26,13 +26,17 @@ export type PointProps = Partial<typeof DefaultPointProps>
 export function createPointVertices(unit: Unit, elementGroup: ElementGroup) {
     const elementCount = OrderedSet.size(elementGroup.elements)
     const vertices = new Float32Array(elementCount * 3)
-    const { x, y, z } = unit.model.atomSiteConformation
+
+    const { x, y, z } = unit
+    const l = Element.Location()
+    l.unit = unit
+
     for (let i = 0; i < elementCount; i++) {
-        const e = OrderedSet.getAt(elementGroup.elements, i)
+        l.element = ElementGroup.getAt(elementGroup, i)
         const i3 = i * 3
-        vertices[i3] = x[e]
-        vertices[i3 + 1] = y[e]
-        vertices[i3 + 2] = z[e]
+        vertices[i3] = x(l.element)
+        vertices[i3 + 1] = y(l.element)
+        vertices[i3 + 2] = z(l.element)
     }
     return vertices
 }
diff --git a/src/mol-geo/representation/structure/spacefill.ts b/src/mol-geo/representation/structure/spacefill.ts
index 4e2f9168361a547201b789eb28fdbddc9b66309b..47d238d2de34c249e29b7bdbe3f7afa217d2fc88 100644
--- a/src/mol-geo/representation/structure/spacefill.ts
+++ b/src/mol-geo/representation/structure/spacefill.ts
@@ -10,15 +10,15 @@ import { RenderObject, createMeshRenderObject, MeshRenderObject } from 'mol-gl/s
 // import { createColorTexture } from 'mol-gl/util';
 import { Vec3, Mat4 } from 'mol-math/linear-algebra'
 import { OrderedSet } from 'mol-data/int'
-import { Unit, ElementGroup } from 'mol-model/structure';
+import { Unit, ElementGroup, Element, Queries } from 'mol-model/structure';
 import { RepresentationProps, UnitsRepresentation } from './index';
 import { Task } from 'mol-task'
 import { MeshBuilder } from '../../shape/mesh-builder';
-import { VdwRadius } from 'mol-model/structure/model/properties/atomic';
 import { createTransforms, createColors } from './utils';
 import { ColorTheme } from '../../theme';
 import VertexMap from '../../shape/vertex-map';
 import CoarseGrained from 'mol-model/structure/model/properties/coarse-grained';
+import { icosahedronVertexCount } from '../../primitive/icosahedron';
 
 export const DefaultSpacefillProps = {
     detail: 0,
@@ -26,72 +26,43 @@ export const DefaultSpacefillProps = {
 }
 export type SpacefillProps = Partial<typeof DefaultSpacefillProps>
 
-function buildAtomSpheres(meshBuilder: MeshBuilder, unit: Unit, elementGroup: ElementGroup, detail: number) {
-    return Task.create('Atom spheres', async ctx => {
-        if (!Unit.isAtomic(unit)) return
-
-        const v = Vec3.zero()
-        const m = Mat4.identity()
-
-        const { x, y, z } = unit.model.atomSiteConformation
-        const { type_symbol } = unit.model.hierarchy.atoms
+function createSpacefillMesh(unit: Unit, elementGroup: ElementGroup, detail: number) {
+    return Task.create('Sphere mesh', async ctx => {
         const elementCount = OrderedSet.size(elementGroup.elements)
-        for (let i = 0; i < elementCount; i++) {
-            const e = OrderedSet.getAt(elementGroup.elements, i)
-            v[0] = x[e]
-            v[1] = y[e]
-            v[2] = z[e]
-            Mat4.setTranslation(m, v)
+        const vertexCount = elementCount * icosahedronVertexCount(detail)
+        const meshBuilder = MeshBuilder.create(vertexCount)
 
-            meshBuilder.setId(i)
-            meshBuilder.addIcosahedron(m, { radius: VdwRadius(type_symbol.value(e)), detail })
-
-            if (i % 10000 === 0 && ctx.shouldUpdate) {
-                await ctx.update({ message: 'Atom spheres', current: i, max: elementCount });
-            }
+        let radius: Element.Property<number>
+        if (Unit.isAtomic(unit)) {
+            radius = Queries.props.atom.vdw_radius
+        } else if (Unit.isCoarse(unit) && unit.elementType === CoarseGrained.ElementType.Sphere) {
+            radius = Queries.props.coarse_grained.sphere_radius
+        } else {
+            console.warn('Unsupported unit type')
+            return meshBuilder.getMesh()
         }
-    })
-}
-
-function buildCoarseSpheres(meshBuilder: MeshBuilder, unit: Unit, elementGroup: ElementGroup, detail: number) {
-    return Task.create('Coarse spheres', async ctx => {
-        if (!Unit.isCoarse(unit) || unit.elementType !== CoarseGrained.ElementType.Sphere) return
 
         const v = Vec3.zero()
         const m = Mat4.identity()
 
-        const { x, y, z, radius } = unit.model.coarseGrained.spheres
-        const elementCount = OrderedSet.size(elementGroup.elements)
-        console.log('building coarse spheres', elementCount)
+        const { x, y, z } = unit
+        const l = Element.Location()
+        l.unit = unit
+
         for (let i = 0; i < elementCount; i++) {
-            const e = OrderedSet.getAt(elementGroup.elements, i)
-            v[0] = x[e]
-            v[1] = y[e]
-            v[2] = z[e]
+            l.element = ElementGroup.getAt(elementGroup, i)
+            v[0] = x(l.element)
+            v[1] = y(l.element)
+            v[2] = z(l.element)
             Mat4.setTranslation(m, v)
 
             meshBuilder.setId(i)
-            meshBuilder.addIcosahedron(m, { radius: radius.value(e), detail })
+            meshBuilder.addIcosahedron(m, { radius: radius(l), detail })
 
             if (i % 10000 === 0 && ctx.shouldUpdate) {
-                await ctx.update({ message: 'Coarse spheres', current: i, max: elementCount });
+                await ctx.update({ message: 'Sphere mesh', current: i, max: elementCount });
             }
         }
-    })
-}
-
-function createSpacefillMesh(unit: Unit, elementGroup: ElementGroup, detail: number) {
-    return Task.create('Spacefill', async ctx => {
-        const meshBuilder = MeshBuilder.create()
-
-        if (Unit.isAtomic(unit)) {
-            await ctx.runChild(buildAtomSpheres(meshBuilder, unit, elementGroup, detail))
-        }
-
-        if (Unit.isCoarse(unit) && unit.elementType === CoarseGrained.ElementType.Sphere) {
-            console.log('building coarse spheres')
-            await ctx.runChild(buildCoarseSpheres(meshBuilder, unit, elementGroup, detail))
-        }
 
         return meshBuilder.getMesh()
     })
diff --git a/src/mol-geo/representation/structure/utils.ts b/src/mol-geo/representation/structure/utils.ts
index 65f7b35962d4b6eb769b8d34de2d4ff3ece77f59..fba67c536e46e9447fd19b170299d25771b19996 100644
--- a/src/mol-geo/representation/structure/utils.ts
+++ b/src/mol-geo/representation/structure/utils.ts
@@ -9,7 +9,7 @@ import { Mat4 } from 'mol-math/linear-algebra'
 
 import { createUniformColor } from '../../util/color-data';
 import { createUniformSize } from '../../util/size-data';
-import { vdwSizeData } from '../../theme/structure/size/vdw';
+import { elementSizeData } from '../../theme/structure/size/element';
 import VertexMap from '../../shape/vertex-map';
 import { ColorTheme, SizeTheme } from '../../theme';
 import { elementIndexColorData, elementSymbolColorData, instanceIndexColorData, chainIdColorData } from '../../theme/structure/color';
@@ -43,6 +43,6 @@ export function createSizes(units: ReadonlyArray<Unit>, elementGroup: ElementGro
         case 'uniform':
             return createUniformSize(props)
         case 'vdw':
-            return vdwSizeData({ units, elementGroup, vertexMap })
+            return elementSizeData({ units, elementGroup, vertexMap })
     }
 }
\ No newline at end of file
diff --git a/src/mol-geo/theme/structure/size/element.ts b/src/mol-geo/theme/structure/size/element.ts
new file mode 100644
index 0000000000000000000000000000000000000000..699bc071a499ab303d3e40d48c3befb465248afe
--- /dev/null
+++ b/src/mol-geo/theme/structure/size/element.ts
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { ElementGroup, Element, Unit, Queries } from 'mol-model/structure';
+import CoarseGrained from 'mol-model/structure/model/properties/coarse-grained';
+import { StructureSizeDataProps } from '.';
+import { createAttributeSize } from '../../../util/size-data';
+
+/** Create attribute data with the size of an element, i.e. vdw for atoms and radius for coarse spheres */
+export function elementSizeData(props: StructureSizeDataProps) {
+    const { units, elementGroup, vertexMap } = props
+    const unit = units[0]
+    let radius: Element.Property<number>
+    if (Unit.isAtomic(unit)) {
+        radius = Queries.props.atom.vdw_radius
+    } else if (Unit.isCoarse(unit) && unit.elementType === CoarseGrained.ElementType.Sphere) {
+        radius = Queries.props.coarse_grained.sphere_radius
+    }
+    const l = Element.Location()
+    l.unit = unit
+    return createAttributeSize({
+        sizeFn: (elementIdx: number) => {
+            l.element = ElementGroup.getAt(elementGroup, elementIdx)
+            return radius(l)
+        },
+        vertexMap
+    })
+}
\ No newline at end of file
diff --git a/src/mol-geo/theme/structure/size/index.ts b/src/mol-geo/theme/structure/size/index.ts
index b178ad42b9f9877bf819b0f2da71aa95e661219c..22caed502febf7ab0dd05a25201fe1c960335f07 100644
--- a/src/mol-geo/theme/structure/size/index.ts
+++ b/src/mol-geo/theme/structure/size/index.ts
@@ -13,4 +13,4 @@ export interface StructureSizeDataProps {
     vertexMap: VertexMap
 }
 
-export { vdwSizeData } from './vdw'
\ No newline at end of file
+export { elementSizeData } from './element'
\ No newline at end of file
diff --git a/src/mol-geo/theme/structure/size/vdw.ts b/src/mol-geo/theme/structure/size/vdw.ts
deleted file mode 100644
index 3010380904ab0810d3d79ff5f0a5b0a0d1f7a921..0000000000000000000000000000000000000000
--- a/src/mol-geo/theme/structure/size/vdw.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
-
-import { OrderedSet } from 'mol-data/int';
-import { VdwRadius } from 'mol-model/structure/model/properties/atomic';
-import { StructureSizeDataProps } from '.';
-import { createAttributeSize } from '../../../util/size-data';
-
-
-export function vdwSizeData(props: StructureSizeDataProps) {
-    const { units, elementGroup, vertexMap } = props
-    const { type_symbol } = units[0].model.hierarchy.atoms
-    return createAttributeSize({
-        sizeFn: (elementIdx: number) => {
-            const e = OrderedSet.getAt(elementGroup.elements, elementIdx)
-            return VdwRadius(type_symbol.value(e))
-        },
-        vertexMap
-    })
-}
\ No newline at end of file
diff --git a/src/mol-model/structure/query/properties.ts b/src/mol-model/structure/query/properties.ts
index 8a766f9b5c6040a4fd7f7ebd8d23820f404bc7b7..98d22ce51ca05136bc70f0bf52c82399d8fbd400 100644
--- a/src/mol-model/structure/query/properties.ts
+++ b/src/mol-model/structure/query/properties.ts
@@ -1,11 +1,12 @@
 /**
- * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2017-2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
 import { Element, Unit } from '../structure'
 import CoarseGrained from '../model/properties/coarse-grained';
+import { VdwRadius } from '../model/properties/atomic';
 
 const constant = {
     true: Element.property(l => true),
@@ -38,7 +39,10 @@ const atom = {
     label_atom_id: Element.property(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.hierarchy.atoms.label_atom_id.value(l.element)),
     auth_atom_id: Element.property(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.hierarchy.atoms.auth_atom_id.value(l.element)),
     label_alt_id: Element.property(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.hierarchy.atoms.label_alt_id.value(l.element)),
-    pdbx_formal_charge: Element.property(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.hierarchy.atoms.pdbx_formal_charge.value(l.element))
+    pdbx_formal_charge: Element.property(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.hierarchy.atoms.pdbx_formal_charge.value(l.element)),
+
+    // Derived
+    vdw_radius: Element.property(l => !Unit.isAtomic(l.unit) ? notAtomic() : VdwRadius(l.unit.hierarchy.atoms.type_symbol.value(l.element))),
 }
 
 const residue = {