diff --git a/src/mol-geo/representation/structure/bond.ts b/src/mol-geo/representation/structure/bond.ts
index 1495ab1c0c89e5a25ae3b4db11f896f657c39d93..afb2cf89c183e25db5c24fa9f47efa2d7784f8ad 100644
--- a/src/mol-geo/representation/structure/bond.ts
+++ b/src/mol-geo/representation/structure/bond.ts
@@ -8,7 +8,7 @@
 import { ValueCell } from 'mol-util/value-cell'
 
 import { RenderObject, createMeshRenderObject, MeshRenderObject } from 'mol-gl/render-object'
-import { Unit, Element } from 'mol-model/structure';
+import { Unit, Element, Bond } from 'mol-model/structure';
 import { UnitsRepresentation, DefaultStructureProps } from './index';
 import { Task } from 'mol-task'
 import { createTransforms } from './utils';
@@ -21,20 +21,21 @@ import { MeshBuilder } from '../../shape/mesh-builder';
 import { Vec3, Mat4 } from 'mol-math/linear-algebra';
 import { createUniformColor } from '../../util/color-data';
 import { defaults } from 'mol-util';
-import { Loci } from 'mol-model/loci';
-import { FlagAction, createEmptyFlags } from '../../util/flag-data';
+import { Loci, isEveryLoci } from 'mol-model/loci';
+import { FlagAction, applyFlagAction, createFlags } from '../../util/flag-data';
 
 function createBondMesh(unit: Unit, mesh?: Mesh) {
     return Task.create('Cylinder mesh', async ctx => {
         if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh)
 
         const elements = unit.elements;
-        const { count, offset, neighbor } = unit.bonds;
-    
-        if (!count) return Mesh.createEmpty(mesh)
+        const bonds = unit.bonds
+        const { edgeCount, a, b } = bonds
+
+        if (!edgeCount) return Mesh.createEmpty(mesh)
 
         // TODO calculate vertextCount properly
-        const vertexCount = 32 * count
+        const vertexCount = 32 * edgeCount
         const meshBuilder = MeshBuilder.create(vertexCount, vertexCount / 2, mesh)
 
         const va = Vec3.zero()
@@ -46,34 +47,23 @@ function createBondMesh(unit: Unit, mesh?: Mesh) {
         const l = Element.Location()
         l.unit = unit
 
-        for (let j = 0; j < offset.length - 1; ++j) {
-            const start = offset[j]
-            const end = offset[j + 1]
-
-            if (end <= start) continue
-
-            const aI = elements[j]
-            va[0] = x(aI)
-            va[1] = y(aI)
-            va[2] = z(aI)
-            for (let _bI = start; _bI < end; ++_bI) {
-                const bI = elements[neighbor[_bI]]
-                if (bI > aI) continue
-
-                vb[0] = x(bI)
-                vb[1] = y(bI)
-                vb[2] = z(bI)
-
-                Vec3.scale(vt, Vec3.add(vt, va, vb), 0.5)
-                Vec3.makeRotation(m, Vec3.create(0, 1, 0), Vec3.sub(vb, vb, va))
-                Mat4.setTranslation(m, vt)
-
-                meshBuilder.setId(j)
-                meshBuilder.addCylinder(m, { radiusTop: 0.2, radiusBottom: 0.2 })
-            }
-
-            if (j % 10000 === 0 && ctx.shouldUpdate) {
-                await ctx.update({ message: 'Cylinder mesh', current: j, max: count });
+        for (let edgeIndex = 0, _eI = edgeCount * 2; edgeIndex < _eI; ++edgeIndex) {
+            const aI = elements[a[edgeIndex]], bI = elements[b[edgeIndex]];
+            // each edge is included twice because of the "adjacency list" structure
+            // keep only the 1st occurence.
+            if (aI >= bI) continue;
+            va[0] = x(aI); va[1] = y(aI); va[2] = z(aI)
+            vb[0] = x(bI); vb[1] = y(bI); vb[2] = z(bI)
+
+            Vec3.scale(vt, Vec3.add(vt, va, vb), 0.5)
+            Vec3.makeRotation(m, Vec3.create(0, 1, 0), Vec3.sub(vb, vb, va))
+            Mat4.setTranslation(m, vt)
+            
+            meshBuilder.setId(edgeIndex)
+            meshBuilder.addCylinder(m, { radiusTop: 0.2, radiusBottom: 0.2 })
+
+            if (edgeIndex % 10000 === 0 && ctx.shouldUpdate) {
+                await ctx.update({ message: 'Cylinder mesh', current: edgeIndex, max: edgeCount });
             }
         }
 
@@ -88,7 +78,7 @@ export const DefaultBondProps = {
 }
 export type BondProps = Partial<typeof DefaultBondProps>
 
-export default function Bond(): UnitsRepresentation<BondProps> {
+export default function BondUnitsRepresentation(): UnitsRepresentation<BondProps> {
     const renderObjects: RenderObject[] = []
     let cylinders: MeshRenderObject
     let currentProps: typeof DefaultBondProps
@@ -105,7 +95,12 @@ export default function Bond(): UnitsRepresentation<BondProps> {
                 renderObjects.length = 0 // clear
                 currentGroup = group
 
-                mesh = await createBondMesh(group.units[0]).runAsChild(ctx, 'Computing bond mesh')
+                const unit = group.units[0]
+                const elementCount = Unit.isAtomic(unit) ? unit.bonds.edgeCount * 2 : 0
+                const instanceCount = group.units.length
+
+                mesh = await createBondMesh(unit).runAsChild(ctx, 'Computing bond mesh')
+
                 // console.log(mesh)
                 // vertexMap = VertexMap.fromMesh(mesh)
 
@@ -116,9 +111,7 @@ export default function Bond(): UnitsRepresentation<BondProps> {
                 const color = createUniformColor({ value: 0xFF0000 })
 
                 await ctx.update('Computing bond flags');
-                const flag = createEmptyFlags()
-
-                const instanceCount = group.units.length
+                const flag = createFlags(instanceCount * elementCount)
 
                 const values: MeshValues = {
                     ...getMeshData(mesh),
@@ -129,7 +122,7 @@ export default function Bond(): UnitsRepresentation<BondProps> {
 
                     uAlpha: ValueCell.create(defaults(props.alpha, 1.0)),
                     uInstanceCount: ValueCell.create(instanceCount),
-                    uElementCount: ValueCell.create(group.elements.length),
+                    uElementCount: ValueCell.create(elementCount),
 
                     elements: mesh.indexBuffer,
 
@@ -168,17 +161,51 @@ export default function Bond(): UnitsRepresentation<BondProps> {
             })
         },
         getLoci(pickingId: PickingId) {
-            // const { objectId, instanceId, elementId } = pickingId
-            // if (cylinders.id === objectId) {
-            //     const unit = currentGroup.units[instanceId]
-            //     const elements = SortedArray.ofSingleton(currentGroup.elements[elementId])
-            //     return Element.Loci([{ unit, elements }])
-            // }
+            const { objectId, instanceId, elementId } = pickingId
+            const unit = currentGroup.units[instanceId]
+            if (cylinders.id === objectId && Unit.isAtomic(unit)) {
+                return Bond.Loci([{
+                    aUnit: unit,
+                    aIndex: unit.bonds.a[elementId],
+                    bUnit: unit,
+                    bIndex: unit.bonds.b[elementId]
+                }])
+            }
             return null
         },
         applyFlags(loci: Loci, action: FlagAction) {
-            currentGroup
-            // TODO
+            const group = currentGroup
+            const tFlag = cylinders.values.tFlag
+            const unit = group.units[0]
+            if (!Unit.isAtomic(unit)) return
+
+            const elementCount = unit.bonds.edgeCount * 2
+            const instanceCount = group.units.length
+
+            let changed = false
+            const array = tFlag.ref.value.array
+            if (isEveryLoci(loci)) {
+                applyFlagAction(array, 0, elementCount * instanceCount, action)
+                changed = true
+            } else if (Bond.isLoci(loci)) {
+                for (const b of loci.bonds) {
+                    const unitIdx = Unit.findUnitById(b.aUnit.id, group.units)
+                    if (unitIdx !== -1) {
+                        const _idx = unit.bonds.getEdgeIndex(b.aIndex, b.bIndex)
+                        if (_idx !== -1) {
+                            const idx = _idx
+                            if (applyFlagAction(array, idx, idx + 1, action) && !changed) {
+                                changed = true
+                            }
+                        }
+                    }
+                }
+            } else {
+                return
+            }
+            if (changed) {
+                ValueCell.update(tFlag, tFlag.ref.value)
+            }
         }
     }
 }
diff --git a/src/mol-geo/representation/structure/point.ts b/src/mol-geo/representation/structure/point.ts
index a45facb642baaa71345cfa2c99ad20f6ba072200..2daed89a676dc1330a36a4283b3b76d926222c42 100644
--- a/src/mol-geo/representation/structure/point.ts
+++ b/src/mol-geo/representation/structure/point.ts
@@ -47,7 +47,7 @@ export function createPointVertices(unit: Unit) {
     return vertices
 }
 
-export default function Point(): UnitsRepresentation<PointProps> {
+export default function PointUnitsRepresentation(): UnitsRepresentation<PointProps> {
     const renderObjects: RenderObject[] = []
     let points: PointRenderObject
     let currentProps = DefaultPointProps
@@ -70,6 +70,7 @@ export default function Point(): UnitsRepresentation<PointProps> {
 
                 const { colorTheme, sizeTheme } = currentProps
                 const elementCount = _elements.length
+                const instanceCount = group.units.length
 
                 const vertexMap = VertexMap.create(
                     elementCount,
@@ -91,9 +92,7 @@ export default function Point(): UnitsRepresentation<PointProps> {
                 const size = createSizes(group, vertexMap, sizeTheme)
 
                 await ctx.update('Computing spacefill flags');
-                const flag = createFlags(group)
-
-                const instanceCount = group.units.length
+                const flag = createFlags(instanceCount * elementCount)
 
                 const values: PointValues = {
                     aPosition: ValueCell.create(vertices),
diff --git a/src/mol-geo/representation/structure/spacefill.ts b/src/mol-geo/representation/structure/spacefill.ts
index d1056a033e7986d7654e47d0987f9001685e8815..573c18547675ae1923077ddba3ede7d93e504a9f 100644
--- a/src/mol-geo/representation/structure/spacefill.ts
+++ b/src/mol-geo/representation/structure/spacefill.ts
@@ -33,7 +33,7 @@ function createSpacefillMesh(unit: Unit, detail: number, mesh?: Mesh) {
         console.warn('Unsupported unit type')
         return Task.constant('Empty mesh', Mesh.createEmpty(mesh))
     }
-    return createSphereMesh(unit, (l) => radius(l) * 1.0, detail, mesh)
+    return createSphereMesh(unit, (l) => radius(l) * 0.3, detail, mesh)
 }
 
 export const DefaultSpacefillProps = {
@@ -44,7 +44,7 @@ export const DefaultSpacefillProps = {
 }
 export type SpacefillProps = Partial<typeof DefaultSpacefillProps>
 
-export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
+export default function SpacefillUnitsRepresentation(): UnitsRepresentation<SpacefillProps> {
     const renderObjects: RenderObject[] = []
     let spheres: MeshRenderObject
     let currentProps: typeof DefaultSpacefillProps
@@ -62,6 +62,8 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
                 currentGroup = group
 
                 const { detail, colorTheme } = { ...DefaultSpacefillProps, ...props }
+                const instanceCount = group.units.length
+                const elementCount = group.elements.length
 
                 mesh = await createSpacefillMesh(group.units[0], detail).runAsChild(ctx, 'Computing spacefill mesh')
                 // console.log(mesh)
@@ -74,9 +76,7 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
                 const color = createColors(group, vertexMap, colorTheme)
 
                 await ctx.update('Computing spacefill flags');
-                const flag = createFlags(group)
-
-                const instanceCount = group.units.length
+                const flag = createFlags(instanceCount * elementCount)
 
                 const values: MeshValues = {
                     ...getMeshData(mesh),
@@ -87,7 +87,7 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
 
                     uAlpha: ValueCell.create(defaults(props.alpha, 1.0)),
                     uInstanceCount: ValueCell.create(instanceCount),
-                    uElementCount: ValueCell.create(group.elements.length),
+                    uElementCount: ValueCell.create(elementCount),
 
                     elements: mesh.indexBuffer,
 
diff --git a/src/mol-geo/representation/structure/utils.ts b/src/mol-geo/representation/structure/utils.ts
index a0a17964c46a0bbba42c4a38281a441c036455ac..e6719eaa741ce5030a06dc361d81c1ffebbdbcdf 100644
--- a/src/mol-geo/representation/structure/utils.ts
+++ b/src/mol-geo/representation/structure/utils.ts
@@ -73,9 +73,7 @@ export function createSphereMesh(unit: Unit, radius: Element.Property<number>, d
 
         for (let i = 0; i < elementCount; i++) {
             l.element = elements[i]
-            v[0] = x(l.element)
-            v[1] = y(l.element)
-            v[2] = z(l.element)
+            v[0] = x(l.element); v[1] = y(l.element); v[2] = z(l.element)
             Mat4.setTranslation(m, v)
 
             meshBuilder.setId(i)
diff --git a/src/mol-geo/util/flag-data.ts b/src/mol-geo/util/flag-data.ts
index 206f1aeae7ea311e45ce112440ae40d4d78a063d..e8049a53ef546b320919a804ed9b40df46a6b764 100644
--- a/src/mol-geo/util/flag-data.ts
+++ b/src/mol-geo/util/flag-data.ts
@@ -4,7 +4,6 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { Unit } from 'mol-model/structure'
 import { ValueCell } from 'mol-util/value-cell'
 import { Vec2 } from 'mol-math/linear-algebra'
 import { TextureImage, createTextureImage } from 'mol-gl/renderable/util';
@@ -72,10 +71,7 @@ export function applyFlagAction(array: Uint8Array, start: number, end: number, a
     return changed
 }
 
-export function createFlags(group: Unit.SymmetryGroup, flagData?: FlagData): FlagData {
-    const instanceCount = group.units.length
-    const elementCount = group.elements.length
-    const count = instanceCount * elementCount
+export function createFlags(count: number, flagData?: FlagData): FlagData {
     const flags = flagData && flagData.tFlag.ref.value.array.length >= count
         ? flagData.tFlag.ref.value
         : createTextureImage(count, 1)
diff --git a/src/mol-math/graph/int/graph.ts b/src/mol-math/graph/int/graph.ts
index fb50ee13f123ed9deec41270e3e81b5923878f56..bc2666a2c064bca1f63193ee27709df9019b3e8c 100644
--- a/src/mol-math/graph/int/graph.ts
+++ b/src/mol-math/graph/int/graph.ts
@@ -86,7 +86,7 @@ namespace IntGraph {
          *     builder.addNextEdge();
          *     builder.assignProperty(property, srcProp[i]);
          *   }
-         * return builder.createGraph({ property });
+         *   return builder.createGraph({ property });
          */
         addNextEdge() {
             const a = this.xs[this.current], b = this.ys[this.current];
diff --git a/src/mol-model/structure/structure/element.ts b/src/mol-model/structure/structure/element.ts
index c9645caa8af484622d96187ebfab117456cd76c9..af6a4cdb275202f29a794c3a4803a0d60359bd2b 100644
--- a/src/mol-model/structure/structure/element.ts
+++ b/src/mol-model/structure/structure/element.ts
@@ -23,7 +23,11 @@ namespace Element {
     export function createEmptyArray(n: number): Element[] { return new Float64Array(n) as any; }
 
     /** All the information required to access element properties */
-    export interface Location { unit: Unit, element: number }
+    export interface Location {
+        unit: Unit,
+        /** Index into element (atomic/coarse) properties of unit.model */
+        element: number
+    }
     export function Location(unit?: Unit, element?: number): Location { return { unit: unit as any, element: element || 0 }; }
     export interface Property<T> { (location: Location): T }
     export interface Predicate extends Property<boolean> { }
diff --git a/src/mol-model/structure/structure/unit/bonds.ts b/src/mol-model/structure/structure/unit/bonds.ts
index 73b6ff8d67893590bf5babc999bd04fd60c9118d..d7268742832c8d7ff04d19199e218655ff48a099 100644
--- a/src/mol-model/structure/structure/unit/bonds.ts
+++ b/src/mol-model/structure/structure/unit/bonds.ts
@@ -4,23 +4,27 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import { Element } from '../../structure'
+import { Unit } from '../../structure'
 
 export * from './bonds/intra-data'
 export * from './bonds/intra-compute'
 
-interface Bond {
-    readonly a: Readonly<Element.Location>,
-    readonly b: Readonly<Element.Location>
-}
-
 namespace Bond {
+    export interface Location {
+        readonly aUnit: Unit,
+        /** Index into aUnit.elements */
+        readonly aIndex: number,
+        readonly bUnit: Unit,
+        /** Index into bUnit.elements */
+        readonly bIndex: number,
+    }
+
     export interface Loci {
         readonly kind: 'bond-loci',
-        readonly bonds: ReadonlyArray<Bond>
+        readonly bonds: ReadonlyArray<Location>
     }
 
-    export function Loci(bonds: ArrayLike<Bond>): Loci {
+    export function Loci(bonds: ArrayLike<Location>): Loci {
         return { kind: 'bond-loci', bonds: bonds as Loci['bonds'] };
     }
 
diff --git a/src/mol-view/label.ts b/src/mol-view/label.ts
index 311abab26217c917c0960f991a1815b7dcdb9b28..578a4a7a53260c5c682edc6a7d648edf692a0031 100644
--- a/src/mol-view/label.ts
+++ b/src/mol-view/label.ts
@@ -9,6 +9,14 @@ import { Unit, Element, Queries } from 'mol-model/structure';
 import { Bond } from 'mol-model/structure/structure/unit/bonds';
 import { Loci } from 'mol-model/loci';
 
+const elementLocA = Element.Location()
+const elementLocB = Element.Location()
+
+function setElementLocation(loc: Element.Location, unit: Unit, index: number) {
+    loc.unit = unit
+    loc.element = unit.elements[index]
+}
+
 export function labelFirst(loci: Loci) {
     if(Element.isLoci(loci)) {
         const e = loci.elements[0]
@@ -18,7 +26,9 @@ export function labelFirst(loci: Loci) {
     } else if (Bond.isLoci(loci)) {
         const bond = loci.bonds[0]
         if (bond) {
-            return `${elementLabel(bond.a)} - ${elementLabel(bond.b)}`
+            setElementLocation(elementLocA, bond.aUnit, bond.aIndex)
+            setElementLocation(elementLocB, bond.bUnit, bond.bIndex)
+            return `${elementLabel(elementLocA)} - ${elementLabel(elementLocB)}`
         }
     }
     return ''
diff --git a/src/mol-view/stage.ts b/src/mol-view/stage.ts
index 1992d98de3ddf92c037d8119f73eb32cf516be96..af44bda4bf3e7f202db99f95f6f971f8ef7b347b 100644
--- a/src/mol-view/stage.ts
+++ b/src/mol-view/stage.ts
@@ -7,7 +7,7 @@
 import Viewer from 'mol-view/viewer'
 import { StateContext } from './state/context';
 import { Progress } from 'mol-task';
-import { MmcifUrlToSpacefill } from './state/transform';
+import { MmcifUrlToModel, ModelToStructure, StructureToSpacefill, StructureToBond } from './state/transform';
 import { UrlEntity } from './state/entity';
 import { SpacefillProps } from 'mol-geo/representation/structure/spacefill';
 
@@ -42,9 +42,12 @@ export class Stage {
         this.loadMmcifUrl(`../../examples/1cbs_full.bcif`)
     }
 
-    loadMmcifUrl (url: string) {
+    async loadMmcifUrl (url: string) {
         const urlEntity = UrlEntity.ofUrl(this.ctx, url)
-        MmcifUrlToSpacefill.apply(this.ctx, urlEntity, spacefillProps)
+        const modelEntity = await MmcifUrlToModel.apply(this.ctx, urlEntity)
+        const structureEntity = await ModelToStructure.apply(this.ctx, modelEntity)
+        StructureToSpacefill.apply(this.ctx, structureEntity, spacefillProps)
+        StructureToBond.apply(this.ctx, structureEntity, spacefillProps) // TODO props
     }
 
     loadPdbid (pdbid: string) {