diff --git a/src/apps/basic-wrapper/helpers.ts b/src/apps/basic-wrapper/helpers.ts
index bbe9e92ab86c2a9f414a2a3f1f095c53a7a132cd..342325ee87e6abca504e1e7be3e018d1acc0f9a7 100644
--- a/src/apps/basic-wrapper/helpers.ts
+++ b/src/apps/basic-wrapper/helpers.ts
@@ -11,6 +11,8 @@ import { StateTransforms } from 'mol-plugin/state/transforms';
 import { StructureRepresentation3DHelpers } from 'mol-plugin/state/transforms/representation';
 import { MolScriptBuilder as MS } from 'mol-script/language/builder';
 import { StateBuilder } from 'mol-state';
+import Expression from 'mol-script/language/expression';
+import { BuiltInColorThemeName } from 'mol-theme/color';
 type SupportedFormats = 'cif' | 'pdb'
 
 export namespace StateHelper {
@@ -27,7 +29,7 @@ export namespace StateHelper {
     }
 
     export function structure(b: StateBuilder.To<PSO.Molecule.Model>) {
-        return b.apply(StateTransforms.Model.StructureFromModel, { tags: 'struct' })
+        return b.apply(StateTransforms.Model.StructureFromModel, { tags: 'structure' })
     };
 
     export function selectChain(b: StateBuilder.To<PSO.Molecule.Structure>, auth_asym_id: string) {
@@ -37,6 +39,23 @@ export namespace StateHelper {
         return b.apply(StateTransforms.Model.StructureSelection, { query, label: `Chain ${auth_asym_id}` });
     }
 
+    export function select(b: StateBuilder.To<PSO.Molecule.Structure>, query: Expression) {
+        return b.apply(StateTransforms.Model.StructureSelection, { query });
+    }
+
+    export function selectSurroundingsOfFirstResidue(b: StateBuilder.To<PSO.Molecule.Structure>, comp_id: string, radius: number) {
+        const query = MS.struct.modifier.includeSurroundings({
+            0: MS.struct.filter.first([
+                MS.struct.generator.atomGroups({
+                    'residue-test': MS.core.rel.eq([MS.struct.atomProperty.macromolecular.label_comp_id(), comp_id]),
+                    'group-by': MS.struct.atomProperty.macromolecular.residueKey()
+                })
+            ]),
+            radius
+        })
+        return b.apply(StateTransforms.Model.StructureSelection, { query, label: `Surr. ${comp_id} (${radius} ang)` });
+    }
+
     export function identityTransform(b: StateBuilder.To<PSO.Molecule.Structure>, m: Mat4) {
         return b.apply(StateTransforms.Model.TransformStructureConformation,
             { axis: Vec3.create(1, 0, 0), angle: 0, translation: Vec3.zero() },
@@ -64,4 +83,12 @@ export namespace StateHelper {
         return visualRoot;
     }
 
+    export function ballsAndSticks(ctx: PluginContext, visualRoot: StateBuilder.To<PSO.Molecule.Structure>, query: Expression, coloring?: BuiltInColorThemeName) {
+        visualRoot
+            .apply(StateTransforms.Model.StructureSelection, { query })
+            .apply(StateTransforms.Representation.StructureRepresentation3D,
+                StructureRepresentation3DHelpers.getDefaultParamsStatic(ctx, 'ball-and-stick', void 0, coloring), { tags: 'het-visual' });
+        return visualRoot;
+    }
+
 }
\ No newline at end of file
diff --git a/src/apps/basic-wrapper/index.html b/src/apps/basic-wrapper/index.html
index 1d68db266336484ba6557079d46d5da0066504c2..6c9f2d9d571045339824a9f9cd10a8d2a207ab39 100644
--- a/src/apps/basic-wrapper/index.html
+++ b/src/apps/basic-wrapper/index.html
@@ -107,7 +107,8 @@
 
             addHeader('Tests');
 
-            addControl('Static Super', () => BasicMolStarWrapper.tests.staticSuperposition());
+            addControl('Static Superposition', () => BasicMolStarWrapper.tests.staticSuperposition());
+            addControl('Dynamic Superposition', () => BasicMolStarWrapper.tests.dynamicSuperposition());
 
             ////////////////////////////////////////////////////////
 
diff --git a/src/apps/basic-wrapper/index.ts b/src/apps/basic-wrapper/index.ts
index fb4392f3d17dd6c057fb1acaa5873a4cb8b20bf2..3520372ac8610ce0941c8138accb15731126e4c6 100644
--- a/src/apps/basic-wrapper/index.ts
+++ b/src/apps/basic-wrapper/index.ts
@@ -13,10 +13,10 @@ import { StructureRepresentation3DHelpers } from 'mol-plugin/state/transforms/re
 import { Color } from 'mol-util/color';
 import { PluginStateObject as PSO } from 'mol-plugin/state/objects';
 import { AnimateModelIndex } from 'mol-plugin/state/animation/built-in';
-import { StateBuilder } from 'mol-state';
+import { StateBuilder, StateTransform } from 'mol-state';
 import { StripedResidues } from './coloring';
 // import { BasicWrapperControls } from './controls';
-import { StaticSuperpositionTestData, buildStaticSuperposition } from './superposition';
+import { StaticSuperpositionTestData, buildStaticSuperposition, dynamicSuperpositionTest } from './superposition';
 require('mol-plugin/skin/light.scss')
 
 type SupportedFormats = 'cif' | 'pdb'
@@ -146,7 +146,12 @@ class BasicWrapper {
         staticSuperposition: async () => {
             const state = this.plugin.state.dataState;
             const tree = buildStaticSuperposition(this.plugin, StaticSuperpositionTestData);
+            await PluginCommands.State.RemoveObject.dispatch(this.plugin, { state, ref: StateTransform.RootRef });
             await PluginCommands.State.Update.dispatch(this.plugin, { state, tree });
+        },
+        dynamicSuperposition: async () => {
+            await PluginCommands.State.RemoveObject.dispatch(this.plugin, { state: this.plugin.state.dataState, ref: StateTransform.RootRef });
+            await dynamicSuperpositionTest(this.plugin, ['1tqn', '2hhb', '4hhb'], 'HEM');
         }
     }
 }
diff --git a/src/apps/basic-wrapper/superposition.ts b/src/apps/basic-wrapper/superposition.ts
index 1961aab48cc207d7f12eb74ced534011e8037050..c2b190603746e2c6df06641baa2dfcceeee8f6d1 100644
--- a/src/apps/basic-wrapper/superposition.ts
+++ b/src/apps/basic-wrapper/superposition.ts
@@ -9,6 +9,14 @@
 import { PluginContext } from 'mol-plugin/context';
 import { Mat4 } from 'mol-math/linear-algebra';
 import { StateHelper } from './helpers';
+import { PluginCommands } from 'mol-plugin/command';
+import { StateSelection, StateBuilder } from 'mol-state';
+import { PluginStateObject as PSO } from 'mol-plugin/state/objects';
+import { MolScriptBuilder as MS } from 'mol-script/language/builder';
+import { compile } from 'mol-script/runtime/query/compiler';
+import { StructureSelection, QueryContext } from 'mol-model/structure';
+import { superposeStructures } from 'mol-model/structure/structure/util/superposition';
+import Expression from 'mol-script/language/expression';
 
 export type SuperpositionTestInput = {
     pdbId: string,
@@ -52,4 +60,49 @@ export const StaticSuperpositionTestData: SuperpositionTestInput = [
          [-0.312, 0.949, 0.057, -12.255],
          [-0.949, -0.307, -0.074, 53.562],
          [0, 0, 0, 1]] )}
-];
\ No newline at end of file
+];
+
+export async function dynamicSuperpositionTest(ctx: PluginContext, src: string[], comp_id: string) {
+    const state = ctx.state.dataState;
+
+    const structures = state.build().toRoot();
+    for (const s of src) {
+        StateHelper.structure(
+            StateHelper.getModel(StateHelper.download(structures, `https://www.ebi.ac.uk/pdbe/static/entry/${s}_updated.cif`), 'cif'));
+    }
+
+    await PluginCommands.State.Update.dispatch(ctx, { state, tree: structures });
+
+    const pivot = MS.struct.filter.first([
+        MS.struct.generator.atomGroups({
+            'residue-test': MS.core.rel.eq([MS.struct.atomProperty.macromolecular.label_comp_id(), comp_id]),
+            'group-by': MS.struct.atomProperty.macromolecular.residueKey()
+        })
+    ]);
+    const rest = MS.struct.modifier.exceptBy({
+        0: MS.struct.generator.all(),
+        by: pivot
+    });
+
+    const query = compile<StructureSelection>(pivot);
+    const xs = state.select(StateSelection.Generators.rootsOfType(PSO.Molecule.Structure));
+    const selections = xs.map(s => StructureSelection.toLoci(query(new QueryContext(s.obj!.data))));
+
+    const transforms = superposeStructures(selections);
+    const visuals = state.build();
+
+    siteVisual(ctx, StateHelper.selectSurroundingsOfFirstResidue(visuals.to(xs[0].transform.ref), 'HEM', 7), pivot, rest);
+    for (let i = 1; i < selections.length; i++) {
+        const root = visuals.to(xs[i].transform.ref);
+        siteVisual(ctx,
+            StateHelper.transform(StateHelper.selectSurroundingsOfFirstResidue(root, 'HEM', 7), transforms[i - 1].bTransform),
+            pivot, rest);
+    }
+
+    await PluginCommands.State.Update.dispatch(ctx, { state, tree: visuals });
+}
+
+function siteVisual(ctx: PluginContext, b: StateBuilder.To<PSO.Molecule.Structure>, pivot: Expression, rest: Expression) {
+    StateHelper.ballsAndSticks(ctx, b, pivot, 'residue-name');
+    StateHelper.ballsAndSticks(ctx, b, rest, 'uniform');
+}
\ No newline at end of file
diff --git a/src/mol-math/linear-algebra/3d.ts b/src/mol-math/linear-algebra/3d.ts
index 88ba25f812d6d3576d81667afe0f706db77567c5..3a98d5ba703c65c011b471624d8669c8fb87c695 100644
--- a/src/mol-math/linear-algebra/3d.ts
+++ b/src/mol-math/linear-algebra/3d.ts
@@ -23,7 +23,6 @@ import Vec2 from './3d/vec2'
 import Vec3 from './3d/vec3'
 import Vec4 from './3d/vec4'
 import Quat from './3d/quat'
