diff --git a/src/mol-model/structure/_spec/atom-set.spec.ts b/src/mol-model/structure/_spec/atom-set.spec.ts
index 797ef623ad856884370d46b091a870399b046474..eb59d6c171c3ecbcd25c386309d0ee545acd2e07 100644
--- a/src/mol-model/structure/_spec/atom-set.spec.ts
+++ b/src/mol-model/structure/_spec/atom-set.spec.ts
@@ -30,6 +30,15 @@ describe('atom set', () => {
         expect(AtomSet.atomCount(set)).toBe(1);
     });
 
+    it('singleton atom', () => {
+        const set = AtomSet.singleton(p(10, 11), AtomSet.Empty);
+        expect(setToPairs(set)).toEqual([p(10, 11)]);
+        expect(AtomSet.atomHas(set, p(10, 11))).toBe(true);
+        expect(AtomSet.atomHas(set, p(11, 11))).toBe(false);
+        expect(AtomSet.atomGetAt(set, 0)).toBe(p(10, 11));
+        expect(AtomSet.atomCount(set)).toBe(1);
+    });
+
     it('multi', () => {
         const gen = AtomSet.Generator();
         gen.add(1, AtomGroup.createNew(OrderedSet.ofSortedArray([4, 6, 7])));
diff --git a/src/mol-model/structure/query/generators.ts b/src/mol-model/structure/query/generators.ts
index d911c167ba5fd23448eb9fb8dad0ca83777ca4bb..31b3ff2c9e8b483bab95a8f0c3c4f56720032428 100644
--- a/src/mol-model/structure/query/generators.ts
+++ b/src/mol-model/structure/query/generators.ts
@@ -12,7 +12,7 @@ import { OrderedSet, Segmentation } from 'mol-data/int'
 
 export const all: Query = s => Selection.Singletons(s, s.atoms);
 
-export interface AtomGroupsParams {
+export interface AtomQueryParams {
     entityTest: Atom.Predicate,
     chainTest: Atom.Predicate,
     residueTest: Atom.Predicate,
@@ -20,11 +20,18 @@ export interface AtomGroupsParams {
     groupBy: Atom.Property<any>
 }
 
-export function atoms(params?: Partial<AtomGroupsParams>): Query {
+export interface AtomGroupsQueryParams extends AtomQueryParams {
+    groupBy: Atom.Property<any>
+}
+
+export function residues(params?: Partial<AtomQueryParams>) { return atoms({ ...params, groupBy: P.residue.key }); }
+export function chains(params?: Partial<AtomQueryParams>) { return atoms({ ...params, groupBy: P.chain.key }); }
+
+export function atoms(params?: Partial<AtomGroupsQueryParams>): Query {
     if (!params || (!params.atomTest && !params.residueTest && !params.chainTest && !params.entityTest && !params.groupBy)) return all;
     if (!!params.atomTest && !params.residueTest && !params.chainTest && !params.entityTest && !params.groupBy) return atomGroupsLinear(params.atomTest);
 
-    const normalized: AtomGroupsParams = {
+    const normalized: AtomGroupsQueryParams = {
         entityTest: params.entityTest || P.constant.true,
         chainTest: params.chainTest || P.constant.true,
         residueTest: params.residueTest || P.constant.true,
@@ -60,7 +67,7 @@ function atomGroupsLinear(atomTest: Atom.Predicate): Query {
     };
 }
 
-function atomGroupsSegmented({ entityTest, chainTest, residueTest, atomTest }: AtomGroupsParams): Query {
+function atomGroupsSegmented({ entityTest, chainTest, residueTest, atomTest }: AtomGroupsQueryParams): Query {
     return structure => {
         const { atoms, units } = structure;
         const unitIds = AtomSet.unitIds(atoms);
@@ -133,17 +140,16 @@ class LinearGroupingBuilder {
     }
 
     private fullSelection() {
-        const sets: AtomSet[] = [];
+        const sets: AtomSet[] = new Array(this.builders.length);
         for (let i = 0, _i = this.builders.length; i < _i; i++) {
             sets[i] = this.builders[i].getSet();
         }
-        return Selection.Seq(this.structure, sets);
+        return Selection.Sequence(this.structure, sets);
     }
 
     getSelection(): Selection {
         const len = this.builders.length;
         if (len === 0) return Selection.Empty(this.structure);
-        if (len === 1) return Selection.Singletons(this.structure, this.builders[0].getSet());
         if (this.allSingletons()) return this.singletonSelection();
         return this.fullSelection();
     }
@@ -151,7 +157,7 @@ class LinearGroupingBuilder {
     constructor(private structure: Structure) { }
 }
 
-function atomGroupsGrouped({ entityTest, chainTest, residueTest, atomTest, groupBy }: AtomGroupsParams): Query {
+function atomGroupsGrouped({ entityTest, chainTest, residueTest, atomTest, groupBy }: AtomGroupsQueryParams): Query {
     return structure => {
         const { atoms, units } = structure;
         const unitIds = AtomSet.unitIds(atoms);
diff --git a/src/mol-model/structure/query/selection.ts b/src/mol-model/structure/query/selection.ts
index f119cd120415cb14204cd658d82bae29feadd1b3..2d8467e0764f13993077c5d6a49761ec66874acc 100644
--- a/src/mol-model/structure/query/selection.ts
+++ b/src/mol-model/structure/query/selection.ts
@@ -8,17 +8,16 @@ import { HashSet } from 'mol-data/util'
 import { Structure, AtomSet } from '../structure'
 
 // A selection is a pair of a Structure and a sequence of unique AtomSets
-type Selection = Selection.Singletons | Selection.Seq
+type Selection = Selection.Singletons | Selection.Sequence
 
 namespace Selection {
     // If each element of the selection is a singleton, we can use a more efficient representation.
     export interface Singletons { readonly kind: 'singletons', readonly structure: Structure, readonly set: AtomSet }
-    export interface Seq { readonly kind: 'seq', readonly structure: Structure, readonly sets: ReadonlyArray<AtomSet> }
+    export interface Sequence { readonly kind: 'sequence', readonly structure: Structure, readonly sets: ReadonlyArray<AtomSet> }
 
     export function Singletons(structure: Structure, set: AtomSet): Singletons { return { kind: 'singletons', structure, set } }
-    export function Seq(structure: Structure, sets: AtomSet[]): Seq { return { kind: 'seq', structure, sets } }
-
-    export function Empty(structure: Structure): Selection { return Seq(structure, []); };
+    export function Sequence(structure: Structure, sets: AtomSet[]): Sequence { return { kind: 'sequence', structure, sets } }
+    export function Empty(structure: Structure): Selection { return Sequence(structure, []); };
 
     export function isSingleton(s: Selection): s is Singletons { return s.kind === 'singletons'; }
     export function isEmpty(s: Selection) { return isSingleton(s) ? AtomSet.atomCount(s.set) === 0 : s.sets.length === 0; }
@@ -37,11 +36,30 @@ namespace Selection {
     export function getAt(sel: Selection, i: number): Structure {
         if (isSingleton(sel)) {
             const atom = AtomSet.atomGetAt(sel.set, i);
-            return Structure.create(sel.structure.units, AtomSet.ofAtoms([atom], sel.structure.atoms));
+            return Structure.create(sel.structure.units, AtomSet.singleton(atom, sel.structure.atoms));
         }
         return Structure.create(sel.structure.units, sel.sets[i]);
     }
 
+    export function toStructures(sel: Selection): Structure[] {
+        const { units } = sel.structure;
+        if (isSingleton(sel)) {
+            const ret: Structure[] = new Array(AtomSet.atomCount(sel.set));
+            const atoms = AtomSet.atoms(sel.set);
+            let offset = 0;
+            while (atoms.hasNext) {
+                const atom = atoms.move();
+                ret[offset++] = Structure.create(units, AtomSet.singleton(atom, sel.structure.atoms))
+            }
+            return ret;
+        } else {
+            const { sets } = sel;
+            const ret: Structure[] = new Array(sets.length);
+            for (let i = 0, _i = sets.length; i < _i; i++) ret[i] = Structure.create(units, sets[i]);
+            return ret;
+        }
+    }
+
     export interface Builder {
         add(set: AtomSet): void,
         getSelection(): Selection
@@ -50,9 +68,8 @@ namespace Selection {
     function getSelection(structure: Structure, sets: AtomSet[], allSingletons: boolean) {
         const len = sets.length;
         if (len === 0) return Empty(structure);
-        if (len === 1) return Singletons(structure, sets[0]);
         if (allSingletons) return Singletons(structure, AtomSet.union(sets, structure.atoms));
-        return Seq(structure, sets);
+        return Sequence(structure, sets);
     }
 
     class LinearBuilderImpl implements Builder {
diff --git a/src/mol-model/structure/structure/atom/impl/set.ts b/src/mol-model/structure/structure/atom/impl/set.ts
index 5919b327c49b05872608f42cb375f4623cb222ca..403af68a9f695902a80e84bc45d8375543f29bd9 100644
--- a/src/mol-model/structure/structure/atom/impl/set.ts
+++ b/src/mol-model/structure/structure/atom/impl/set.ts
@@ -20,6 +20,10 @@ export function ofAtoms(atoms: ArrayLike<Atom>, template: AtomSetImpl): AtomSetI
     return ofAtomsImpl(atoms, template);
 }
 
+export function singleton(atom: Atom, template: AtomSetImpl) {
+    return singletonImpl(atom, template);
+}
+
 export function getKeys(set: AtomSetImpl): SortedArray {
     return set.keys;
 }
@@ -358,6 +362,21 @@ function ofAtomsImpl(xs: ArrayLike<Atom>, template: AtomSetImpl) {
     return generator.getSet();
 }
 
+function singletonImpl(atom: Atom, template: AtomSetImpl) {
+    const k = Atom.unit(atom), i = Atom.index(atom);
+    const { groups } = template;
+    const gs = IntMap.Mutable<AtomGroup>();
+    if (groups.has(k)) {
+        const g = groups.get(k);
+        if (AtomGroup.size(g) === 1 && AtomGroup.getAt(g, 0) === i) {
+            gs.set(k, g);
+            return create([k], gs);
+        }
+    }
+    gs.set(k, AtomGroup.createNew(OS.ofSingleton(i)));
+    return create([k], gs);
+}
+
 function getOffsetIndex(xs: ArrayLike<number>, value: number) {
     let min = 0, max = xs.length - 1;
     while (min < max) {
diff --git a/src/mol-model/structure/structure/atom/set.ts b/src/mol-model/structure/structure/atom/set.ts
index a50f79db70c37fafb37fdecc0f67533fdd1e40e8..318aa8b8583285b9d152d92f43e7468d0a68c725 100644
--- a/src/mol-model/structure/structure/atom/set.ts
+++ b/src/mol-model/structure/structure/atom/set.ts
@@ -15,6 +15,7 @@ namespace AtomSet {
     export const Empty: AtomSet = Impl.Empty as any;
 
     export const ofAtoms: (atoms: ArrayLike<Atom>, template: AtomSet) => AtomSet = Impl.ofAtoms as any;
+    export const singleton: (atom: Atom, template: AtomSet) => AtomSet = Impl.singleton as any;
 
     export const unitCount: (set: AtomSet) => number = Impl.keyCount as any;
     export const unitIds: (set: AtomSet) => SortedArray = Impl.getKeys as any;