diff --git a/src/examples/proteopedia-wrapper/helpers.ts b/src/examples/proteopedia-wrapper/helpers.ts
index 01b89bc62ce9a2f824304a0ef169c19ee86129b0..913465a6fc681385021d318ae1ed16edda112fc8 100644
--- a/src/examples/proteopedia-wrapper/helpers.ts
+++ b/src/examples/proteopedia-wrapper/helpers.ts
@@ -4,13 +4,83 @@
  * @author David Sehnal <david.sehnal@gmail.com>
  */
 
-import { ResidueIndex } from 'mol-model/structure';
+import { ResidueIndex, Model } from 'mol-model/structure';
 import { BuiltInStructureRepresentationsName } from 'mol-repr/structure/registry';
 import { BuiltInColorThemeName } from 'mol-theme/color';
+import { AminoAcidNames } from 'mol-model/structure/model/types';
+import { PluginContext } from 'mol-plugin/context';
 
-export interface StructureInfo {
-    ligands: { name: string, indices: ResidueIndex[] }[],
-    assemblies: { id: string, description: string, isPreferred: boolean }[]
+export interface ModelInfo {
+    hetResidues: { name: string, indices: ResidueIndex[] }[],
+    assemblies: { id: string, details: string, isPreferred: boolean }[],
+    preferredAssemblyId: string | undefined
+}
+
+export namespace ModelInfo {
+    async function getPreferredAssembly(ctx: PluginContext, model: Model) {
+        if (model.label.length <= 3) return void 0;
+        try {
+            const id = model.label.toLowerCase();
+            const src = await ctx.runTask(ctx.fetch(`https://www.ebi.ac.uk/pdbe/api/pdb/entry/summary/${id}`)) as string;
+            const json = JSON.parse(src);
+            const data = json && json[id];
+
+            console.log(data);
+
+            const assemblies = data[0] && data[0].assemblies;
+            if (!assemblies || !assemblies.length) return void 0;
+
+            for (const asm of assemblies) {
+                if (asm.preferred) {
+                    return asm.assembly_id;
+                }
+            }
+            return void 0;
+        } catch (e) {
+            console.warn('getPreferredAssembly', e);
+        }
+    }
+
+    export async function get(ctx: PluginContext, model: Model, checkPreferred: boolean): Promise<ModelInfo> {
+        const { _rowCount: residueCount } = model.atomicHierarchy.residues;
+        const { offsets: residueOffsets } = model.atomicHierarchy.residueAtomSegments;
+        const chainIndex = model.atomicHierarchy.chainAtomSegments.index;
+        // const resn = SP.residue.label_comp_id, entType = SP.entity.type;
+
+        const pref = checkPreferred
+            ? getPreferredAssembly(ctx, model)
+            : void 0;
+
+        const hetResidues: ModelInfo['hetResidues'] = [];
+        const hetMap = new Map<string, ModelInfo['hetResidues'][0]>();
+
+        for (let rI = 0 as ResidueIndex; rI < residueCount; rI++) {
+            const comp_id = model.atomicHierarchy.residues.label_comp_id.value(rI);
+            if (AminoAcidNames.has(comp_id)) continue;
+            const mod_parent = model.properties.modifiedResidues.parentId.get(comp_id);
+            if (mod_parent && AminoAcidNames.has(mod_parent)) continue;
+
+            const cI = chainIndex[residueOffsets[rI]];
+            const eI = model.atomicHierarchy.index.getEntityFromChain(cI);
+            if (model.entities.data.type.value(eI) === 'water') continue;
+
+            let lig = hetMap.get(comp_id);
+            if (!lig) {
+                lig = { name: comp_id, indices: [] };
+                hetResidues.push(lig);
+                hetMap.set(comp_id, lig);
+            }
+            lig.indices.push(rI);
+        }
+
+        const preferredAssemblyId = await pref;
+
+        return {
+            hetResidues: hetResidues,
+            assemblies: model.symmetry.assemblies.map(a => ({ id: a.id, details: a.details, isPreferred: a.id === preferredAssemblyId })),
+            preferredAssemblyId
+        };
+    }
 }
 
 export type SupportedFormats = 'cif' | 'pdb'
diff --git a/src/examples/proteopedia-wrapper/index.html b/src/examples/proteopedia-wrapper/index.html
index 8e2219d8eba2f84474ef99187c02d084d68a321f..59b5a762d6d7dc89cb42d34f862df3c5bc70f86f 100644
--- a/src/examples/proteopedia-wrapper/index.html
+++ b/src/examples/proteopedia-wrapper/index.html
@@ -61,7 +61,7 @@
 
             function $(id) { return document.getElementById(id); }
         
-            var pdbId = '1grm', assemblyId= '1';
+            var pdbId = '3usb', assemblyId= 'preferred';
             var url = 'https://www.ebi.ac.uk/pdbe/static/entry/' + pdbId + '_updated.cif';
             var format = 'cif';
             
@@ -81,6 +81,10 @@
             MolStarProteopediaWrapper.load({ url: url, format: format, assemblyId: assemblyId });
             MolStarProteopediaWrapper.toggleSpin();
 
+            MolStarProteopediaWrapper.events.modelInfo.subscribe(function (info) {
+                console.log('Model Info', info);
+            });
+
             addControl('Load Asym Unit', () => MolStarProteopediaWrapper.load({ url: url, format: format }));
             addControl('Load Assembly', () => MolStarProteopediaWrapper.load({ url: url, format: format, assemblyId: assemblyId }));
 
diff --git a/src/examples/proteopedia-wrapper/index.ts b/src/examples/proteopedia-wrapper/index.ts
index 5370a843a1b1717048a5b5db903b99b071cd75e4..3868ddf08a495c14e553e41fe969087b7f7ff298 100644
--- a/src/examples/proteopedia-wrapper/index.ts
+++ b/src/examples/proteopedia-wrapper/index.ts
@@ -13,14 +13,21 @@ import { StructureRepresentation3DHelpers } from 'mol-plugin/state/transforms/re
 import { Color } from 'mol-util/color';
 import { PluginStateObject as PSO, PluginStateObject } from 'mol-plugin/state/objects';
 import { AnimateModelIndex } from 'mol-plugin/state/animation/built-in';
-import { StateBuilder } from 'mol-state';
+import { StateBuilder, StateObject } from 'mol-state';
 import { StripedResidues } from './annotation';
-import { LoadParams, SupportedFormats, RepresentationStyle } from './helpers';
+import { LoadParams, SupportedFormats, RepresentationStyle, ModelInfo } from './helpers';
+import { RxEventHelper } from 'mol-util/rx-event-helper';
 require('mol-plugin/skin/light.scss')
 
 class MolStarProteopediaWrapper {
     static VERSION_MAJOR = 1;
 
+    private _ev = RxEventHelper.create();
+
+    readonly events = {
+        modelInfo: this._ev<ModelInfo>()
+    };
+
     plugin: PluginContext;
 
     init(target: string | HTMLElement) {
@@ -45,24 +52,28 @@ class MolStarProteopediaWrapper {
         return b.apply(StateTransforms.Data.Download, { url, isBinary: false })
     }
 
-    private parse(b: StateBuilder.To<PSO.Data.Binary | PSO.Data.String>, format: SupportedFormats, assemblyId: string) {
+    private model(b: StateBuilder.To<PSO.Data.Binary | PSO.Data.String>, format: SupportedFormats, assemblyId: string) {
         const parsed = format === 'cif'
             ? b.apply(StateTransforms.Data.ParseCif).apply(StateTransforms.Model.TrajectoryFromMmCif)
             : b.apply(StateTransforms.Model.TrajectoryFromPDB);
 
         return parsed
-            .apply(StateTransforms.Model.ModelFromTrajectory, { modelIndex: 0 })
+            .apply(StateTransforms.Model.ModelFromTrajectory, { modelIndex: 0 }, { ref: 'model' });
+    }
+
+    private structure(assemblyId: string) {
+        const model = this.state.build().to('model');
+
+        return model
             .apply(StateTransforms.Model.CustomModelProperties, { properties: [StripedResidues.Descriptor.name] }, { ref: 'props', props: { isGhost: false } })
             .apply(StateTransforms.Model.StructureAssemblyFromModel, { id: assemblyId || 'deposited' }, { ref: 'asm' });
     }
 
     private visual(ref: string, style?: RepresentationStyle) {
-        const state = this.state;
-        const cell = state.select(ref)[0];
-        if (!cell || !cell.obj) return void 0;
-        const structure = (cell.obj as PluginStateObject.Molecule.Structure).data;
+        const structure = this.getObj<PluginStateObject.Molecule.Structure>(ref);
+        if (!structure) return;
 
-        const root = state.build().to(ref);
+        const root = this.state.build().to(ref);
 
         root.apply(StateTransforms.Model.StructureComplexElement, { type: 'atomic-sequence' }, { ref: 'sequence' })
             .apply(StateTransforms.Representation.StructureRepresentation3D,
@@ -86,6 +97,26 @@ class MolStarProteopediaWrapper {
         return root;
     }
 
+    private getObj<T extends StateObject>(ref: string) {
+        const state = this.state;
+        const cell = state.select(ref)[0];
+        if (!cell || !cell.obj) return void 0;
+        return (cell.obj as T).data;
+    }
+
+    private async doInfo(checkPreferredAssembly: boolean) {
+        const s = this.getObj<PluginStateObject.Molecule.Model>('model');
+        if (!s) return;
+
+        const info = await ModelInfo.get(this.plugin, s, checkPreferredAssembly)
+        this.events.modelInfo.next(info);
+        return info;
+    }
+
+    private applyState(tree: StateBuilder) {
+        return PluginCommands.State.Update.dispatch(this.plugin, { state: this.plugin.state.dataState, tree });
+    }
+
     private loadedParams: LoadParams = { url: '', format: 'cif', assemblyId: '' };
     async load({ url, format = 'cif', assemblyId = '', representationStyle }: LoadParams) {
         let loadType: 'full' | 'update' = 'full';
@@ -98,17 +129,19 @@ class MolStarProteopediaWrapper {
             if (state.select('asm').length > 0) loadType = 'update';
         }
 
-        let tree: StateBuilder.Root;
         if (loadType === 'full') {
             await PluginCommands.State.RemoveObject.dispatch(this.plugin, { state, ref: state.tree.root.ref });
-            tree = state.build();
-            this.parse(this.download(tree.toRoot(), url), format, assemblyId);
+            const modelTree = this.model(this.download(state.build().toRoot(), url), format, assemblyId);
+            await this.applyState(modelTree);
+            const info = await this.doInfo(true);
+            const structureTree = this.structure((assemblyId === 'preferred' && info && info.preferredAssemblyId) || assemblyId);
+            await this.applyState(structureTree);
         } else {
-            tree = state.build();
+            const tree = state.build();
             tree.to('asm').update(StateTransforms.Model.StructureAssemblyFromModel, p => ({ ...p, id: assemblyId || 'deposited' }));
+            await this.applyState(tree);
         }
 
-        await PluginCommands.State.Update.dispatch(this.plugin, { state: this.plugin.state.dataState, tree });
         await this.updateStyle(representationStyle);
 
         this.loadedParams = { url, format, assemblyId };