-import MinimizeRmsd from './3d/minimize-rmsd'
 import { EPSILON } from './3d/common'
 
-export { Mat4, Mat3, Vec2, Vec3, Vec4, Quat, EPSILON, MinimizeRmsd }
\ No newline at end of file
+export { Mat4, Mat3, Vec2, Vec3, Vec4, Quat, EPSILON }
\ No newline at end of file
diff --git a/src/mol-math/linear-algebra/3d/minimize-rmsd.ts b/src/mol-math/linear-algebra/3d/minimize-rmsd.ts
index 1296e10f3aa316031ac5a048b26c702b9269ebe8..b757b2e7afa5394716cd76548d5490e2b9ee5d0b 100644
--- a/src/mol-math/linear-algebra/3d/minimize-rmsd.ts
+++ b/src/mol-math/linear-algebra/3d/minimize-rmsd.ts
@@ -10,8 +10,7 @@ import { EVD } from '../matrix/evd';
 import { CentroidHelper } from 'mol-math/geometry/centroid-helper';
 import Matrix from '../matrix/matrix';
 
-export default MinimizeRmsd;
-
+export { MinimizeRmsd };
 namespace MinimizeRmsd {
     export interface Result {
         bTransform: Mat4,
diff --git a/src/mol-model/structure/structure/util/superposition.ts b/src/mol-model/structure/structure/util/superposition.ts
index 8c41ba996510e03eadbbf815c56715787fd41718..bcd72625890736cc51ee102d8759f0c84e7069d3 100644
--- a/src/mol-model/structure/structure/util/superposition.ts
+++ b/src/mol-model/structure/structure/util/superposition.ts
@@ -4,7 +4,7 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import { MinimizeRmsd } from 'mol-math/linear-algebra';
+import { MinimizeRmsd } from 'mol-math/linear-algebra/3d/minimize-rmsd';
 import StructureElement from '../element';
 import { OrderedSet } from 'mol-data/int';
 
diff --git a/src/mol-state/state/selection.ts b/src/mol-state/state/selection.ts
index 2a47745f5c84e51b9ec4116a91a10b88e6033461..097d73b70a9af5b95f72137bd9be10356360044c 100644
--- a/src/mol-state/state/selection.ts
+++ b/src/mol-state/state/selection.ts
@@ -49,7 +49,7 @@ namespace StateSelection {
         parent(): Builder<C>;
         first(): Builder<C>;
         filter(p: (n: C) => boolean): Builder<C>;
-        withTag(tag: string): Builder<C>;
+        withTag<D extends StateObjectCell = C>(tag: string): Builder<D>;
         withTransformer<T extends StateTransformer<any, StateObjectCell.Obj<C>, any>>(t: T): Builder<StateObjectCell<StateObjectCell.Obj<C>, StateTransform<T>>>;
         withStatus(s: StateObjectCell.Status): Builder<C>;
         subtree(): Builder;