diff --git a/package.json b/package.json
index 461fde5d6a38a9176f6a7c387ae2e1f8d2b317bb..770ce3ae85a694e2154ec4ba013bb98430eb11c5 100644
--- a/package.json
+++ b/package.json
@@ -3,15 +3,8 @@
   "version": "2.4.0",
   "description": "HBP interactive atlas viewer. Integrating KG query, dataset previews & more. Based on humanbrainproject/nehuba & google/neuroglancer. Built with angular",
   "scripts": {
-    "dev-server-export": "webpack-dev-server --config webpack.export.js",
-    "build-export": "webpack --config webpack.export.js",
-    "build-export-min": "webpack --config webpack.export.min.js",
-    "build-export-aot": "webpack --config webpack.export.aot.js",
-    "build-aot": "PRODUCTION=true GIT_HASH=`jq -r '.version' package.json` webpack --config webpack.aot.js && node ./third_party/matomo/processMatomo.js",
-    "plugin-server": "node ./src/plugin_examples/server.js",
-    "dev-server": "BACKEND_URL=${BACKEND_URL:-http://localhost:3000/} webpack-dev-server --config webpack.dev.js --mode development",
-    "dev-server-aot": "BACKEND_URL=${BACKEND_URL:-http://localhost:3000/} PRODUCTION=true GIT_HASH=`jq -r '.version' package.json` webpack-dev-server --config webpack.dev-aot.js",
-    "dev-server-all-interfaces": "webpack-dev-server --config webpack.dev.js --mode development --hot --host 0.0.0.0",
+    "build-aot": "PRODUCTION=true GIT_HASH=`jq -r '.version' package.json` webpack --config ./webpack/webpack.aot.js && node ./third_party/matomo/processMatomo.js",
+    "dev-server-aot": "BACKEND_URL=${BACKEND_URL:-http://localhost:3000/} PRODUCTION=true GIT_HASH=`jq -r '.version' package.json` webpack-dev-server --config ./webpack/webpack.dev-aot.js",
     "test": "karma start spec/karma.conf.js",
     "e2e": "protractor e2e/protractor.conf",
     "lint": "eslint src --ext .ts",
diff --git a/spec/karma.conf.js b/spec/karma.conf.js
index 4f4eb985a36341172d86343a1b95e194e9300bbc..cff56013dafa5ae119154af750913ee51078c5ac 100644
--- a/spec/karma.conf.js
+++ b/spec/karma.conf.js
@@ -2,8 +2,8 @@
 // Generated on Mon Aug 06 2018 12:37:42 GMT+0200 (CEST)
 
 const merge = require('webpack-merge')
-const webpackTest = require('../webpack.test')
-const webpackConfig = require('../webpack.dev')
+const webpackTest = require('../webpack/webpack.test')
+const webpackConfig = require('../webpack/webpack.dev')
 const fullWebpack = merge(webpackTest, webpackConfig)
 
 const singleRun = process.env.NODE_ENV === 'test'
diff --git a/src/ui/connectivityBrowser/connectivityBrowser.component.ts b/src/atlasComponents/connectivity/connectivityBrowser/connectivityBrowser.component.ts
similarity index 97%
rename from src/ui/connectivityBrowser/connectivityBrowser.component.ts
rename to src/atlasComponents/connectivity/connectivityBrowser/connectivityBrowser.component.ts
index 03f768c8a7b9968f5e5bef33d15a1ff812f89a4b..9f454d3e1d958832ff0e2e7a195d03ba99480521 100644
--- a/src/ui/connectivityBrowser/connectivityBrowser.component.ts
+++ b/src/atlasComponents/connectivity/connectivityBrowser/connectivityBrowser.component.ts
@@ -71,6 +71,9 @@ export class ConnectivityBrowserComponent implements OnInit, AfterViewInit, OnDe
       })
     }
 
+    @Output()
+    connectivityDataReceived = new EventEmitter<any>()
+
     @Output()
     setOpenState: EventEmitter<boolean> = new EventEmitter()
 
@@ -132,7 +135,7 @@ export class ConnectivityBrowserComponent implements OnInit, AfterViewInit, OnDe
     constructor(
         private store$: Store<any>,
         private changeDetectionRef: ChangeDetectorRef,
-        private httpClient: HttpClient
+        private httpClient: HttpClient,
     ) {
 
       this.overwrittenColorMap$ = this.store$.pipe(
@@ -149,8 +152,8 @@ export class ConnectivityBrowserComponent implements OnInit, AfterViewInit, OnDe
     ngOnInit(): void {
       this.httpClient.get<[]>(this.connectivityUrl).subscribe(res => {
         this.datasetList = res.filter(dl => dl['parcellation id'] === this.parcellationId)
-        this.selectedDataset = this.datasetList[0].name
-        this.selectedDatasetDescription = this.datasetList[0].description
+        this.selectedDataset = this.datasetList[0]?.name
+        this.selectedDatasetDescription = this.datasetList[0]?.description
 
         this.changeDataset()
       })
@@ -209,7 +212,7 @@ export class ConnectivityBrowserComponent implements OnInit, AfterViewInit, OnDe
           this.setColorMap$.pipe(
             distinctUntilChanged()
           ),
-          fromEvent(this.connectivityComponentElement.nativeElement, 'connectivityDataReceived').pipe(
+          fromEvent(this.connectivityComponentElement?.nativeElement, 'connectivityDataReceived').pipe(
             map((e: CustomEvent) => e.detail)
           )
         ).subscribe(([flag, connectedAreas]) => {
@@ -225,7 +228,6 @@ export class ConnectivityBrowserComponent implements OnInit, AfterViewInit, OnDe
               })
             )
             this.noDataReceived = false
-
             this.connectivityNumberReceived.emit(connectedAreas.length)
             this.connectedAreas = connectedAreas
 
diff --git a/src/ui/connectivityBrowser/connectivityBrowser.template.html b/src/atlasComponents/connectivity/connectivityBrowser/connectivityBrowser.template.html
similarity index 98%
rename from src/ui/connectivityBrowser/connectivityBrowser.template.html
rename to src/atlasComponents/connectivity/connectivityBrowser/connectivityBrowser.template.html
index 3f69aa9c292f8d61a236f30bad6f9f963938b84e..fa47192a66062082a8d29c557871a35bb6726a49 100644
--- a/src/ui/connectivityBrowser/connectivityBrowser.template.html
+++ b/src/atlasComponents/connectivity/connectivityBrowser/connectivityBrowser.template.html
@@ -1,5 +1,6 @@
 <div class="w-100 h-100 d-block d-flex flex-column pb-2">
     <hbp-connectivity-matrix-row
+            (connectivityDataReceived)="connectivityDataReceived.emit($event)"
             #connectivityComponent
             *ngIf="regionName"
             [region]="regionName + (regionHemisphere? ' - ' + regionHemisphere : '')"
diff --git a/src/atlasComponents/connectivity/index.ts b/src/atlasComponents/connectivity/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c9a2e808fc6290283e77ea4bccff8f199eea3ca0
--- /dev/null
+++ b/src/atlasComponents/connectivity/index.ts
@@ -0,0 +1,2 @@
+export { ConnectivityBrowserComponent } from "./connectivityBrowser/connectivityBrowser.component";
+export { AtlasCmptConnModule } from "./module";
\ No newline at end of file
diff --git a/src/atlasComponents/connectivity/module.ts b/src/atlasComponents/connectivity/module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8d629f66cfeb00b9f7b1f38fa45780725cac8f87
--- /dev/null
+++ b/src/atlasComponents/connectivity/module.ts
@@ -0,0 +1,24 @@
+import { CommonModule } from "@angular/common";
+import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from "@angular/core";
+import { AngularMaterialModule } from "src/ui/sharedModules/angularMaterial.module";
+import { DatabrowserModule } from "../databrowserModule";
+import { ConnectivityBrowserComponent } from "./connectivityBrowser/connectivityBrowser.component";
+
+@NgModule({
+  imports: [
+    CommonModule,
+    DatabrowserModule,
+    AngularMaterialModule,
+  ],
+  declarations: [
+    ConnectivityBrowserComponent,
+  ],
+  exports: [
+    ConnectivityBrowserComponent,
+  ],
+  schemas: [
+    CUSTOM_ELEMENTS_SCHEMA,
+  ],
+})
+
+export class AtlasCmptConnModule{}
\ No newline at end of file
diff --git a/src/ui/databrowserModule/bulkDownload/bulkDownloadBtn.component.ts b/src/atlasComponents/databrowserModule/bulkDownload/bulkDownloadBtn.component.ts
similarity index 100%
rename from src/ui/databrowserModule/bulkDownload/bulkDownloadBtn.component.ts
rename to src/atlasComponents/databrowserModule/bulkDownload/bulkDownloadBtn.component.ts
diff --git a/src/ui/databrowserModule/bulkDownload/bulkDownloadBtn.template.html b/src/atlasComponents/databrowserModule/bulkDownload/bulkDownloadBtn.template.html
similarity index 100%
rename from src/ui/databrowserModule/bulkDownload/bulkDownloadBtn.template.html
rename to src/atlasComponents/databrowserModule/bulkDownload/bulkDownloadBtn.template.html
diff --git a/src/ui/databrowserModule/constants.ts b/src/atlasComponents/databrowserModule/constants.ts
similarity index 100%
rename from src/ui/databrowserModule/constants.ts
rename to src/atlasComponents/databrowserModule/constants.ts
diff --git a/src/ui/databrowserModule/contributor/index.ts b/src/atlasComponents/databrowserModule/contributor/index.ts
similarity index 100%
rename from src/ui/databrowserModule/contributor/index.ts
rename to src/atlasComponents/databrowserModule/contributor/index.ts
diff --git a/src/ui/databrowserModule/contributor/kgLink.pipe.ts b/src/atlasComponents/databrowserModule/contributor/kgLink.pipe.ts
similarity index 100%
rename from src/ui/databrowserModule/contributor/kgLink.pipe.ts
rename to src/atlasComponents/databrowserModule/contributor/kgLink.pipe.ts
diff --git a/src/ui/databrowserModule/contributor/module.ts b/src/atlasComponents/databrowserModule/contributor/module.ts
similarity index 100%
rename from src/ui/databrowserModule/contributor/module.ts
rename to src/atlasComponents/databrowserModule/contributor/module.ts
diff --git a/src/ui/databrowserModule/contributor/util.ts b/src/atlasComponents/databrowserModule/contributor/util.ts
similarity index 100%
rename from src/ui/databrowserModule/contributor/util.ts
rename to src/atlasComponents/databrowserModule/contributor/util.ts
diff --git a/src/ui/databrowserModule/databrowser.module.ts b/src/atlasComponents/databrowserModule/databrowser.module.ts
similarity index 99%
rename from src/ui/databrowserModule/databrowser.module.ts
rename to src/atlasComponents/databrowserModule/databrowser.module.ts
index b03aec66953c43b10a40dca97a1f308b85f4cfcd..60aa012d2ee3cb06d4f9364125156a8f2fc0ada1 100644
--- a/src/ui/databrowserModule/databrowser.module.ts
+++ b/src/atlasComponents/databrowserModule/databrowser.module.ts
@@ -40,7 +40,7 @@ import {
 import { ShownPreviewsDirective } from "./preview/shownPreviews.directive";
 import { FilterPreviewByType } from "./preview/filterPreview.pipe";
 import { PreviewCardComponent } from "./preview/previewCard/previewCard.component";
-import { LayerBrowserModule } from "../layerbrowser";
+import { LayerBrowserModule } from "../../ui/layerbrowser";
 import { DatabrowserDirective } from "./databrowser/databrowser.directive";
 import { ContributorModule } from "./contributor";
 import { DatabrowserService } from "./databrowser.service";
diff --git a/src/ui/databrowserModule/databrowser.service.spec.ts b/src/atlasComponents/databrowserModule/databrowser.service.spec.ts
similarity index 100%
rename from src/ui/databrowserModule/databrowser.service.spec.ts
rename to src/atlasComponents/databrowserModule/databrowser.service.spec.ts
diff --git a/src/ui/databrowserModule/databrowser.service.ts b/src/atlasComponents/databrowserModule/databrowser.service.ts
similarity index 100%
rename from src/ui/databrowserModule/databrowser.service.ts
rename to src/atlasComponents/databrowserModule/databrowser.service.ts
diff --git a/src/ui/databrowserModule/databrowser.useEffect.spec.ts b/src/atlasComponents/databrowserModule/databrowser.useEffect.spec.ts
similarity index 100%
rename from src/ui/databrowserModule/databrowser.useEffect.spec.ts
rename to src/atlasComponents/databrowserModule/databrowser.useEffect.spec.ts
diff --git a/src/ui/databrowserModule/databrowser.useEffect.ts b/src/atlasComponents/databrowserModule/databrowser.useEffect.ts
similarity index 100%
rename from src/ui/databrowserModule/databrowser.useEffect.ts
rename to src/atlasComponents/databrowserModule/databrowser.useEffect.ts
diff --git a/src/ui/databrowserModule/databrowser/databrowser.base.ts b/src/atlasComponents/databrowserModule/databrowser/databrowser.base.ts
similarity index 100%
rename from src/ui/databrowserModule/databrowser/databrowser.base.ts
rename to src/atlasComponents/databrowserModule/databrowser/databrowser.base.ts
diff --git a/src/ui/databrowserModule/databrowser/databrowser.component.ts b/src/atlasComponents/databrowserModule/databrowser/databrowser.component.ts
similarity index 100%
rename from src/ui/databrowserModule/databrowser/databrowser.component.ts
rename to src/atlasComponents/databrowserModule/databrowser/databrowser.component.ts
diff --git a/src/ui/databrowserModule/databrowser/databrowser.directive.ts b/src/atlasComponents/databrowserModule/databrowser/databrowser.directive.ts
similarity index 100%
rename from src/ui/databrowserModule/databrowser/databrowser.directive.ts
rename to src/atlasComponents/databrowserModule/databrowser/databrowser.directive.ts
diff --git a/src/ui/databrowserModule/databrowser/databrowser.style.css b/src/atlasComponents/databrowserModule/databrowser/databrowser.style.css
similarity index 100%
rename from src/ui/databrowserModule/databrowser/databrowser.style.css
rename to src/atlasComponents/databrowserModule/databrowser/databrowser.style.css
diff --git a/src/ui/databrowserModule/databrowser/databrowser.template.html b/src/atlasComponents/databrowserModule/databrowser/databrowser.template.html
similarity index 100%
rename from src/ui/databrowserModule/databrowser/databrowser.template.html
rename to src/atlasComponents/databrowserModule/databrowser/databrowser.template.html
diff --git a/src/ui/databrowserModule/index.ts b/src/atlasComponents/databrowserModule/index.ts
similarity index 100%
rename from src/ui/databrowserModule/index.ts
rename to src/atlasComponents/databrowserModule/index.ts
diff --git a/src/ui/databrowserModule/kgSingleDatasetService.service.ts b/src/atlasComponents/databrowserModule/kgSingleDatasetService.service.ts
similarity index 100%
rename from src/ui/databrowserModule/kgSingleDatasetService.service.ts
rename to src/atlasComponents/databrowserModule/kgSingleDatasetService.service.ts
diff --git a/src/ui/databrowserModule/modalityPicker/modalityPicker.component.spec.ts b/src/atlasComponents/databrowserModule/modalityPicker/modalityPicker.component.spec.ts
similarity index 100%
rename from src/ui/databrowserModule/modalityPicker/modalityPicker.component.spec.ts
rename to src/atlasComponents/databrowserModule/modalityPicker/modalityPicker.component.spec.ts
diff --git a/src/ui/databrowserModule/modalityPicker/modalityPicker.component.ts b/src/atlasComponents/databrowserModule/modalityPicker/modalityPicker.component.ts
similarity index 100%
rename from src/ui/databrowserModule/modalityPicker/modalityPicker.component.ts
rename to src/atlasComponents/databrowserModule/modalityPicker/modalityPicker.component.ts
diff --git a/src/ui/databrowserModule/modalityPicker/modalityPicker.style.css b/src/atlasComponents/databrowserModule/modalityPicker/modalityPicker.style.css
similarity index 100%
rename from src/ui/databrowserModule/modalityPicker/modalityPicker.style.css
rename to src/atlasComponents/databrowserModule/modalityPicker/modalityPicker.style.css
diff --git a/src/ui/databrowserModule/modalityPicker/modalityPicker.template.html b/src/atlasComponents/databrowserModule/modalityPicker/modalityPicker.template.html
similarity index 100%
rename from src/ui/databrowserModule/modalityPicker/modalityPicker.template.html
rename to src/atlasComponents/databrowserModule/modalityPicker/modalityPicker.template.html
diff --git a/src/ui/databrowserModule/preview/datasetPreviews/datasetPreviewsList/datasetPreviewList.component.ts b/src/atlasComponents/databrowserModule/preview/datasetPreviews/datasetPreviewsList/datasetPreviewList.component.ts
similarity index 100%
rename from src/ui/databrowserModule/preview/datasetPreviews/datasetPreviewsList/datasetPreviewList.component.ts
rename to src/atlasComponents/databrowserModule/preview/datasetPreviews/datasetPreviewsList/datasetPreviewList.component.ts
diff --git a/src/ui/databrowserModule/preview/datasetPreviews/datasetPreviewsList/datasetPreviewList.template.html b/src/atlasComponents/databrowserModule/preview/datasetPreviews/datasetPreviewsList/datasetPreviewList.template.html
similarity index 100%
rename from src/ui/databrowserModule/preview/datasetPreviews/datasetPreviewsList/datasetPreviewList.template.html
rename to src/atlasComponents/databrowserModule/preview/datasetPreviews/datasetPreviewsList/datasetPreviewList.template.html
diff --git a/src/ui/databrowserModule/preview/filterPreview.pipe.ts b/src/atlasComponents/databrowserModule/preview/filterPreview.pipe.ts
similarity index 100%
rename from src/ui/databrowserModule/preview/filterPreview.pipe.ts
rename to src/atlasComponents/databrowserModule/preview/filterPreview.pipe.ts
diff --git a/src/ui/databrowserModule/preview/preview.base.ts b/src/atlasComponents/databrowserModule/preview/preview.base.ts
similarity index 100%
rename from src/ui/databrowserModule/preview/preview.base.ts
rename to src/atlasComponents/databrowserModule/preview/preview.base.ts
diff --git a/src/ui/databrowserModule/preview/previewCard/previewCard.component.ts b/src/atlasComponents/databrowserModule/preview/previewCard/previewCard.component.ts
similarity index 100%
rename from src/ui/databrowserModule/preview/previewCard/previewCard.component.ts
rename to src/atlasComponents/databrowserModule/preview/previewCard/previewCard.component.ts
diff --git a/src/ui/databrowserModule/preview/previewCard/previewCard.style.css b/src/atlasComponents/databrowserModule/preview/previewCard/previewCard.style.css
similarity index 100%
rename from src/ui/databrowserModule/preview/previewCard/previewCard.style.css
rename to src/atlasComponents/databrowserModule/preview/previewCard/previewCard.style.css
diff --git a/src/ui/databrowserModule/preview/previewCard/previewCard.template.html b/src/atlasComponents/databrowserModule/preview/previewCard/previewCard.template.html
similarity index 100%
rename from src/ui/databrowserModule/preview/previewCard/previewCard.template.html
rename to src/atlasComponents/databrowserModule/preview/previewCard/previewCard.template.html
diff --git a/src/ui/databrowserModule/preview/previewComponentWrapper/previewCW.component.ts b/src/atlasComponents/databrowserModule/preview/previewComponentWrapper/previewCW.component.ts
similarity index 100%
rename from src/ui/databrowserModule/preview/previewComponentWrapper/previewCW.component.ts
rename to src/atlasComponents/databrowserModule/preview/previewComponentWrapper/previewCW.component.ts
diff --git a/src/ui/databrowserModule/preview/previewComponentWrapper/previewCW.style.css b/src/atlasComponents/databrowserModule/preview/previewComponentWrapper/previewCW.style.css
similarity index 100%
rename from src/ui/databrowserModule/preview/previewComponentWrapper/previewCW.style.css
rename to src/atlasComponents/databrowserModule/preview/previewComponentWrapper/previewCW.style.css
diff --git a/src/ui/databrowserModule/preview/previewComponentWrapper/previewCW.template.html b/src/atlasComponents/databrowserModule/preview/previewComponentWrapper/previewCW.template.html
similarity index 100%
rename from src/ui/databrowserModule/preview/previewComponentWrapper/previewCW.template.html
rename to src/atlasComponents/databrowserModule/preview/previewComponentWrapper/previewCW.template.html
diff --git a/src/ui/databrowserModule/preview/previewDatasetFile.directive.spec.ts b/src/atlasComponents/databrowserModule/preview/previewDatasetFile.directive.spec.ts
similarity index 100%
rename from src/ui/databrowserModule/preview/previewDatasetFile.directive.spec.ts
rename to src/atlasComponents/databrowserModule/preview/previewDatasetFile.directive.spec.ts
diff --git a/src/ui/databrowserModule/preview/previewDatasetFile.directive.ts b/src/atlasComponents/databrowserModule/preview/previewDatasetFile.directive.ts
similarity index 100%
rename from src/ui/databrowserModule/preview/previewDatasetFile.directive.ts
rename to src/atlasComponents/databrowserModule/preview/previewDatasetFile.directive.ts
diff --git a/src/ui/databrowserModule/preview/previewFileIcon.pipe.ts b/src/atlasComponents/databrowserModule/preview/previewFileIcon.pipe.ts
similarity index 100%
rename from src/ui/databrowserModule/preview/previewFileIcon.pipe.ts
rename to src/atlasComponents/databrowserModule/preview/previewFileIcon.pipe.ts
diff --git a/src/ui/databrowserModule/preview/previewFileType.pipe.ts b/src/atlasComponents/databrowserModule/preview/previewFileType.pipe.ts
similarity index 100%
rename from src/ui/databrowserModule/preview/previewFileType.pipe.ts
rename to src/atlasComponents/databrowserModule/preview/previewFileType.pipe.ts
diff --git a/src/ui/databrowserModule/preview/shownPreviews.directive.ts b/src/atlasComponents/databrowserModule/preview/shownPreviews.directive.ts
similarity index 100%
rename from src/ui/databrowserModule/preview/shownPreviews.directive.ts
rename to src/atlasComponents/databrowserModule/preview/shownPreviews.directive.ts
diff --git a/src/ui/databrowserModule/pure.spec.ts b/src/atlasComponents/databrowserModule/pure.spec.ts
similarity index 100%
rename from src/ui/databrowserModule/pure.spec.ts
rename to src/atlasComponents/databrowserModule/pure.spec.ts
diff --git a/src/ui/databrowserModule/pure.ts b/src/atlasComponents/databrowserModule/pure.ts
similarity index 100%
rename from src/ui/databrowserModule/pure.ts
rename to src/atlasComponents/databrowserModule/pure.ts
diff --git a/src/ui/databrowserModule/showDatasetDialog.directive.spec.ts b/src/atlasComponents/databrowserModule/showDatasetDialog.directive.spec.ts
similarity index 98%
rename from src/ui/databrowserModule/showDatasetDialog.directive.spec.ts
rename to src/atlasComponents/databrowserModule/showDatasetDialog.directive.spec.ts
index 18fa8349d210f0f86fdc82ecd8a2af4efaf57db4..4dbac0cb6856c0bacb1218aef34d2e66a456d666 100644
--- a/src/ui/databrowserModule/showDatasetDialog.directive.spec.ts
+++ b/src/atlasComponents/databrowserModule/showDatasetDialog.directive.spec.ts
@@ -1,6 +1,6 @@
 import { Component } from "@angular/core";
 import { async, TestBed } from "@angular/core/testing";
-import { AngularMaterialModule } from "../sharedModules/angularMaterial.module";
+import { AngularMaterialModule } from "../../ui/sharedModules/angularMaterial.module";
 import { ShowDatasetDialogDirective, IAV_DATASET_SHOW_DATASET_DIALOG_CMP } from "./showDatasetDialog.directive";
 import { By } from "@angular/platform-browser";
 import { MatDialog } from "@angular/material/dialog";
diff --git a/src/ui/databrowserModule/showDatasetDialog.directive.ts b/src/atlasComponents/databrowserModule/showDatasetDialog.directive.ts
similarity index 100%
rename from src/ui/databrowserModule/showDatasetDialog.directive.ts
rename to src/atlasComponents/databrowserModule/showDatasetDialog.directive.ts
diff --git a/src/ui/databrowserModule/shownDataset.directive.ts b/src/atlasComponents/databrowserModule/shownDataset.directive.ts
similarity index 100%
rename from src/ui/databrowserModule/shownDataset.directive.ts
rename to src/atlasComponents/databrowserModule/shownDataset.directive.ts
diff --git a/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.component.spec.ts b/src/atlasComponents/databrowserModule/singleDataset/detailedView/singleDataset.component.spec.ts
similarity index 100%
rename from src/ui/databrowserModule/singleDataset/detailedView/singleDataset.component.spec.ts
rename to src/atlasComponents/databrowserModule/singleDataset/detailedView/singleDataset.component.spec.ts
diff --git a/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.component.ts b/src/atlasComponents/databrowserModule/singleDataset/detailedView/singleDataset.component.ts
similarity index 100%
rename from src/ui/databrowserModule/singleDataset/detailedView/singleDataset.component.ts
rename to src/atlasComponents/databrowserModule/singleDataset/detailedView/singleDataset.component.ts
diff --git a/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.style.css b/src/atlasComponents/databrowserModule/singleDataset/detailedView/singleDataset.style.css
similarity index 100%
rename from src/ui/databrowserModule/singleDataset/detailedView/singleDataset.style.css
rename to src/atlasComponents/databrowserModule/singleDataset/detailedView/singleDataset.style.css
diff --git a/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.template.html b/src/atlasComponents/databrowserModule/singleDataset/detailedView/singleDataset.template.html
similarity index 100%
rename from src/ui/databrowserModule/singleDataset/detailedView/singleDataset.template.html
rename to src/atlasComponents/databrowserModule/singleDataset/detailedView/singleDataset.template.html
diff --git a/src/ui/databrowserModule/singleDataset/listView/singleDatasetListView.component.ts b/src/atlasComponents/databrowserModule/singleDataset/listView/singleDatasetListView.component.ts
similarity index 100%
rename from src/ui/databrowserModule/singleDataset/listView/singleDatasetListView.component.ts
rename to src/atlasComponents/databrowserModule/singleDataset/listView/singleDatasetListView.component.ts
diff --git a/src/ui/databrowserModule/singleDataset/listView/singleDatasetListView.style.css b/src/atlasComponents/databrowserModule/singleDataset/listView/singleDatasetListView.style.css
similarity index 100%
rename from src/ui/databrowserModule/singleDataset/listView/singleDatasetListView.style.css
rename to src/atlasComponents/databrowserModule/singleDataset/listView/singleDatasetListView.style.css
diff --git a/src/ui/databrowserModule/singleDataset/listView/singleDatasetListView.template.html b/src/atlasComponents/databrowserModule/singleDataset/listView/singleDatasetListView.template.html
similarity index 100%
rename from src/ui/databrowserModule/singleDataset/listView/singleDatasetListView.template.html
rename to src/atlasComponents/databrowserModule/singleDataset/listView/singleDatasetListView.template.html
diff --git a/src/ui/databrowserModule/singleDataset/sideNavView/sDsSideNavView.component.ts b/src/atlasComponents/databrowserModule/singleDataset/sideNavView/sDsSideNavView.component.ts
similarity index 100%
rename from src/ui/databrowserModule/singleDataset/sideNavView/sDsSideNavView.component.ts
rename to src/atlasComponents/databrowserModule/singleDataset/sideNavView/sDsSideNavView.component.ts
diff --git a/src/ui/databrowserModule/singleDataset/sideNavView/sDsSideNavView.style.css b/src/atlasComponents/databrowserModule/singleDataset/sideNavView/sDsSideNavView.style.css
similarity index 100%
rename from src/ui/databrowserModule/singleDataset/sideNavView/sDsSideNavView.style.css
rename to src/atlasComponents/databrowserModule/singleDataset/sideNavView/sDsSideNavView.style.css
diff --git a/src/ui/databrowserModule/singleDataset/sideNavView/sDsSideNavView.template.html b/src/atlasComponents/databrowserModule/singleDataset/sideNavView/sDsSideNavView.template.html
similarity index 100%
rename from src/ui/databrowserModule/singleDataset/sideNavView/sDsSideNavView.template.html
rename to src/atlasComponents/databrowserModule/singleDataset/sideNavView/sDsSideNavView.template.html
diff --git a/src/ui/databrowserModule/singleDataset/singleDataset.base.spec.ts b/src/atlasComponents/databrowserModule/singleDataset/singleDataset.base.spec.ts
similarity index 100%
rename from src/ui/databrowserModule/singleDataset/singleDataset.base.spec.ts
rename to src/atlasComponents/databrowserModule/singleDataset/singleDataset.base.spec.ts
diff --git a/src/ui/databrowserModule/singleDataset/singleDataset.base.ts b/src/atlasComponents/databrowserModule/singleDataset/singleDataset.base.ts
similarity index 100%
rename from src/ui/databrowserModule/singleDataset/singleDataset.base.ts
rename to src/atlasComponents/databrowserModule/singleDataset/singleDataset.base.ts
diff --git a/src/ui/databrowserModule/singleDataset/singleDataset.directive.ts b/src/atlasComponents/databrowserModule/singleDataset/singleDataset.directive.ts
similarity index 100%
rename from src/ui/databrowserModule/singleDataset/singleDataset.directive.ts
rename to src/atlasComponents/databrowserModule/singleDataset/singleDataset.directive.ts
diff --git a/src/ui/databrowserModule/store.module.ts b/src/atlasComponents/databrowserModule/store.module.ts
similarity index 100%
rename from src/ui/databrowserModule/store.module.ts
rename to src/atlasComponents/databrowserModule/store.module.ts
diff --git a/src/ui/databrowserModule/util/aggregateArrayIntoRoot.pipe.ts b/src/atlasComponents/databrowserModule/util/aggregateArrayIntoRoot.pipe.ts
similarity index 100%
rename from src/ui/databrowserModule/util/aggregateArrayIntoRoot.pipe.ts
rename to src/atlasComponents/databrowserModule/util/aggregateArrayIntoRoot.pipe.ts
diff --git a/src/ui/databrowserModule/util/appendFilterModality.pipe.ts b/src/atlasComponents/databrowserModule/util/appendFilterModality.pipe.ts
similarity index 100%
rename from src/ui/databrowserModule/util/appendFilterModality.pipe.ts
rename to src/atlasComponents/databrowserModule/util/appendFilterModality.pipe.ts
diff --git a/src/ui/databrowserModule/util/copyProperty.pipe.spec.ts b/src/atlasComponents/databrowserModule/util/copyProperty.pipe.spec.ts
similarity index 100%
rename from src/ui/databrowserModule/util/copyProperty.pipe.spec.ts
rename to src/atlasComponents/databrowserModule/util/copyProperty.pipe.spec.ts
diff --git a/src/ui/databrowserModule/util/copyProperty.pipe.ts b/src/atlasComponents/databrowserModule/util/copyProperty.pipe.ts
similarity index 100%
rename from src/ui/databrowserModule/util/copyProperty.pipe.ts
rename to src/atlasComponents/databrowserModule/util/copyProperty.pipe.ts
diff --git a/src/ui/databrowserModule/util/datasetIsFaved.pipe.ts b/src/atlasComponents/databrowserModule/util/datasetIsFaved.pipe.ts
similarity index 100%
rename from src/ui/databrowserModule/util/datasetIsFaved.pipe.ts
rename to src/atlasComponents/databrowserModule/util/datasetIsFaved.pipe.ts
diff --git a/src/ui/databrowserModule/util/filterDataEntriesByMethods.pipe.ts b/src/atlasComponents/databrowserModule/util/filterDataEntriesByMethods.pipe.ts
similarity index 100%
rename from src/ui/databrowserModule/util/filterDataEntriesByMethods.pipe.ts
rename to src/atlasComponents/databrowserModule/util/filterDataEntriesByMethods.pipe.ts
diff --git a/src/ui/databrowserModule/util/filterDataEntriesByRegion.pipe.spec.ts b/src/atlasComponents/databrowserModule/util/filterDataEntriesByRegion.pipe.spec.ts
similarity index 100%
rename from src/ui/databrowserModule/util/filterDataEntriesByRegion.pipe.spec.ts
rename to src/atlasComponents/databrowserModule/util/filterDataEntriesByRegion.pipe.spec.ts
diff --git a/src/ui/databrowserModule/util/filterDataEntriesByRegion.pipe.ts b/src/atlasComponents/databrowserModule/util/filterDataEntriesByRegion.pipe.ts
similarity index 100%
rename from src/ui/databrowserModule/util/filterDataEntriesByRegion.pipe.ts
rename to src/atlasComponents/databrowserModule/util/filterDataEntriesByRegion.pipe.ts
diff --git a/src/ui/databrowserModule/util/getKgSchemaIdFromFullId.pipe.ts b/src/atlasComponents/databrowserModule/util/getKgSchemaIdFromFullId.pipe.ts
similarity index 100%
rename from src/ui/databrowserModule/util/getKgSchemaIdFromFullId.pipe.ts
rename to src/atlasComponents/databrowserModule/util/getKgSchemaIdFromFullId.pipe.ts
diff --git a/src/ui/databrowserModule/util/pathToNestedChildren.pipe.spec.ts b/src/atlasComponents/databrowserModule/util/pathToNestedChildren.pipe.spec.ts
similarity index 100%
rename from src/ui/databrowserModule/util/pathToNestedChildren.pipe.spec.ts
rename to src/atlasComponents/databrowserModule/util/pathToNestedChildren.pipe.spec.ts
diff --git a/src/ui/databrowserModule/util/pathToNestedChildren.pipe.ts b/src/atlasComponents/databrowserModule/util/pathToNestedChildren.pipe.ts
similarity index 100%
rename from src/ui/databrowserModule/util/pathToNestedChildren.pipe.ts
rename to src/atlasComponents/databrowserModule/util/pathToNestedChildren.pipe.ts
diff --git a/src/ui/databrowserModule/util/previewFileDisabledByReferenceSpace.pipe.ts b/src/atlasComponents/databrowserModule/util/previewFileDisabledByReferenceSpace.pipe.ts
similarity index 100%
rename from src/ui/databrowserModule/util/previewFileDisabledByReferenceSpace.pipe.ts
rename to src/atlasComponents/databrowserModule/util/previewFileDisabledByReferenceSpace.pipe.ts
diff --git a/src/ui/databrowserModule/util/regionBackgroundToRgb.pipe.ts b/src/atlasComponents/databrowserModule/util/regionBackgroundToRgb.pipe.ts
similarity index 100%
rename from src/ui/databrowserModule/util/regionBackgroundToRgb.pipe.ts
rename to src/atlasComponents/databrowserModule/util/regionBackgroundToRgb.pipe.ts
diff --git a/src/ui/databrowserModule/util/resetCounterModality.pipe.ts b/src/atlasComponents/databrowserModule/util/resetCounterModality.pipe.ts
similarity index 100%
rename from src/ui/databrowserModule/util/resetCounterModality.pipe.ts
rename to src/atlasComponents/databrowserModule/util/resetCounterModality.pipe.ts
diff --git a/src/atlasComponents/parcellation/index.ts b/src/atlasComponents/parcellation/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4af8252e223c89fce580454087e7038563e1fab4
--- /dev/null
+++ b/src/atlasComponents/parcellation/index.ts
@@ -0,0 +1,4 @@
+export { FilterNameBySearch } from "./regionHierachy/filterNameBySearch.pipe";
+export { AtlasCmpParcellationModule } from "./module";
+export { RegionHierarchy } from "./regionHierachy/regionHierarchy.component";
+export { RegionTextSearchAutocomplete } from "./regionSearch/regionSearch.component";
diff --git a/src/atlasComponents/parcellation/module.ts b/src/atlasComponents/parcellation/module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..78821146430138aa7afe3998ce3959c09f3c099f
--- /dev/null
+++ b/src/atlasComponents/parcellation/module.ts
@@ -0,0 +1,34 @@
+import { CommonModule } from "@angular/common";
+import { NgModule } from "@angular/core";
+import { AngularMaterialModule } from "src/ui/sharedModules/angularMaterial.module";
+import { ParcellationRegionModule } from "src/atlasComponents/parcellationRegion";
+import { RegionHierarchy } from "./regionHierachy/regionHierarchy.component";
+import { RegionTextSearchAutocomplete } from "./regionSearch/regionSearch.component";
+import { FilterNameBySearch } from "./regionHierachy/filterNameBySearch.pipe";
+import { UtilModule } from "src/util";
+import { FormsModule, ReactiveFormsModule } from "@angular/forms";
+import { ComponentsModule } from "src/components";
+
+@NgModule({
+  imports: [
+    CommonModule,
+    UtilModule,
+    FormsModule,
+    ReactiveFormsModule,
+    AngularMaterialModule,
+    ParcellationRegionModule,
+    ComponentsModule,
+  ],
+  declarations: [
+    RegionHierarchy,
+    RegionTextSearchAutocomplete,
+
+    FilterNameBySearch,
+  ],
+  exports: [
+    RegionHierarchy,
+    RegionTextSearchAutocomplete,
+    FilterNameBySearch,
+  ]
+})
+export class AtlasCmpParcellationModule{}
\ No newline at end of file
diff --git a/src/ui/viewerStateController/regionHierachy/filterNameBySearch.pipe.ts b/src/atlasComponents/parcellation/regionHierachy/filterNameBySearch.pipe.ts
similarity index 100%
rename from src/ui/viewerStateController/regionHierachy/filterNameBySearch.pipe.ts
rename to src/atlasComponents/parcellation/regionHierachy/filterNameBySearch.pipe.ts
diff --git a/src/ui/viewerStateController/regionHierachy/regionHierarchy.component.ts b/src/atlasComponents/parcellation/regionHierachy/regionHierarchy.component.ts
similarity index 97%
rename from src/ui/viewerStateController/regionHierachy/regionHierarchy.component.ts
rename to src/atlasComponents/parcellation/regionHierachy/regionHierarchy.component.ts
index 2534f5548129666f3201ea821e1319c6b2bbc572..715f000757552e41ee4e67ace06e9de56006e69e 100644
--- a/src/ui/viewerStateController/regionHierachy/regionHierarchy.component.ts
+++ b/src/atlasComponents/parcellation/regionHierachy/regionHierarchy.component.ts
@@ -1,8 +1,8 @@
 import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, HostListener, Input, OnInit, Output, ViewChild } from "@angular/core";
 import { fromEvent, Subject, Subscription } from "rxjs";
 import { buffer, debounceTime } from "rxjs/operators";
-import { generateLabelIndexId } from "src/services/stateStore.service";
 import { FilterNameBySearch } from "./filterNameBySearch.pipe";
+import { serialiseParcellationRegion } from "common/util"
 
 const insertHighlight: (name: string, searchTerm: string) => string = (name: string, searchTerm: string = '') => {
   const regex = new RegExp(searchTerm, 'gi')
@@ -15,7 +15,7 @@ const getDisplayTreeNode: (searchTerm: string, selectedRegions: any[]) => (item:
   return !!labelIndex
     && !!ngId
     && selectedRegions.findIndex(re =>
-      generateLabelIndexId({ labelIndex: re.labelIndex, ngId: re.ngId }) === generateLabelIndexId({ ngId, labelIndex }),
+      serialiseParcellationRegion({ labelIndex: re.labelIndex, ngId: re.ngId }) === serialiseParcellationRegion({ ngId, labelIndex }),
     ) >= 0
     ? `<span class="cursor-default regionSelected">${insertHighlight(name, searchTerm)}</span>` + (status ? ` <span class="text-muted">(${insertHighlight(status, searchTerm)})</span>` : ``)
     : `<span class="cursor-default regionNotSelected">${insertHighlight(name, searchTerm)}</span>` + (status ? ` <span class="text-muted">(${insertHighlight(status, searchTerm)})</span>` : ``)
diff --git a/src/ui/viewerStateController/regionHierachy/regionHierarchy.style.css b/src/atlasComponents/parcellation/regionHierachy/regionHierarchy.style.css
similarity index 100%
rename from src/ui/viewerStateController/regionHierachy/regionHierarchy.style.css
rename to src/atlasComponents/parcellation/regionHierachy/regionHierarchy.style.css
diff --git a/src/ui/viewerStateController/regionHierachy/regionHierarchy.template.html b/src/atlasComponents/parcellation/regionHierachy/regionHierarchy.template.html
similarity index 100%
rename from src/ui/viewerStateController/regionHierachy/regionHierarchy.template.html
rename to src/atlasComponents/parcellation/regionHierachy/regionHierarchy.template.html
diff --git a/src/ui/viewerStateController/regionSearch/regionSearch.component.ts b/src/atlasComponents/parcellation/regionSearch/regionSearch.component.ts
similarity index 95%
rename from src/ui/viewerStateController/regionSearch/regionSearch.component.ts
rename to src/atlasComponents/parcellation/regionSearch/regionSearch.component.ts
index c5989bbb4f29ac46ba5ce1d05fc87974f95c95da..87a600839de215e162a3baf9dd6ba82d7446c8eb 100644
--- a/src/ui/viewerStateController/regionSearch/regionSearch.component.ts
+++ b/src/atlasComponents/parcellation/regionSearch/regionSearch.component.ts
@@ -5,13 +5,14 @@ import { combineLatest, Observable, Subject, merge } from "rxjs";
 import { debounceTime, distinctUntilChanged, filter, map, shareReplay, startWith, take, tap, withLatestFrom } from "rxjs/operators";
 import { VIEWER_STATE_ACTION_TYPES } from "src/services/effect/effect";
 import { ADD_TO_REGIONS_SELECTION_WITH_IDS, CHANGE_NAVIGATION, SELECT_REGIONS } from "src/services/state/viewerState.store";
-import { generateLabelIndexId, getMultiNgIdsRegionsLabelIndexMap, IavRootStoreInterface } from "src/services/stateStore.service";
+import { getMultiNgIdsRegionsLabelIndexMap } from "src/services/stateStore.service";
 import { LoggingService } from "src/logging";
 import { MatDialog } from "@angular/material/dialog";
 import { MatAutocompleteSelectedEvent } from "@angular/material/autocomplete";
 import { PureContantService } from "src/util";
 import { viewerStateToggleRegionSelect, viewerStateNavigateToRegion, viewerStateSetSelectedRegions, viewerStateSetSelectedRegionsWithIds } from "src/services/state/viewerState.store.helper";
 import { ARIA_LABELS, CONST } from 'common/constants'
+import { serialiseParcellationRegion } from "common/util"
 
 const filterRegionBasedOnText = searchTerm => region => `${region.name.toLowerCase()}${region.status? ' (' + region.status + ')' : null}`.includes(searchTerm.toLowerCase())
   || (region.relatedAreas && region.relatedAreas.some(relatedArea => relatedArea.name && relatedArea.name.toLowerCase().includes(searchTerm.toLowerCase())))
@@ -53,7 +54,7 @@ export class RegionTextSearchAutocomplete {
   public selectedRegionLabelIndexSet: Set<string> = new Set()
 
   constructor(
-    private store$: Store<IavRootStoreInterface>,
+    private store$: Store<any>,
     private dialog: MatDialog,
     private pureConstantService: PureContantService,
     private log: LoggingService
@@ -80,7 +81,7 @@ export class RegionTextSearchAutocomplete {
                 ...region,
                 ngId,
                 labelIndex,
-                labelIndexId: generateLabelIndexId({ ngId, labelIndex }),
+                labelIndexId: serialiseParcellationRegion({ ngId, labelIndex }),
               })
             }
           }
@@ -97,7 +98,7 @@ export class RegionTextSearchAutocomplete {
       select('regionsSelected'),
       distinctUntilChanged(),
       tap(regions => {
-        const arrLabelIndexId = regions.map(({ ngId, labelIndex }) => generateLabelIndexId({ ngId, labelIndex }))
+        const arrLabelIndexId = regions.map(({ ngId, labelIndex }) => serialiseParcellationRegion({ ngId, labelIndex }))
         this.selectedRegionLabelIndexSet = new Set(arrLabelIndexId)
       }),
       startWith([]),
diff --git a/src/ui/viewerStateController/regionSearch/regionSearch.style.css b/src/atlasComponents/parcellation/regionSearch/regionSearch.style.css
similarity index 100%
rename from src/ui/viewerStateController/regionSearch/regionSearch.style.css
rename to src/atlasComponents/parcellation/regionSearch/regionSearch.style.css
diff --git a/src/ui/viewerStateController/regionSearch/regionSearch.template.html b/src/atlasComponents/parcellation/regionSearch/regionSearch.template.html
similarity index 100%
rename from src/ui/viewerStateController/regionSearch/regionSearch.template.html
rename to src/atlasComponents/parcellation/regionSearch/regionSearch.template.html
diff --git a/src/atlasComponents/parcellationRegion/index.ts b/src/atlasComponents/parcellationRegion/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b3f4198bc8c372d02e1c43b01cd9809d18de3d1c
--- /dev/null
+++ b/src/atlasComponents/parcellationRegion/index.ts
@@ -0,0 +1,10 @@
+export {
+  ParcellationRegionModule,
+} from "./module"
+
+
+export { RegionDirective } from "./region.directive";
+export { RegionListSimpleViewComponent } from "./regionListSimpleView/regionListSimpleView.component";
+export { RegionMenuComponent } from "./regionMenu/regionMenu.component";
+export { SimpleRegionComponent } from "./regionSimple/regionSimple.component";
+export { RenderViewOriginDatasetLabelPipe } from "./region.base";
\ No newline at end of file
diff --git a/src/atlasComponents/parcellationRegion/module.ts b/src/atlasComponents/parcellationRegion/module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1e400b5e25835f7ae6cee44a939f993b2e1f2253
--- /dev/null
+++ b/src/atlasComponents/parcellationRegion/module.ts
@@ -0,0 +1,39 @@
+import { CommonModule } from "@angular/common";
+import { NgModule } from "@angular/core";
+import { ComponentsModule } from "src/components";
+import { DatabrowserModule } from "src/atlasComponents/databrowserModule";
+import { AngularMaterialModule } from "src/ui/sharedModules/angularMaterial.module";
+import { UtilModule } from "src/util";
+import { RenderViewOriginDatasetLabelPipe } from "./region.base";
+import { RegionDirective } from "./region.directive";
+import { RegionListSimpleViewComponent } from "./regionListSimpleView/regionListSimpleView.component";
+import { RegionMenuComponent } from "./regionMenu/regionMenu.component";
+import { SimpleRegionComponent } from "./regionSimple/regionSimple.component";
+
+@NgModule({
+  imports: [
+    CommonModule,
+    UtilModule,
+    DatabrowserModule,
+    AngularMaterialModule,
+    ComponentsModule,
+  ],
+  declarations: [
+    RegionMenuComponent,
+    RegionListSimpleViewComponent,
+    SimpleRegionComponent,
+
+    RegionDirective,
+    RenderViewOriginDatasetLabelPipe,
+  ],
+  exports: [
+    RegionMenuComponent,
+    RegionListSimpleViewComponent,
+    SimpleRegionComponent,
+
+    RegionDirective,
+    RenderViewOriginDatasetLabelPipe,
+  ]
+})
+
+export class ParcellationRegionModule{}
\ No newline at end of file
diff --git a/src/ui/parcellationRegion/region.base.spec.ts b/src/atlasComponents/parcellationRegion/region.base.spec.ts
similarity index 100%
rename from src/ui/parcellationRegion/region.base.spec.ts
rename to src/atlasComponents/parcellationRegion/region.base.spec.ts
diff --git a/src/ui/parcellationRegion/region.base.ts b/src/atlasComponents/parcellationRegion/region.base.ts
similarity index 100%
rename from src/ui/parcellationRegion/region.base.ts
rename to src/atlasComponents/parcellationRegion/region.base.ts
diff --git a/src/ui/parcellationRegion/region.directive.ts b/src/atlasComponents/parcellationRegion/region.directive.ts
similarity index 100%
rename from src/ui/parcellationRegion/region.directive.ts
rename to src/atlasComponents/parcellationRegion/region.directive.ts
diff --git a/src/ui/parcellationRegion/regionListSimpleView/regionListSimpleView.component.ts b/src/atlasComponents/parcellationRegion/regionListSimpleView/regionListSimpleView.component.ts
similarity index 100%
rename from src/ui/parcellationRegion/regionListSimpleView/regionListSimpleView.component.ts
rename to src/atlasComponents/parcellationRegion/regionListSimpleView/regionListSimpleView.component.ts
diff --git a/src/ui/parcellationRegion/regionListSimpleView/regionListSimpleView.style.css b/src/atlasComponents/parcellationRegion/regionListSimpleView/regionListSimpleView.style.css
similarity index 100%
rename from src/ui/parcellationRegion/regionListSimpleView/regionListSimpleView.style.css
rename to src/atlasComponents/parcellationRegion/regionListSimpleView/regionListSimpleView.style.css
diff --git a/src/ui/parcellationRegion/regionListSimpleView/regionListSimpleView.template.html b/src/atlasComponents/parcellationRegion/regionListSimpleView/regionListSimpleView.template.html
similarity index 100%
rename from src/ui/parcellationRegion/regionListSimpleView/regionListSimpleView.template.html
rename to src/atlasComponents/parcellationRegion/regionListSimpleView/regionListSimpleView.template.html
diff --git a/src/ui/parcellationRegion/regionMenu/regionMenu.component.spec.ts b/src/atlasComponents/parcellationRegion/regionMenu/regionMenu.component.spec.ts
similarity index 100%
rename from src/ui/parcellationRegion/regionMenu/regionMenu.component.spec.ts
rename to src/atlasComponents/parcellationRegion/regionMenu/regionMenu.component.spec.ts
diff --git a/src/ui/parcellationRegion/regionMenu/regionMenu.component.ts b/src/atlasComponents/parcellationRegion/regionMenu/regionMenu.component.ts
similarity index 100%
rename from src/ui/parcellationRegion/regionMenu/regionMenu.component.ts
rename to src/atlasComponents/parcellationRegion/regionMenu/regionMenu.component.ts
diff --git a/src/ui/parcellationRegion/regionMenu/regionMenu.style.css b/src/atlasComponents/parcellationRegion/regionMenu/regionMenu.style.css
similarity index 100%
rename from src/ui/parcellationRegion/regionMenu/regionMenu.style.css
rename to src/atlasComponents/parcellationRegion/regionMenu/regionMenu.style.css
diff --git a/src/ui/parcellationRegion/regionMenu/regionMenu.template.html b/src/atlasComponents/parcellationRegion/regionMenu/regionMenu.template.html
similarity index 93%
rename from src/ui/parcellationRegion/regionMenu/regionMenu.template.html
rename to src/atlasComponents/parcellationRegion/regionMenu/regionMenu.template.html
index 65f9d1b40ad7a03247fd7248a62e396e05d281ba..ac243dc5cf13882cadeafd73c0ddb4ce3700fc8b 100644
--- a/src/ui/parcellationRegion/regionMenu/regionMenu.template.html
+++ b/src/atlasComponents/parcellationRegion/regionMenu/regionMenu.template.html
@@ -108,18 +108,6 @@
   </div>
 </mat-card>
 
-<!-- ToDo make dynamic with AVAILABLE CONNECTIVITY DATASETS data - get info from atlas viewer core -->
-<mat-menu
-  #connectivitySourceDatasets="matMenu"
-  xPosition="before"
-  hasBackdrop="false">
-  <div>
-    <button mat-menu-item (mousedown)="showConnectivity(region.name)">
-      <span>1000 Brain Study - DTI connectivity</span>
-    </button>
-  </div>
-</mat-menu>
-
 <!-- template for switching template -->
 <mat-menu #regionInOtherTemplatesMenu="matMenu"
   [aria-label]="SHOW_IN_OTHER_REF_SPACE">
diff --git a/src/ui/parcellationRegion/regionSimple/regionSimple.component.ts b/src/atlasComponents/parcellationRegion/regionSimple/regionSimple.component.ts
similarity index 100%
rename from src/ui/parcellationRegion/regionSimple/regionSimple.component.ts
rename to src/atlasComponents/parcellationRegion/regionSimple/regionSimple.component.ts
diff --git a/src/ui/parcellationRegion/regionSimple/regionSimple.style.css b/src/atlasComponents/parcellationRegion/regionSimple/regionSimple.style.css
similarity index 100%
rename from src/ui/parcellationRegion/regionSimple/regionSimple.style.css
rename to src/atlasComponents/parcellationRegion/regionSimple/regionSimple.style.css
diff --git a/src/ui/parcellationRegion/regionSimple/regionSimple.template.html b/src/atlasComponents/parcellationRegion/regionSimple/regionSimple.template.html
similarity index 100%
rename from src/ui/parcellationRegion/regionSimple/regionSimple.template.html
rename to src/atlasComponents/parcellationRegion/regionSimple/regionSimple.template.html
diff --git a/src/ui/regionalFeatures/featureContainer/featureContainer.component.ts b/src/atlasComponents/regionalFeatures/featureContainer/featureContainer.component.ts
similarity index 100%
rename from src/ui/regionalFeatures/featureContainer/featureContainer.component.ts
rename to src/atlasComponents/regionalFeatures/featureContainer/featureContainer.component.ts
diff --git a/src/ui/regionalFeatures/index.ts b/src/atlasComponents/regionalFeatures/index.ts
similarity index 100%
rename from src/ui/regionalFeatures/index.ts
rename to src/atlasComponents/regionalFeatures/index.ts
diff --git a/src/ui/regionalFeatures/module.ts b/src/atlasComponents/regionalFeatures/module.ts
similarity index 94%
rename from src/ui/regionalFeatures/module.ts
rename to src/atlasComponents/regionalFeatures/module.ts
index f90b3a6ee0593d324d30394b8ba746541f8fa2c0..d18d51d9002d2a764c460b1da5a65ffad3ed8e79 100644
--- a/src/ui/regionalFeatures/module.ts
+++ b/src/atlasComponents/regionalFeatures/module.ts
@@ -1,7 +1,7 @@
 import { CommonModule } from "@angular/common";
 import { NgModule } from "@angular/core";
 import { UtilModule } from "src/util";
-import { AngularMaterialModule } from "../sharedModules/angularMaterial.module";
+import { AngularMaterialModule } from "../../ui/sharedModules/angularMaterial.module";
 import { FeatureContainer } from "./featureContainer/featureContainer.component";
 import { FilterRegionalFeaturesByTypePipe } from "./pipes/filterRegionalFeaturesByType.pipe";
 import { FilterRegionFeaturesById } from "./pipes/filterRegionFeaturesById.pipe";
diff --git a/src/ui/regionalFeatures/pipes/filterRegionFeaturesById.pipe.ts b/src/atlasComponents/regionalFeatures/pipes/filterRegionFeaturesById.pipe.ts
similarity index 100%
rename from src/ui/regionalFeatures/pipes/filterRegionFeaturesById.pipe.ts
rename to src/atlasComponents/regionalFeatures/pipes/filterRegionFeaturesById.pipe.ts
diff --git a/src/ui/regionalFeatures/pipes/filterRegionalFeaturesByType.pipe.ts b/src/atlasComponents/regionalFeatures/pipes/filterRegionalFeaturesByType.pipe.ts
similarity index 100%
rename from src/ui/regionalFeatures/pipes/filterRegionalFeaturesByType.pipe.ts
rename to src/atlasComponents/regionalFeatures/pipes/filterRegionalFeaturesByType.pipe.ts
diff --git a/src/ui/regionalFeatures/pipes/findRegionFeatureById.pipe.ts b/src/atlasComponents/regionalFeatures/pipes/findRegionFeatureById.pipe.ts
similarity index 100%
rename from src/ui/regionalFeatures/pipes/findRegionFeatureById.pipe.ts
rename to src/atlasComponents/regionalFeatures/pipes/findRegionFeatureById.pipe.ts
diff --git a/src/ui/regionalFeatures/regionGetAllFeatures.directive.ts b/src/atlasComponents/regionalFeatures/regionGetAllFeatures.directive.ts
similarity index 100%
rename from src/ui/regionalFeatures/regionGetAllFeatures.directive.ts
rename to src/atlasComponents/regionalFeatures/regionGetAllFeatures.directive.ts
diff --git a/src/ui/regionalFeatures/regionalFeature.service.ts b/src/atlasComponents/regionalFeatures/regionalFeature.service.ts
similarity index 100%
rename from src/ui/regionalFeatures/regionalFeature.service.ts
rename to src/atlasComponents/regionalFeatures/regionalFeature.service.ts
diff --git a/src/ui/regionalFeatures/singleFeatures/base/regionFeature.base.ts b/src/atlasComponents/regionalFeatures/singleFeatures/base/regionFeature.base.ts
similarity index 100%
rename from src/ui/regionalFeatures/singleFeatures/base/regionFeature.base.ts
rename to src/atlasComponents/regionalFeatures/singleFeatures/base/regionFeature.base.ts
diff --git a/src/ui/regionalFeatures/singleFeatures/iEEGRecordings/iEEGRecordings/iEEGRecordings.component.ts b/src/atlasComponents/regionalFeatures/singleFeatures/iEEGRecordings/iEEGRecordings/iEEGRecordings.component.ts
similarity index 97%
rename from src/ui/regionalFeatures/singleFeatures/iEEGRecordings/iEEGRecordings/iEEGRecordings.component.ts
rename to src/atlasComponents/regionalFeatures/singleFeatures/iEEGRecordings/iEEGRecordings/iEEGRecordings.component.ts
index 37c0fdc07a32a9d479d8f1fa85c804f8ad6b2f5b..af0dcab8913fa06d2f7ad55f6ffadc309aae69dc 100644
--- a/src/ui/regionalFeatures/singleFeatures/iEEGRecordings/iEEGRecordings/iEEGRecordings.component.ts
+++ b/src/atlasComponents/regionalFeatures/singleFeatures/iEEGRecordings/iEEGRecordings/iEEGRecordings.component.ts
@@ -3,7 +3,7 @@ import { Store } from "@ngrx/store";
 import { merge, Subject, Subscription } from "rxjs";
 import { debounceTime, map, scan, take } from "rxjs/operators";
 import { viewerStateChangeNavigation } from "src/services/state/viewerState/actions";
-import { RegionalFeaturesService } from "src/ui/regionalFeatures/regionalFeature.service";
+import { RegionalFeaturesService } from "src/atlasComponents/regionalFeatures/regionalFeature.service";
 import { ClickInterceptor, CLICK_INTERCEPTOR_INJECTOR } from "src/util";
 import { IHasId } from "src/util/interfaces";
 import { RegionFeatureBase } from "../../base/regionFeature.base";
diff --git a/src/ui/regionalFeatures/singleFeatures/iEEGRecordings/iEEGRecordings/iEEGRecordings.style.css b/src/atlasComponents/regionalFeatures/singleFeatures/iEEGRecordings/iEEGRecordings/iEEGRecordings.style.css
similarity index 100%
rename from src/ui/regionalFeatures/singleFeatures/iEEGRecordings/iEEGRecordings/iEEGRecordings.style.css
rename to src/atlasComponents/regionalFeatures/singleFeatures/iEEGRecordings/iEEGRecordings/iEEGRecordings.style.css
diff --git a/src/ui/regionalFeatures/singleFeatures/iEEGRecordings/iEEGRecordings/iEEGRecordings.template.html b/src/atlasComponents/regionalFeatures/singleFeatures/iEEGRecordings/iEEGRecordings/iEEGRecordings.template.html
similarity index 100%
rename from src/ui/regionalFeatures/singleFeatures/iEEGRecordings/iEEGRecordings/iEEGRecordings.template.html
rename to src/atlasComponents/regionalFeatures/singleFeatures/iEEGRecordings/iEEGRecordings/iEEGRecordings.template.html
diff --git a/src/ui/regionalFeatures/singleFeatures/iEEGRecordings/module.ts b/src/atlasComponents/regionalFeatures/singleFeatures/iEEGRecordings/module.ts
similarity index 100%
rename from src/ui/regionalFeatures/singleFeatures/iEEGRecordings/module.ts
rename to src/atlasComponents/regionalFeatures/singleFeatures/iEEGRecordings/module.ts
diff --git a/src/ui/regionalFeatures/singleFeatures/interfaces.ts b/src/atlasComponents/regionalFeatures/singleFeatures/interfaces.ts
similarity index 100%
rename from src/ui/regionalFeatures/singleFeatures/interfaces.ts
rename to src/atlasComponents/regionalFeatures/singleFeatures/interfaces.ts
diff --git a/src/ui/regionalFeatures/singleFeatures/receptorDensity/filterReceptorBytype.pipe.ts b/src/atlasComponents/regionalFeatures/singleFeatures/receptorDensity/filterReceptorBytype.pipe.ts
similarity index 100%
rename from src/ui/regionalFeatures/singleFeatures/receptorDensity/filterReceptorBytype.pipe.ts
rename to src/atlasComponents/regionalFeatures/singleFeatures/receptorDensity/filterReceptorBytype.pipe.ts
diff --git a/src/ui/regionalFeatures/singleFeatures/receptorDensity/getAllReceptors.pipe.ts b/src/atlasComponents/regionalFeatures/singleFeatures/receptorDensity/getAllReceptors.pipe.ts
similarity index 100%
rename from src/ui/regionalFeatures/singleFeatures/receptorDensity/getAllReceptors.pipe.ts
rename to src/atlasComponents/regionalFeatures/singleFeatures/receptorDensity/getAllReceptors.pipe.ts
diff --git a/src/ui/regionalFeatures/singleFeatures/receptorDensity/getId.pipe.ts b/src/atlasComponents/regionalFeatures/singleFeatures/receptorDensity/getId.pipe.ts
similarity index 100%
rename from src/ui/regionalFeatures/singleFeatures/receptorDensity/getId.pipe.ts
rename to src/atlasComponents/regionalFeatures/singleFeatures/receptorDensity/getId.pipe.ts
diff --git a/src/ui/regionalFeatures/singleFeatures/receptorDensity/getUrl.pipe.ts b/src/atlasComponents/regionalFeatures/singleFeatures/receptorDensity/getUrl.pipe.ts
similarity index 100%
rename from src/ui/regionalFeatures/singleFeatures/receptorDensity/getUrl.pipe.ts
rename to src/atlasComponents/regionalFeatures/singleFeatures/receptorDensity/getUrl.pipe.ts
diff --git a/src/ui/regionalFeatures/singleFeatures/receptorDensity/module.ts b/src/atlasComponents/regionalFeatures/singleFeatures/receptorDensity/module.ts
similarity index 100%
rename from src/ui/regionalFeatures/singleFeatures/receptorDensity/module.ts
rename to src/atlasComponents/regionalFeatures/singleFeatures/receptorDensity/module.ts
diff --git a/src/ui/regionalFeatures/singleFeatures/receptorDensity/receptorDensity/receptorDensity.component.ts b/src/atlasComponents/regionalFeatures/singleFeatures/receptorDensity/receptorDensity/receptorDensity.component.ts
similarity index 95%
rename from src/ui/regionalFeatures/singleFeatures/receptorDensity/receptorDensity/receptorDensity.component.ts
rename to src/atlasComponents/regionalFeatures/singleFeatures/receptorDensity/receptorDensity/receptorDensity.component.ts
index 1ecf5f8d6c8b1f60bcb2520039666fe0b4a3f17d..a9b5f3652f04a53961f3a334f7a951ba36fa5407 100644
--- a/src/ui/regionalFeatures/singleFeatures/receptorDensity/receptorDensity/receptorDensity.component.ts
+++ b/src/atlasComponents/regionalFeatures/singleFeatures/receptorDensity/receptorDensity/receptorDensity.component.ts
@@ -1,6 +1,6 @@
 import { Component, ElementRef, EventEmitter, HostListener, OnDestroy, Optional } from "@angular/core";
 import { fromEvent, Observable, of, Subscription } from "rxjs";
-import { RegionalFeaturesService } from "src/ui/regionalFeatures/regionalFeature.service";
+import { RegionalFeaturesService } from "src/atlasComponents/regionalFeatures/regionalFeature.service";
 import { PureContantService } from "src/util";
 import { RegionFeatureBase } from "../../base/regionFeature.base";
 import { ISingleFeature } from "../../interfaces";
diff --git a/src/ui/regionalFeatures/singleFeatures/receptorDensity/receptorDensity/receptorDensity.style.css b/src/atlasComponents/regionalFeatures/singleFeatures/receptorDensity/receptorDensity/receptorDensity.style.css
similarity index 100%
rename from src/ui/regionalFeatures/singleFeatures/receptorDensity/receptorDensity/receptorDensity.style.css
rename to src/atlasComponents/regionalFeatures/singleFeatures/receptorDensity/receptorDensity/receptorDensity.style.css
diff --git a/src/ui/regionalFeatures/singleFeatures/receptorDensity/receptorDensity/receptorDensity.template.html b/src/atlasComponents/regionalFeatures/singleFeatures/receptorDensity/receptorDensity/receptorDensity.template.html
similarity index 100%
rename from src/ui/regionalFeatures/singleFeatures/receptorDensity/receptorDensity/receptorDensity.template.html
rename to src/atlasComponents/regionalFeatures/singleFeatures/receptorDensity/receptorDensity/receptorDensity.template.html
diff --git a/src/ui/regionalFeatures/util.ts b/src/atlasComponents/regionalFeatures/util.ts
similarity index 100%
rename from src/ui/regionalFeatures/util.ts
rename to src/atlasComponents/regionalFeatures/util.ts
diff --git a/src/atlasComponents/splashScreen/index.ts b/src/atlasComponents/splashScreen/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..182552e5a83684d6b8b762e7ad6a5debda9e1d0f
--- /dev/null
+++ b/src/atlasComponents/splashScreen/index.ts
@@ -0,0 +1,2 @@
+export { GetTemplateImageSrcPipe, ImgSrcSetPipe, SplashScreen } from "./splashScreen/splashScreen.component";
+export { SplashUiModule } from './module'
\ No newline at end of file
diff --git a/src/atlasComponents/splashScreen/module.ts b/src/atlasComponents/splashScreen/module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e5817edb31543ba8c3680bc010129436df4774bf
--- /dev/null
+++ b/src/atlasComponents/splashScreen/module.ts
@@ -0,0 +1,27 @@
+import { CommonModule } from "@angular/common";
+import { NgModule } from "@angular/core";
+import { ComponentsModule } from "src/components";
+import { KgTosModule } from "src/ui/kgtos/module";
+import { AngularMaterialModule } from "src/ui/sharedModules/angularMaterial.module";
+import { UtilModule } from "src/util";
+import { GetTemplateImageSrcPipe, SplashScreen, ImgSrcSetPipe } from "./splashScreen/splashScreen.component";
+
+@NgModule({
+  imports: [
+    AngularMaterialModule,
+    CommonModule,
+    UtilModule,
+    KgTosModule,
+    ComponentsModule,
+  ],
+  declarations: [
+    SplashScreen,
+    GetTemplateImageSrcPipe,
+    ImgSrcSetPipe,
+  ],
+  exports: [
+    SplashScreen,
+  ]
+})
+
+export class SplashUiModule{}
\ No newline at end of file
diff --git a/src/ui/nehubaContainer/splashScreen/splashScreen.component.ts b/src/atlasComponents/splashScreen/splashScreen/splashScreen.component.ts
similarity index 100%
rename from src/ui/nehubaContainer/splashScreen/splashScreen.component.ts
rename to src/atlasComponents/splashScreen/splashScreen/splashScreen.component.ts
diff --git a/src/ui/nehubaContainer/splashScreen/splashScreen.style.css b/src/atlasComponents/splashScreen/splashScreen/splashScreen.style.css
similarity index 100%
rename from src/ui/nehubaContainer/splashScreen/splashScreen.style.css
rename to src/atlasComponents/splashScreen/splashScreen/splashScreen.style.css
diff --git a/src/ui/nehubaContainer/splashScreen/splashScreen.template.html b/src/atlasComponents/splashScreen/splashScreen/splashScreen.template.html
similarity index 100%
rename from src/ui/nehubaContainer/splashScreen/splashScreen.template.html
rename to src/atlasComponents/splashScreen/splashScreen/splashScreen.template.html
diff --git a/src/ui/atlasDropdown/atlasDropdown.component.spec.ts b/src/atlasComponents/uiSelectors/atlasDropdown/atlasDropdown.component.spec.ts
similarity index 100%
rename from src/ui/atlasDropdown/atlasDropdown.component.spec.ts
rename to src/atlasComponents/uiSelectors/atlasDropdown/atlasDropdown.component.spec.ts
diff --git a/src/ui/atlasDropdown/atlasDropdown.component.ts b/src/atlasComponents/uiSelectors/atlasDropdown/atlasDropdown.component.ts
similarity index 100%
rename from src/ui/atlasDropdown/atlasDropdown.component.ts
rename to src/atlasComponents/uiSelectors/atlasDropdown/atlasDropdown.component.ts
diff --git a/src/ui/atlasDropdown/atlasDropdown.style.css b/src/atlasComponents/uiSelectors/atlasDropdown/atlasDropdown.style.css
similarity index 100%
rename from src/ui/atlasDropdown/atlasDropdown.style.css
rename to src/atlasComponents/uiSelectors/atlasDropdown/atlasDropdown.style.css
diff --git a/src/ui/atlasDropdown/atlasDropdown.template.html b/src/atlasComponents/uiSelectors/atlasDropdown/atlasDropdown.template.html
similarity index 100%
rename from src/ui/atlasDropdown/atlasDropdown.template.html
rename to src/atlasComponents/uiSelectors/atlasDropdown/atlasDropdown.template.html
diff --git a/src/ui/atlasLayerSelector/atlasLayerSelector.component.ts b/src/atlasComponents/uiSelectors/atlasLayerSelector/atlasLayerSelector.component.ts
similarity index 70%
rename from src/ui/atlasLayerSelector/atlasLayerSelector.component.ts
rename to src/atlasComponents/uiSelectors/atlasLayerSelector/atlasLayerSelector.component.ts
index 2ee14f1e192dfa35eee58ac0f168e7f8071c5461..088c98dbefb4b85f4eb19b0f88ff9efcf59cf263 100644
--- a/src/ui/atlasLayerSelector/atlasLayerSelector.component.ts
+++ b/src/atlasComponents/uiSelectors/atlasLayerSelector/atlasLayerSelector.component.ts
@@ -20,35 +20,94 @@ export class AtlasLayerSelector implements OnInit {
     @ViewChildren(MatMenuTrigger) matMenuTriggers: QueryList<MatMenuTrigger>
     public atlas: any
 
-    public nonGroupedLayers$: Observable<any[]>
-    public groupedLayers$: Observable<any[]>
+    public selectedAtlas$: Observable<any> = this.store$.pipe(
+      select(viewerStateGetSelectedAtlas),
+      distinctUntilChanged(),
+      shareReplay(1)
+    )
+    private layersGroupBy$ = this.selectedAtlas$.pipe(
+      switchMap(selectedAtlas => from((selectedAtlas?.parcellations) || []).pipe(
+        /**
+         * do not show base layers
+         */
+        filter(p => !(p as any).baseLayer),
+        groupBy((parcellation: any) => parcellation.groupName, p => p),
+        mergeMap(group => zip(
+          of(group.key),
+          group.pipe(toArray()))
+        ),
+        scan((acc, curr) => acc.concat([ curr ]), []),
+        shareReplay(1),
+      ))
+    )
+
 
+    private atlasLayersLatest$ = this.store$.pipe(
+      select(viewerStateAtlasLatestParcellationSelector),
+      shareReplay(1),
+    )
+
+    public nonGroupedLayers$: Observable<any[]> = this.atlasLayersLatest$.pipe(
+      map(allParcellations => 
+        allParcellations
+          .filter(p => !p['groupName'])
+          .filter(p => !p['baseLayer'])
+      ),
+    )
+
+    public groupedLayers$: Observable<any[]> = combineLatest([
+      this.atlasLayersLatest$.pipe(
+        map(allParcellations => 
+          allParcellations.filter(p => !p['baseLayer'])
+        ),
+      ),
+      this.layersGroupBy$
+    ]).pipe(
+      map(([ allParcellations, arr]) => arr
+        .filter(([ key ]) => !!key )
+        .map(([key, parcellations]) => ({
+          name: key,
+          previewUrl: parcellations[0].previewUrl,
+          parcellations: parcellations.map(p => {
+            const fullInfo = allParcellations.find(fullP => fullP['@id'] === p['@id']) || {}
+            return {
+              ...fullInfo,
+              ...p,
+              darktheme: (fullInfo || {}).useTheme === 'dark'
+            }
+          })
+        }))
+      ),
+    )
     public selectedTemplateSpaceId: string
     public selectedLayers = []
 
     public selectedTemplate$: Observable<any>
     private selectedParcellation$: Observable<any>
-    public selectedAtlas$: Observable<any>
+
     private subscriptions: Subscription[] = []
 
     @HostBinding('attr.data-opened')
     public selectorExpanded: boolean = false
     public selectedTemplatePreviewUrl: string = ''
 
-    public availableTemplates$: Observable<any[]>
+    public availableTemplates$ = this.store$.pipe<any[]>(
+      select(viewerStateSelectedTemplateFullInfoSelector)
+    )
 
     public containerMaxWidth: number
 
-    constructor(private store$: Store<any>) {
-      this.selectedAtlas$ = this.store$.pipe(
-        select(viewerStateGetSelectedAtlas),
-        distinctUntilChanged(),
-        shareReplay(1)
-      )
+    public shouldShowRenderPlaceHolder$ = combineLatest([
+      this.availableTemplates$,
+      this.groupedLayers$,
+      this.nonGroupedLayers$,
+    ]).pipe(
+      map(([ availTmpl, grpL, ungrpL ]) => {
+        return availTmpl?.length > 0 || (grpL?.length || 0) + (ungrpL?.length || 0) > 0
+      })
+    )
 
-      this.availableTemplates$ = this.store$.pipe(
-        select(viewerStateSelectedTemplateFullInfoSelector)
-      )
+    constructor(private store$: Store<any>) {
 
       this.selectedTemplate$ = this.store$.pipe(
         select(viewerStateSelectedTemplatePureSelector),
@@ -64,59 +123,6 @@ export class AtlasLayerSelector implements OnInit {
         select(viewerStateSelectedParcellationSelector)
       )
 
-      const layersGroupBy$ = this.selectedAtlas$.pipe(
-        switchMap(selectedAtlas => from((selectedAtlas?.parcellations) || []).pipe(
-          /**
-           * do not show base layers
-           */
-          filter(p => !(p as any).baseLayer),
-          groupBy((parcellation: any) => parcellation.groupName, p => p),
-          mergeMap(group => zip(
-            of(group.key),
-            group.pipe(toArray()))
-          ),
-          scan((acc, curr) => acc.concat([ curr ]), []),
-          shareReplay(1),
-        ))
-      )
-
-      const atlasLayersLatest$ = this.store$.pipe(
-        select(viewerStateAtlasLatestParcellationSelector),
-        shareReplay(1),
-      )
-
-      this.nonGroupedLayers$ = atlasLayersLatest$.pipe(
-        map(allParcellations => 
-          allParcellations
-            .filter(p => !p['groupName'])
-            .filter(p => !p['baseLayer'])
-        ),
-      )
-
-      this.groupedLayers$ = combineLatest(
-        atlasLayersLatest$.pipe(
-          map(allParcellations => 
-            allParcellations.filter(p => !p['baseLayer'])
-          ),
-        ),
-        layersGroupBy$
-      ).pipe(
-        map(([ allParcellations, arr]) => arr
-          .filter(([ key ]) => !!key )
-          .map(([key, parcellations]) => ({
-            name: key,
-            previewUrl: parcellations[0].previewUrl,
-            parcellations: parcellations.map(p => {
-              const fullInfo = allParcellations.find(fullP => fullP['@id'] === p['@id']) || {}
-              return {
-                ...fullInfo,
-                ...p,
-                darktheme: (fullInfo || {}).useTheme === 'dark'
-              }
-            })
-          }))
-        ),
-      )
     }
 
     ngOnInit(): void {
@@ -183,6 +189,7 @@ export class AtlasLayerSelector implements OnInit {
     }
 
     getTooltipText(layer) {
+      if (!this.atlas) return
       if (this.atlas.templateSpaces.map(tmpl => tmpl['@id']).includes(layer['@id'])) return layer.name
       if (layer.availableIn) {
         if (this.currentTemplateIncludesLayer(layer)) return layer.name
diff --git a/src/ui/atlasLayerSelector/atlasLayerSelector.style.css b/src/atlasComponents/uiSelectors/atlasLayerSelector/atlasLayerSelector.style.css
similarity index 100%
rename from src/ui/atlasLayerSelector/atlasLayerSelector.style.css
rename to src/atlasComponents/uiSelectors/atlasLayerSelector/atlasLayerSelector.style.css
diff --git a/src/ui/atlasLayerSelector/atlasLayerSelector.template.html b/src/atlasComponents/uiSelectors/atlasLayerSelector/atlasLayerSelector.template.html
similarity index 98%
rename from src/ui/atlasLayerSelector/atlasLayerSelector.template.html
rename to src/atlasComponents/uiSelectors/atlasLayerSelector/atlasLayerSelector.template.html
index a4e8883b6769fce8f473aa2bd9b4ced768425114..d73fda145cd10295d6f6494643a289e723a11066 100644
--- a/src/ui/atlasLayerSelector/atlasLayerSelector.template.html
+++ b/src/atlasComponents/uiSelectors/atlasLayerSelector/atlasLayerSelector.template.html
@@ -64,7 +64,7 @@
         <button color="primary"
                 matTooltip="Select layer"
                 mat-mini-fab
-                *ngIf="((availableTemplates$ | async).length > 1) || ((groupedLayers$ | async).length + (nonGroupedLayers$ | async).length > 1)"
+                *ngIf="shouldShowRenderPlaceHolder$ | async"
                 [attr.aria-label]="TOGGLE_ATLAS_LAYER_SELECTOR"
                 (click)="selectorExpanded = !selectorExpanded">
             <i class="fas fa-layer-group"></i>
diff --git a/src/atlasComponents/uiSelectors/index.ts b/src/atlasComponents/uiSelectors/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..28925e7dac73fcc4f6b8896a1026ec6c556a24e4
--- /dev/null
+++ b/src/atlasComponents/uiSelectors/index.ts
@@ -0,0 +1,3 @@
+export { AtlasCmpUiSelectorsModule } from "./module"
+export { AtlasDropdownSelector } from "./atlasDropdown/atlasDropdown.component"
+export { AtlasLayerSelector } from "./atlasLayerSelector/atlasLayerSelector.component"
\ No newline at end of file
diff --git a/src/atlasComponents/uiSelectors/module.ts b/src/atlasComponents/uiSelectors/module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..034f9445353f4e43e0a2f7e8e1b62055eccdb419
--- /dev/null
+++ b/src/atlasComponents/uiSelectors/module.ts
@@ -0,0 +1,26 @@
+import { CommonModule } from "@angular/common";
+import { NgModule } from "@angular/core";
+import { AngularMaterialModule } from "src/ui/sharedModules/angularMaterial.module";
+import { UtilModule } from "src/util";
+import { DatabrowserModule } from "src/atlasComponents/databrowserModule";
+import { AtlasDropdownSelector } from "./atlasDropdown/atlasDropdown.component";
+import { AtlasLayerSelector } from "./atlasLayerSelector/atlasLayerSelector.component";
+
+@NgModule({
+  imports: [
+    CommonModule,
+    AngularMaterialModule,
+    UtilModule,
+    DatabrowserModule,
+  ],
+  declarations: [
+    AtlasDropdownSelector,
+    AtlasLayerSelector,
+  ],
+  exports: [
+    AtlasDropdownSelector,
+    AtlasLayerSelector,
+  ]
+})
+
+export class AtlasCmpUiSelectorsModule{}
\ No newline at end of file
diff --git a/src/atlasViewer/atlasViewer.apiService.service.spec.ts b/src/atlasViewer/atlasViewer.apiService.service.spec.ts
index f8dd6f5a8eb71361a90e4dbf07069205808d6235..290bb068a1845621d8f8940d39537d5386b487f6 100644
--- a/src/atlasViewer/atlasViewer.apiService.service.spec.ts
+++ b/src/atlasViewer/atlasViewer.apiService.service.spec.ts
@@ -5,7 +5,7 @@ import { defaultRootState } from "src/services/stateStore.service";
 import { AngularMaterialModule } from "src/ui/sharedModules/angularMaterial.module";
 import { WidgetModule } from 'src/widget';
 import { HttpClientTestingModule, HttpTestingController } from "@angular/common/http/testing";
-import { PluginServices } from "./pluginUnit";
+import { PluginServices } from "src/plugin";
 
 describe('atlasViewer.apiService.service.ts', () => {
 
diff --git a/src/atlasViewer/atlasViewer.apiService.service.ts b/src/atlasViewer/atlasViewer.apiService.service.ts
index 05eba0de7e6c56770513349a68046df851987d77..fed71fcf1bb89b9093b3719aeb7a268094ec0a5a 100644
--- a/src/atlasViewer/atlasViewer.apiService.service.ts
+++ b/src/atlasViewer/atlasViewer.apiService.service.ts
@@ -13,9 +13,9 @@ import {
   IavRootStoreInterface,
   safeFilter
 } from "src/services/stateStore.service";
-import { FRAGMENT_EMIT_RED } from "src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component";
 import { ClickInterceptor, CLICK_INTERCEPTOR_INJECTOR } from "src/util";
-import { IPluginManifest, PluginServices } from "./pluginUnit";
+import { FRAGMENT_EMIT_RED } from "src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component";
+import { IPluginManifest, PluginServices } from "src/plugin";
 
 declare let window
 
@@ -385,39 +385,7 @@ export interface IInteractiveViewerInterface {
     datasetsBSubject: Observable<any[]>
   }
 
-  viewerHandle?: {
-    setNavigationLoc: (coordinates: [number, number, number], realSpace?: boolean) => void
-    moveToNavigationLoc: (coordinates: [number, number, number], realSpace?: boolean) => void
-    setNavigationOri: (quat: [number, number, number, number]) => void
-    moveToNavigationOri: (quat: [number, number, number, number]) => void
-    showSegment: (labelIndex: number) => void
-    hideSegment: (labelIndex: number) => void
-    showAllSegments: () => void
-    hideAllSegments: () => void
-
-    // TODO deprecate
-    segmentColourMap: Map<number, {red: number, green: number, blue: number}>
-
-    getLayersSegmentColourMap: () => Map<string, Map<number, {red: number, green: number, blue: number}>>
-
-    // TODO deprecate
-    applyColourMap: (newColourMap: Map<number, {red: number, green: number, blue: number}>) => void
-
-    applyLayersColourMap: (newLayerColourMap: Map<string, Map<number, {red: number, green: number, blue: number}>>) => void
-
-    loadLayer: (layerobj: any) => any
-    removeLayer: (condition: {name: string | RegExp}) => string[]
-    setLayerVisibility: (condition: {name: string|RegExp}, visible: boolean) => void
-
-    add3DLandmarks: (landmarks: IUserLandmark[]) => void
-    remove3DLandmarks: (ids: string[]) => void
-
-    mouseEvent: Observable<{eventName: string, event: MouseEvent}>
-    mouseOverNehuba: Observable<{labelIndex: number, foundRegion: any | null}>
-    mouseOverNehubaLayers: Observable<Array<{layer: {name: string}, segment: any | number }>>
-    mouseOverNehubaUI: Observable<{ segments: any, landmark: any, customLandmark: any }>
-    getNgHash: () => string
-  }
+  viewerHandle?: IVIewerHandle
 
   uiHandle: {
     getModalHandler: () => void
@@ -464,8 +432,45 @@ export interface ICustomRegionSpec{
   type: string // type of EnumCustomRegion
 }
 
-export const API_SERVICE_SET_VIEWER_HANDLE_TOKEN = new InjectionToken<(viewerHandle) => void>('API_SERVICE_SET_VIEWER_HANDLE_TOKEN')
+export interface IVIewerHandle {
+
+  setNavigationLoc: (coordinates: [number, number, number], realSpace?: boolean) => void
+  moveToNavigationLoc: (coordinates: [number, number, number], realSpace?: boolean) => void
+  setNavigationOri: (quat: [number, number, number, number]) => void
+  moveToNavigationOri: (quat: [number, number, number, number]) => void
+  showSegment: (labelIndex: number) => void
+  hideSegment: (labelIndex: number) => void
+  showAllSegments: () => void
+  hideAllSegments: () => void
+
+  // TODO deprecate
+  segmentColourMap: Map<number, {red: number, green: number, blue: number}>
+
+  getLayersSegmentColourMap: () => Map<string, Map<number, {red: number, green: number, blue: number}>>
+
+  // TODO deprecate
+  applyColourMap: (newColourMap: Map<number, {red: number, green: number, blue: number}>) => void
+
+  applyLayersColourMap: (newLayerColourMap: Map<string, Map<number, {red: number, green: number, blue: number}>>) => void
+
+  loadLayer: (layerobj: any) => any
+  removeLayer: (condition: {name: string | RegExp}) => string[]
+  setLayerVisibility: (condition: {name: string|RegExp}, visible: boolean) => void
+
+  add3DLandmarks: (landmarks: IUserLandmark[]) => void
+  remove3DLandmarks: (ids: string[]) => void
+
+  mouseEvent: Observable<{eventName: string, event: MouseEvent}>
+  mouseOverNehuba: Observable<{labelIndex: number, foundRegion: any | null}>
+  mouseOverNehubaLayers: Observable<Array<{layer: {name: string}, segment: any | number }>>
+  mouseOverNehubaUI: Observable<{ segments: any, landmark: any, customLandmark: any }>
+  getNgHash: () => string
+}
+
+export type TSetViewerHandle = (viewerHandle: IVIewerHandle) => void
+
+export const API_SERVICE_SET_VIEWER_HANDLE_TOKEN = new InjectionToken<TSetViewerHandle>('API_SERVICE_SET_VIEWER_HANDLE_TOKEN')
 
 export const setViewerHandleFactory = (apiService: AtlasViewerAPIServices) => {
-  return viewerHandle => apiService.interactiveViewer.viewerHandle = viewerHandle
+  return (viewerHandle: IVIewerHandle) => apiService.interactiveViewer.viewerHandle = viewerHandle
 }
diff --git a/src/atlasViewer/atlasViewer.component.ts b/src/atlasViewer/atlasViewer.component.ts
index 8f1410127afa88217bd84cb22b2708121a4c795f..0c17df576656ab199a6fb6f820c9a6132eb06d23 100644
--- a/src/atlasViewer/atlasViewer.component.ts
+++ b/src/atlasViewer/atlasViewer.component.ts
@@ -8,12 +8,9 @@ import {
   TemplateRef,
   ViewChild,
   ElementRef,
-  Inject,
-  Optional,
-  InjectionToken,
 } from "@angular/core";
 import { Store, select, ActionsSubject } from "@ngrx/store";
-import { Observable, Subscription, combineLatest, interval, merge, of, timer, fromEvent } from "rxjs";
+import { Observable, Subscription, interval, merge, of, timer, fromEvent } from "rxjs";
 import { map, filter, distinctUntilChanged, delay, withLatestFrom, switchMapTo, take, startWith } from "rxjs/operators";
 
 import { LayoutMainSide } from "../layouts/mainside/mainside.component";
@@ -28,9 +25,9 @@ import { WidgetServices } from "src/widget";
 import { LocalFileService } from "src/services/localFile.service";
 import { AGREE_COOKIE, AGREE_KG_TOS, SHOW_KG_TOS } from "src/services/state/uiState.store";
 import { isSame } from "src/util/fn";
-import { NehubaContainer } from "../ui/nehubaContainer/nehubaContainer.component";
+// import { NehubaContainer } from "../ui/nehubaContainer/nehubaContainer.component";
 import { colorAnimation } from "./atlasViewer.animation"
-import { MouseHoverDirective } from "src/atlasViewer/mouseOver.directive";
+import { MouseHoverDirective } from "src/mouseoverModule";
 import {MatSnackBar, MatSnackBarRef} from "@angular/material/snack-bar";
 import {MatDialog, MatDialogRef} from "@angular/material/dialog";
 import { ARIA_LABELS, CONST } from 'common/constants'
@@ -38,13 +35,8 @@ import { ARIA_LABELS, CONST } from 'common/constants'
 import { MIN_REQ_EXPLAINER } from 'src/util/constants'
 import { SlServiceService } from "src/spotlight/sl-service.service";
 import { PureContantService } from "src/util";
-import { viewerStateSetSelectedRegions, viewerStateRemoveAdditionalLayer, viewerStateHelperSelectParcellationWithId } from "src/services/state/viewerState.store.helper";
-import { viewerStateGetOverlayingAdditionalParcellations, viewerStateParcVersionSelector, viewerStateStandAloneVolumes } from "src/services/state/viewerState/selectors";
-import { ngViewerSelectorClearViewEntries } from "src/services/state/ngViewerState/selectors";
-import { ngViewerActionClearView } from "src/services/state/ngViewerState/actions";
 import { uiStateMouseOverSegmentsSelector } from "src/services/state/uiState/selectors";
 import { ClickInterceptorService } from "src/glue";
-import {SET_OVERWRITTEN_COLOR_MAP} from "src/services/state/viewerState.store";
 
 /**
  * TODO
@@ -75,7 +67,7 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit {
   @ViewChild('kgToS', {read: TemplateRef}) public kgTosComponent: TemplateRef<any>
   @ViewChild(LayoutMainSide) public layoutMainSide: LayoutMainSide
 
-  @ViewChild(NehubaContainer) public nehubaContainer: NehubaContainer
+  // @ViewChild(NehubaContainer) public nehubaContainer: NehubaContainer
 
   @ViewChild(MouseHoverDirective) private mouseOverNehuba: MouseHoverDirective
 
@@ -88,9 +80,6 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit {
   public sidePanelView$: Observable<string|null>
   private newViewer$: Observable<any>
 
-  public selectedRegions$: Observable<any[]>
-  public selectedPOI$: Observable<any[]>
-
   private snackbarRef: MatSnackBarRef<any>
   public snackbarMessage$: Observable<string>
 
@@ -109,35 +98,12 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit {
 
   public MIN_REQ_EXPLAINER = MIN_REQ_EXPLAINER
 
-  public isStandaloneVolumes$ = this.store.pipe(
-    select(viewerStateStandAloneVolumes),
-    map(v => v.length > 0)
-  )
-
-  public selectedAdditionalLayers$ = this.store.pipe(
-    select(viewerStateGetOverlayingAdditionalParcellations),
-  )
-
-  public selectedLayerVersions$ = this.store.pipe(
-    select(viewerStateParcVersionSelector),
-    map(arr => arr.map(item => {
-      const overwrittenName = item['@version'] && item['@version']['name']
-      return overwrittenName
-        ? { ...item, displayName: overwrittenName }
-        : item
-    }))
-  )
-
   private selectedParcellation$: Observable<any>
   public selectedParcellation: any
 
   private cookieDialogRef: MatDialogRef<any>
   private kgTosDialogRef: MatDialogRef<any>
 
-  public clearViewKeys$ = this.store.pipe(
-    select(ngViewerSelectorClearViewEntries)
-  )
-
   constructor(
     private store: Store<IavRootStoreInterface>,
     private widgetServices: WidgetServices,
@@ -164,25 +130,6 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit {
       map(state => state.focusedSidePanel),
     )
 
-    this.selectedRegions$ = this.store.pipe(
-      select('viewerState'),
-      filter(state => isDefined(state) && isDefined(state.regionsSelected)),
-      map(state => state.regionsSelected),
-      distinctUntilChanged(),
-    )
-
-    this.selectedPOI$ = combineLatest(
-      this.selectedRegions$,
-      this.store.pipe(
-        select('viewerState'),
-        filter(state => isDefined(state) && isDefined(state.landmarksSelected)),
-        map(state => state.landmarksSelected),
-        distinctUntilChanged(),
-      ),
-    ).pipe(
-      map(results => [...results[0], ...results[1]]),
-    )
-
     this.newViewer$ = this.store.pipe(
       select('viewerState'),
       select('templateSelected'),
@@ -249,7 +196,6 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit {
 
   public ngOnInit() {
     this.meetsRequirement = this.meetsRequirements()
-    this.clickIntService.addInterceptor(this.selectHoveredRegion.bind(this), true)
 
     if (KIOSK_MODE) {
 
@@ -351,9 +297,9 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit {
       this.rd.appendChild(document.head, prefecthMainBundle)
     }
 
-    this.onhoverLandmark$ = this.mouseOverNehuba.currentOnHoverObs$.pipe(
-      select('landmark')
-    )
+    // this.onhoverLandmark$ = this.mouseOverNehuba.currentOnHoverObs$.pipe(
+    //   select('landmark')
+    // )
 
     /**
      * Show Cookie disclaimer if not yet agreed
@@ -389,58 +335,6 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit {
    */
   public ngOnDestroy() {
     this.subscriptions.forEach(s => s.unsubscribe())
-    this.clickIntService.removeInterceptor(this.selectHoveredRegion.bind(this))
-  }
-
-  private selectHoveredRegion(ev: any, next: Function){
-    if (!this.onhoverSegments) return
-      
-    this.store.dispatch(
-      viewerStateSetSelectedRegions({
-        selectRegions: this.onhoverSegments.slice(0, 1)
-      })
-    )
-    next()
-  }
-
-  public unsetClearViewByKey(key: string){
-    this.store.dispatch(
-      ngViewerActionClearView({ payload: {
-        [key]: false
-      }})
-    )
-  }
-
-  public selectParcellation(parc: any) {
-    this.store.dispatch(
-      viewerStateHelperSelectParcellationWithId({
-        payload: parc
-      })
-    )
-  }
-
-  public bindFns(fns){
-    return () => {
-      for (const [ fn, ...arg] of fns) {
-        fn(...arg)
-      }
-    }
-  }
-
-  public clearAdditionalLayer(layer: { ['@id']: string }){
-    this.store.dispatch(
-      viewerStateRemoveAdditionalLayer({
-        payload: layer
-      })
-    )
-  }
-
-  public clearSelectedRegions(){
-    this.store.dispatch(
-      viewerStateSetSelectedRegions({
-        selectRegions: []
-      })
-    )
   }
 
   public mouseClickDocument(_event: MouseEvent) {
diff --git a/src/atlasViewer/atlasViewer.constantService.service.spec.ts b/src/atlasViewer/atlasViewer.constantService.service.spec.ts
index e9fe3faeeb0dae335c04d2e0b28d840966b87d5a..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/src/atlasViewer/atlasViewer.constantService.service.spec.ts
+++ b/src/atlasViewer/atlasViewer.constantService.service.spec.ts
@@ -1,128 +0,0 @@
-import {} from 'jasmine'
-import { decodeToNumber, encodeNumber } from './atlasViewer.constantService.service'
-
-const FLOAT_PRECISION = 6
-
-describe('encodeNumber/decodeToNumber', () => {
-
-  const getCompareOriginal = (original: number[]) => (element: string, index: number) =>
-    original[index].toString().length >= element.length
-
-  const lengthShortened = (original: number[], encodedString: string[]) =>
-    encodedString.every(getCompareOriginal(original))
-
-  it('should encode/decode positive integer as expected', () => {
-
-    const positiveInt = [
-      0,
-      1,
-      99999999999,
-      12347,
-    ]
-
-    const encodedString = positiveInt.map(n => encodeNumber(n))
-    const decodedString = encodedString.map(s => decodeToNumber(s))
-    expect(decodedString).toEqual(positiveInt)
-
-    expect(lengthShortened(positiveInt, encodedString)).toBe(true)
-  })
-
-  it('should encode/decode ANY positive integer as expected', () => {
-    const posInt = Array(1000).fill(null).map(() => {
-      const numDig = Math.ceil(Math.random() * 7)
-      return Math.floor(Math.random() * Math.pow(10, numDig))
-    })
-    const encodedString = posInt.map(n => encodeNumber(n))
-    const decodedNumber = encodedString.map(s => decodeToNumber(s))
-    expect(decodedNumber).toEqual(posInt)
-
-    expect(lengthShortened(posInt, encodedString)).toBe(true)
-  })
-
-  it('should encode/decode signed integer as expected', () => {
-
-    const signedInt = [
-      0,
-      -0,
-      -1,
-      1,
-      128,
-      -54,
-    ]
-
-    const encodedString = signedInt.map(n => encodeNumber(n))
-    const decodedNumber = encodedString.map(s => decodeToNumber(s))
-
-    /**
-     * -0 will be converted to 0 by the encode/decode process, but does not deep equal, according to jasmine
-     */
-    expect(decodedNumber).toEqual(signedInt.map(v => v === 0 ? 0 : v))
-
-    expect(lengthShortened(signedInt, encodedString)).toBe(true)
-  })
-
-  it('should encode/decode ANY signed integer as expected', () => {
-
-    const signedInt = Array(1000).fill(null).map(() => {
-      const numDig = Math.ceil(Math.random() * 7)
-      return Math.floor(Math.random() * Math.pow(10, numDig)) * (Math.random() > 0.5 ? 1 : -1)
-    })
-    const encodedString = signedInt.map(n => encodeNumber(n))
-    const decodedNumber = encodedString.map(s => decodeToNumber(s))
-
-    /**
-     * -0 will be converted to 0 by the encode/decode process, but does not deep equal, according to jasmine
-     */
-    expect(decodedNumber).toEqual(signedInt.map(v => v === 0 ? 0 : v))
-
-    expect(lengthShortened(signedInt, encodedString)).toBe(true)
-  })
-
-  it('should encode/decode float as expected', () => {
-    const floatNum = [
-      0.111,
-      12.23,
-      1723.0,
-    ]
-
-    const encodedString = floatNum.map(f => encodeNumber(f, { float: true }))
-    const decodedNumber = encodedString.map(s => decodeToNumber(s, { float: true }))
-    expect(decodedNumber.map(n => n.toFixed(FLOAT_PRECISION))).toEqual(floatNum.map(n => n.toFixed(FLOAT_PRECISION)))
-  })
-
-  it('should encode/decode ANY float as expected', () => {
-    const floatNums = Array(1000).fill(null).map(() => {
-      const numDig = Math.ceil(Math.random() * 7)
-      return (Math.random() > 0.5 ? 1 : -1) * Math.floor(
-        Math.random() * Math.pow(10, numDig),
-      )
-    })
-
-    const encodedString = floatNums.map(f => encodeNumber(f, { float: true }))
-    const decodedNumber = encodedString.map(s => decodeToNumber(s, { float: true }))
-
-    expect(floatNums.map(v => v.toFixed(FLOAT_PRECISION))).toEqual(decodedNumber.map(n => n.toFixed(FLOAT_PRECISION)))
-  })
-
-  it('poisoned hash should throw', () => {
-    const illegialCharacters = './\\?#!@#^%&*()+={}[]\'"\n\t;:'
-    for (const char of illegialCharacters.split('')) {
-      expect(() => {
-        decodeToNumber(char)
-      }).toThrow()
-    }
-  })
-
-  it('poisoned hash can be caught', () => {
-
-    const testArray = ['abc', './\\', 'Cde']
-    const decodedNum = testArray.map(v => {
-      try {
-        return decodeToNumber(v)
-      } catch (e) {
-        return null
-      }
-    }).filter(v => !!v)
-    expect(decodedNum.length).toEqual(2)
-  })
-})
diff --git a/src/atlasViewer/atlasViewer.constantService.service.ts b/src/atlasViewer/atlasViewer.constantService.service.ts
index b6e8358f72470566bf4350d61a78860038edf30c..c0ca5d31ccc0075d008fa626b0e884941ee60230 100644
--- a/src/atlasViewer/atlasViewer.constantService.service.ts
+++ b/src/atlasViewer/atlasViewer.constantService.service.ts
@@ -257,103 +257,3 @@ export const UNSUPPORTED_PREVIEW = [{
 
 export const UNSUPPORTED_INTERVAL = 7000
 
-
-/**
- * First attempt at encoding int (e.g. selected region, navigation location) from number (loc info density) to b64 (higher info density)
- * The constraint is that the cipher needs to be commpatible with URI encoding
- * and a URI compatible separator is required.
- *
- * The implementation below came from
- * https://stackoverflow.com/a/6573119/6059235
- *
- * While a faster solution exist in the same post, this operation is expected to be done:
- * - once per 1 sec frequency
- * - on < 1000 numbers
- *
- * So performance is not really that important (Also, need to learn bitwise operation)
- */
-
-const cipher = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-'
-export const separator = "."
-const negString = '~'
-
-const encodeInt = (number: number) => {
-  if (number % 1 !== 0) { throw new Error('cannot encodeInt on a float. Ensure float flag is set') }
-  if (isNaN(Number(number)) || number === null || number === Number.POSITIVE_INFINITY) { throw new Error('The input is not valid') }
-
-  let rixit // like 'digit', only in some non-decimal radix
-  let residual
-  let result = ''
-
-  if (number < 0) {
-    result += negString
-    residual = Math.floor(number * -1)
-  } else {
-    residual = Math.floor(number)
-  }
-
-  /* eslint-disable-next-line no-constant-condition */
-  while (true) {
-    rixit = residual % 64
-    // this.log.log("rixit : " + rixit)
-    // this.log.log("result before : " + result)
-    result = cipher.charAt(rixit) + result
-    // this.log.log("result after : " + result)
-    // this.log.log("residual before : " + residual)
-    residual = Math.floor(residual / 64)
-    // this.log.log("residual after : " + residual)
-
-    if (residual === 0) {
-      break;
-    }
-  }
-  return result
-}
-
-interface IB64EncodingOption {
-  float: boolean
-}
-
-const defaultB64EncodingOption = {
-  float: false,
-}
-
-export const encodeNumber:
-  (number: number, option?: IB64EncodingOption) => string =
-  (number: number, { float = false }: IB64EncodingOption = defaultB64EncodingOption) => {
-    if (!float) { return encodeInt(number) } else {
-      const floatArray = new Float32Array(1)
-      floatArray[0] = number
-      const intArray = new Uint32Array(floatArray.buffer)
-      const castedInt = intArray[0]
-      return encodeInt(castedInt)
-    }
-  }
-
-const decodetoInt = (encodedString: string) => {
-  let _encodedString
-  let negFlag = false
-  if (encodedString.slice(-1) === negString) {
-    negFlag = true
-    _encodedString = encodedString.slice(0, -1)
-  } else {
-    _encodedString = encodedString
-  }
-  return (negFlag ? -1 : 1) * [..._encodedString].reduce((acc, curr) => {
-    const index = cipher.indexOf(curr)
-    if (index < 0) { throw new Error(`Poisoned b64 encoding ${encodedString}`) }
-    return acc * 64 + index
-  }, 0)
-}
-
-export const decodeToNumber:
-  (encodedString: string, option?: IB64EncodingOption) => number =
-  (encodedString: string, {float = false} = defaultB64EncodingOption) => {
-    if (!float) { return decodetoInt(encodedString) } else {
-      const _int = decodetoInt(encodedString)
-      const intArray = new Uint32Array(1)
-      intArray[0] = _int
-      const castedFloat = new Float32Array(intArray.buffer)
-      return castedFloat[0]
-    }
-  }
diff --git a/src/atlasViewer/atlasViewer.style.css b/src/atlasViewer/atlasViewer.style.css
index c5024d44227a8cb0e0594637e583f392418efcbb..1a6915506e6049e60f33fca36781b9fa6e29ba80 100644
--- a/src/atlasViewer/atlasViewer.style.css
+++ b/src/atlasViewer/atlasViewer.style.css
@@ -68,7 +68,6 @@ mat-sidenav {
   box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
 }
 
-landmark-ui,
 region-menu
 {
   display:inline-block;
diff --git a/src/atlasViewer/atlasViewer.template.html b/src/atlasViewer/atlasViewer.template.html
index a45ee29bc896c9957348da909d03410244d579b8..fcf8a02d79b6cdbec9f10fbc29572426a9f566fe 100644
--- a/src/atlasViewer/atlasViewer.template.html
+++ b/src/atlasViewer/atlasViewer.template.html
@@ -40,312 +40,17 @@
 
 <!-- atlas template -->
 <ng-template #viewerBody>
-  <div class="atlas-container"
+  <div class="atlas-container w-100 h-100"
     iav-media-query
     #media="iavMediaQuery">
     <!-- prevent default is required so that user do not zoom in on UI or scroll on mobile UI -->
-    <ui-nehuba-container
-      class="z-index-10"
-      #uiNehubaContainer="uiNehubaContainer"
-      iav-mouse-hover
-      #iavMouseHoverEl="iavMouseHover"
-      [currentOnHoverObs$]="iavMouseHoverEl.currentOnHoverObs$"
-      [currentOnHover]="iavMouseHoverEl.currentOnHoverObs$ | async"
+    <iav-cmp-viewer-container
+      class="w-100 h-100 d-block"
+      [ismobile]="(media.mediaBreakPoint$ | async) > 3"
       iav-captureClickListenerDirective
       [iav-captureClickListenerDirective-captureDocument]="true"
-      (iav-captureClickListenerDirective-onUnmovedClick)="mouseClickDocument($event)"
-      (drag-drop)="localFileService.handleFileDrop($event)">
-
-      <!-- top right content transclusion -->
-      <div ui-nehuba-container-overlay-top-right class="d-inline-flex flex-row justify-content-end align-items-start z-index-6 position-absolute pe-none w-100 h-100">
-
-        <signin-banner
-          class="mt-3 mr-2"
-          [parcellationIsSelected]="!!selectedParcellation"
-          [ismobile]="(media.mediaBreakPoint$ | async) > 3">
-        </signin-banner>
-
-        <!-- atlas selector -->
-        <div *ngIf="uiNehubaContainer.viewerLoaded"
-          class="iv-custom-comp bg card m-2 mat-elevation-z2">
-          <atlas-dropdown-selector class="pe-all mt-2">
-          </atlas-dropdown-selector>
-        </div>
-
-      </div>
-
-      <!-- bottom left content transclusion -->
-      <div ui-nehuba-container-overlay-bottom-left class="d-inline-flex pe-none w-100 align-items-end m-2 mb-4">
-
-        <!-- only load atlas layer selector and chips if viewer is loaded -->
-        <ng-template [ngIf]="uiNehubaContainer.viewerLoaded  && !(isStandaloneVolumes$ | async)">
-
-          <!-- Viewer Selector Container-->
-          <atlas-layer-selector
-            #alSelector="atlasLayerSelector"
-            class="pe-all"
-            (iav-outsideClick)="alSelector.selectorExpanded = false">
-          </atlas-layer-selector>
-          <mat-chip-list class="mb-2">
-            <!-- additional layer -->
-
-            <ng-container>
-              <ng-container *ngTemplateOutlet="currParcellationTmpl; context: { addParc: (selectedAdditionalLayers$ | async), parc: selectedParcellation }">
-              </ng-container>
-            </ng-container>
-
-            <!-- any selected region(s) -->
-            <ng-container>
-              <ng-container *ngTemplateOutlet="selectedRegionTmpl">
-              </ng-container>
-            </ng-container>
-
-            <!-- controls for iav volumes -->
-            <div class="hidden" iav-shown-previews #previews="iavShownPreviews"></div>
-            <ng-container *ngTemplateOutlet="selectedDatasetPreview; context: { layers: previews.iavAdditionalLayers$ | async | filterPreviewByType : [previews.FILETYPES.VOLUMES] }">
-            </ng-container>
-
-          </mat-chip-list>
-
-          <!-- current layer tmpl -->
-
-          <ng-template #currParcellationTmpl let-parc="parc" let-addParc="addParc">
-
-            <div [matMenuTriggerFor]="layerVersionMenu"
-              [matMenuTriggerData]="{ layerVersionMenuTrigger: layerVersionMenuTrigger }"
-              #layerVersionMenuTrigger="matMenuTrigger">
-
-              <ng-template [ngIf]="addParc.length > 0" [ngIfElse]="defaultParcTmpl">
-                <ng-container *ngFor="let p of addParc">
-                  <ng-container *ngTemplateOutlet="chipTmpl; context: {
-                    parcel: p,
-                    selected: true,
-                    dismissable: true,
-                    onclick: layerVersionMenuTrigger.toggleMenu.bind(layerVersionMenuTrigger)
-                  }">
-                  </ng-container>
-                </ng-container>
-              </ng-template>
-              <ng-template #defaultParcTmpl>
-                <ng-container *ngTemplateOutlet="chipTmpl; context: {
-                  parcel: parc,
-                  selected: false,
-                  dismissable: false,
-                  onclick: layerVersionMenuTrigger.toggleMenu.bind(layerVersionMenuTrigger)
-                }">
-                </ng-container>
-              </ng-template>
-            </div>
-          </ng-template>
-
-          <!-- render parc templ -->
-          <ng-template #chipTmpl
-            let-parcel="parcel"
-            let-selected="selected"
-            let-dismissable="dismissable"
-            let-chipClass="class"
-            let-onclick="onclick">
-            <mat-chip class="pe-all position-relative z-index-2 d-inline-flex justify-content-between"
-              [ngClass]="chipClass"
-              (click)="onclick && onclick()"
-              [selected]="selected">
-
-              <span>
-                {{ parcel?.groupName ? (parcel?.groupName + ' - ') : '' }}{{ parcel && (parcel.displayName || parcel.name) }}
-              </span>
-
-              <!-- info icon -->
-              <ng-template [ngIf]="parcel?.originDatasets?.length > 0" [ngIfElse]="infoIconBasic">
-
-                <mat-icon
-                  *ngFor="let ds of parcel.originDatasets"
-                  fontSet="fas"
-                  fontIcon="fa-info-circle"
-                  iav-stop="click"
-                  iav-dataset-show-dataset-dialog
-                  [iav-dataset-show-dataset-dialog-kgid]="ds['kgId']"
-                  [iav-dataset-show-dataset-dialog-kgschema]="ds['kgSchema']"
-                  [iav-dataset-show-dataset-dialog-name]="parcel?.properties?.name"
-                  [iav-dataset-show-dataset-dialog-description]="parcel?.properties?.description">
-                </mat-icon>
-
-              </ng-template>
-
-              <ng-template #infoIconBasic>
-                <mat-icon *ngIf="parcel?.properties?.name && parcel?.properties?.description"
-                  fontSet="fas"
-                  fontIcon="fa-info-circle"
-                  iav-stop="click"
-                  iav-dataset-show-dataset-dialog
-                  [iav-dataset-show-dataset-dialog-name]="parcel.properties.name"
-                  [iav-dataset-show-dataset-dialog-description]="parcel.properties.description">
-
-                </mat-icon>
-              </ng-template>
-
-              <!-- dismiss icon -->
-              <mat-icon
-                *ngIf="dismissable"
-                (click)="clearAdditionalLayer(parcel); $event.stopPropagation()"
-                fontSet="fas"
-                fontIcon="fa-times">
-              </mat-icon>
-            </mat-chip>
-          </ng-template>
-
-          <!-- layer version selector -->
-          <mat-menu #layerVersionMenu
-            class="bg-none box-shadow-none"
-            [hasBackdrop]="false">
-            <ng-template matMenuContent let-layerVersionMenuTrigger="layerVersionMenuTrigger">
-              <div (iav-outsideClick)="layerVersionMenuTrigger.closeMenu()">
-                <ng-container *ngFor="let parcVer of selectedLayerVersions$ | async">
-                  <ng-container *ngTemplateOutlet="chipTmpl; context: {
-                    parcel: parcVer,
-                    selected: selectedParcellation && selectedParcellation['@id'] === parcVer['@id'],
-                    dismissable: false,
-                    class: 'w-100',
-                    onclick: bindFns([
-                      [ selectParcellation.bind(this), parcVer ],
-                      [ layerVersionMenuTrigger.closeMenu.bind(layerVersionMenuTrigger) ]
-                    ])
-                  }">
-                  </ng-container>
-                  <div class="mt-1"></div>
-                </ng-container>
-              </div>
-            </ng-template>
-          </mat-menu>
-
-          <ng-template #selectedRegionTmpl>
-
-            <!-- regions chip -->
-            <ng-template [ngIf]="selectedRegions$ | async" let-selectedRegions="ngIf">
-              <!-- if regions.length > 1 -->
-              <!-- use group chip -->
-              <ng-template [ngIf]="selectedRegions.length > 1" [ngIfElse]="singleRegionTmpl">
-                <mat-chip
-                  color="primary"
-                  selected
-                  (click)="uiNehubaContainer.matDrawerMinor.open() && uiNehubaContainer.navSideDrawerMainSwitch.open()"
-                  class="pe-all position-relative z-index-1 ml-8-n">
-                  <span class="iv-custom-comp text text-truncate d-inline pl-4">
-                    {{ CONST.MULTI_REGION_SELECTION }}
-                  </span>
-                  <mat-icon
-                    (click)="clearSelectedRegions()"
-                    fontSet="fas"
-                    iav-stop="click"
-                    fontIcon="fa-times">
-                  </mat-icon>
-                </mat-chip>
-              </ng-template>
-
-              <!-- if reginos.lengt === 1 -->
-              <!-- use single region chip -->
-              <ng-template #singleRegionTmpl>
-                <ng-container *ngFor="let r of selectedRegions">
-
-                  <!-- region chip for discrete map -->
-                  <mat-chip
-                    iav-region
-                    (click)="uiNehubaContainer.matDrawerMinor.open() && uiNehubaContainer.navSideDrawerMainSwitch.open()"
-                    [region]="r"
-                    class="pe-all position-relative z-index-1 ml-8-n"
-                    [ngClass]="{
-                      'darktheme':regionDirective.rgbDarkmode === true,
-                      'lighttheme': regionDirective.rgbDarkmode === false
-                    }"
-                    [style.backgroundColor]="regionDirective.rgbString"
-                    #regionDirective="iavRegion">
-                    <span class="iv-custom-comp text text-truncate d-inline pl-4">
-                      {{ r.name }}
-                    </span>
-                    <mat-icon
-                      class="iv-custom-comp text"
-                      (click)="clearSelectedRegions()"
-                      fontSet="fas"
-                      iav-stop="click"
-                      fontIcon="fa-times">
-                    </mat-icon>
-                  </mat-chip>
-    
-                  <!-- chips for previewing origin datasets/continous map -->
-                  <ng-container *ngFor="let originDataset of (r.originDatasets || []); let index = index">
-                    <div class="hidden"
-                      iav-dataset-preview-dataset-file
-                      [iav-dataset-preview-dataset-file-kgid]="originDataset.kgId"
-                      [iav-dataset-preview-dataset-file-filename]="originDataset.filename"
-                      #previewDirective="iavDatasetPreviewDatasetFile">
-                    </div>
-                    <mat-chip *ngIf="previewDirective.active"
-                      (click)="uiNehubaContainer.matDrawerMinor.open() && uiNehubaContainer.navSideDrawerMainSwitch.open()"
-                      class="pe-all position-relative ml-8-n">
-                      <span class="pl-4">
-                        {{ regionDirective.regionOriginDatasetLabels$ | async | renderViewOriginDatasetlabel : index }}
-                      </span>
-                      <mat-icon (click)="previewDirective.onClick()"
-                        fontSet="fas"
-                        iav-stop="click"
-                        fontIcon="fa-times">
-                      </mat-icon>
-                    </mat-chip>
-    
-                    <mat-chip *ngFor="let key of clearViewKeys$ | async"
-                      (click)="uiNehubaContainer.matDrawerMinor.open() && uiNehubaContainer.navSideDrawerMainSwitch.open()"
-                      class="pe-all position-relative ml-8-n">
-                      <span class="pl-4">
-                        {{ key }}
-                      </span>
-                      <mat-icon (click)="unsetClearViewByKey(key)"
-                        fontSet="fas"
-                        iav-stop="click"
-                        fontIcon="fa-times">
-    
-                      </mat-icon>
-                    </mat-chip>
-                  </ng-container>
-    
-                </ng-container>
-              </ng-template>
-            </ng-template>
-
-          </ng-template>
-
-          <ng-template #selectedDatasetPreview let-layers="layers">
-
-            <ng-container *ngFor="let layer of layers">
-              <div class="hidden"
-                iav-dataset-preview-dataset-file
-                [iav-dataset-preview-dataset-file-kgid]="layer.datasetId"
-                [iav-dataset-preview-dataset-file-filename]="layer.filename"
-                #preview="iavDatasetPreviewDatasetFile">
-
-              </div>
-              <mat-chip class="pe-all"
-                (click)="uiNehubaContainer.matDrawerMinor.open() && uiNehubaContainer.navSideDrawerMainSwitch.open()">
-                {{ layer.file?.name || layer.filename || 'Unknown data preview' }}
-                <mat-icon fontSet="fas" fontIcon="fa-times"
-                  (click)="preview.onClick()"
-                  iav-stop="click">
-                </mat-icon>
-              </mat-chip>
-            </ng-container>
-          </ng-template>
-
-        </ng-template>
-      </div>
-
-      <!-- top left content transclusion -->
-      <div ui-nehuba-container-overlay-top-left class="d-inline-flex pe-none w-100 align-items-start m-2">
-        <ui-status-card
-          *ngIf="uiNehubaContainer.viewerLoaded"
-          class="pe-all muted-7"
-          [selectedTemplateName]="uiNehubaContainer?.selectedTemplate?.name"
-          [nehubaViewer]="uiNehubaContainer?.nehubaViewer">
-        </ui-status-card>
-      </div>
-    </ui-nehuba-container>
+      (iav-captureClickListenerDirective-onUnmovedClick)="mouseClickDocument($event)">
+    </iav-cmp-viewer-container>
 
     <layout-floating-container
       zIndex="13"
diff --git a/src/atlasViewer/atlasViewer.urlUtil.spec.ts b/src/atlasViewer/atlasViewer.urlUtil.spec.ts
index c018f8718488fad6cc61f7508bda4cca3bae8332..bc47b72d3c868418c2563489d3ec9bf89e99d59f 100644
--- a/src/atlasViewer/atlasViewer.urlUtil.spec.ts
+++ b/src/atlasViewer/atlasViewer.urlUtil.spec.ts
@@ -2,7 +2,7 @@
 
 import {} from 'jasmine'
 import { defaultRootState } from 'src/services/stateStore.service'
-import { cvtSearchParamToState, cvtStateToSearchParam } from './atlasViewer.urlUtil'
+import { cvtSearchParamToState, cvtStateToSearchParam, decodeToNumber, encodeNumber } from './atlasViewer.urlUtil'
 
 const bigbrainJson = require('!json-loader!src/res/ext/bigbrain.json')
 const colin = require('!json-loader!src/res/ext/colin.json')
@@ -207,4 +207,131 @@ describe('atlasViewer.urlUtil.ts', () => {
       expect(stringified).toBe('templateSelected=Big+Brain+%28Histology%29&parcellationSelected=Cytoarchitectonic+Maps+-+v2.4')
     })
   })
+
+  const FLOAT_PRECISION = 6
+  
+  describe('encodeNumber/decodeToNumber', () => {
+  
+    const getCompareOriginal = (original: number[]) => (element: string, index: number) =>
+      original[index].toString().length >= element.length
+  
+    const lengthShortened = (original: number[], encodedString: string[]) =>
+      encodedString.every(getCompareOriginal(original))
+  
+    it('should encode/decode positive integer as expected', () => {
+  
+      const positiveInt = [
+        0,
+        1,
+        99999999999,
+        12347,
+      ]
+  
+      const encodedString = positiveInt.map(n => encodeNumber(n))
+      const decodedString = encodedString.map(s => decodeToNumber(s))
+      expect(decodedString).toEqual(positiveInt)
+  
+      expect(lengthShortened(positiveInt, encodedString)).toBe(true)
+    })
+  
+    it('should encode/decode ANY positive integer as expected', () => {
+      const posInt = Array(1000).fill(null).map(() => {
+        const numDig = Math.ceil(Math.random() * 7)
+        return Math.floor(Math.random() * Math.pow(10, numDig))
+      })
+      const encodedString = posInt.map(n => encodeNumber(n))
+      const decodedNumber = encodedString.map(s => decodeToNumber(s))
+      expect(decodedNumber).toEqual(posInt)
+  
+      expect(lengthShortened(posInt, encodedString)).toBe(true)
+    })
+  
+    it('should encode/decode signed integer as expected', () => {
+  
+      const signedInt = [
+        0,
+        -0,
+        -1,
+        1,
+        128,
+        -54,
+      ]
+  
+      const encodedString = signedInt.map(n => encodeNumber(n))
+      const decodedNumber = encodedString.map(s => decodeToNumber(s))
+  
+      /**
+       * -0 will be converted to 0 by the encode/decode process, but does not deep equal, according to jasmine
+       */
+      expect(decodedNumber).toEqual(signedInt.map(v => v === 0 ? 0 : v))
+  
+      expect(lengthShortened(signedInt, encodedString)).toBe(true)
+    })
+  
+    it('should encode/decode ANY signed integer as expected', () => {
+  
+      const signedInt = Array(1000).fill(null).map(() => {
+        const numDig = Math.ceil(Math.random() * 7)
+        return Math.floor(Math.random() * Math.pow(10, numDig)) * (Math.random() > 0.5 ? 1 : -1)
+      })
+      const encodedString = signedInt.map(n => encodeNumber(n))
+      const decodedNumber = encodedString.map(s => decodeToNumber(s))
+  
+      /**
+       * -0 will be converted to 0 by the encode/decode process, but does not deep equal, according to jasmine
+       */
+      expect(decodedNumber).toEqual(signedInt.map(v => v === 0 ? 0 : v))
+  
+      expect(lengthShortened(signedInt, encodedString)).toBe(true)
+    })
+  
+    it('should encode/decode float as expected', () => {
+      const floatNum = [
+        0.111,
+        12.23,
+        1723.0,
+      ]
+  
+      const encodedString = floatNum.map(f => encodeNumber(f, { float: true }))
+      const decodedNumber = encodedString.map(s => decodeToNumber(s, { float: true }))
+      expect(decodedNumber.map(n => n.toFixed(FLOAT_PRECISION))).toEqual(floatNum.map(n => n.toFixed(FLOAT_PRECISION)))
+    })
+  
+    it('should encode/decode ANY float as expected', () => {
+      const floatNums = Array(1000).fill(null).map(() => {
+        const numDig = Math.ceil(Math.random() * 7)
+        return (Math.random() > 0.5 ? 1 : -1) * Math.floor(
+          Math.random() * Math.pow(10, numDig),
+        )
+      })
+  
+      const encodedString = floatNums.map(f => encodeNumber(f, { float: true }))
+      const decodedNumber = encodedString.map(s => decodeToNumber(s, { float: true }))
+  
+      expect(floatNums.map(v => v.toFixed(FLOAT_PRECISION))).toEqual(decodedNumber.map(n => n.toFixed(FLOAT_PRECISION)))
+    })
+  
+    it('poisoned hash should throw', () => {
+      const illegialCharacters = './\\?#!@#^%&*()+={}[]\'"\n\t;:'
+      for (const char of illegialCharacters.split('')) {
+        expect(() => {
+          decodeToNumber(char)
+        }).toThrow()
+      }
+    })
+  
+    it('poisoned hash can be caught', () => {
+  
+      const testArray = ['abc', './\\', 'Cde']
+      const decodedNum = testArray.map(v => {
+        try {
+          return decodeToNumber(v)
+        } catch (e) {
+          return null
+        }
+      }).filter(v => !!v)
+      expect(decodedNum.length).toEqual(2)
+    })
+  })
+  
 })
diff --git a/src/atlasViewer/atlasViewer.urlUtil.ts b/src/atlasViewer/atlasViewer.urlUtil.ts
index 59640205e71446281e4329b776b7f1b3bfbb133b..690094788ba8320c0af070611cf3b62daa3943bb 100644
--- a/src/atlasViewer/atlasViewer.urlUtil.ts
+++ b/src/atlasViewer/atlasViewer.urlUtil.ts
@@ -1,10 +1,9 @@
-import { getGetRegionFromLabelIndexId } from "src/services/effect/effect";
+import { getGetRegionFromLabelIndexId } from 'src/util/fn'
 import { mixNgLayers } from "src/services/state/ngViewerState.store";
 import { PLUGINSTORE_CONSTANTS } from 'src/services/state/pluginState.store'
-import { generateLabelIndexId, getNgIdLabelIndexFromRegion, IavRootStoreInterface } from "../services/stateStore.service";
-import { decodeToNumber, encodeNumber, separator } from "./atlasViewer.constantService.service";
 import { getShader, PMAP_DEFAULT_CONFIG } from "src/util/constants";
 import { viewerStateHelperStoreName } from "src/services/state/viewerState.store.helper";
+import { serialiseParcellationRegion } from "common/util"
 export const PARSING_SEARCHPARAM_ERROR = {
   TEMPALTE_NOT_SET: 'TEMPALTE_NOT_SET',
   TEMPLATE_NOT_FOUND: 'TEMPLATE_NOT_FOUND',
@@ -20,6 +19,107 @@ export const CVT_STATE_TO_SEARCHPARAM_ERROR = {
   TEMPLATE_NOT_SELECTED: 'TEMPLATE_NOT_SELECTED',
 }
 
+/**
+ * First attempt at encoding int (e.g. selected region, navigation location) from number (loc info density) to b64 (higher info density)
+ * The constraint is that the cipher needs to be commpatible with URI encoding
+ * and a URI compatible separator is required.
+ *
+ * The implementation below came from
+ * https://stackoverflow.com/a/6573119/6059235
+ *
+ * While a faster solution exist in the same post, this operation is expected to be done:
+ * - once per 1 sec frequency
+ * - on < 1000 numbers
+ *
+ * So performance is not really that important (Also, need to learn bitwise operation)
+ */
+
+const cipher = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-'
+export const separator = "."
+const negString = '~'
+
+const encodeInt = (number: number) => {
+  if (number % 1 !== 0) { throw new Error('cannot encodeInt on a float. Ensure float flag is set') }
+  if (isNaN(Number(number)) || number === null || number === Number.POSITIVE_INFINITY) { throw new Error('The input is not valid') }
+
+  let rixit // like 'digit', only in some non-decimal radix
+  let residual
+  let result = ''
+
+  if (number < 0) {
+    result += negString
+    residual = Math.floor(number * -1)
+  } else {
+    residual = Math.floor(number)
+  }
+
+  /* eslint-disable-next-line no-constant-condition */
+  while (true) {
+    rixit = residual % 64
+    // this.log.log("rixit : " + rixit)
+    // this.log.log("result before : " + result)
+    result = cipher.charAt(rixit) + result
+    // this.log.log("result after : " + result)
+    // this.log.log("residual before : " + residual)
+    residual = Math.floor(residual / 64)
+    // this.log.log("residual after : " + residual)
+
+    if (residual === 0) {
+      break;
+    }
+  }
+  return result
+}
+
+interface IB64EncodingOption {
+  float: boolean
+}
+
+const defaultB64EncodingOption = {
+  float: false,
+}
+
+export const encodeNumber:
+  (number: number, option?: IB64EncodingOption) => string =
+  (number: number, { float = false }: IB64EncodingOption = defaultB64EncodingOption) => {
+    if (!float) { return encodeInt(number) } else {
+      const floatArray = new Float32Array(1)
+      floatArray[0] = number
+      const intArray = new Uint32Array(floatArray.buffer)
+      const castedInt = intArray[0]
+      return encodeInt(castedInt)
+    }
+  }
+
+const decodetoInt = (encodedString: string) => {
+  let _encodedString
+  let negFlag = false
+  if (encodedString.slice(-1) === negString) {
+    negFlag = true
+    _encodedString = encodedString.slice(0, -1)
+  } else {
+    _encodedString = encodedString
+  }
+  return (negFlag ? -1 : 1) * [..._encodedString].reduce((acc, curr) => {
+    const index = cipher.indexOf(curr)
+    if (index < 0) { throw new Error(`Poisoned b64 encoding ${encodedString}`) }
+    return acc * 64 + index
+  }, 0)
+}
+
+export const decodeToNumber:
+  (encodedString: string, option?: IB64EncodingOption) => number =
+  (encodedString: string, {float = false} = defaultB64EncodingOption) => {
+    if (!float) { return decodetoInt(encodedString) } else {
+      const _int = decodetoInt(encodedString)
+      const intArray = new Uint32Array(1)
+      intArray[0] = _int
+      const castedFloat = new Float32Array(intArray.buffer)
+      return castedFloat[0]
+    }
+  }
+
+
 export const cvtStateToSearchParam = (state: any): URLSearchParams => {
   const searchParam = new URLSearchParams()
 
@@ -38,7 +138,7 @@ export const cvtStateToSearchParam = (state: any): URLSearchParams => {
     // encoding selected regions
     const accumulatorMap = new Map<string, number[]>()
     for (const region of regionsSelected) {
-      const { ngId, labelIndex } = getNgIdLabelIndexFromRegion({ region })
+      const { ngId, labelIndex } = region
       const existingEntry = accumulatorMap.get(ngId)
       if (existingEntry) { existingEntry.push(labelIndex) } else { accumulatorMap.set(ngId, [ labelIndex ]) }
     }
@@ -92,7 +192,7 @@ export const cvtStateToSearchParam = (state: any): URLSearchParams => {
 const { TEMPLATE_NOT_FOUND, TEMPALTE_NOT_SET, PARCELLATION_NOT_UPDATED } = PARSING_SEARCHPARAM_ERROR
 const { UNKNOWN_PARCELLATION, DECODE_CIPHER_ERROR, ID_ERROR } = PARSING_SEARCHPARAM_WARNING
 
-const parseSearchParamForTemplateParcellationRegion = (searchparams: URLSearchParams, state: IavRootStoreInterface, cb?: (arg: any) => void) => {
+const parseSearchParamForTemplateParcellationRegion = (searchparams: URLSearchParams, state: any, cb?: (arg: any) => void) => {
 
 
   /**
@@ -169,7 +269,7 @@ const parseSearchParamForTemplateParcellationRegion = (searchparams: URLSearchPa
             }
           }).filter(v => !!v)
           for (const labelIndex of labelIndicies) {
-            selectRegionIds.push( generateLabelIndexId({ ngId, labelIndex }) )
+            selectRegionIds.push( serialiseParcellationRegion({ ngId, labelIndex }) )
           }
         }
         return selectRegionIds
@@ -197,9 +297,9 @@ const parseSearchParamForTemplateParcellationRegion = (searchparams: URLSearchPa
   }
 }
 
-export const cvtSearchParamToState = (searchparams: URLSearchParams, state: IavRootStoreInterface, callback?: (error: any) => void): IavRootStoreInterface => {
+export const cvtSearchParamToState = (searchparams: URLSearchParams, state: any, callback?: (error: any) => void): any => {
 
-  const returnState = JSON.parse(JSON.stringify(state)) as IavRootStoreInterface
+  const returnState = JSON.parse(JSON.stringify(state)) as any
 
   /* eslint-disable-next-line @typescript-eslint/no-empty-function */
   const warningCb = callback || (() => {})
diff --git a/src/atlasViewer/mouseOver.directive.ts b/src/atlasViewer/mouseOver.directive.ts
deleted file mode 100644
index 7938d4a36c1ef02ce7431565426a34af42af7b62..0000000000000000000000000000000000000000
--- a/src/atlasViewer/mouseOver.directive.ts
+++ /dev/null
@@ -1,250 +0,0 @@
-import { Directive, Pipe, PipeTransform, SecurityContext } from "@angular/core";
-import { DomSanitizer, SafeHtml } from "@angular/platform-browser";
-import { select, Store } from "@ngrx/store";
-import { combineLatest, merge, Observable } from "rxjs";
-import { distinctUntilChanged, filter, map, scan, shareReplay, startWith, withLatestFrom } from "rxjs/operators";
-import { TransformOnhoverSegmentPipe } from "src/atlasViewer/onhoverSegment.pipe";
-import { LoggingService } from "src/logging";
-import { uiStateMouseOverSegmentsSelector, uiStateMouseoverUserLandmark } from "src/services/state/uiState/selectors";
-import { getNgIdLabelIndexFromId } from "src/services/stateStore.service";
-
-/**
- * Scan function which prepends newest positive (i.e. defined) value
- *
- * e.g. const source = new Subject()
- * source.pipe(
- *  scan(temporalPositveScanFn, [])
- * ).subscribe(this.log.log) // outputs
- *
- *
- *
- */
-export const temporalPositveScanFn = (acc: Array<{segments: any, landmark: any, userLandmark: any}>, curr: {segments: any, landmark: any, userLandmark: any}) => {
-
-  const keys = Object.keys(curr)
-
-  // empty array is truthy
-  const isPositive = keys.some(key => Array.isArray(curr[key])
-    ? curr[key].length > 0
-    : !!curr[key]
-  )
-
-  return isPositive
-    ? [curr, ...(acc.filter(item => !keys.some(key => !!item[key])))] as Array<{segments?: any, landmark?: any, userLandmark?: any}>
-    : acc.filter(item => !keys.some(key => !!item[key]))
-}
-
-@Directive({
-  selector: '[iav-mouse-hover]',
-  exportAs: 'iavMouseHover',
-})
-
-export class MouseHoverDirective {
-
-  public onHoverObs$: Observable<{segments: any, landmark: any, userLandmark: any}>
-  public currentOnHoverObs$: Observable<{segments: any, landmark: any, userLandmark: any}>
-
-  constructor(
-    private store$: Store<any>,
-    private log: LoggingService,
-  ) {
-
-    // TODO consider moving these into a single obs serviced by a DI service
-    // can potentially net better performance
-
-    const onHoverUserLandmark$ = this.store$.pipe(
-      select(uiStateMouseoverUserLandmark)
-    )
-
-    const onHoverLandmark$ = combineLatest(
-      this.store$.pipe(
-        select('uiState'),
-        select('mouseOverLandmark'),
-      ),
-      this.store$.pipe(
-        select('dataStore'),
-        select('fetchedSpatialData'),
-        startWith([]),
-      ),
-    ).pipe(
-      map(([landmark, spatialDatas]) => {
-        if (landmark === null) { return landmark }
-        const idx = Number(landmark.replace('label=', ''))
-        if (isNaN(idx)) {
-          this.log.warn(`Landmark index could not be parsed as a number: ${landmark}`)
-          return {
-            landmarkName: idx,
-          }
-        } else {
-          return {
-            ...spatialDatas[idx],
-            landmarkName: spatialDatas[idx].name,
-          }
-        }
-      }),
-    )
-
-    const onHoverSegments$ = this.store$.pipe(
-      select(uiStateMouseOverSegmentsSelector),
-      filter(v => !!v),
-      withLatestFrom(
-        this.store$.pipe(
-          select('viewerState'),
-          select('parcellationSelected'),
-          startWith(null),
-        ),
-      ),
-      map(([ arr, parcellationSelected ]) => parcellationSelected && parcellationSelected.auxillaryMeshIndices
-        ? arr.filter(({ segment }) => {
-          // if segment is not a string (i.e., not labelIndexId) return true
-          if (typeof segment !== 'string') { return true }
-          const { labelIndex } = getNgIdLabelIndexFromId({ labelIndexId: segment })
-          return parcellationSelected.auxillaryMeshIndices.indexOf(labelIndex) < 0
-        })
-        : arr),
-      distinctUntilChanged((o, n) => o.length === n.length
-        && n.every(segment =>
-          o.find(oSegment => oSegment.layer.name === segment.layer.name
-            && oSegment.segment === segment.segment))),
-    )
-
-    const mergeObs = merge(
-      onHoverSegments$.pipe(
-        distinctUntilChanged(),
-        map(segments => {
-          return { segments }
-        }),
-      ),
-      onHoverLandmark$.pipe(
-        distinctUntilChanged(),
-        map(landmark => {
-          return { landmark }
-        }),
-      ),
-      onHoverUserLandmark$.pipe(
-        distinctUntilChanged(),
-        map(userLandmark => {
-          return { userLandmark }
-        }),
-      ),
-    ).pipe(
-      shareReplay(1),
-    )
-
-    this.onHoverObs$ = mergeObs.pipe(
-      scan((acc, curr) => {
-        return {
-          ...acc,
-          ...curr,
-        }
-      }, { segments: null, landmark: null, userLandmark: null }),
-      shareReplay(1),
-    )
-
-    this.currentOnHoverObs$ = mergeObs.pipe(
-      scan(temporalPositveScanFn, []),
-      map(arr => {
-
-        let returnObj = {
-          segments: null,
-          landmark: null,
-          userLandmark: null,
-        }
-
-        for (const val of arr) {
-          returnObj = {
-            ...returnObj,
-            ...val
-          }
-        }
-
-        return returnObj
-      }),
-      shareReplay(1),
-    )
-  }
-}
-
-@Pipe({
-  name: 'mouseOverTextPipe',
-})
-
-export class MouseOverTextPipe implements PipeTransform {
-
-  private transformOnHoverSegmentPipe: TransformOnhoverSegmentPipe
-  constructor(private sanitizer: DomSanitizer) {
-    this.transformOnHoverSegmentPipe = new TransformOnhoverSegmentPipe(this.sanitizer)
-  }
-
-  private renderText = ({ label, obj }): SafeHtml[] => {
-    switch (label) {
-    case 'landmark': {
-      const { dataset = [] } = obj
-      return [
-        this.sanitizer.sanitize(SecurityContext.HTML, obj.landmarkName),
-        ...(dataset.map(ds => this.sanitizer.bypassSecurityTrustHtml(`
-<span class="text-muted">
-  ${this.sanitizer.sanitize(SecurityContext.HTML, ds.name)}
-</span>
-`)))
-      ]
-    }
-    case 'segments':
-      return obj.map(({ segment }) => this.transformOnHoverSegmentPipe.transform(segment))
-    case 'userLandmark':
-      return [this.sanitizer.sanitize(SecurityContext.HTML, obj.name)]
-    default:
-      // ts-lint:disable-next-line
-      console.warn(`mouseOver.directive.ts#mouseOverTextPipe: Cannot be displayed: label: ${label}`)
-      return [this.sanitizer.bypassSecurityTrustHtml(`Cannot be displayed: label: ${label}`)]
-    }
-  }
-
-  public transform(inc: {segments: any, landmark: any, userLandmark: any}): Array<{label: string, text: SafeHtml[]}> {
-    const keys = Object.keys(inc)
-    return keys
-      // if is segments, filter out if lengtth === 0
-      .filter(key => Array.isArray(inc[key]) ? inc[key].length > 0 : true )
-      // for other properties, check if value is defined
-      .filter(key => !!inc[key])
-      .map(key => {
-        return {
-          label: key,
-          text: this.renderText({ label: key, obj: inc[key] })
-        }
-      })
-  }
-}
-
-@Pipe({
-  name: 'mouseOverIconPipe',
-})
-
-export class MouseOverIconPipe implements PipeTransform {
-
-  public transform(type: string): {fontSet: string, fontIcon: string} {
-
-    switch (type) {
-    case 'landmark':
-      return {
-        fontSet: 'fas',
-        fontIcon: 'fa-map-marker-alt',
-      }
-    case 'segments':
-      return {
-        fontSet: 'fas',
-        fontIcon: 'fa-brain',
-      }
-    case 'userLandmark':
-      return {
-        fontSet: 'fas',
-        fontIcon: 'fa-map-marker-alt',
-      }
-    default:
-      return {
-        fontSet: 'fas',
-        fontIcon: 'fa-file',
-      }
-    }
-  }
-}
diff --git a/src/atlasViewer/pluginUnit/index.ts b/src/atlasViewer/pluginUnit/index.ts
deleted file mode 100644
index cc1c5058b8b8133b2d2c1e8547b6c9c51404a752..0000000000000000000000000000000000000000
--- a/src/atlasViewer/pluginUnit/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { PluginServices, IPluginManifest } from './atlasViewer.pluginService.service'
\ No newline at end of file
diff --git a/src/atlasViewer/pluginUnit/plugin_styles.css b/src/atlasViewer/pluginUnit/plugin_styles.css
deleted file mode 100644
index dea00063b288c84bc44229f447abd358aaf82552..0000000000000000000000000000000000000000
--- a/src/atlasViewer/pluginUnit/plugin_styles.css
+++ /dev/null
@@ -1,69 +0,0 @@
-/* layout */
-
-[plugincontainer] .btn,
-[plugincontainer] .input-group-addon,
-[plugincontainer] input[type="text"],
-[plugincontainer] .panel
-{
-  border-radius:0px;
-  border:none;
-}
-
-[plugincontainer] .btn
-{
-  opacity : 0.9;
-  transition: opacity 0.3s ease, transform 0.3s ease;
-  box-shadow : rgba(5, 5, 5, 0.1) 0px 4px 6px 0px;
-}
-
-[plugincontainer] .btn:hover
-{
-  opacity:1.0;
-  transform:translateY(-5%);
-  box-shadow : rgba(5, 5, 5, 0.25) 0px 4px 6px 0px;
-}
-
-[plugincontainer] .form-control
-{
-  background:none;
-  border:none;
-}
-
-/* colour */
-[darktheme="true"] [plugincontainer] .btn,
-[darktheme="true"] [plugincontainer] input[type="text"],
-[darktheme="true"] [plugincontainer] input[type="number"],
-[darktheme="true"] [plugincontainer] .panel
-{
-  background-color:rgba(81,81,81,0.8);
-  color:rgba(255,255,255,0.8);
-}
-
-[darktheme="true"] [plugincontainer] .input-group-addon
-{
-  background-color:rgba(60,60,60,0.2);
-  color:rgba(255,255,255,0.8);
-  /* border-top:1px solid rgba(255,255,255,0.05);
-  border-left:1px solid rgba(255,255,255,0.05);
-  border-right:1px solid rgba(255,255,255,0.05); */
-}
-
-[darktheme="true"] [plugincontainer] hr
-{
-  border-color:rgba(100,100,100,0.5);
-}
-
-[darktheme="true"] [plugincontainer] .btn.btn-active
-{
-  background-color:rgba(65,65,65,0.8);
-  transform: translateY(2px);
-  color:rgba(255,255,255,1.0);
-  box-shadow: inset 0 2px 2px -2px rgba(0,0,0,0.2);
-}
-
-[darktheme="true"] .alert.alert-danger
-{
-  color: #f2dede;
-  background-color: rgba(169, 68, 66, 0.5);
-  border-color: rgba(169, 68, 66,0.2)
-}
diff --git a/src/auth/auth.directive.ts b/src/auth/auth.directive.ts
index 982a57b3d0a82945c38079b5bcd21dde0ff2cfc7..94d64d7e6da8f090014553537bca7ca040a48132 100644
--- a/src/auth/auth.directive.ts
+++ b/src/auth/auth.directive.ts
@@ -3,7 +3,7 @@ import { Observable } from "rxjs";
 import { IUser, AuthService } from './auth.service'
 
 @Directive({
-  selector: '[iav-auth-authState]',
+  selector: '[iav-auth-auth-state]',
   exportAs: 'iavAuthAuthState'
 })
 
diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts
index 12720ca923e6bd1399deeaecdd8475f5ef9c400e..fdec1e6ef5ec008b4d4bb01f8a3897ff4c482934 100644
--- a/src/auth/auth.service.ts
+++ b/src/auth/auth.service.ts
@@ -1,7 +1,7 @@
 import { HttpClient } from "@angular/common/http";
 import { Injectable, OnDestroy } from "@angular/core";
 import { Observable, of, Subscription } from "rxjs";
-import { catchError, shareReplay, mapTo } from "rxjs/operators";
+import { catchError, shareReplay } from "rxjs/operators";
 
 const IV_REDIRECT_TOKEN = `IV_REDIRECT_TOKEN`
 
diff --git a/src/glue.spec.ts b/src/glue.spec.ts
index aba6f15912e2050d8e2a25bc11d58216bd001934..02e5c00049375fd3c0100bfd0f2ca1f86d5ee944 100644
--- a/src/glue.spec.ts
+++ b/src/glue.spec.ts
@@ -14,7 +14,7 @@ import { EnumColorMapName } from "./util/colorMaps"
 import { ngViewerSelectorClearView } from "./services/state/ngViewerState/selectors"
 import { tap, ignoreElements } from "rxjs/operators"
 import { merge, of } from "rxjs"
-import { GET_KGDS_PREVIEW_INFO_FROM_ID_FILENAME } from "./ui/databrowserModule/pure"
+import { GET_KGDS_PREVIEW_INFO_FROM_ID_FILENAME } from "./atlasComponents/databrowserModule/pure"
 import { viewerStateSelectedTemplateSelector } from "./services/state/viewerState/selectors"
 import { generalActionError } from "./services/stateStore.helper"
 
diff --git a/src/glue.ts b/src/glue.ts
index 5d94c0c6a839b9b4c85042123044d6899cd501b3..f0d9430a1a4bf6bf90bad761b6ca7946aaf65fee 100644
--- a/src/glue.ts
+++ b/src/glue.ts
@@ -1,6 +1,6 @@
 import { uiActionSetPreviewingDatasetFiles, IDatasetPreviewData, uiStateShowBottomSheet, uiStatePreviewingDatasetFilesSelector } from "./services/state/uiState.store.helper"
 import { OnDestroy, Injectable, Optional, Inject, InjectionToken } from "@angular/core"
-import { PreviewComponentWrapper, DatasetPreview, determinePreviewFileType, EnumPreviewFileTypes, IKgDataEntry, getKgSchemaIdFromFullId, GET_KGDS_PREVIEW_INFO_FROM_ID_FILENAME } from "./ui/databrowserModule/pure"
+import { PreviewComponentWrapper, DatasetPreview, determinePreviewFileType, EnumPreviewFileTypes, IKgDataEntry, getKgSchemaIdFromFullId, GET_KGDS_PREVIEW_INFO_FROM_ID_FILENAME } from "./atlasComponents/databrowserModule/pure"
 import { Subscription, Observable, forkJoin, of, merge, combineLatest } from "rxjs"
 import { select, Store, ActionReducer, createAction, props, createSelector, Action } from "@ngrx/store"
 import { startWith, map, shareReplay, pairwise, debounceTime, distinctUntilChanged, tap, switchMap, withLatestFrom, mapTo, switchMapTo, filter, skip, catchError, bufferTime } from "rxjs/operators"
@@ -590,7 +590,6 @@ export class DatasetPreviewGlue implements IDatasetPreviewGlue, OnDestroy{
   }
 
   private openDatasetPreviewWidget(data: IDatasetPreviewData) {
-    console.log({ data })
     const { datasetId: kgId, filename } = data
 
     if (!!this.actionOnWidget) {
diff --git a/src/ui/config/currentLayout/currentLayout.component.ts b/src/layouts/currentLayout/currentLayout.component.ts
similarity index 100%
rename from src/ui/config/currentLayout/currentLayout.component.ts
rename to src/layouts/currentLayout/currentLayout.component.ts
diff --git a/src/ui/config/currentLayout/currentLayout.style.css b/src/layouts/currentLayout/currentLayout.style.css
similarity index 100%
rename from src/ui/config/currentLayout/currentLayout.style.css
rename to src/layouts/currentLayout/currentLayout.style.css
diff --git a/src/ui/config/currentLayout/currentLayout.template.html b/src/layouts/currentLayout/currentLayout.template.html
similarity index 100%
rename from src/ui/config/currentLayout/currentLayout.template.html
rename to src/layouts/currentLayout/currentLayout.template.html
diff --git a/src/layouts/fourCorners/fourCorners.component.ts b/src/layouts/fourCorners/fourCorners.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..181bb85285ed389cc4fd59f5bf34d527b52cbc65
--- /dev/null
+++ b/src/layouts/fourCorners/fourCorners.component.ts
@@ -0,0 +1,11 @@
+import { Component } from "@angular/core";
+
+@Component({
+  selector: 'iav-layout-fourcorners',
+  templateUrl: './fourCorners.template.html',
+  styleUrls: [
+    './fourCorners.style.css'
+  ]
+})
+
+export class FourCornersCmp{}
\ No newline at end of file
diff --git a/src/layouts/fourCorners/fourCorners.style.css b/src/layouts/fourCorners/fourCorners.style.css
new file mode 100644
index 0000000000000000000000000000000000000000..352b490b2acf42d4d92344bdc0be28d4f8cf80da
--- /dev/null
+++ b/src/layouts/fourCorners/fourCorners.style.css
@@ -0,0 +1,13 @@
+:host
+{
+  display: block;
+  width: 100%;
+  height: 100%;
+
+  position: relative;
+}
+
+.corner-container
+{
+  z-index: 5;
+}
\ No newline at end of file
diff --git a/src/layouts/fourCorners/fourCorners.template.html b/src/layouts/fourCorners/fourCorners.template.html
new file mode 100644
index 0000000000000000000000000000000000000000..c99f8b0a8bf791a3b6efc256bf8b86cf3594c9b4
--- /dev/null
+++ b/src/layouts/fourCorners/fourCorners.template.html
@@ -0,0 +1,16 @@
+<div class="position-absolute top-0 left-0 w-100 h-100">
+  <ng-content select="[iavLayoutFourCornersContent]"></ng-content>
+</div>
+
+<div class="corner-container position-absolute top-0 left-0">
+  <ng-content select="[iavLayoutFourCornersTopLeft]"></ng-content>  
+</div>
+<div class="corner-container position-absolute top-0 right-0">
+  <ng-content select="[iavLayoutFourCornersTopRight]"></ng-content>  
+</div>
+<div class="corner-container position-absolute bottom-0 left-0">
+  <ng-content select="[iavLayoutFourCornersBottomLeft]"></ng-content>  
+</div>
+<div class="corner-container position-absolute bottom-0 right-0">
+  <ng-content select="[iavLayoutFourCornersBottomRight]"></ng-content>  
+</div>
\ No newline at end of file
diff --git a/src/layouts/layout.module.ts b/src/layouts/layout.module.ts
index b10a09b6bb519316c56a22550bc445afc5c5875b..9ddb115a81f3f0588c5dec7933daecd2b53bbb08 100644
--- a/src/layouts/layout.module.ts
+++ b/src/layouts/layout.module.ts
@@ -2,7 +2,13 @@ import { NgModule } from "@angular/core";
 import { BrowserModule } from "@angular/platform-browser";
 import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
 import { ComponentsModule } from "../components/components.module";
+import { CurrentLayout } from "./currentLayout/currentLayout.component";
 import { FloatingLayoutContainer } from "./floating/floating.component";
+import { FourCornersCmp } from "./fourCorners/fourCorners.component";
+import { FourPanelLayout } from "./layouts/fourPanel/fourPanel.component";
+import { HorizontalOneThree } from "./layouts/h13/h13.component";
+import { SinglePanel } from "./layouts/single/single.component";
+import { VerticalOneThree } from "./layouts/v13/v13.component";
 import { LayoutsExample } from "./layoutsExample/layoutsExample.component";
 import { LayoutMainSide } from "./mainside/mainside.component";
 
@@ -15,14 +21,25 @@ import { LayoutMainSide } from "./mainside/mainside.component";
   declarations : [
     LayoutMainSide,
     FloatingLayoutContainer,
+    FourCornersCmp,
+    CurrentLayout,
 
+    FourPanelLayout,
+    HorizontalOneThree,
+    SinglePanel,
+    VerticalOneThree,
     LayoutsExample,
   ],
   exports : [
     BrowserAnimationsModule,
     LayoutMainSide,
     FloatingLayoutContainer,
-
+    FourCornersCmp,
+    CurrentLayout,
+    FourPanelLayout,
+    HorizontalOneThree,
+    SinglePanel,
+    VerticalOneThree,
     LayoutsExample,
   ],
 })
diff --git a/src/ui/config/layouts/fourPanel/fourPanel.component.ts b/src/layouts/layouts/fourPanel/fourPanel.component.ts
similarity index 100%
rename from src/ui/config/layouts/fourPanel/fourPanel.component.ts
rename to src/layouts/layouts/fourPanel/fourPanel.component.ts
diff --git a/src/ui/config/layouts/fourPanel/fourPanel.style.css b/src/layouts/layouts/fourPanel/fourPanel.style.css
similarity index 100%
rename from src/ui/config/layouts/fourPanel/fourPanel.style.css
rename to src/layouts/layouts/fourPanel/fourPanel.style.css
diff --git a/src/ui/config/layouts/fourPanel/fourPanel.template.html b/src/layouts/layouts/fourPanel/fourPanel.template.html
similarity index 100%
rename from src/ui/config/layouts/fourPanel/fourPanel.template.html
rename to src/layouts/layouts/fourPanel/fourPanel.template.html
diff --git a/src/ui/config/layouts/h13/h13.component.ts b/src/layouts/layouts/h13/h13.component.ts
similarity index 100%
rename from src/ui/config/layouts/h13/h13.component.ts
rename to src/layouts/layouts/h13/h13.component.ts
diff --git a/src/ui/config/layouts/h13/h13.style.css b/src/layouts/layouts/h13/h13.style.css
similarity index 100%
rename from src/ui/config/layouts/h13/h13.style.css
rename to src/layouts/layouts/h13/h13.style.css
diff --git a/src/ui/config/layouts/h13/h13.template.html b/src/layouts/layouts/h13/h13.template.html
similarity index 100%
rename from src/ui/config/layouts/h13/h13.template.html
rename to src/layouts/layouts/h13/h13.template.html
diff --git a/src/ui/config/layouts/single/single.component.ts b/src/layouts/layouts/single/single.component.ts
similarity index 100%
rename from src/ui/config/layouts/single/single.component.ts
rename to src/layouts/layouts/single/single.component.ts
diff --git a/src/ui/config/layouts/single/single.style.css b/src/layouts/layouts/single/single.style.css
similarity index 100%
rename from src/ui/config/layouts/single/single.style.css
rename to src/layouts/layouts/single/single.style.css
diff --git a/src/ui/config/layouts/single/single.template.html b/src/layouts/layouts/single/single.template.html
similarity index 100%
rename from src/ui/config/layouts/single/single.template.html
rename to src/layouts/layouts/single/single.template.html
diff --git a/src/ui/config/layouts/v13/v13.component.ts b/src/layouts/layouts/v13/v13.component.ts
similarity index 100%
rename from src/ui/config/layouts/v13/v13.component.ts
rename to src/layouts/layouts/v13/v13.component.ts
diff --git a/src/ui/config/layouts/v13/v13.style.css b/src/layouts/layouts/v13/v13.style.css
similarity index 100%
rename from src/ui/config/layouts/v13/v13.style.css
rename to src/layouts/layouts/v13/v13.style.css
diff --git a/src/ui/config/layouts/v13/v13.template.html b/src/layouts/layouts/v13/v13.template.html
similarity index 100%
rename from src/ui/config/layouts/v13/v13.template.html
rename to src/layouts/layouts/v13/v13.template.html
diff --git a/src/main.module.ts b/src/main.module.ts
index 11a705ee245213a857e933cd3c82dce5010beb9b..189e7a8a0e20a72f542fbcf9c436d6263f98ad63 100644
--- a/src/main.module.ts
+++ b/src/main.module.ts
@@ -1,6 +1,6 @@
 import { DragDropModule } from '@angular/cdk/drag-drop'
 import { CommonModule } from "@angular/common";
-import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from "@angular/core";
+import { NgModule } from "@angular/core";
 import { FormsModule } from "@angular/forms";
 import { StoreModule, ActionReducer } from "@ngrx/store";
 import { AngularMaterialModule } from 'src/ui/sharedModules/angularMaterial.module'
@@ -16,7 +16,7 @@ import { HttpClientModule } from "@angular/common/http";
 import { EffectsModule } from "@ngrx/effects";
 import { AtlasViewerAPIServices, CANCELLABLE_DIALOG, API_SERVICE_SET_VIEWER_HANDLE_TOKEN, setViewerHandleFactory, LOAD_MESH_TOKEN, ILoadMesh } from "./atlasViewer/atlasViewer.apiService.service";
 import { AtlasWorkerService } from "./atlasViewer/atlasViewer.workerService.service";
-import { TransformOnhoverSegmentPipe } from "./atlasViewer/onhoverSegment.pipe";
+
 import { ConfirmDialogComponent } from "./components/confirmDialog/confirmDialog.component";
 import { DialogComponent } from "./components/dialog/dialog.component";
 import { DialogService } from "./services/dialogService.service";
@@ -25,8 +25,8 @@ import { LocalFileService } from "./services/localFile.service";
 import { NgViewerUseEffect } from "./services/state/ngViewerState.store";
 import { ViewerStateUseEffect } from "./services/state/viewerState.store";
 import { UIService } from "./services/uiService.service";
-import { DatabrowserModule, OVERRIDE_IAV_DATASET_PREVIEW_DATASET_FN, DataBrowserFeatureStore, GET_KGDS_PREVIEW_INFO_FROM_ID_FILENAME, DatabrowserService } from "src/ui/databrowserModule";
-import { ViewerStateControllerUseEffect } from "./ui/viewerStateController/viewerState.useEffect";
+import { DatabrowserModule, OVERRIDE_IAV_DATASET_PREVIEW_DATASET_FN, DataBrowserFeatureStore, GET_KGDS_PREVIEW_INFO_FROM_ID_FILENAME, DatabrowserService } from "src/atlasComponents/databrowserModule";
+import { ViewerStateControllerUseEffect } from "src/state";
 import { DockedContainerDirective } from "./util/directives/dockedContainer.directive";
 import { DragDropDirective } from "./util/directives/dragDrop.directive";
 import { FloatingContainerDirective } from "./util/directives/floatingContainer.directive";
@@ -35,18 +35,16 @@ import { NewViewerDisctinctViewToLayer } from "./util/pipes/newViewerDistinctVie
 import { ClickInterceptor, CLICK_INTERCEPTOR_INJECTOR, UtilModule } from "src/util";
 import { SpotLightModule } from 'src/spotlight/spot-light.module'
 import { TryMeComponent } from "./ui/tryme/tryme.component";
-import { MouseHoverDirective, MouseOverIconPipe, MouseOverTextPipe } from "./atlasViewer/mouseOver.directive";
 import { UiStateUseEffect } from "src/services/state/uiState.store";
 import { AtlasViewerHistoryUseEffect } from "./atlasViewer/atlasViewer.history.service";
 import { PluginServiceUseEffect } from './services/effect/pluginUseEffect';
 import { TemplateCoordinatesTransformation } from "src/services/templateCoordinatesTransformation.service";
 import { NewTemplateUseEffect } from './services/effect/newTemplate.effect';
 import { WidgetModule } from 'src/widget';
-import { PluginModule } from './atlasViewer/pluginUnit/plugin.module';
+import { PluginModule } from './plugin/plugin.module';
 import { LoggingModule } from './logging/logging.module';
-import { ShareModule } from './share';
 import { AuthService } from './auth'
-import { IAV_DATASET_PREVIEW_ACTIVE } from 'src/ui/databrowserModule'
+import { IAV_DATASET_PREVIEW_ACTIVE } from 'src/atlasComponents/databrowserModule'
 
 import 'hammerjs'
 import 'src/res/css/extra_styles.css'
@@ -54,9 +52,14 @@ import 'src/res/css/version.css'
 import 'src/theme.scss'
 import { DatasetPreviewGlue, datasetPreviewMetaReducer, IDatasetPreviewGlue, GlueEffects, ClickInterceptorService } from './glue';
 import { viewerStateHelperReducer, viewerStateMetaReducers, ViewerStateHelperEffect } from './services/state/viewerState.store.helper';
-import { TOS_OBS_INJECTION_TOKEN } from './ui/kgtos/kgtos.component';
+import { TOS_OBS_INJECTION_TOKEN } from './ui/kgtos';
 import { UiEffects } from './services/state/uiState/ui.effects';
 import { MesssagingModule } from './messaging/module';
+import { ParcellationRegionModule } from './atlasComponents/parcellationRegion';
+import { ViewerModule } from './viewerModule';
+import { CookieModule } from './ui/cookieAgreement/module';
+import { KgTosModule } from './ui/kgtos/module';
+import { MouseoverModule } from './mouseoverModule/mouseover.module';
 
 export function debug(reducer: ActionReducer<any>): ActionReducer<any> {
   return function(state, action) {
@@ -82,10 +85,13 @@ export function debug(reducer: ActionReducer<any>): ActionReducer<any> {
     WidgetModule,
     PluginModule,
     LoggingModule,
-    ShareModule,
     MesssagingModule,
-
+    ViewerModule,
     SpotLightModule,
+    ParcellationRegionModule,
+    CookieModule,
+    KgTosModule,
+    MouseoverModule,
     
     EffectsModule.forRoot([
       UseEffects,
@@ -127,15 +133,11 @@ export function debug(reducer: ActionReducer<any>): ActionReducer<any> {
     FloatingContainerDirective,
     FloatingMouseContextualContainerDirective,
     DragDropDirective,
-    MouseHoverDirective, 
 
     /* pipes */
     GetNamesPipe,
     GetNamePipe,
-    TransformOnhoverSegmentPipe,
     NewViewerDisctinctViewToLayer,
-    MouseOverTextPipe,
-    MouseOverIconPipe,
   ],
   entryComponents : [
     DialogComponent,
@@ -246,9 +248,6 @@ export function debug(reducer: ActionReducer<any>): ActionReducer<any> {
   bootstrap : [
     AtlasViewer,
   ],
-  schemas: [
-    CUSTOM_ELEMENTS_SCHEMA,
-  ],
 })
 
 export class MainModule {
diff --git a/src/mouseoverModule/index.ts b/src/mouseoverModule/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6e9cd09486d0a2da56b1f28f86dce2cc6382d78d
--- /dev/null
+++ b/src/mouseoverModule/index.ts
@@ -0,0 +1,5 @@
+export { MouseOverIconPipe } from './mouseOverIcon.pipe'
+export { MouseOverTextPipe } from './mouseOverText.pipe'
+export { MouseHoverDirective } from './mouseover.directive'
+export { MouseoverModule } from './mouseover.module'
+export { TransformOnhoverSegmentPipe } from './transformOnhoverSegment.pipe'
\ No newline at end of file
diff --git a/src/mouseoverModule/mouseOverIcon.pipe.ts b/src/mouseoverModule/mouseOverIcon.pipe.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ba5f7686798d9417eb365580a84f16955cdf53d7
--- /dev/null
+++ b/src/mouseoverModule/mouseOverIcon.pipe.ts
@@ -0,0 +1,34 @@
+import { Pipe, PipeTransform } from "@angular/core"
+
+@Pipe({
+  name: 'mouseOverIconPipe',
+})
+
+export class MouseOverIconPipe implements PipeTransform {
+
+  public transform(type: string): {fontSet: string, fontIcon: string} {
+
+    switch (type) {
+    case 'landmark':
+      return {
+        fontSet: 'fas',
+        fontIcon: 'fa-map-marker-alt',
+      }
+    case 'segments':
+      return {
+        fontSet: 'fas',
+        fontIcon: 'fa-brain',
+      }
+    case 'userLandmark':
+      return {
+        fontSet: 'fas',
+        fontIcon: 'fa-map-marker-alt',
+      }
+    default:
+      return {
+        fontSet: 'fas',
+        fontIcon: 'fa-file',
+      }
+    }
+  }
+}
diff --git a/src/mouseoverModule/mouseOverText.pipe.ts b/src/mouseoverModule/mouseOverText.pipe.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5ba11425c0e78eb8dee14e9a25ba02a0ed0f9adf
--- /dev/null
+++ b/src/mouseoverModule/mouseOverText.pipe.ts
@@ -0,0 +1,54 @@
+import { Pipe, PipeTransform, SecurityContext } from "@angular/core"
+import { DomSanitizer, SafeHtml } from "@angular/platform-browser"
+import { TransformOnhoverSegmentPipe } from "./transformOnhoverSegment.pipe"
+
+@Pipe({
+  name: 'mouseOverTextPipe',
+})
+
+export class MouseOverTextPipe implements PipeTransform {
+
+  private transformOnHoverSegmentPipe: TransformOnhoverSegmentPipe
+  constructor(private sanitizer: DomSanitizer) {
+    this.transformOnHoverSegmentPipe = new TransformOnhoverSegmentPipe(this.sanitizer)
+  }
+
+  private renderText = ({ label, obj }): SafeHtml[] => {
+    switch (label) {
+    case 'landmark': {
+      const { dataset = [] } = obj
+      return [
+        this.sanitizer.sanitize(SecurityContext.HTML, obj.landmarkName),
+        ...(dataset.map(ds => this.sanitizer.bypassSecurityTrustHtml(`
+<span class="text-muted">
+  ${this.sanitizer.sanitize(SecurityContext.HTML, ds.name)}
+</span>
+`)))
+      ]
+    }
+    case 'segments':
+      return obj.map(({ segment }) => this.transformOnHoverSegmentPipe.transform(segment))
+    case 'userLandmark':
+      return [this.sanitizer.sanitize(SecurityContext.HTML, obj.name)]
+    default:
+      // ts-lint:disable-next-line
+      console.warn(`mouseOver.directive.ts#mouseOverTextPipe: Cannot be displayed: label: ${label}`)
+      return [this.sanitizer.bypassSecurityTrustHtml(`Cannot be displayed: label: ${label}`)]
+    }
+  }
+
+  public transform(inc: {segments: any, landmark: any, userLandmark: any}): Array<{label: string, text: SafeHtml[]}> {
+    const keys = Object.keys(inc)
+    return keys
+      // if is segments, filter out if lengtth === 0
+      .filter(key => Array.isArray(inc[key]) ? inc[key].length > 0 : true )
+      // for other properties, check if value is defined
+      .filter(key => !!inc[key])
+      .map(key => {
+        return {
+          label: key,
+          text: this.renderText({ label: key, obj: inc[key] })
+        }
+      })
+  }
+}
diff --git a/src/mouseoverModule/mouseover.directive.ts b/src/mouseoverModule/mouseover.directive.ts
new file mode 100644
index 0000000000000000000000000000000000000000..25f33743ce536d91150185cfab6c2e52e3764c8e
--- /dev/null
+++ b/src/mouseoverModule/mouseover.directive.ts
@@ -0,0 +1,127 @@
+import { Directive } from "@angular/core"
+import { select, Store } from "@ngrx/store"
+import { merge, Observable } from "rxjs"
+import { distinctUntilChanged, filter, map, scan, shareReplay, startWith, withLatestFrom } from "rxjs/operators"
+import { LoggingService } from "src/logging"
+import { uiStateMouseOverSegmentsSelector, uiStateMouseoverUserLandmark } from "src/services/state/uiState/selectors"
+import { viewerStateSelectedParcellationSelector } from "src/services/state/viewerState/selectors"
+import { deserialiseParcRegionId } from "common/util"
+import { temporalPositveScanFn } from "./util"
+
+@Directive({
+  selector: '[iav-mouse-hover]',
+  exportAs: 'iavMouseHover',
+})
+
+export class MouseHoverDirective {
+
+  public onHoverObs$: Observable<{segments: any, landmark: any, userLandmark: any}>
+  public currentOnHoverObs$: Observable<{segments: any, landmark: any, userLandmark: any}>
+
+  constructor(
+    private store$: Store<any>,
+    private log: LoggingService,
+  ) {
+
+    // TODO consider moving these into a single obs serviced by a DI service
+    // can potentially net better performance
+
+    const onHoverUserLandmark$ = this.store$.pipe(
+      select(uiStateMouseoverUserLandmark)
+    )
+
+    const onHoverLandmark$ = this.store$.pipe(
+      select('uiState'),
+      select('mouseOverLandmark'),
+    ).pipe(
+      map(landmark => {
+        if (landmark === null) { return landmark }
+        const idx = Number(landmark.replace('label=', ''))
+        if (isNaN(idx)) {
+          this.log.warn(`Landmark index could not be parsed as a number: ${landmark}`)
+          return {
+            landmarkName: idx,
+          }
+        } 
+      }),
+    )
+
+    const onHoverSegments$ = this.store$.pipe(
+      select(uiStateMouseOverSegmentsSelector),
+      filter(v => !!v),
+      withLatestFrom(
+        this.store$.pipe(
+          select(viewerStateSelectedParcellationSelector),
+          startWith(null),
+        ),
+      ),
+      map(([ arr, parcellationSelected ]) => parcellationSelected && parcellationSelected.auxillaryMeshIndices
+        ? arr.filter(({ segment }) => {
+          // if segment is not a string (i.e., not labelIndexId) return true
+          if (typeof segment !== 'string') { return true }
+          const { labelIndex } = deserialiseParcRegionId(segment)
+          return parcellationSelected.auxillaryMeshIndices.indexOf(labelIndex) < 0
+        })
+        : arr),
+      distinctUntilChanged((o, n) => o.length === n.length
+        && n.every(segment =>
+          o.find(oSegment => oSegment.layer.name === segment.layer.name
+            && oSegment.segment === segment.segment))),
+    )
+
+    const mergeObs = merge(
+      onHoverSegments$.pipe(
+        distinctUntilChanged(),
+        map(segments => {
+          return { segments }
+        }),
+      ),
+      onHoverLandmark$.pipe(
+        distinctUntilChanged(),
+        map(landmark => {
+          return { landmark }
+        }),
+      ),
+      onHoverUserLandmark$.pipe(
+        distinctUntilChanged(),
+        map(userLandmark => {
+          return { userLandmark }
+        }),
+      ),
+    ).pipe(
+      shareReplay(1),
+    )
+
+    this.onHoverObs$ = mergeObs.pipe(
+      scan((acc, curr) => {
+        return {
+          ...acc,
+          ...curr,
+        }
+      }, { segments: null, landmark: null, userLandmark: null }),
+      shareReplay(1),
+    )
+
+    this.currentOnHoverObs$ = mergeObs.pipe(
+      scan(temporalPositveScanFn, []),
+      map(arr => {
+
+        let returnObj = {
+          segments: null,
+          landmark: null,
+          userLandmark: null,
+        }
+
+        for (const val of arr) {
+          returnObj = {
+            ...returnObj,
+            ...val
+          }
+        }
+
+        return returnObj
+      }),
+      shareReplay(1),
+    )
+  }
+}
diff --git a/src/mouseoverModule/mouseover.module.ts b/src/mouseoverModule/mouseover.module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..476fc900a2a6a3731b5bae0d7f6a2f60d836dd8a
--- /dev/null
+++ b/src/mouseoverModule/mouseover.module.ts
@@ -0,0 +1,26 @@
+import { CommonModule } from "@angular/common";
+import { NgModule } from "@angular/core";
+import { TransformOnhoverSegmentPipe } from "src/atlasViewer/onhoverSegment.pipe";
+import { MouseHoverDirective } from "./mouseover.directive";
+import { MouseOverIconPipe } from "./mouseOverIcon.pipe";
+import { MouseOverTextPipe } from "./mouseOverText.pipe";
+
+@NgModule({
+  imports: [
+    CommonModule,
+  ],
+  declarations: [
+    MouseHoverDirective,
+    MouseOverTextPipe,
+    TransformOnhoverSegmentPipe,
+    MouseOverIconPipe,
+  ],
+  exports: [
+    MouseHoverDirective,
+    MouseOverTextPipe,
+    TransformOnhoverSegmentPipe,
+    MouseOverIconPipe,
+  ]
+})
+
+export class MouseoverModule{}
\ No newline at end of file
diff --git a/src/mouseoverModule/transformOnhoverSegment.pipe.ts b/src/mouseoverModule/transformOnhoverSegment.pipe.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5199a582a1ba2e5084d7097996652a492211a342
--- /dev/null
+++ b/src/mouseoverModule/transformOnhoverSegment.pipe.ts
@@ -0,0 +1,29 @@
+import { Pipe, PipeTransform, SecurityContext } from "@angular/core";
+import { DomSanitizer, SafeHtml } from "@angular/platform-browser";
+
+@Pipe({
+  name: 'transformOnhoverSegment',
+})
+
+export class TransformOnhoverSegmentPipe implements PipeTransform {
+  constructor(private sanitizer: DomSanitizer) {
+
+  }
+
+  private sanitizeHtml(inc: string): SafeHtml {
+    return this.sanitizer.sanitize(SecurityContext.HTML, inc)
+  }
+
+  private getStatus(text: string) {
+    return ` <span class="text-muted">(${this.sanitizeHtml(text)})</span>`
+  }
+
+  public transform(segment: any | number): SafeHtml {
+    return this.sanitizer.bypassSecurityTrustHtml((
+      ( this.sanitizeHtml(segment.name) || segment) +
+      (segment.status
+        ? this.getStatus(segment.status)
+        : '')
+    ))
+  }
+}
diff --git a/src/atlasViewer/mouseOver.directive.spec.ts b/src/mouseoverModule/util.spec..ts
similarity index 94%
rename from src/atlasViewer/mouseOver.directive.spec.ts
rename to src/mouseoverModule/util.spec..ts
index 613d78ee825f93026770c06378d28e1b9464de9c..07453e0343eb31d5e6b1279b3a249a19b5301c2c 100644
--- a/src/atlasViewer/mouseOver.directive.spec.ts
+++ b/src/mouseoverModule/util.spec..ts
@@ -1,7 +1,7 @@
 import {} from 'jasmine'
 import { forkJoin, Subject } from 'rxjs';
 import { scan, skip, take } from 'rxjs/operators';
-import { temporalPositveScanFn } from './mouseOver.directive'
+import { temporalPositveScanFn } from './util'
 
 const segmentsPositive = { segments: [{ hello: 'world' }] } as {segments: any}
 const segmentsNegative = { segments: [] }
@@ -42,12 +42,12 @@ describe('temporalPositveScanFn', () => {
       take(1),
     )
 
-    forkJoin(
+    forkJoin([
       testFirstEv,
       testSecondEv,
       testThirdEv,
       testFourthEv,
-    ).pipe(
+    ]).pipe(
       take(1),
     ).subscribe(([ arr1, arr2, arr3, arr4 ]) => {
       expect(arr1).toEqual([ segmentsPositive ])
diff --git a/src/mouseoverModule/util.ts b/src/mouseoverModule/util.ts
new file mode 100644
index 0000000000000000000000000000000000000000..519202f8878440faf249ad3da41b163e5c66fd4b
--- /dev/null
+++ b/src/mouseoverModule/util.ts
@@ -0,0 +1,26 @@
+
+/**
+ * Scan function which prepends newest positive (i.e. defined) value
+ *
+ * e.g. const source = new Subject()
+ * source.pipe(
+ *  scan(temporalPositveScanFn, [])
+ * ).subscribe(this.log.log) // outputs
+ *
+ *
+ *
+ */
+export const temporalPositveScanFn = (acc: Array<{segments: any, landmark: any, userLandmark: any}>, curr: {segments: any, landmark: any, userLandmark: any}) => {
+
+  const keys = Object.keys(curr)
+
+  // empty array is truthy
+  const isPositive = keys.some(key => Array.isArray(curr[key])
+    ? curr[key].length > 0
+    : !!curr[key]
+  )
+
+  return isPositive
+    ? [curr, ...(acc.filter(item => !keys.some(key => !!item[key])))] as Array<{segments?: any, landmark?: any, userLandmark?: any}>
+    : acc.filter(item => !keys.some(key => !!item[key]))
+}
\ No newline at end of file
diff --git a/src/atlasViewer/pluginUnit/atlasViewer.pluginService.service.spec.ts b/src/plugin/atlasViewer.pluginService.service.spec.ts
similarity index 98%
rename from src/atlasViewer/pluginUnit/atlasViewer.pluginService.service.spec.ts
rename to src/plugin/atlasViewer.pluginService.service.spec.ts
index 9020d72d286d667fe88f174f3d75b9981968f594..fe239f32b6d5121562cd4bd19cc53f1f7bf356f4 100644
--- a/src/atlasViewer/pluginUnit/atlasViewer.pluginService.service.spec.ts
+++ b/src/plugin/atlasViewer.pluginService.service.spec.ts
@@ -1,7 +1,7 @@
 import { CommonModule } from "@angular/common"
 import { HttpClientTestingModule, HttpTestingController } from "@angular/common/http/testing"
 import { NgModule } from "@angular/core"
-import { async, fakeAsync, flushMicrotasks, TestBed, tick } from "@angular/core/testing"
+import { async, fakeAsync, TestBed, tick } from "@angular/core/testing"
 import { MockStore, provideMockStore } from "@ngrx/store/testing"
 import { ComponentsModule } from "src/components"
 import { DialogService } from "src/services/dialogService.service"
@@ -10,7 +10,7 @@ import { AngularMaterialModule } from "src/ui/sharedModules/angularMaterial.modu
 import { APPEND_SCRIPT_TOKEN, REMOVE_SCRIPT_TOKEN } from "src/util/constants"
 import { WidgetModule, WidgetServices } from "src/widget"
 import { PluginServices } from "./atlasViewer.pluginService.service"
-import { PluginUnit } from "./pluginUnit.component"
+import { PluginUnit } from "./pluginUnit/pluginUnit.component"
 
 const MOCK_PLUGIN_MANIFEST = {
   name: 'fzj.xg.MOCK_PLUGIN_MANIFEST',
diff --git a/src/atlasViewer/pluginUnit/atlasViewer.pluginService.service.ts b/src/plugin/atlasViewer.pluginService.service.ts
similarity index 99%
rename from src/atlasViewer/pluginUnit/atlasViewer.pluginService.service.ts
rename to src/plugin/atlasViewer.pluginService.service.ts
index 8299f6cf59e61024c4f3dceb0898a63a46f301c6..52b100cb55d7c60e0a7b55eeb706d66329eab86f 100644
--- a/src/atlasViewer/pluginUnit/atlasViewer.pluginService.service.ts
+++ b/src/plugin/atlasViewer.pluginService.service.ts
@@ -1,7 +1,7 @@
 import { HttpClient } from '@angular/common/http'
 import { ComponentFactory, ComponentFactoryResolver, Injectable, ViewContainerRef, Inject, SecurityContext } from "@angular/core";
 import { PLUGINSTORE_ACTION_TYPES } from "src/services/state/pluginState.helper";
-import { PluginUnit } from "./pluginUnit.component";
+import { PluginUnit } from "./pluginUnit/pluginUnit.component";
 import { select, Store } from "@ngrx/store";
 import { BehaviorSubject, from, merge, Observable, of } from "rxjs";
 import { catchError, filter, map, mapTo, shareReplay, switchMap, switchMapTo, take, tap } from "rxjs/operators";
diff --git a/src/plugin/index.ts b/src/plugin/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bae5875b5d19c8b096188c6c8074e42a2ff14674
--- /dev/null
+++ b/src/plugin/index.ts
@@ -0,0 +1,9 @@
+export {
+  IPluginManifest,
+  PluginServices,
+  registerPluginFactoryDirectiveFactory,
+} from './atlasViewer.pluginService.service'
+
+export {
+  PluginModule
+} from './plugin.module'
\ No newline at end of file
diff --git a/src/atlasViewer/pluginUnit/plugin.module.ts b/src/plugin/plugin.module.ts
similarity index 54%
rename from src/atlasViewer/pluginUnit/plugin.module.ts
rename to src/plugin/plugin.module.ts
index 12763521faa0539bdf7eb38d7b275eba8263dcb7..5ba71ea0297eb761cc9a9fb71ecdeaaf6864ee3e 100644
--- a/src/atlasViewer/pluginUnit/plugin.module.ts
+++ b/src/plugin/plugin.module.ts
@@ -1,27 +1,36 @@
+import { CommonModule, DOCUMENT } from "@angular/common";
 import { NgModule } from "@angular/core";
-import { PluginUnit } from "./pluginUnit.component";
+import { LoggingModule } from "src/logging";
+import { AngularMaterialModule } from "src/ui/sharedModules/angularMaterial.module";
+import { UtilModule } from "src/util";
+import { appendScriptFactory, APPEND_SCRIPT_TOKEN, removeScriptFactory, REMOVE_SCRIPT_TOKEN } from "src/util/constants";
 import { PluginServices, registerPluginFactoryDirectiveFactory } from "./atlasViewer.pluginService.service";
+import { PluginBannerUI } from "./pluginBanner/pluginBanner.component";
+import { PluginCspCtrlCmp } from "./pluginCsp/pluginCsp.component";
 import { PluginFactoryDirective, REGISTER_PLUGIN_FACTORY_DIRECTIVE } from "./pluginFactory.directive";
-import { LoggingModule } from "src/logging";
-import { APPEND_SCRIPT_TOKEN, appendScriptFactory, REMOVE_SCRIPT_TOKEN, removeScriptFactory } from "src/util/constants";
-import { DOCUMENT } from "@angular/common";
+import { PluginUnit } from "./pluginUnit/pluginUnit.component";
 
 @NgModule({
-  imports:[
+  imports: [
+    CommonModule,
     LoggingModule,
+    UtilModule,
+    AngularMaterialModule,
   ],
   declarations: [
+    PluginCspCtrlCmp,
     PluginUnit,
-    PluginFactoryDirective
-  ],
-  entryComponents: [
-    PluginUnit
+    PluginFactoryDirective,
+    PluginBannerUI,
   ],
   exports: [
+    PluginCspCtrlCmp,
+    PluginBannerUI,
     PluginUnit,
-    PluginFactoryDirective
+    PluginFactoryDirective,
   ],
   providers: [
+
     PluginServices,
     {
       provide: REGISTER_PLUGIN_FACTORY_DIRECTIVE,
@@ -40,5 +49,4 @@ import { DOCUMENT } from "@angular/common";
     },
   ]
 })
-
 export class PluginModule{}
\ No newline at end of file
diff --git a/src/ui/pluginBanner/pluginBanner.component.ts b/src/plugin/pluginBanner/pluginBanner.component.ts
similarity index 90%
rename from src/ui/pluginBanner/pluginBanner.component.ts
rename to src/plugin/pluginBanner/pluginBanner.component.ts
index c154f1b666a4aa1ba19cd4568eef5d91394f1888..59de1360d44b7db00fc1f9e5567371debf03b650 100644
--- a/src/ui/pluginBanner/pluginBanner.component.ts
+++ b/src/plugin/pluginBanner/pluginBanner.component.ts
@@ -1,5 +1,5 @@
 import { Component, ViewChild, TemplateRef } from "@angular/core";
-import { IPluginManifest, PluginServices } from "src/atlasViewer/pluginUnit";
+import { IPluginManifest, PluginServices } from "../atlasViewer.pluginService.service";
 import { MatDialog } from "@angular/material/dialog";
 
 @Component({
diff --git a/src/ui/pluginBanner/pluginBanner.style.css b/src/plugin/pluginBanner/pluginBanner.style.css
similarity index 100%
rename from src/ui/pluginBanner/pluginBanner.style.css
rename to src/plugin/pluginBanner/pluginBanner.style.css
diff --git a/src/ui/pluginBanner/pluginBanner.template.html b/src/plugin/pluginBanner/pluginBanner.template.html
similarity index 100%
rename from src/ui/pluginBanner/pluginBanner.template.html
rename to src/plugin/pluginBanner/pluginBanner.template.html
diff --git a/src/ui/config/pluginCsp/pluginCsp.component.ts b/src/plugin/pluginCsp/pluginCsp.component.ts
similarity index 87%
rename from src/ui/config/pluginCsp/pluginCsp.component.ts
rename to src/plugin/pluginCsp/pluginCsp.component.ts
index 73a50c6b4dce3d579a52f110f01b6de31b833913..7ff3c8a1fcfcc7faa96237f9cbb9ad539104812c 100644
--- a/src/ui/config/pluginCsp/pluginCsp.component.ts
+++ b/src/plugin/pluginCsp/pluginCsp.component.ts
@@ -1,7 +1,7 @@
 import { Component } from "@angular/core";
 import { select, Store } from "@ngrx/store";
-import { map, tap } from "rxjs/operators";
-import { PluginServices } from "src/atlasViewer/pluginUnit";
+import { map } from "rxjs/operators";
+import { PluginServices } from "../atlasViewer.pluginService.service";
 import { selectorAllPluginsCspPermission } from "src/services/state/userConfigState.store";
 
 @Component({
diff --git a/src/ui/config/pluginCsp/pluginCsp.style.css b/src/plugin/pluginCsp/pluginCsp.style.css
similarity index 100%
rename from src/ui/config/pluginCsp/pluginCsp.style.css
rename to src/plugin/pluginCsp/pluginCsp.style.css
diff --git a/src/ui/config/pluginCsp/pluginCsp.template.html b/src/plugin/pluginCsp/pluginCsp.template.html
similarity index 100%
rename from src/ui/config/pluginCsp/pluginCsp.template.html
rename to src/plugin/pluginCsp/pluginCsp.template.html
diff --git a/src/atlasViewer/pluginUnit/pluginFactory.directive.spec.ts b/src/plugin/pluginFactory.directive.spec.ts
similarity index 100%
rename from src/atlasViewer/pluginUnit/pluginFactory.directive.spec.ts
rename to src/plugin/pluginFactory.directive.spec.ts
diff --git a/src/atlasViewer/pluginUnit/pluginFactory.directive.ts b/src/plugin/pluginFactory.directive.ts
similarity index 100%
rename from src/atlasViewer/pluginUnit/pluginFactory.directive.ts
rename to src/plugin/pluginFactory.directive.ts
diff --git a/src/atlasViewer/pluginUnit/pluginUnit.component.ts b/src/plugin/pluginUnit/pluginUnit.component.ts
similarity index 100%
rename from src/atlasViewer/pluginUnit/pluginUnit.component.ts
rename to src/plugin/pluginUnit/pluginUnit.component.ts
diff --git a/src/atlasViewer/pluginUnit/pluginUnit.template.html b/src/plugin/pluginUnit/pluginUnit.template.html
similarity index 100%
rename from src/atlasViewer/pluginUnit/pluginUnit.template.html
rename to src/plugin/pluginUnit/pluginUnit.template.html
diff --git a/src/res/css/extra_styles.css b/src/res/css/extra_styles.css
index 081fa25ea672331dbdb2509fcaf98e891028bbf8..88e4a8d10e17d410aa6dcce4fbd3a842cb437766 100644
--- a/src/res/css/extra_styles.css
+++ b/src/res/css/extra_styles.css
@@ -381,6 +381,11 @@ markdown-dom pre code
   height: 2rem!important;
 }
 
+.h-50vh
+{
+  height: 50vh!important;
+}
+
 .h-5em
 {
   height: 5em!important;
diff --git a/src/services/effect/effect.spec.ts b/src/services/effect/effect.spec.ts
index a414cb18e56ecaabce80113fb72a096f2819a4d6..7b58172fd1be56692d8c10c469ca22ba9aae54bd 100644
--- a/src/services/effect/effect.spec.ts
+++ b/src/services/effect/effect.spec.ts
@@ -1,5 +1,5 @@
 import {} from 'jasmine'
-import { getGetRegionFromLabelIndexId, UseEffects } from './effect'
+import { UseEffects } from './effect'
 import { TestBed } from '@angular/core/testing'
 import { Observable } from 'rxjs'
 import { SELECT_PARCELLATION, NEWVIEWER, SELECT_REGIONS } from '../state/viewerState.store'
@@ -8,27 +8,7 @@ import { hot } from 'jasmine-marbles'
 import { provideMockStore } from '@ngrx/store/testing'
 import { defaultRootState } from '../stateStore.service'
 
-const colinsJson = require('!json-loader!../../res/ext/colin.json')
-
-const COLIN_JULICHBRAIN_LAYER_NAME = `COLIN_V25_LEFT_NG_SPLIT_HEMISPHERE`
-const COLIN_V25_ID = 'minds/core/parcellationatlas/v1.0.0/94c1125b-b87e-45e4-901c-00daee7f2579-25'
-
 describe('effect.ts', () => {
-  describe('getGetRegionFromLabelIndexId', () => {
-    it('translateds hoc1 from labelIndex to region', () => {
-
-      const getRegionFromlabelIndexId = getGetRegionFromLabelIndexId({
-        parcellation: {
-          ...colinsJson.parcellations.find(p => p['@id'] === COLIN_V25_ID),
-          updated: true,
-        },
-      })
-      const fetchedRegion = getRegionFromlabelIndexId({ labelIndexId: `${COLIN_JULICHBRAIN_LAYER_NAME}#116` })
-      expect(fetchedRegion).toBeTruthy()
-      expect(fetchedRegion.fullId.kg.kgId).toEqual('c9753e82-80ca-4074-a704-9dd2c4c0d58b')
-      
-    })
-  })
 
   describe('UseEffects', () => {
     let actions$:Observable<any>
diff --git a/src/services/effect/effect.ts b/src/services/effect/effect.ts
index c206014533f352a8530b8b232b2b96141a05b8e8..965a48e2a9ff15af90efa9379252427e7b6aef0d 100644
--- a/src/services/effect/effect.ts
+++ b/src/services/effect/effect.ts
@@ -5,8 +5,10 @@ import { merge, Observable, Subscription, combineLatest } from "rxjs";
 import { filter, map, shareReplay, switchMap, take, withLatestFrom, mapTo, distinctUntilChanged } from "rxjs/operators";
 import { LoggingService } from "src/logging";
 import { ADD_TO_REGIONS_SELECTION_WITH_IDS, DESELECT_REGIONS, NEWVIEWER, SELECT_PARCELLATION, SELECT_REGIONS, SELECT_REGIONS_WITH_ID, SELECT_LANDMARKS } from "../state/viewerState.store";
-import { generateLabelIndexId, getNgIdLabelIndexFromId, IavRootStoreInterface, recursiveFindRegionWithLabelIndexId } from '../stateStore.service';
+import { IavRootStoreInterface, recursiveFindRegionWithLabelIndexId } from '../stateStore.service';
 import { viewerStateSelectAtlas, viewerStateSetSelectedRegionsWithIds, viewerStateToggleLayer } from "../state/viewerState.store.helper";
+import { deserialiseParcRegionId, serialiseParcellationRegion } from "common/util"
+import { getGetRegionFromLabelIndexId } from 'src/util/fn'
 
 @Injectable({
   providedIn: 'root',
@@ -85,7 +87,7 @@ export class UseEffects implements OnDestroy {
         return {
           type: SELECT_REGIONS,
           selectRegions: alreadySelectedRegions
-            .filter(({ ngId, labelIndex }) => !deselectSet.has(generateLabelIndexId({ ngId, labelIndex }))),
+            .filter(({ ngId, labelIndex }) => !deselectSet.has(serialiseParcellationRegion({ ngId, labelIndex }))),
         }
       }),
     )
@@ -143,10 +145,10 @@ export class UseEffects implements OnDestroy {
   private convertRegionIdsToRegion = ([selectRegionIds, parcellation]) => {
     const { ngId: defaultNgId } = parcellation
     return (selectRegionIds as any[])
-      .map(labelIndexId => getNgIdLabelIndexFromId({ labelIndexId }))
+      .map(labelIndexId => deserialiseParcRegionId(labelIndexId))
       .map(({ ngId, labelIndex }) => {
         return {
-          labelIndexId: generateLabelIndexId({
+          labelIndexId: serialiseParcellationRegion({
             ngId: ngId || defaultNgId,
             labelIndex,
           }),
@@ -246,13 +248,6 @@ export class UseEffects implements OnDestroy {
   )
 }
 
-export const getGetRegionFromLabelIndexId = ({ parcellation }) => {
-  const { ngId: defaultNgId, regions } = parcellation
-  // if (!updated) throw new Error(`parcellation not yet updated`)
-  return ({ labelIndexId }) =>
-    recursiveFindRegionWithLabelIndexId({ regions, labelIndexId, inheritedNgId: defaultNgId })
-}
-
 export const compareRegions: (r1: any, r2: any) => boolean = (r1, r2) => {
   if (!r1) { return !r2 }
   if (!r2) { return !r1 }
diff --git a/src/services/effect/pluginUseEffect.spec.ts b/src/services/effect/pluginUseEffect.spec.ts
index cda6dccb71cee8d819344a25946cd6c73369922c..693f8235226e9e2cca2514742404ff4b8d16a714 100644
--- a/src/services/effect/pluginUseEffect.spec.ts
+++ b/src/services/effect/pluginUseEffect.spec.ts
@@ -10,7 +10,7 @@ import { PLUGINSTORE_CONSTANTS } from '../state/pluginState.store'
 import { PLUGINSTORE_ACTION_TYPES } from '../state/pluginState.helper'
 import { Injectable } from "@angular/core";
 import { getRandomHex } from 'common/util'
-import { PluginServices } from "src/atlasViewer/pluginUnit";
+import { PluginServices } from "src/plugin";
 import { AngularMaterialModule } from "src/ui/sharedModules/angularMaterial.module";
 import { hot } from "jasmine-marbles";
 
diff --git a/src/services/effect/pluginUseEffect.ts b/src/services/effect/pluginUseEffect.ts
index c6d0048d72f60925a8eead672b93a3419e215930..098d2fd6c02ead4545ff47aa1dcda9825150656c 100644
--- a/src/services/effect/pluginUseEffect.ts
+++ b/src/services/effect/pluginUseEffect.ts
@@ -4,7 +4,7 @@ import { select, Store } from "@ngrx/store"
 import { Observable, forkJoin } from "rxjs"
 import { filter, map, startWith, switchMap } from "rxjs/operators"
 import { AtlasViewerConstantsServices } from "src/atlasViewer/atlasViewer.constantService.service"
-import { PluginServices } from "src/atlasViewer/pluginUnit"
+import { PluginServices } from "src/plugin/atlasViewer.pluginService.service"
 import { PLUGINSTORE_CONSTANTS } from 'src/services/state/pluginState.store'
 import { PLUGINSTORE_ACTION_TYPES } from 'src/services/state/pluginState.helper'
 import { IavRootStoreInterface } from "../stateStore.service"
diff --git a/src/services/localFile.service.ts b/src/services/localFile.service.ts
index d4386edeca620ea7fc2ded16cd54623a265b6c97..045ac686b54f7b65e2985f7d75c2bce85ce705c6 100644
--- a/src/services/localFile.service.ts
+++ b/src/services/localFile.service.ts
@@ -1,6 +1,5 @@
 import { Injectable } from "@angular/core";
 import { Store } from "@ngrx/store";
-import { KgSingleDatasetService } from "src/ui/databrowserModule/kgSingleDatasetService.service";
 import { SNACKBAR_MESSAGE } from "./state/uiState.store";
 import { IavRootStoreInterface } from "./stateStore.service";
 import { DATASETS_ACTIONS_TYPES } from "./state/dataStore.store";
@@ -19,12 +18,11 @@ export class LocalFileService {
 
   constructor(
     private store: Store<IavRootStoreInterface>,
-    private singleDsService: KgSingleDatasetService,
   ) {
 
   }
 
-  private niiUrl
+  private niiUrl: string
 
   public handleFileDrop(files: File[]) {
     try {
diff --git a/src/services/state/ngViewerState.store.helper.ts b/src/services/state/ngViewerState.store.helper.ts
index 2d0ca1500648a3654e7108cc7a22588055ac50ba..6f23c74d1c306a3b74e824fb69c7adc0743d0cc8 100644
--- a/src/services/state/ngViewerState.store.helper.ts
+++ b/src/services/state/ngViewerState.store.helper.ts
@@ -1,9 +1,7 @@
 // TODO to be merged with ng viewer state after refactor
-import { INgLayerInterface, PANELS } from './ngViewerState/constants'
+export { INgLayerInterface, PANELS } from './ngViewerState/constants'
 
-export { INgLayerInterface, PANELS }
-
-import {
+export {
   ngViewerActionAddNgLayer,
   ngViewerActionRemoveNgLayer,
   ngViewerActionSetPerspOctantRemoval,
@@ -14,29 +12,11 @@ import {
 } from './ngViewerState/actions'
 
 export {
-  ngViewerActionAddNgLayer,
-  ngViewerActionRemoveNgLayer,
-  ngViewerActionSetPerspOctantRemoval,
-  ngViewerActionToggleMax,
-  ngViewerActionClearView,
-  ngViewerActionSetPanelOrder,
-  ngViewerActionForceShowSegment,
-}
-
-import {
   ngViewerSelectorClearView,
   ngViewerSelectorClearViewEntries,
   ngViewerSelectorNehubaReady,
   ngViewerSelectorOctantRemoval,
   ngViewerSelectorPanelMode,
   ngViewerSelectorPanelOrder,
+  ngViewerSelectorLayers,
 } from './ngViewerState/selectors'
-
-export {
-  ngViewerSelectorClearView,
-  ngViewerSelectorClearViewEntries,
-  ngViewerSelectorNehubaReady,
-  ngViewerSelectorOctantRemoval,
-  ngViewerSelectorPanelMode,
-  ngViewerSelectorPanelOrder,
-}
\ No newline at end of file
diff --git a/src/services/state/ngViewerState.store.ts b/src/services/state/ngViewerState.store.ts
index bc3b7fb8ce0abfcf2c3c1799a9fccf28238b71e3..1cbec3990ee43f0900b36201154cfd178b5e76a6 100644
--- a/src/services/state/ngViewerState.store.ts
+++ b/src/services/state/ngViewerState.store.ts
@@ -2,8 +2,7 @@ import { Injectable, OnDestroy } from '@angular/core';
 import { Observable, combineLatest, fromEvent, Subscription, from, of } from 'rxjs';
 import { Effect, Actions, ofType } from '@ngrx/effects';
 import { withLatestFrom, map, distinctUntilChanged, scan, shareReplay, filter, mapTo, debounceTime, catchError, skip, throttleTime } from 'rxjs/operators';
-import { SNACKBAR_MESSAGE } from './uiState.store';
-import { getNgIds, IavRootStoreInterface, GENERAL_ACTION_TYPES } from '../stateStore.service';
+import { getNgIds } from 'src/util/fn';
 import { Action, select, Store, createReducer, on } from '@ngrx/store'
 import { BACKENDURL, CYCLE_PANEL_MESSAGE } from 'src/util/constants';
 import { HttpClient } from '@angular/common/http';
@@ -13,6 +12,7 @@ import { PANELS } from './ngViewerState.store.helper'
 import { ngViewerActionToggleMax, ngViewerActionClearView, ngViewerActionSetPanelOrder, ngViewerActionSwitchPanelMode, ngViewerActionForceShowSegment, ngViewerActionNehubaReady } from './ngViewerState/actions';
 import { generalApplyState } from '../stateStore.helper';
 import { ngViewerSelectorPanelMode, ngViewerSelectorPanelOrder } from './ngViewerState/selectors';
+import { uiActionSnackbarMessage } from './uiState/actions';
 
 export function mixNgLayers(oldLayers: INgLayerInterface[], newLayers: INgLayerInterface|INgLayerInterface[]): INgLayerInterface[] {
   if (newLayers instanceof Array) {
@@ -181,7 +181,7 @@ export class NgViewerUseEffect implements OnDestroy {
 
   constructor(
     private actions: Actions,
-    private store$: Store<IavRootStoreInterface>,
+    private store$: Store<any>,
     private pureConstantService: PureContantService,
     private http: HttpClient,
   ){
@@ -215,16 +215,14 @@ export class NgViewerUseEffect implements OnDestroy {
       withLatestFrom(this.store$),
       map(([{ngViewerState: fetchedNgViewerState}, state]) => {
         const { ngViewerState } = state
-        return {
-          type: GENERAL_ACTION_TYPES.APPLY_STATE,
+        return generalApplyState({
           state: {
             ...state,
             ngViewerState: {
               ...ngViewerState,
               ...fetchedNgViewerState
-            }
-          }
-        }
+            }}
+        })
       })
     )
 
@@ -335,10 +333,9 @@ export class NgViewerUseEffect implements OnDestroy {
       filter(([_, useMobileUI]) => !useMobileUI),
       map(([toggleMaximiseMode, _]) => toggleMaximiseMode),
       filter(({ payload }) => payload.panelMode && payload.panelMode === PANELS.SINGLE_PANEL),
-      mapTo({
-        type: SNACKBAR_MESSAGE,
-        snackbarMessage: CYCLE_PANEL_MESSAGE,
-      }),
+      mapTo(uiActionSnackbarMessage({
+        snackbarMessage: CYCLE_PANEL_MESSAGE
+      })),
     )
 
     this.spacebarListener$ = fromEvent(document.body, 'keydown', { capture: true }).pipe(
diff --git a/src/services/state/ngViewerState/selectors.ts b/src/services/state/ngViewerState/selectors.ts
index db84dcdb944e8e9f3d07b80a8d02464a492d4c3b..7222296d4627a32cf20716d05e2ea9e81d898e2e 100644
--- a/src/services/state/ngViewerState/selectors.ts
+++ b/src/services/state/ngViewerState/selectors.ts
@@ -35,3 +35,8 @@ export const ngViewerSelectorNehubaReady = createSelector(
   state => state['ngViewerState'],
   ngViewerState => ngViewerState.nehubaReady
 )
+
+export const ngViewerSelectorLayers = createSelector(
+  state => state['ngViewerState'],
+  ngViewerState => ngViewerState?.layers || []
+)
\ No newline at end of file
diff --git a/src/services/state/pluginState.store.ts b/src/services/state/pluginState.store.ts
index ac8ee486240d8bedce71d2b11d0218ec73b8cf5b..e71b49dc076b66bd375dbaddd2ede233d6e90fce 100644
--- a/src/services/state/pluginState.store.ts
+++ b/src/services/state/pluginState.store.ts
@@ -1,5 +1,5 @@
 import { Action } from '@ngrx/store'
-import { GENERAL_ACTION_TYPES } from '../stateStore.service'
+import { generalApplyState } from '../stateStore.helper'
 import { PLUGINSTORE_ACTION_TYPES } from './pluginState.helper'
 export const defaultState: StateInterface = {
   initManifests: []
@@ -41,7 +41,7 @@ export const getStateStore = ({ state = defaultState } = {}) => (prevState: Stat
       initManifests: newManifests,
     }
   }
-  case GENERAL_ACTION_TYPES.APPLY_STATE: {
+  case generalApplyState.type: {
     const { pluginState } = (action as any).state
     return pluginState
   }
diff --git a/src/services/state/uiState.store.helper.ts b/src/services/state/uiState.store.helper.ts
index 94e404cb5359acaf491e7b321e60a57d1a77e0a6..0c0070f8d074b5ee25ded0830a9b48e9380bf84a 100644
--- a/src/services/state/uiState.store.helper.ts
+++ b/src/services/state/uiState.store.helper.ts
@@ -1,6 +1,6 @@
 // TODO merge with uiState.store.ts after refactor completes
 
-import {
+export {
   uiActionSetPreviewingDatasetFiles,
   uiActionShowSidePanelConnectivity,
   uiStateCloseSidePanel,
@@ -10,34 +10,16 @@ import {
   uiStateShowBottomSheet,
   uiActionHideDatasetWithId,
   uiActionShowDatasetWtihId,
+  uiActionSnackbarMessage,
 } from './uiState/actions'
 
 export {
-  uiActionSetPreviewingDatasetFiles,
-  uiActionShowSidePanelConnectivity,
-  uiStateCloseSidePanel,
-  uiStateCollapseSidePanel,
-  uiStateExpandSidePanel,
-  uiStateOpenSidePanel,
-  uiStateShowBottomSheet,
-  uiActionHideDatasetWithId,
-  uiActionShowDatasetWtihId,
-}
-
-import {
   uiStatePreviewingDatasetFilesSelector,
   uiStateMouseOverSegmentsSelector,
   uiStateMouseoverUserLandmark,
   uiStateShownDatasetIdSelector,
 } from './uiState/selectors'
 
-export {
-  uiStatePreviewingDatasetFilesSelector,
-  uiStateMouseOverSegmentsSelector,
-  uiStateMouseoverUserLandmark,
-  uiStateShownDatasetIdSelector,
-}
-
 export enum EnumWidgetTypes{
   DATASET_PREVIEW,
 }
diff --git a/src/services/state/uiState.store.ts b/src/services/state/uiState.store.ts
index 5769426bfa2f5124e278d46fcdfbcc67af528650..a31d256de9126b42201220596aa7985cad63caab 100644
--- a/src/services/state/uiState.store.ts
+++ b/src/services/state/uiState.store.ts
@@ -10,7 +10,7 @@ import { MatBottomSheetRef, MatBottomSheet } from '@angular/material/bottom-shee
 import { uiStateCloseSidePanel, uiStateOpenSidePanel, uiStateCollapseSidePanel, uiStateExpandSidePanel, uiActionSetPreviewingDatasetFiles, uiStateShowBottomSheet, uiActionShowSidePanelConnectivity } from './uiState.store.helper';
 import { viewerStateMouseOverCustomLandmark } from './viewerState/actions';
 import { IUiState } from './uiState/common'
-import { uiActionHideAllDatasets, uiActionHideDatasetWithId, uiActionShowDatasetWtihId } from './uiState/actions';
+import { uiActionHideAllDatasets, uiActionHideDatasetWithId, uiActionShowDatasetWtihId, uiActionSnackbarMessage } from './uiState/actions';
 export const defaultState: IUiState = {
   shownDatasetId: [],
 
@@ -92,6 +92,7 @@ export const getStateStore = ({ state = defaultState } = {}) => (prevState: IUiS
       ...prevState,
       mouseOverLandmark : action.landmark,
     }
+  case uiActionSnackbarMessage.type:
   case SNACKBAR_MESSAGE: {
     const { snackbarMessage } = action
     /**
@@ -270,5 +271,5 @@ export const AGREE_COOKIE = `AGREE_COOKIE`
 export const AGREE_KG_TOS = `AGREE_KG_TOS`
 export const SHOW_KG_TOS = `SHOW_KG_TOS`
 
-export const SNACKBAR_MESSAGE = `SNACKBAR_MESSAGE`
+export const SNACKBAR_MESSAGE = uiActionSnackbarMessage.type
 export const SHOW_BOTTOM_SHEET = `SHOW_BOTTOM_SHEET`
diff --git a/src/services/state/uiState/actions.ts b/src/services/state/uiState/actions.ts
index bfd0548766e1ce870b3747b155805657826316dc..961511e110429f46b0a5e850b06b720c44e47a9d 100644
--- a/src/services/state/uiState/actions.ts
+++ b/src/services/state/uiState/actions.ts
@@ -46,3 +46,8 @@ export const uiActionHideDatasetWithId = createAction(
 export const uiActionHideAllDatasets = createAction(
   `[uiState] hideAllDatasets`
 )
+
+export const uiActionSnackbarMessage = createAction(
+  `[uiState] snackbarMessage`,
+  props<{snackbarMessage: string}>()
+)
\ No newline at end of file
diff --git a/src/services/state/viewerState.store.ts b/src/services/state/viewerState.store.ts
index 25adedb5c6eb7fecba4215550f1376b9379c4d72..543350c50da30bb7cf5c2f0d33a303c3d3322cd3 100644
--- a/src/services/state/viewerState.store.ts
+++ b/src/services/state/viewerState.store.ts
@@ -7,13 +7,12 @@ import { IUserLandmark } from 'src/atlasViewer/atlasViewer.apiService.service';
 import { INgLayerInterface } from 'src/atlasViewer/atlasViewer.component';
 import { getViewer } from 'src/util/fn';
 import { LoggingService } from 'src/logging';
-import { generateLabelIndexId, IavRootStoreInterface } from '../stateStore.service';
+import { IavRootStoreInterface } from '../stateStore.service';
 import { GENERAL_ACTION_TYPES } from '../stateStore.service'
 import { CLOSE_SIDE_PANEL } from './uiState.store';
 import { 
   viewerStateSetSelectedRegions,
   viewerStateSetConnectivityRegion,
-  viewerStateSelectAtlas,
   viewerStateSelectParcellation,
   viewerStateSelectRegionWithIdDeprecated,
   viewerStateCustomLandmarkSelector,
@@ -24,8 +23,9 @@ import {
   viewerStateMouseOverCustomLandmarkInPerspectiveView,
   viewerStateNewViewer
 } from './viewerState.store.helper';
-import { cvtNehubaConfigToNavigationObj } from 'src/ui/viewerStateController/viewerState.useEffect';
+import { cvtNehubaConfigToNavigationObj } from 'src/state';
 import { viewerStateChangeNavigation } from './viewerState/actions';
+import { serialiseParcellationRegion } from "common/util"
 
 export interface StateInterface {
   fetchedTemplates: any[]
@@ -378,8 +378,8 @@ export class ViewerStateUseEffect {
         startWith([]),
       )),
       map(([{ segments }, regionsSelected]) => {
-        const selectedSet = new Set(regionsSelected.map(generateLabelIndexId))
-        const toggleArr = segments.map(({ segment, layer }) => generateLabelIndexId({ ngId: layer.name, ...segment }))
+        const selectedSet = new Set(regionsSelected.map(serialiseParcellationRegion))
+        const toggleArr = segments.map(({ segment, layer }) => serialiseParcellationRegion({ ngId: layer.name, ...segment }))
 
         const deleteFlag = toggleArr.some(id => selectedSet.has(id))
 
diff --git a/src/services/stateStore.service.ts b/src/services/stateStore.service.ts
index 209c3a2a9fab036f695cda969de68b7514bdacaf..fab546d7876dee4ec5a2d06c7285753715ba0381 100644
--- a/src/services/stateStore.service.ts
+++ b/src/services/stateStore.service.ts
@@ -1,9 +1,5 @@
 import { filter } from 'rxjs/operators';
-export {
-  serialiseParcellationRegion as generateLabelIndexId,
-  deserialiseParcRegionId as getNgIdLabelIndexFromId,
 
-} from 'common/util'
 export {
   recursiveFindRegionWithLabelIndexId
 } from 'src/util/fn'
@@ -71,12 +67,6 @@ export function safeFilter(key: string) {
     typeof state[key] !== 'undefined' && state[key] !== null)
 }
 
-export function getNgIdLabelIndexFromRegion({ region }) {
-  const { ngId, labelIndex } = region
-  if (ngId && labelIndex) { return { ngId, labelIndex } }
-  throw new Error(`ngId: ${ngId} or labelIndex: ${labelIndex} not defined`)
-}
-
 export function getMultiNgIdsRegionsLabelIndexMap(parcellation: any = {}, inheritAttrsOpt: any = { ngId: 'root' }): Map<string, Map<number, any>> {
   const map: Map<string, Map<number, any>> = new Map()
   
@@ -167,7 +157,7 @@ export interface IavRootStoreInterface {
   userConfigState: UserConfigStateInterface
 }
 
-import { DATASTORE_DEFAULT_STATE } from 'src/ui/databrowserModule'
+import { DATASTORE_DEFAULT_STATE } from 'src/atlasComponents/databrowserModule'
 
 export const defaultRootState: any = {
   pluginState: pluginDefaultState,
diff --git a/src/spotlight/sl-service.service.ts b/src/spotlight/sl-service.service.ts
index c045ebfdbeb4ef5f2e5f1c682bf814cd7718dda1..241fe068cb335726119d8532d31d3a06ff6351f1 100644
--- a/src/spotlight/sl-service.service.ts
+++ b/src/spotlight/sl-service.service.ts
@@ -21,6 +21,9 @@ export class SlServiceService implements OnDestroy{
     this.cf = cfr.resolveComponentFactory(SpotlightBackdropComponent)
   }
 
+  /**
+   * TODO use angular cdk overlay
+   */
   public showBackdrop(tmp?: TemplateRef<any>){
     this.hideBackdrop()
 
diff --git a/src/ui/viewerStateController/viewerState.useEffect.spec.ts b/src/state/effects/viewerState.useEffect.spec.ts
similarity index 99%
rename from src/ui/viewerStateController/viewerState.useEffect.spec.ts
rename to src/state/effects/viewerState.useEffect.spec.ts
index b38a7db90370f82ebe1c53b4811cefb053e0555a..1a82e4220584adcf038f32b8f47049bbdd9f7313 100644
--- a/src/ui/viewerStateController/viewerState.useEffect.spec.ts
+++ b/src/state/effects/viewerState.useEffect.spec.ts
@@ -7,10 +7,10 @@ import { defaultRootState, generalActionError } from 'src/services/stateStore.se
 import { Injectable } from '@angular/core'
 import { TemplateCoordinatesTransformation, ITemplateCoordXformResp } from 'src/services/templateCoordinatesTransformation.service'
 import { hot } from 'jasmine-marbles'
-import { AngularMaterialModule } from '../sharedModules/angularMaterial.module'
+import { AngularMaterialModule } from 'src/ui/sharedModules/angularMaterial.module'
 import { HttpClientModule } from '@angular/common/http'
 import { WidgetModule } from 'src/widget'
-import { PluginModule } from 'src/atlasViewer/pluginUnit/plugin.module'
+import { PluginModule } from 'src/plugin'
 import { viewerStateFetchedTemplatesSelector, viewerStateNavigateToRegion, viewerStateNavigationStateSelector, viewerStateNewViewer, viewerStateSelectAtlas, viewerStateSelectTemplateWithName } from 'src/services/state/viewerState.store.helper'
 import { viewerStateFetchedAtlasesSelector } from 'src/services/state/viewerState/selectors'
 import { CONST } from 'common/constants'
diff --git a/src/ui/viewerStateController/viewerState.useEffect.ts b/src/state/effects/viewerState.useEffect.ts
similarity index 94%
rename from src/ui/viewerStateController/viewerState.useEffect.ts
rename to src/state/effects/viewerState.useEffect.ts
index 18eef3feafbaebc9d4bdf05b60447a6619ce870c..a56794c215c671f56b71abbecd05b55f3226d826 100644
--- a/src/ui/viewerStateController/viewerState.useEffect.ts
+++ b/src/state/effects/viewerState.useEffect.ts
@@ -3,8 +3,7 @@ import { Actions, Effect, ofType } from "@ngrx/effects";
 import { Action, select, Store } from "@ngrx/store";
 import { Observable, Subscription, of, merge } from "rxjs";
 import { distinctUntilChanged, filter, map, shareReplay, withLatestFrom, switchMap, mapTo, startWith } from "rxjs/operators";
-import { CHANGE_NAVIGATION, FETCHED_TEMPLATE, IavRootStoreInterface, SELECT_PARCELLATION, SELECT_REGIONS, generalActionError } from "src/services/stateStore.service";
-import { VIEWERSTATE_CONTROLLER_ACTION_TYPES } from "./viewerState.base";
+import { FETCHED_TEMPLATE, IavRootStoreInterface, SELECT_PARCELLATION, SELECT_REGIONS, generalActionError } from "src/services/stateStore.service";
 import { TemplateCoordinatesTransformation } from "src/services/templateCoordinatesTransformation.service";
 import { CLEAR_STANDALONE_VOLUMES } from "src/services/state/viewerState.store";
 import { viewerStateToggleRegionSelect, viewerStateHelperSelectParcellationWithId, viewerStateSelectTemplateWithId, viewerStateNavigateToRegion, viewerStateSelectedTemplateSelector, viewerStateFetchedTemplatesSelector, viewerStateNewViewer, viewerStateSelectedParcellationSelector, viewerStateNavigationStateSelector, viewerStateSelectTemplateWithName, viewerStateSelectedRegionsSelector, viewerStateSelectAtlas } from "src/services/state/viewerState.store.helper";
@@ -15,6 +14,7 @@ import { verifyPositionArg } from 'common/util'
 import { CONST } from 'common/constants'
 import { uiActionHideAllDatasets } from "src/services/state/uiState/actions";
 import { viewerStateFetchedAtlasesSelector } from "src/services/state/viewerState/selectors";
+import { viewerStateChangeNavigation } from "src/services/state/viewerState/actions";
 
 const defaultPerspectiveZoom = 1e6
 const defaultZoom = 1e6
@@ -385,22 +385,6 @@ export class ViewerStateControllerUseEffect implements OnDestroy {
         map(({ payload }) => payload['@id'])
       ),
 
-      /**
-       * deprecated method...
-       * finding id from name
-       */
-      this.actions$.pipe(
-        ofType(VIEWERSTATE_CONTROLLER_ACTION_TYPES.SELECT_PARCELLATION_WITH_NAME),
-        withLatestFrom(viewerState$.pipe(
-          select('templateSelected')
-        )),
-        map(([ action, templateSelected ]) => {
-          const parcellationName = (action as any).payload.name
-          const foundParcellation = templateSelected.parcellations.find(p => p.name === parcellationName)
-          return foundParcellation && foundParcellation['@id']
-        }),
-        filter(v => !!v)
-      )
     ).pipe(
       withLatestFrom(viewerState$.pipe(
         select('templateSelected'),
@@ -444,13 +428,12 @@ export class ViewerStateControllerUseEffect implements OnDestroy {
           })
         }
 
-        return {
-          type: CHANGE_NAVIGATION,
+        return viewerStateChangeNavigation({
           navigation: {
             position,
             animation: {},
-          },
-        }
+          }
+        })
       }),
     )
 
diff --git a/src/state/index.ts b/src/state/index.ts
index d5efade12f4641c39c4a808d81c7eb7e531ba31b..755a484148037e78de1a8536176c408ddc46b81b 100644
--- a/src/state/index.ts
+++ b/src/state/index.ts
@@ -1 +1,6 @@
-export { StateModule } from './state.module'
+export { StateModule } from "./state.module"
+export {
+  ViewerStateControllerUseEffect,
+  cvtNavigationObjToNehubaConfig,
+  cvtNehubaConfigToNavigationObj,
+} from "./effects/viewerState.useEffect"
\ No newline at end of file
diff --git a/src/state/stateAggregator.directive.ts b/src/state/stateAggregator.directive.ts
index c9fd436c3b8ee3370b4df72acee3174c18769fae..fdf9bd9b4dce4ddbb4aaf3334305b06f1c2de0fa 100644
--- a/src/state/stateAggregator.directive.ts
+++ b/src/state/stateAggregator.directive.ts
@@ -2,7 +2,6 @@ import { Directive } from "@angular/core";
 import { Store } from "@ngrx/store";
 import { Observable } from "rxjs";
 import { map, debounceTime, shareReplay } from "rxjs/operators";
-import { IavRootStoreInterface } from "src/services/stateStore.service";
 import { cvtStateToSearchParam } from "src/atlasViewer/atlasViewer.urlUtil";
 
 const jsonVersion = '0.0.1'
@@ -21,7 +20,7 @@ export class StateAggregator{
 
   public jsonifiedSstate$: Observable<IJsonifiedState>
   constructor(
-    private store$: Store<IavRootStoreInterface>
+    private store$: Store<any>
   ){
     this.jsonifiedSstate$ = this.store$.pipe(
       debounceTime(100),
diff --git a/src/ui/btnShadow.style.css b/src/ui/btnShadow.style.css
deleted file mode 100644
index 3d4bb9c2dd3ef38fcaa74e5deb5406132ffbde03..0000000000000000000000000000000000000000
--- a/src/ui/btnShadow.style.css
+++ /dev/null
@@ -1,23 +0,0 @@
-.btnWrapper
-{
-  display:flex;
-  align-items: center;
-  justify-content: center;
-}
-
-
-.btnWrapper > .btn
-{
-  width: 2.5em;
-  height: 2.5em;
-
-  display: flex;
-  align-items: center;
-  justify-content: center;
-}
-
-.btnWrapper.btnWrapper-lg > .btn
-{
-  width: 5rem;
-  height: 5rem;
-}
\ No newline at end of file
diff --git a/src/ui/config/config.component.ts b/src/ui/config/configCmp/config.component.ts
similarity index 98%
rename from src/ui/config/config.component.ts
rename to src/ui/config/configCmp/config.component.ts
index 4127b3bf990e732f1fccd4d94b69a5a0306d18f2..15f92277c707e22aeeb25cb64dec3e562f907030 100644
--- a/src/ui/config/config.component.ts
+++ b/src/ui/config/configCmp/config.component.ts
@@ -6,7 +6,7 @@ import { SUPPORTED_PANEL_MODES } from 'src/services/state/ngViewerState.store';
 import { ngViewerActionSetPanelOrder } from 'src/services/state/ngViewerState.store.helper';
 import { VIEWER_CONFIG_ACTION_TYPES, StateInterface as ViewerConfiguration } from 'src/services/state/viewerConfig.store'
 import { IavRootStoreInterface } from 'src/services/stateStore.service';
-import { isIdentityQuat } from '../nehubaContainer/util';
+import { isIdentityQuat } from 'src/viewerModule/nehuba/util';
 import {MatSlideToggleChange} from "@angular/material/slide-toggle";
 import {MatSliderChange} from "@angular/material/slider";
 import { PureContantService } from 'src/util';
diff --git a/src/ui/config/config.style.css b/src/ui/config/configCmp/config.style.css
similarity index 100%
rename from src/ui/config/config.style.css
rename to src/ui/config/configCmp/config.style.css
diff --git a/src/ui/config/config.template.html b/src/ui/config/configCmp/config.template.html
similarity index 100%
rename from src/ui/config/config.template.html
rename to src/ui/config/configCmp/config.template.html
diff --git a/src/ui/helpOnePager/helpOnePager.style.css b/src/ui/config/index.ts
similarity index 100%
rename from src/ui/helpOnePager/helpOnePager.style.css
rename to src/ui/config/index.ts
diff --git a/src/ui/config/module.ts b/src/ui/config/module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..34ed41cb182f81d22a42905f06a6ceddddf462f0
--- /dev/null
+++ b/src/ui/config/module.ts
@@ -0,0 +1,22 @@
+import { CommonModule } from "@angular/common";
+import { NgModule } from "@angular/core";
+import { LayoutModule } from "src/layouts/layout.module";
+import { PluginModule } from "src/plugin";
+import { AngularMaterialModule } from "../sharedModules/angularMaterial.module";
+import { ConfigComponent } from "./configCmp/config.component";
+
+@NgModule({
+  imports: [
+    CommonModule,
+    AngularMaterialModule,
+    PluginModule,
+    LayoutModule,
+  ],
+  declarations: [
+    ConfigComponent,
+  ],
+  exports: [
+    ConfigComponent,
+  ]
+})
+export class ConfigModule{}
\ No newline at end of file
diff --git a/src/ui/cookieAgreement/cookieAgreement.component.ts b/src/ui/cookieAgreement/cookieAgreement/cookieAgreement.component.ts
similarity index 81%
rename from src/ui/cookieAgreement/cookieAgreement.component.ts
rename to src/ui/cookieAgreement/cookieAgreement/cookieAgreement.component.ts
index 55f114b49121f2f7bc8c7e8d879a672346eaf4f8..fe1643a45e2a5152199d7aea5211695183b44310 100644
--- a/src/ui/cookieAgreement/cookieAgreement.component.ts
+++ b/src/ui/cookieAgreement/cookieAgreement/cookieAgreement.component.ts
@@ -1,7 +1,7 @@
 import { ChangeDetectionStrategy, Component } from '@angular/core'
-import info from '!!raw-loader!./data/info.md'
-import readmore from '!!raw-loader!./data/readmore.md'
-import matomoInfo from '!!raw-loader!./data/aboutMatomo.md'
+import info from '!!raw-loader!../data/info.md'
+import readmore from '!!raw-loader!../data/readmore.md'
+import matomoInfo from '!!raw-loader!../data/aboutMatomo.md'
 
 @Component({
   selector: 'cookie-agreement',
diff --git a/src/ui/cookieAgreement/cookieAgreement.style.css b/src/ui/cookieAgreement/cookieAgreement/cookieAgreement.style.css
similarity index 100%
rename from src/ui/cookieAgreement/cookieAgreement.style.css
rename to src/ui/cookieAgreement/cookieAgreement/cookieAgreement.style.css
diff --git a/src/ui/cookieAgreement/cookieAgreement.template.html b/src/ui/cookieAgreement/cookieAgreement/cookieAgreement.template.html
similarity index 100%
rename from src/ui/cookieAgreement/cookieAgreement.template.html
rename to src/ui/cookieAgreement/cookieAgreement/cookieAgreement.template.html
diff --git a/src/ui/kgtos/kgtos.style.css b/src/ui/cookieAgreement/index.ts
similarity index 100%
rename from src/ui/kgtos/kgtos.style.css
rename to src/ui/cookieAgreement/index.ts
diff --git a/src/ui/cookieAgreement/module.ts b/src/ui/cookieAgreement/module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8ee42e1697f8f932fc6545c8a010bbe5c5cda853
--- /dev/null
+++ b/src/ui/cookieAgreement/module.ts
@@ -0,0 +1,23 @@
+import { CommonModule } from "@angular/common";
+import { NgModule } from "@angular/core";
+import { ComponentsModule } from "src/components";
+import { UtilModule } from "src/util";
+import { AngularMaterialModule } from "../sharedModules/angularMaterial.module";
+import { CookieAgreement } from "./cookieAgreement/cookieAgreement.component";
+
+@NgModule({
+  imports: [
+    CommonModule,
+    AngularMaterialModule,
+    UtilModule,
+    ComponentsModule,
+  ],
+  declarations: [
+    CookieAgreement,
+  ],
+  exports: [
+    CookieAgreement
+  ]
+})
+
+export class CookieModule{}
\ No newline at end of file
diff --git a/src/ui/help/help.component.ts b/src/ui/help/about/about.component.ts
similarity index 89%
rename from src/ui/help/help.component.ts
rename to src/ui/help/about/about.component.ts
index af6c46dff917b60fcf74c86fcb89a5d62eb6de54..f3e35041d0b2dc7a32a98b32438805e0d029d1ff 100644
--- a/src/ui/help/help.component.ts
+++ b/src/ui/help/about/about.component.ts
@@ -3,14 +3,14 @@ import { DomSanitizer } from '@angular/platform-browser';
 import { AtlasViewerConstantsServices } from 'src/atlasViewer/atlasViewer.constantService.service';
 
 @Component({
-  selector: 'help-component',
-  templateUrl: './help.template.html',
+  selector: 'iav-about',
+  templateUrl: './about.template.html',
   styleUrls: [
-    './help.style.css',
+    './about.style.css',
   ],
 })
 
-export class HelpComponent {
+export class AboutCmp {
 
   public generalHelp = this.constantService.showHelpGeneralMap
   public sliceviewHelp = this.constantService.showHelpSliceViewMap
diff --git a/src/ui/help/help.style.css b/src/ui/help/about/about.style.css
similarity index 100%
rename from src/ui/help/help.style.css
rename to src/ui/help/about/about.style.css
diff --git a/src/ui/help/help.template.html b/src/ui/help/about/about.template.html
similarity index 100%
rename from src/ui/help/help.template.html
rename to src/ui/help/about/about.template.html
diff --git a/src/ui/helpOnePager/helpOnePager.component.spec.ts b/src/ui/help/helpOnePager/helpOnePager.component.spec.ts
similarity index 100%
rename from src/ui/helpOnePager/helpOnePager.component.spec.ts
rename to src/ui/help/helpOnePager/helpOnePager.component.spec.ts
diff --git a/src/ui/helpOnePager/helpOnePager.component.ts b/src/ui/help/helpOnePager/helpOnePager.component.ts
similarity index 100%
rename from src/ui/helpOnePager/helpOnePager.component.ts
rename to src/ui/help/helpOnePager/helpOnePager.component.ts
diff --git a/src/ui/nehubaContainer/maximisePanelButton/maximisePanelButton.style.css b/src/ui/help/helpOnePager/helpOnePager.style.css
similarity index 100%
rename from src/ui/nehubaContainer/maximisePanelButton/maximisePanelButton.style.css
rename to src/ui/help/helpOnePager/helpOnePager.style.css
diff --git a/src/ui/helpOnePager/helpOnePager.template.html b/src/ui/help/helpOnePager/helpOnePager.template.html
similarity index 100%
rename from src/ui/helpOnePager/helpOnePager.template.html
rename to src/ui/help/helpOnePager/helpOnePager.template.html
diff --git a/src/ui/templateParcellationCitations/templateParcellationCitations.style.css b/src/ui/help/index.ts
similarity index 100%
rename from src/ui/templateParcellationCitations/templateParcellationCitations.style.css
rename to src/ui/help/index.ts
diff --git a/src/ui/help/module.ts b/src/ui/help/module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4a34ab43a3cf9efa449eb2edcd2150921a53e744
--- /dev/null
+++ b/src/ui/help/module.ts
@@ -0,0 +1,26 @@
+import { CommonModule } from "@angular/common";
+import { NgModule } from "@angular/core";
+import { ComponentsModule } from "src/components";
+import { UtilModule } from "src/util";
+import { AngularMaterialModule } from "../sharedModules/angularMaterial.module";
+import { AboutCmp } from './about/about.component'
+import { HelpOnePager } from "./helpOnePager/helpOnePager.component";
+
+@NgModule({
+  imports: [
+    CommonModule,
+    AngularMaterialModule,
+    ComponentsModule,
+    UtilModule,
+  ],
+  declarations: [
+    AboutCmp,
+    HelpOnePager,
+  ],
+  exports: [
+    AboutCmp,
+    HelpOnePager,
+  ]
+})
+
+export class HelpModule{}
\ No newline at end of file
diff --git a/src/ui/kgEntryViewer/kgentry.component.ts b/src/ui/kgEntryViewer/kgentry.component.ts
deleted file mode 100644
index fada06ab098aafc41acc8f27848455897c1258e0..0000000000000000000000000000000000000000
--- a/src/ui/kgEntryViewer/kgentry.component.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { Component, Input } from "@angular/core";
-import { IDataEntry } from "src/services/stateStore.service";
-
-@Component({
-  selector : 'kg-entry-viewer',
-  templateUrl : './kgentry.template.html',
-  styleUrls : [
-    './kgentry.style.css',
-  ],
-})
-
-export class KgEntryViewer {
-  @Input() public dataset: IDataEntry
-
-  public kgData: any = null
-  public kgError: any = null
-
-  get tableColClass1() {
-    return `col-xs-4 col-lg-4 tableEntry`
-  }
-
-  get tableColClass2() {
-    return `col-xs-8 col-lg-8 tableEntry`
-  }
-
-  public isArray(v) {
-    return v.constructor === Array
-  }
-}
diff --git a/src/ui/kgEntryViewer/kgentry.style.css b/src/ui/kgEntryViewer/kgentry.style.css
deleted file mode 100644
index 4ac3fc6f4bd8f118c0339fff562389ee4d18239c..0000000000000000000000000000000000000000
--- a/src/ui/kgEntryViewer/kgentry.style.css
+++ /dev/null
@@ -1,34 +0,0 @@
-div[heading],
-div[body]
-{
-  padding: 0.5rem;
-}
-
-div[heading]
-{
-  background-color:rgba(128,128,128,0.1);
-}
-
-div[body]
-{
-  font-size: 90%;
-  max-height:20em;
-  overflow-y:auto;
-  overflow-x:hidden;
-}
-
-div[container]
-{
-  overflow:hidden;
-}
-
-a[link]
-{
-  display: inline-block;
-  margin-top: 1rem;
-}
-
-a[link]:hover
-{
-  text-decoration: none;
-}
\ No newline at end of file
diff --git a/src/ui/kgEntryViewer/kgentry.template.html b/src/ui/kgEntryViewer/kgentry.template.html
deleted file mode 100644
index cb309ebd9a5bc6fc307968557c3e7357ef8b0faf..0000000000000000000000000000000000000000
--- a/src/ui/kgEntryViewer/kgentry.template.html
+++ /dev/null
@@ -1,84 +0,0 @@
-<div *ngIf="dataset" container>
-
-  <!-- description -->
-  <readmore-component>
-    {{ dataset.description }}
-  </readmore-component>
-
-  <!-- other data -->
-
-  <panel-component *ngIf = "false"  [collapseBody] = "true" [bodyCollapsable] = "true">
-    <div heading>
-      Contributor(s)
-    </div>
-    <div body>
-      <!-- TODO maybe object instead of array -->
-      <div *ngFor = "let contributor of dataset.contributors">
-        {{ contributor.value }}
-      </div>
-    </div>
-  </panel-component>
-
-  <panel-component [collapseBody] = "true" [bodyCollapsable] = "true">
-    <div heading>
-      Custodian(s)
-    </div>
-    <div body>
-      <!-- TODO Maybe array -->
-      <div *ngFor="let custodian of dataset.custodians">
-        {{ custodian }}
-      </div>
-    </div>
-  </panel-component>
-
-  <panel-component *ngIf = "dataset.publications" [collapseBody] = "true" [bodyCollapsable] = "true">
-    <div heading>
-      Related Publication(s)
-    </div>
-    <div body>
-      <div *ngFor="let publication of dataset.publications">
-        <a target="_blank" link [href]="'https://doi.org/' + publication.doi">
-          {{ publication.cite }}
-          <i class = "fas fa-new-window"></i>
-        </a>
-      </div>
-    </div>
-  </panel-component>
-
-  <panel-component *ngIf = "dataset.licenseInfo || dataset.license" [collapseBody] = "true" [bodyCollapsable] = "true">
-    <div heading>
-      License
-    </div>
-    <div body>
-      <div *ngFor="let l of dataset.license">
-        {{ l }}
-      </div>
-      <div *ngFor="let l of dataset.licenseInfo">
-        {{ l }}
-      </div>
-    </div>
-  </panel-component>
-
-  <panel-component *ngIf = "dataset.files" [collapseBody] = "true" [bodyCollapsable] = "true">
-    <div heading>
-      Files
-    </div>
-    <div body>
-      <div *ngFor="let file of dataset.files">
-        <a link target="_blank" [href]="file.absolutePath">
-          {{ file.name }}
-          <i class="fas fa-download-alt"></i>
-        </a>
-      </div>
-    </div>
-  </panel-component>
-
-  <a
-    *ngFor="let ref of dataset.kgReference"
-    [href]="'https://doi.org/' + ref"
-    target="_blank">
-    Open in Knowledge Graph
-    <i class = "fas fa-new-window"></i>
-  </a>
-
-</div>
\ No newline at end of file
diff --git a/src/ui/kgEntryViewer/subjectViewer/subjectViewer.component.ts b/src/ui/kgEntryViewer/subjectViewer/subjectViewer.component.ts
deleted file mode 100644
index 6b0a80cd18cd8dfa92517a54125e5fde870d6a2d..0000000000000000000000000000000000000000
--- a/src/ui/kgEntryViewer/subjectViewer/subjectViewer.component.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import { ChangeDetectionStrategy, Component, Input } from "@angular/core";
-
-@Component({
-  selector : 'kg-entry-viewer-subject-viewer',
-  templateUrl : './subjectViewer.template.html',
-  styleUrls : ['./subjectViewer.style.css'],
-  changeDetection : ChangeDetectionStrategy.OnPush,
-})
-
-export class SubjectViewer {
-  @Input() public subjects: any = []
-
-  get isSingle(): boolean {
-    return this.subjects.constructor !== Array
-  }
-
-  get species(): string[] {
-    return this.isSingle
-      ? [this.subjects.children.species.value]
-      : this.subjects.reduce((acc: string[], curr: any) =>
-        acc.findIndex(species => species === curr.children.species.value) >= 0
-          ? acc
-          : acc.concat(curr.children.species.value)
-      , [])
-  }
-
-  get groupBySex() {
-    return this.isSingle
-      ? [{
-        name : this.subjects.children.sex.value,
-        count : 1,
-      }]
-      : this.subjects.reduce((acc: any[], curr) =>
-        acc.findIndex(item => item.name === curr.children.sex.value) >= 0
-          ? acc.map(item => item.name === curr.children.sex.value
-            ? Object.assign({}, item, { count: item.count + 1 })
-            : item)
-          : acc.concat({name: curr.children.sex.value, count: 1})
-      , [])
-  }
-}
diff --git a/src/ui/kgEntryViewer/subjectViewer/subjectViewer.style.css b/src/ui/kgEntryViewer/subjectViewer/subjectViewer.style.css
deleted file mode 100644
index 974639e6c80263ea3c2277365e3bbc06e995db8e..0000000000000000000000000000000000000000
--- a/src/ui/kgEntryViewer/subjectViewer/subjectViewer.style.css
+++ /dev/null
@@ -1,4 +0,0 @@
-div.row:nth-child(even)
-{
-  background-color:rgba(128,128,128,0.2);
-}
\ No newline at end of file
diff --git a/src/ui/kgEntryViewer/subjectViewer/subjectViewer.template.html b/src/ui/kgEntryViewer/subjectViewer/subjectViewer.template.html
deleted file mode 100644
index e295f00d6711c2dd3902289a8ea6e695b471b6b6..0000000000000000000000000000000000000000
--- a/src/ui/kgEntryViewer/subjectViewer/subjectViewer.template.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<div>
-
-  <div class = "row">
-    <div class = "col-xs-4 col-lg-4">
-      Species:
-    </div>
-    <div class = "col-xs-8 col-lg-8">
-      {{ species.join(',') }}
-    </div>
-  </div>
-
-  <div class = "row">
-    <div class = "col-xs-4 col-lg-4">
-      Number of Subjects:
-    </div>
-    <div class = "col-xs-8 col-lg-8">
-      {{ subjects.length }}
-    </div>
-  </div>
-
-  <div class = "row">
-    <div class = "col-xs-4 col-lg-4">
-      Sex:
-    </div>
-    <div class = "col-xs-8 col-lg-8">
-      <div *ngFor = "let sexGroup of groupBySex">
-        {{ sexGroup.name }} (n = {{ sexGroup.count }})
-      </div>
-    </div>
-  </div>
-
-</div>
\ No newline at end of file
diff --git a/src/ui/kgtos/index.ts b/src/ui/kgtos/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d683b099119fbee7cb1f239686943c2fa0923a16
--- /dev/null
+++ b/src/ui/kgtos/index.ts
@@ -0,0 +1,4 @@
+import { InjectionToken } from "@angular/core";
+import { Observable } from "rxjs";
+
+export const TOS_OBS_INJECTION_TOKEN = new InjectionToken<Observable<string>>('TOS_STRING')
diff --git a/src/ui/kgtos/kgtos.component.ts b/src/ui/kgtos/kgtos/kgtos.component.ts
similarity index 66%
rename from src/ui/kgtos/kgtos.component.ts
rename to src/ui/kgtos/kgtos/kgtos.component.ts
index 52a3a4239f2c5a636fa0becdd1306f9621fa8921..8f968d8ee2269f96124a945cd9f7ddf8725b7804 100644
--- a/src/ui/kgtos/kgtos.component.ts
+++ b/src/ui/kgtos/kgtos/kgtos.component.ts
@@ -1,7 +1,6 @@
-import { Component, Inject, InjectionToken, Optional } from "@angular/core";
+import { Component, Inject, Optional } from "@angular/core";
 import { Observable } from "rxjs";
-
-export const TOS_OBS_INJECTION_TOKEN = new InjectionToken<Observable<string>>('TOS_STRING')
+import { TOS_OBS_INJECTION_TOKEN } from "..";
 
 @Component({
   selector: 'kgtos-component',
diff --git a/src/ui/viewerStateController/viewerStateCMini/viewerStateMini.style.css b/src/ui/kgtos/kgtos/kgtos.style.css
similarity index 100%
rename from src/ui/viewerStateController/viewerStateCMini/viewerStateMini.style.css
rename to src/ui/kgtos/kgtos/kgtos.style.css
diff --git a/src/ui/kgtos/kgtos.template.html b/src/ui/kgtos/kgtos/kgtos.template.html
similarity index 100%
rename from src/ui/kgtos/kgtos.template.html
rename to src/ui/kgtos/kgtos/kgtos.template.html
diff --git a/src/ui/kgtos/module.ts b/src/ui/kgtos/module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..dea1b4f60392d590f7210bee4df1a609eaaeb900
--- /dev/null
+++ b/src/ui/kgtos/module.ts
@@ -0,0 +1,19 @@
+import { CommonModule } from "@angular/common";
+import { NgModule } from "@angular/core";
+import { ComponentsModule } from "src/components";
+import { KGToS } from "./kgtos/kgtos.component";
+
+@NgModule({
+  imports: [
+    CommonModule,
+    ComponentsModule,
+  ],
+  declarations: [
+    KGToS
+  ],
+  exports: [
+    KGToS
+  ]
+})
+
+export class KgTosModule{}
\ No newline at end of file
diff --git a/src/ui/landmarkUI/landmarkUI.component.ts b/src/ui/landmarkUI/landmarkUI.component.ts
deleted file mode 100644
index 9b4635830d5668b7bf6981c7d87c988b0b88ea3e..0000000000000000000000000000000000000000
--- a/src/ui/landmarkUI/landmarkUI.component.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-import { Component, Input, OnChanges, Output, EventEmitter, ChangeDetectionStrategy, ChangeDetectorRef, AfterContentChecked } from "@angular/core";
-import { IDataEntry } from "src/services/stateStore.service"; 
-import { GetKgSchemaIdFromFullIdPipe } from 'src/ui/databrowserModule/util/getKgSchemaIdFromFullId.pipe'
-import { AtlasViewerConstantsServices } from "src/atlasViewer/atlasViewer.constantService.service";
-import { Observable } from "rxjs";
-import { DS_PREVIEW_URL } from 'src/util/constants'
-
-@Component({
-  selector: 'landmark-ui',
-  templateUrl: './landmarkUI.template.html',
-  styleUrls: [
-    './landmarkUI.style.css'
-  ],
-  changeDetection: ChangeDetectionStrategy.OnPush
-})
-
-export class LandmarkUIComponent implements OnChanges, AfterContentChecked{
-  @Input() name: string
-  @Input() fullId: string
-  @Input() datasets: Partial<IDataEntry>[]
-
-  @Output() relayout: EventEmitter<any> = new EventEmitter()
-
-  private pipe = new GetKgSchemaIdFromFullIdPipe()
-
-  public DS_PREVIEW_URL = DS_PREVIEW_URL
-
-  public previewFilesMap: Map<string, any[]> = new Map()
-  public previewFiles: any[] = []
-
-  handleKgDsPrvUpdate(event: CustomEvent, datasetKgId: string){
-    const { detail } = event
-    const { datasetFiles } = detail
-
-    this.previewFilesMap.set(datasetKgId, datasetFiles)
-
-    this.previewFiles = []
-
-    for (const [datasetKgId, previewFiles] of Array.from(this.previewFilesMap)){
-      for (const singlePreviewFile of previewFiles){
-        this.previewFiles.push({
-          ...singlePreviewFile,
-          datasetKgId
-        })
-      }
-    }
-    this.cdr.markForCheck()
-  }
-
-  public filterCriteria: string
-  ngOnChanges(){
-    this.filterCriteria = null
-    if (!this.fullId) return
-    const [kgSchema, kgId] = this.pipe.transform(this.fullId)
-    this.filterCriteria = JSON.stringify([ `${kgSchema}/${kgId}` ])
-  }
-
-  // TODO need to optimise this. This calls way too frequently.
-  ngAfterContentChecked(){
-    this.relayout.emit()
-  }
-
-  public darktheme$: Observable<boolean>
-
-  constructor(
-    constantService: AtlasViewerConstantsServices,
-    private cdr: ChangeDetectorRef
-  ){
-    this.darktheme$ = constantService.darktheme$
-  }
-}
\ No newline at end of file
diff --git a/src/ui/landmarkUI/landmarkUI.style.css b/src/ui/landmarkUI/landmarkUI.style.css
deleted file mode 100644
index 757b1a7bcba50d2da823755e085849b453bff61a..0000000000000000000000000000000000000000
--- a/src/ui/landmarkUI/landmarkUI.style.css
+++ /dev/null
@@ -1,21 +0,0 @@
-kg-dataset-previewer
-{
-  height: 20em;
-  width: 30em;
-}
-.scroll-snap-container
-{
-  scroll-snap-type: x mandatory;
-  scroll-padding-left: 1em;
-  scroll-padding-right: 1em;
-}
-
-.scroll-snap-container > .scroll-snap-child
-{
-  scroll-snap-align: center;
-}
-
-.w-30em
-{
-  width:30em!important;
-}
\ No newline at end of file
diff --git a/src/ui/landmarkUI/landmarkUI.template.html b/src/ui/landmarkUI/landmarkUI.template.html
deleted file mode 100644
index 46085769ecdd1ea45a56ef7cc7f05a6bf690744f..0000000000000000000000000000000000000000
--- a/src/ui/landmarkUI/landmarkUI.template.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<mat-card>
-  <mat-card-title>
-
-    {{ name }}
-  </mat-card-title>
-  <mat-card-subtitle>
-
-    <i class="fas fa-map-marker-alt"></i>
-    <span>
-      spatial landmark
-    </span>
-  </mat-card-subtitle>
-
-  <div class="scroll-snap-container w-100 d-flex flex-row w-30em overflow-auto" mat-card-image>
-    <div *ngFor="let dsPreview of previewFiles"
-      class="scroll-snap-child w-30em">
-      <kg-dataset-previewer
-        [darkmode]="darktheme$ | async"
-        [filename]="dsPreview.filename"
-        [kgId]="dsPreview.datasetKgId"
-        [backendUrl]="DS_PREVIEW_URL">
-      </kg-dataset-previewer>
-    </div>
-
-  </div>
-  <mat-card-content>
-
-    <!-- preview -->
-    <div>
-      <small class="text-muted">
-        Dataset preview
-      </small>
-
-      <ng-container *ngFor="let dataset of datasets; let index = index">
-        <kg-dataset-list
-          class="d-none"
-          [backendUrl]="DS_PREVIEW_URL"
-          [filterCriteriaProp]="filterCriteria"
-          *ngIf="dataset.fullId | getKgSchemaIdFromFullIdPipe as kgSchemaId"
-          (kgDsPrvUpdated)="handleKgDsPrvUpdate($event, kgSchemaId[1])"
-          [kgId]="kgSchemaId[1]">
-
-        </kg-dataset-list>
-      </ng-container>
-    </div>
-
-    <hr class="text-muted">
-    <!-- associated datasets -->
-    <div>
-      <small class="text-muted">
-        Associated datasets
-      </small>
-      <div>
-        <ng-container *ngFor="let dataset of datasets">
-
-          <single-dataset-list-view
-            *ngIf="dataset.fullId | getKgSchemaIdFromFullIdPipe as kgSchemaId"
-            [ripple]="true"
-            [kgSchema]="kgSchemaId[0]"
-            [kgId]="kgSchemaId[1]">
-
-          </single-dataset-list-view>
-        </ng-container>
-      </div>
-    </div>
-  </mat-card-content>
-</mat-card>
diff --git a/src/ui/nehubaContainer/2dLandmarks/landmark.base.ts b/src/ui/nehubaContainer/2dLandmarks/landmark.base.ts
index 52144fb7a41476a6387914067062fd6af99a3653..9d424edba5344b152eb561d4f8e3b92a0414925e 100644
--- a/src/ui/nehubaContainer/2dLandmarks/landmark.base.ts
+++ b/src/ui/nehubaContainer/2dLandmarks/landmark.base.ts
@@ -4,4 +4,6 @@ export class LandmarkUnitBase{
   @Input() public positionX: number = 0
   @Input() public positionY: number = 0
   @Input() public positionZ: number = 0
+
+  @Input() public color: number[] = [255, 255, 255]
 }
diff --git a/src/ui/nehubaContainer/nehuba.module.ts b/src/ui/nehubaContainer/nehuba.module.ts
deleted file mode 100644
index 0104d0c011daa059f725a9b218abfac7f3b494cb..0000000000000000000000000000000000000000
--- a/src/ui/nehubaContainer/nehuba.module.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { NgModule } from "@angular/core";
-import { NehubaViewerContainerDirective } from './nehubaViewerInterface/nehubaViewerInterface.directive'
-import { NehubaViewerUnit } from "./nehubaViewer/nehubaViewer.component";
-import { CommonModule } from "@angular/common";
-@NgModule({
-  imports: [
-    CommonModule
-  ],
-  declarations: [
-    NehubaViewerContainerDirective,
-    NehubaViewerUnit
-  ],
-  exports: [
-    NehubaViewerContainerDirective,
-    NehubaViewerUnit
-  ],
-  entryComponents: [
-    NehubaViewerUnit
-  ]
-})
-
-export class NehubaModule{}
diff --git a/src/ui/nehubaContainer/nehubaContainer.component.spec.ts b/src/ui/nehubaContainer/nehubaContainer.component.spec.ts
deleted file mode 100644
index 796c6ce287776f4c87d2b24cb3b4de8c524ecef7..0000000000000000000000000000000000000000
--- a/src/ui/nehubaContainer/nehubaContainer.component.spec.ts
+++ /dev/null
@@ -1,701 +0,0 @@
-import { CUSTOM_ELEMENTS_SCHEMA, DebugElement } from '@angular/core'
-import { TestBed, async, ComponentFixture, fakeAsync, tick, flush, discardPeriodicTasks } from "@angular/core/testing"
-import { NehubaContainer } from "./nehubaContainer.component"
-import { provideMockStore, MockStore } from "@ngrx/store/testing"
-import { defaultRootState } from 'src/services/stateStore.service'
-import { AngularMaterialModule } from "../sharedModules/angularMaterial.module"
-import { TouchSideClass } from "./touchSideClass.directive"
-import { MaximmisePanelButton } from "./maximisePanelButton/maximisePanelButton.component"
-import { LayoutModule } from 'src/layouts/layout.module'
-import { PureContantService, UtilModule } from "src/util"
-import { AtlasLayerSelector } from "../atlasLayerSelector/atlasLayerSelector.component"
-import { StatusCardComponent } from './statusCard/statusCard.component'
-import { NehubaViewerTouchDirective } from './nehubaViewerInterface/nehubaViewerTouch.directive'
-import { MobileOverlay } from "./mobileOverlay/mobileOverlay.component"
-import { RegionMenuComponent } from "../parcellationRegion/regionMenu/regionMenu.component"
-import { DatabrowserModule } from "../databrowserModule"
-import { SplashScreen } from "./splashScreen/splashScreen.component"
-import { CurrentLayout } from 'src/ui/config/currentLayout/currentLayout.component'
-import { RegionDirective } from 'src/ui/parcellationRegion/region.directive'
-import { RegionTextSearchAutocomplete } from "../viewerStateController/regionSearch/regionSearch.component"
-import { MobileControlNubStylePipe } from './pipes/mobileControlNubStyle.pipe'
-import { ReorderPanelIndexPipe } from './reorderPanelIndex.pipe'
-import { AuthModule } from 'src/auth'
-import { StateModule } from 'src/state'
-import { ReactiveFormsModule, FormsModule } from '@angular/forms'
-import { HttpClientModule } from '@angular/common/http'
-import { WidgetModule } from 'src/widget'
-import { NehubaModule } from './nehuba.module'
-import { CommonModule } from '@angular/common'
-import { IMPORT_NEHUBA_INJECT_TOKEN } from './nehubaViewer/nehubaViewer.component'
-import { viewerStateCustomLandmarkSelector, viewerStateHelperStoreName } from 'src/services/state/viewerState.store.helper'
-import { RenderViewOriginDatasetLabelPipe } from '../parcellationRegion/region.base'
-import { By } from '@angular/platform-browser'
-import { ARIA_LABELS } from 'common/constants'
-import { NoopAnimationsModule } from '@angular/platform-browser/animations'
-import { RegionAccordionTooltipTextPipe } from '../util'
-import { hot } from 'jasmine-marbles'
-import { HttpClientTestingModule } from '@angular/common/http/testing'
-import { ngViewerSelectorOctantRemoval, ngViewerSelectorPanelMode, ngViewerSelectorPanelOrder } from 'src/services/state/ngViewerState/selectors'
-import { PANELS } from 'src/services/state/ngViewerState/constants'
-import { RegionalFeaturesModule } from '../regionalFeatures'
-import { Landmark2DModule } from './2dLandmarks/module'
-
-const { 
-  TOGGLE_SIDE_PANEL,
-  EXPAND,
-  COLLAPSE,
-  ZOOM_IN,
-  ZOOM_OUT,
-  TOGGLE_FRONTAL_OCTANT
-} = ARIA_LABELS
-
-const _bigbrainJson = require('!json-loader!src/res/ext/bigbrain.json')
-const _bigbrainNehubaConfigJson = require('!json-loader!src/res/ext/bigbrainNehubaConfig.json')
-const bigbrainJson = {
-  ..._bigbrainJson,
-  nehubaConfig: _bigbrainNehubaConfigJson
-}
-const humanAtlas = require('!json-loader!src/res/ext/atlas/atlas_multiLevelHuman.json')
-const importNehubaSpy = jasmine.createSpy('importNehubaSpy').and.returnValue(Promise.reject())
-
-describe('> nehubaContainer.component.ts', () => {
-
-  describe('> NehubaContainer', () => {
-
-    beforeEach(async(() => {
-
-      TestBed.configureTestingModule({
-        imports: [
-          NoopAnimationsModule,
-          WidgetModule,
-          AngularMaterialModule,
-          LayoutModule,
-          UtilModule,
-          DatabrowserModule,
-          NehubaModule,
-          AuthModule,
-          StateModule,
-          FormsModule,
-          ReactiveFormsModule,
-          HttpClientModule,
-          CommonModule,
-          RegionalFeaturesModule,
-
-          /**
-           * because the change done to pureconstant service, need to intercept http call to avoid crypto error message
-           * so and so components needs to be compiled first. make sure you call compileComponents
-           */
-          HttpClientTestingModule,
-          Landmark2DModule,
-        ],
-        declarations: [
-          NehubaContainer,
-          TouchSideClass,
-          MaximmisePanelButton,
-          AtlasLayerSelector,
-          StatusCardComponent,
-          NehubaViewerTouchDirective,
-          MobileOverlay,
-          RegionMenuComponent,
-          SplashScreen,
-          CurrentLayout,
-          RegionDirective,
-          RegionTextSearchAutocomplete,
-  
-          // pipes
-          MobileControlNubStylePipe,
-          ReorderPanelIndexPipe,
-          RenderViewOriginDatasetLabelPipe,
-          RegionAccordionTooltipTextPipe,
-        ],
-        providers: [
-          provideMockStore({ initialState: defaultRootState }),
-          {
-            provide: IMPORT_NEHUBA_INJECT_TOKEN,
-            useValue: importNehubaSpy
-          },
-          PureContantService,
-        ],
-        schemas: [
-          CUSTOM_ELEMENTS_SCHEMA
-        ],
-      }).compileComponents()
-      
-    }))
-
-    it('> component can be created', () => {
-      const fixture = TestBed.createComponent(NehubaContainer)
-      fixture.componentInstance.currentOnHoverObs$ = hot('')
-      const el = fixture.debugElement.componentInstance
-      expect(el).toBeTruthy()
-    })
-
-    describe('> on selectedTemplatechange', () => {
-      it('> calls importNehubaPr', async () => {
-        const fixture = TestBed.createComponent(NehubaContainer)
-        fixture.componentInstance.currentOnHoverObs$ = hot('')
-
-        const mockStore = TestBed.inject(MockStore)
-        const newState = {
-          ...defaultRootState,
-          viewerState: {
-            ...defaultRootState.viewerState,
-            fetchedTemplates: [ bigbrainJson ],
-            templateSelected: bigbrainJson,
-            parcellationSelected: bigbrainJson.parcellations[0]
-          },
-          [viewerStateHelperStoreName]: {
-            fetchedAtlases: [ humanAtlas ],
-            selectedAtlasId: humanAtlas['@id']
-          }
-        }
-
-        mockStore.setState(newState)
-        fixture.detectChanges()
-        expect(importNehubaSpy).toHaveBeenCalled()
-      })
-
-      /**
-       * TODO perhaps move this to e2e?
-       */
-      it('> drag handle reattaches properly')
-    })
-
-    describe('> on selectedparcellation change', () => {
-      it('> should set ngId of nehubaViewer', () => {
-        
-        const fixture = TestBed.createComponent(NehubaContainer)
-        fixture.componentInstance.currentOnHoverObs$ = hot('')
-        const el = fixture.debugElement.componentInstance as NehubaContainer
-        const mockStore = TestBed.inject(MockStore)
-        const newState = {
-          ...defaultRootState,
-          viewerState: {
-            ...defaultRootState.viewerState,
-            fetchedTemplates: [ bigbrainJson ],
-            templateSelected: bigbrainJson,
-            parcellationSelected: bigbrainJson.parcellations[0]
-          },
-          [viewerStateHelperStoreName]: {
-            fetchedAtlases: [ humanAtlas ],
-            selectedAtlasId: humanAtlas['@id']
-          }
-        }
-
-        mockStore.setState(newState)
-        fixture.detectChanges()
-
-        const setSpy = spyOnProperty(el.nehubaViewer, 'ngIds', 'set')
-
-        const newState2 = {
-          ...defaultRootState,
-          viewerState: {
-            ...defaultRootState.viewerState,
-            fetchedTemplates: [ bigbrainJson ],
-            templateSelected: bigbrainJson,
-            parcellationSelected: bigbrainJson.parcellations[1]
-          },
-          [viewerStateHelperStoreName]: {
-            fetchedAtlases: [ humanAtlas ],
-            selectedAtlasId: humanAtlas['@id']
-          }
-        }
-
-        mockStore.setState(newState2)
-        fixture.detectChanges()
-
-        expect(setSpy).toHaveBeenCalled()
-        
-      })
-    })
-
-    describe('> extended sidepanel hides and shows as expected', () => {
-      describe('> on start, if nothing is selected', () => {
-        beforeEach(() => {
-          const mockStore = TestBed.inject(MockStore)
-          const newState = {
-            ...defaultRootState,
-            viewerState: {
-              ...defaultRootState.viewerState,
-              fetchedTemplates: [ bigbrainJson ],
-              templateSelected: bigbrainJson,
-              parcellationSelected: bigbrainJson.parcellations[0]
-            },
-            [viewerStateHelperStoreName]: {
-              fetchedAtlases: [ humanAtlas ],
-              selectedAtlasId: humanAtlas['@id']
-            }
-          }
-
-          mockStore.setState(newState)
-        })
-
-        it('> both should be shut', () => {
-          const fixture = TestBed.createComponent(NehubaContainer)
-          fixture.componentInstance.currentOnHoverObs$ = hot('')
-          fixture.detectChanges()
-          expect(
-            fixture.componentInstance.matDrawerMain.opened
-          ).toEqual(false)
-          expect(
-            fixture.componentInstance.matDrawerMinor.opened
-          ).toEqual(false)
-        })
-
-        it('> opening via tab should result in only top drawer open', () => {
-
-          const fixture = TestBed.createComponent(NehubaContainer)
-          fixture.componentInstance.currentOnHoverObs$ = hot('')
-          fixture.detectChanges()
-          const toggleBtn = fixture.debugElement.query( By.css(`[aria-label="${TOGGLE_SIDE_PANEL}"]`) )
-          toggleBtn.triggerEventHandler('click', null)
-          fixture.detectChanges()
-          
-          expect(
-            fixture.componentInstance.matDrawerMain.opened
-          ).toEqual(true)
-          expect(
-            fixture.componentInstance.matDrawerMinor.opened
-          ).toEqual(false)
-        })
-
-        it('> on opening top drawer, explore features should not be present', () => {
-
-          const fixture = TestBed.createComponent(NehubaContainer)
-          fixture.componentInstance.currentOnHoverObs$ = hot('')
-          fixture.detectChanges()
-          const toggleBtn = fixture.debugElement.query( By.css(`[aria-label="${TOGGLE_SIDE_PANEL}"]`) )
-          toggleBtn.triggerEventHandler('click', null)
-          fixture.detectChanges()
-          const expandRegionFeatureBtn = fixture.debugElement.query( By.css(`mat-drawer[data-mat-drawer-secondary-open="true"] [aria-label="${EXPAND}"]`) )
-          expect(expandRegionFeatureBtn).toBeNull()
-        })
-        it('> collapse btn should not be visible', () => {
-
-          const fixture = TestBed.createComponent(NehubaContainer)
-          fixture.componentInstance.currentOnHoverObs$ = hot('')
-          fixture.detectChanges()
-          const toggleBtn = fixture.debugElement.query( By.css(`[aria-label="${TOGGLE_SIDE_PANEL}"]`) )
-          toggleBtn.triggerEventHandler('click', null)
-          fixture.detectChanges()
-          const expandRegionFeatureBtn = fixture.debugElement.query( By.css(`mat-drawer[data-mat-drawer-secondary-open="true"] [aria-label="${COLLAPSE}"]`) )
-          expect(expandRegionFeatureBtn).toBeNull()
-        })
-      })
-
-      describe('> on start, if something is selected', () => {
-        beforeEach(() => {
-          const mockStore = TestBed.inject(MockStore)
-          const newState = {
-            ...defaultRootState,
-            viewerState: {
-              ...defaultRootState.viewerState,
-              fetchedTemplates: [ bigbrainJson ],
-              templateSelected: bigbrainJson,
-              parcellationSelected: bigbrainJson.parcellations[0],
-              regionsSelected: [{
-                name: "foobar",
-                ngId: 'untitled',
-                labelIndex: 15
-              }]
-            },
-            [viewerStateHelperStoreName]: {
-              fetchedAtlases: [ humanAtlas ],
-              selectedAtlasId: humanAtlas['@id']
-            }
-          }
-
-          mockStore.setState(newState)
-        })
-        it('> both should be open', () => {
-          const fixture = TestBed.createComponent(NehubaContainer)
-          fixture.componentInstance.currentOnHoverObs$ = hot('')
-          fixture.detectChanges()
-          expect(
-            fixture.componentInstance.matDrawerMain.opened
-          ).toEqual(true)
-          expect(
-            fixture.componentInstance.matDrawerMinor.opened
-          ).toEqual(true)
-
-          expect(
-            fixture.componentInstance.navSideDrawerMainSwitch.switchState
-          ).toEqual(true)
-          expect(
-            fixture.componentInstance.navSideDrawerMinorSwitch.switchState
-          ).toEqual(true)
-        })
-
-        it('> closing main drawer via tag should close both', () => {
-          const fixture = TestBed.createComponent(NehubaContainer)
-          fixture.componentInstance.currentOnHoverObs$ = hot('')
-          fixture.detectChanges()
-          const toggleBtn = fixture.debugElement.query( By.css(`[aria-label="${TOGGLE_SIDE_PANEL}"]`) )
-          toggleBtn.triggerEventHandler('click', null)
-          fixture.detectChanges()
-          expect(
-            fixture.componentInstance.matDrawerMain.opened
-          ).toEqual(false)
-
-          /**
-           * TODO investigate why openedStart/closedStart events fail to fire
-           */
-          // expect(
-          //   fixture.componentInstance.matDrawerMinor.opened
-          // ).toEqual(false)
-
-          // expect(
-          //   fixture.componentInstance.navSideDrawerMainSwitch.switchState
-          // ).toEqual(false)
-          // expect(
-          //   fixture.componentInstance.navSideDrawerMinorSwitch.switchState
-          // ).toEqual(false)
-        })
-        it('> collapse btn should be visible', () => {
-
-          const fixture = TestBed.createComponent(NehubaContainer)
-          fixture.componentInstance.currentOnHoverObs$ = hot('')
-          fixture.detectChanges()
-          const collapseRegionFeatureBtn = fixture.debugElement.query( By.css(`mat-drawer[data-mat-drawer-secondary-open="true"] [aria-label="${COLLAPSE}"]`) )
-          expect(collapseRegionFeatureBtn).not.toBeNull()
-        })
-        it('> clicking on collapse btn should minimize 1 drawer', () => {
-
-          const fixture = TestBed.createComponent(NehubaContainer)
-          fixture.componentInstance.currentOnHoverObs$ = hot('')
-          fixture.detectChanges()
-          const collapseRegionFeatureBtn = fixture.debugElement.query( By.css(`mat-drawer[data-mat-drawer-secondary-open="true"] [aria-label="${COLLAPSE}"]`) )
-          collapseRegionFeatureBtn.triggerEventHandler('click', null)
-          fixture.detectChanges()
-          expect(
-            fixture.componentInstance.matDrawerMain.opened
-          ).toEqual(true)
-
-          /**
-           * TODO investigate why property does not get updated
-           */
-          // expect(
-          //   fixture.componentInstance.matDrawerMinor.opened
-          // ).toEqual(false)
-
-          expect(
-            fixture.componentInstance.navSideDrawerMainSwitch.switchState
-          ).toEqual(true)
-          expect(
-            fixture.componentInstance.navSideDrawerMinorSwitch.switchState
-          ).toEqual(false)
-        })
-
-        it('> on minimize drawer, clicking expand btn should expand everything', () => {
-          const fixture = TestBed.createComponent(NehubaContainer)
-          fixture.componentInstance.currentOnHoverObs$ = hot('')
-          fixture.detectChanges()
-          const collapseRegionFeatureBtn = fixture.debugElement.query( By.css(`mat-drawer[data-mat-drawer-secondary-open="true"] [aria-label="${COLLAPSE}"]`) )
-          collapseRegionFeatureBtn.triggerEventHandler('click', null)
-          fixture.detectChanges()
-          const expandRegionFeatureBtn = fixture.debugElement.query( By.css(`mat-drawer[data-mat-drawer-primary-open="true"] [aria-label="${EXPAND}"]`) )
-          expandRegionFeatureBtn.triggerEventHandler('click', null)
-          fixture.detectChanges()
-
-          expect(
-            fixture.componentInstance.matDrawerMain.opened
-          ).toEqual(true)
-          expect(
-            fixture.componentInstance.matDrawerMinor.opened
-          ).toEqual(true)
-
-          expect(
-            fixture.componentInstance.navSideDrawerMainSwitch.switchState
-          ).toEqual(true)
-          /**
-           * TODO figoure out why switch state is updated async, and karma can't force update state
-           */
-          // expect(
-          //   fixture.componentInstance.navSideDrawerMinorSwitch.switchState
-          // ).toEqual(true)
-        })
-      })
-
-      describe('> side bar content', () => {
-
-        /**
-         * TODO
-         */
-        it('> if nothing is shown, it should show place holder text')
-
-        /**
-         * TODO
-         */
-        it('> if something (region features/connectivity) exists, placeh holder text should be hdiden')
-      })
-    })
-  
-    describe('> panelCtrl', () => {
-      let fixture: ComponentFixture<NehubaContainer>
-      const setViewerLoaded = () => {
-        fixture.componentInstance.viewerLoaded = true
-      }
-      const ctrlElementIsVisible = (el: DebugElement) => {
-        const visible = (el.nativeElement as HTMLElement).getAttribute('data-viewer-controller-visible')
-        return visible === 'true'
-      }
-      beforeEach(() => {
-        fixture = TestBed.createComponent(NehubaContainer)
-      })
-      it('> on start, all four ctrl panels exists', () => {
-        fixture.detectChanges()
-        setViewerLoaded()
-        fixture.detectChanges()
-        for (const idx of [0, 1, 2, 3]) {
-          const el = fixture.debugElement.query(
-            By.css(`[data-viewer-controller-index="${idx}"]`)
-          )
-          expect(el).toBeTruthy()
-        }
-      })
-
-      it('> on start all four ctrl panels are invisible', () => {
-        
-        fixture.detectChanges()
-        setViewerLoaded()
-        fixture.detectChanges()
-        for (const idx of [0, 1, 2, 3]) {
-          const el = fixture.debugElement.query(
-            By.css(`[data-viewer-controller-index="${idx}"]`)
-          )
-          expect(ctrlElementIsVisible(el)).toBeFalsy()
-        }
-      })
-
-      describe('> on hover, only the hovered panel have ctrl shown', () => {
-
-        for (const idx of [0, 1, 2, 3]) {
-          
-          it(`> on hoveredPanelIndices$ emit ${idx}, the panel index ${idx} ctrl becomes visible`, fakeAsync(() => {
-            fixture.detectChanges()
-            const findPanelIndexSpy = spyOn<any>(fixture.componentInstance, 'findPanelIndex').and.callFake(() => {
-              return idx
-            })
-            setViewerLoaded()
-            fixture.detectChanges()
-            const nativeElement = fixture.componentInstance['elementRef'].nativeElement
-            nativeElement.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }))
-  
-            /**
-             * assert findPanelIndex called with event.target, i.e. native element in thsi case
-             */
-            expect(findPanelIndexSpy).toHaveBeenCalledWith(nativeElement)
-            tick(200)
-            fixture.detectChanges()
-            
-            /**
-             * every panel index should be non visible
-             * only when idx matches, it can be visible
-             * n.b. this does not test visual visibility (which is controlled by extra-style.css)
-             * (which is also affected by global [ismobile] configuration)
-             * 
-             * this merely test the unit logic, and sets the flag appropriately
-             */
-            for (const iterativeIdx of [0, 1, 2, 3]) {
-              const el = fixture.debugElement.query(
-                By.css(`[data-viewer-controller-index="${iterativeIdx}"]`)
-              )
-              if (iterativeIdx === idx) {
-                expect(ctrlElementIsVisible(el)).toBeTruthy()
-              } else {
-                expect(ctrlElementIsVisible(el)).toBeFalsy()
-              }
-            }
-            discardPeriodicTasks()
-          }))
-        }
-  
-      })
-
-      describe('> on maximise top right slice panel (idx 1)', () => {
-        beforeEach(() => {
-          const mockStore = TestBed.inject(MockStore)
-          mockStore.overrideSelector(ngViewerSelectorPanelMode, PANELS.SINGLE_PANEL)
-          mockStore.overrideSelector(ngViewerSelectorPanelOrder, '1230')
-
-          fixture.detectChanges()
-          setViewerLoaded()
-          fixture.detectChanges()
-        })
-        it('> toggle front octant btn not visible', () => {
-
-          const toggleBtn = fixture.debugElement.query(
-            By.css(`[cell-i] [aria-label="${TOGGLE_FRONTAL_OCTANT}"]`)
-          )
-          expect(toggleBtn).toBeFalsy()
-        })
-
-        it('> zoom in and out btns are visible', () => {
-
-          const zoomInBtn = fixture.debugElement.query(
-            By.css(`[cell-i] [aria-label="${ZOOM_IN}"]`)
-          )
-
-          const zoomOutBtn = fixture.debugElement.query(
-            By.css(`[cell-i] [aria-label="${ZOOM_OUT}"]`)
-          )
-
-          expect(zoomInBtn).toBeTruthy()
-          expect(zoomOutBtn).toBeTruthy()
-        })
-
-        it('> zoom in btn calls fn with right param', () => {
-          const zoomViewSpy = spyOn(fixture.componentInstance, 'zoomNgView')
-
-          const zoomInBtn = fixture.debugElement.query(
-            By.css(`[cell-i] [aria-label="${ZOOM_IN}"]`)
-          )
-          zoomInBtn.triggerEventHandler('click', null)
-          expect(zoomViewSpy).toHaveBeenCalled()
-          const { args } = zoomViewSpy.calls.first()
-          expect(args[0]).toEqual(1)
-          /**
-           * zoom in < 1
-           */
-          expect(args[1]).toBeLessThan(1)
-        })
-        it('> zoom out btn calls fn with right param', () => {
-          const zoomViewSpy = spyOn(fixture.componentInstance, 'zoomNgView')
-
-          const zoomOutBtn = fixture.debugElement.query(
-            By.css(`[cell-i] [aria-label="${ZOOM_OUT}"]`)
-          )
-          zoomOutBtn.triggerEventHandler('click', null)
-          expect(zoomViewSpy).toHaveBeenCalled()
-          const { args } = zoomViewSpy.calls.first()
-          expect(args[0]).toEqual(1)
-          /**
-           * zoom out > 1
-           */
-          expect(args[1]).toBeGreaterThan(1)
-        })
-      })
-      describe('> on maximise perspective panel', () => {
-        beforeEach(() => {
-          const mockStore = TestBed.inject(MockStore)
-          mockStore.overrideSelector(ngViewerSelectorPanelMode, PANELS.SINGLE_PANEL)
-          mockStore.overrideSelector(ngViewerSelectorPanelOrder, '3012')
-
-          fixture.detectChanges()
-          setViewerLoaded()
-          fixture.detectChanges()
-        })
-        it('> toggle octant btn visible and functional', () => {
-          const setOctantRemovalSpy = spyOn(fixture.componentInstance, 'setOctantRemoval')
-
-          const toggleBtn = fixture.debugElement.query(
-            By.css(`[cell-i] [aria-label="${TOGGLE_FRONTAL_OCTANT}"]`)
-          )
-          expect(toggleBtn).toBeTruthy()
-          toggleBtn.nativeElement.dispatchEvent(
-            new MouseEvent('click', { bubbles: true })
-          )
-          expect(setOctantRemovalSpy).toHaveBeenCalled()
-        })
-
-        it('> zoom in btn visible and functional', () => {
-          const zoomViewSpy = spyOn(fixture.componentInstance, 'zoomNgView')
-
-          const zoomInBtn = fixture.debugElement.query(
-            By.css(`[cell-i] [aria-label="${ZOOM_IN}"]`)
-          )
-          expect(zoomInBtn).toBeTruthy()
-
-          zoomInBtn.triggerEventHandler('click', null)
-          expect(zoomViewSpy).toHaveBeenCalled()
-          const { args } = zoomViewSpy.calls.first()
-          expect(args[0]).toEqual(3)
-          /**
-           * zoom in < 1
-           */
-          expect(args[1]).toBeLessThan(1)
-        })
-        it('> zoom out btn visible and functional', () => {
-          const zoomViewSpy = spyOn(fixture.componentInstance, 'zoomNgView')
-
-          const zoomOutBtn = fixture.debugElement.query(
-            By.css(`[cell-i] [aria-label="${ZOOM_OUT}"]`)
-          )
-          expect(zoomOutBtn).toBeTruthy()
-
-          zoomOutBtn.triggerEventHandler('click', null)
-          expect(zoomViewSpy).toHaveBeenCalled()
-          const { args } = zoomViewSpy.calls.first()
-          expect(args[0]).toEqual(3)
-          /**
-           * zoom in < 1
-           */
-          expect(args[1]).toBeGreaterThan(1)
-        })
-      
-      })
-    })
-  
-    describe('> on userLandmarks change', () => {
-      const lm1 = {
-        id: 'test-1',
-        position: [0, 0, 0]
-      }
-      const lm2 = {
-        id: 'test-2',
-        position: [1, 1,1 ]
-      }
-      it('> calls nehubaViewer.updateUserLandmarks', () => {
-        const fixture = TestBed.createComponent(NehubaContainer)
-
-        fixture.componentInstance.nehubaViewer = {
-          updateUserLandmarks: () => {}
-        } as any
-
-        const updateUserLandmarksSpy = spyOn(
-          fixture.componentInstance.nehubaViewer,
-          'updateUserLandmarks'
-        )
-
-        const mockStore = TestBed.inject(MockStore)
-        mockStore.overrideSelector(viewerStateCustomLandmarkSelector, [
-          lm1, 
-          lm2
-        ])
-        fixture.detectChanges()
-        expect(
-          updateUserLandmarksSpy
-        ).toHaveBeenCalledWith([
-          lm1, lm2
-        ])
-      })
-    
-      it('> calls togglecotantREmoval', () => {
-        
-        const fixture = TestBed.createComponent(NehubaContainer)
-
-        fixture.componentInstance.nehubaContainerDirective = {
-          toggleOctantRemoval: () => {},
-          clear: () => {}
-        } as any
-
-        const toggleOctantRemovalSpy = spyOn(
-          fixture.componentInstance.nehubaContainerDirective,
-          'toggleOctantRemoval'
-        )
-
-        const mockStore = TestBed.inject(MockStore)
-        mockStore.overrideSelector(viewerStateCustomLandmarkSelector, [
-          lm1, 
-          lm2
-        ])
-        mockStore.overrideSelector(ngViewerSelectorOctantRemoval, true)
-        fixture.detectChanges()
-        expect(
-          toggleOctantRemovalSpy
-        ).toHaveBeenCalledWith(false)
-      })
-    })
-  })
-})
diff --git a/src/ui/nehubaContainer/nehubaContainer.component.ts b/src/ui/nehubaContainer/nehubaContainer.component.ts
index 31baa10763f7dfb2bffb6266a62a982c57b56131..3582fc984ef9c10db69e3af977c6fed9c9586b25 100644
--- a/src/ui/nehubaContainer/nehubaContainer.component.ts
+++ b/src/ui/nehubaContainer/nehubaContainer.component.ts
@@ -1,1183 +1,1181 @@
-import { Component, ElementRef, Input, OnChanges, OnDestroy, OnInit, ViewChild, ChangeDetectorRef, Output, EventEmitter, Inject, Optional } from "@angular/core";
-import { select, Store } from "@ngrx/store";
-import { combineLatest, fromEvent, merge, Observable, of, Subscription, timer, asyncScheduler, BehaviorSubject, Subject } from "rxjs";
-import { buffer, debounceTime, distinctUntilChanged, filter, map, mapTo, scan, shareReplay, skip, startWith, switchMap, switchMapTo, take, tap, withLatestFrom, delayWhen, throttleTime } from "rxjs/operators";
-import { trigger, state, style, animate, transition } from '@angular/animations'
-import { MatDrawer } from "@angular/material/sidenav";
-
-import { LoggingService } from "src/logging";
-import {
-  CHANGE_NAVIGATION,
-  generateLabelIndexId,
-  getMultiNgIdsRegionsLabelIndexMap,
-  getNgIds,
-  ILandmark,
-  IOtherLandmarkGeometry,
-  IPlaneLandmarkGeometry,
-  IPointLandmarkGeometry,
-  isDefined,
-  MOUSE_OVER_LANDMARK,
-  NgViewerStateInterface
-} from "src/services/stateStore.service";
-
-import { getExportNehuba, isSame } from "src/util/fn";
-import { API_SERVICE_SET_VIEWER_HANDLE_TOKEN, IUserLandmark } from "src/atlasViewer/atlasViewer.apiService.service";
-import { NehubaViewerUnit } from "./nehubaViewer/nehubaViewer.component";
-import { compareLandmarksChanged } from "src/util/constants";
-import { PureContantService } from "src/util";
-import { ARIA_LABELS, IDS, CONST } from 'common/constants'
-import { ngViewerActionSetPerspOctantRemoval, PANELS, ngViewerActionToggleMax, ngViewerActionAddNgLayer, ngViewerActionRemoveNgLayer } from "src/services/state/ngViewerState.store.helper";
-import { viewerStateSelectRegionWithIdDeprecated, viewerStateAddUserLandmarks, viewreStateRemoveUserLandmarks, viewerStateCustomLandmarkSelector, viewerStateSelectedParcellationSelector, viewerStateSelectedTemplateSelector, viewerStateSelectedRegionsSelector } from 'src/services/state/viewerState.store.helper'
-import { SwitchDirective } from "src/util/directives/switch.directive";
-import {
-  viewerStateDblClickOnViewer,
-} from "src/services/state/viewerState.store.helper";
-
-import { getFourPanel, getHorizontalOneThree, getSinglePanel, getVerticalOneThree, calculateSliceZoomFactor, scanSliceViewRenderFn as scanFn, takeOnePipe } from "./util";
-import { NehubaViewerContainerDirective } from "./nehubaViewerInterface/nehubaViewerInterface.directive";
-import { ITunableProp } from "./mobileOverlay/mobileOverlay.component";
-import {ConnectivityBrowserComponent} from "src/ui/connectivityBrowser/connectivityBrowser.component";
-import { viewerStateMouseOverCustomLandmark } from "src/services/state/viewerState/actions";
-import { ngViewerSelectorNehubaReady, ngViewerSelectorOctantRemoval, ngViewerSelectorPanelMode, ngViewerSelectorPanelOrder } from "src/services/state/ngViewerState/selectors";
-import { REGION_OF_INTEREST } from "src/util/interfaces";
-import { uiActionHideAllDatasets, uiActionHideDatasetWithId } from "src/services/state/uiState/actions";
-
-const { MESH_LOADING_STATUS } = IDS
-
-const sortByFreshness: (acc: any[], curr: any[]) => any[] = (acc, curr) => {
-
-  const getLayerName = ({layer} = {layer: {}}) => {
-    const { name } = layer as any
-    return name
-  }
-
-  const newEntries = (curr && curr.filter(entry => {
-    const name = getLayerName(entry)
-    return acc.map(getLayerName).indexOf(name) < 0
-  })) || []
-
-  const entryChanged: (itemPrevState, newArr) => boolean = (itemPrevState, newArr) => {
-    const layerName = getLayerName(itemPrevState)
-    const { segment } = itemPrevState
-    const foundItem = newArr?.find((_item) =>
-      getLayerName(_item) === layerName)
-
-    if (foundItem) {
-      const { segment: foundSegment } = foundItem
-      return segment !== foundSegment
-    } else {
-      /**
-       * if item was not found in the new array, meaning hovering nothing
-       */
-      return segment !== null
-    }
-  }
-
-  const getItemFromLayerName = (item, arr) => {
-    const foundItem = arr?.find(i => getLayerName(i) === getLayerName(item))
-    return foundItem
-      ? foundItem
-      : {
-        layer: item.layer,
-        segment: null,
-      }
-  }
-
-  const getReduceExistingLayers = (newArr) => ([changed, unchanged], _curr) => {
-    const changedFlag = entryChanged(_curr, newArr)
-    return changedFlag
-      ? [ changed.concat( getItemFromLayerName(_curr, newArr) ), unchanged ]
-      : [ changed, unchanged.concat(_curr) ]
-  }
-
-  /**
-   * now, for all the previous layers, separate into changed and unchanged layers
-   */
-  const [changed, unchanged] = acc.reduce(getReduceExistingLayers(curr), [[], []])
-  return [...newEntries, ...changed, ...unchanged]
-}
-
-const {
-  ZOOM_IN,
-  ZOOM_OUT,
-  TOGGLE_FRONTAL_OCTANT,
-  TOGGLE_SIDE_PANEL,
-  EXPAND,
-  COLLAPSE,
-  ADDITIONAL_VOLUME_CONTROL,
-} = ARIA_LABELS
-
-@Component({
-  selector : 'ui-nehuba-container',
-  templateUrl : './nehubaContainer.template.html',
-  styleUrls : [
-    `./nehubaContainer.style.css`,
-  ],
-  animations: [
-    trigger('openClose', [
-      state('open', style({
-        transform: 'translateY(0)',
-        opacity: 1
-      })),
-      state('closed', style({
-        transform: 'translateY(-100vh)',
-        opacity: 0
-      })),
-      transition('open => closed', [
-        animate('200ms cubic-bezier(0.35, 0, 0.25, 1)')
-      ]),
-      transition('closed => open', [
-        animate('200ms cubic-bezier(0.35, 0, 0.25, 1)')
-      ])
-    ]),
-    trigger('openCloseAnchor', [
-      state('open', style({
-        transform: 'translateY(0)'
-      })),
-      state('closed', style({
-        transform: 'translateY(100vh)'
-      })),
-      transition('open => closed', [
-        animate('200ms cubic-bezier(0.35, 0, 0.25, 1)')
-      ]),
-      transition('closed => open', [
-        animate('200ms cubic-bezier(0.35, 0, 0.25, 1)')
-      ])
-    ]),
-  ],
-  exportAs: 'uiNehubaContainer',
-  providers: [
-    {
-      provide: REGION_OF_INTEREST,
-      useFactory: (store: Store<any>) => store.pipe(
-        select(viewerStateSelectedRegionsSelector),
-        map(rs => rs[0] || null)
-      ),
-      deps: [
-        Store
-      ]
-    }
-  ]
-})
-
-export class NehubaContainer implements OnInit, OnChanges, OnDestroy {
-
-  public CONST = CONST
-  public ARIA_LABEL_ZOOM_IN = ZOOM_IN
-  public ARIA_LABEL_ZOOM_OUT = ZOOM_OUT
-  public ARIA_LABEL_TOGGLE_FRONTAL_OCTANT = TOGGLE_FRONTAL_OCTANT
-  public ARIA_LABEL_TOGGLE_SIDE_PANEL = TOGGLE_SIDE_PANEL
-  public ARIA_LABEL_EXPAND = EXPAND
-  public ARIA_LABEL_COLLAPSE = COLLAPSE
-  public ARIA_LABEL_ADDITIONAL_VOLUME_CONTROL = ADDITIONAL_VOLUME_CONTROL
+// import { Component, ElementRef, Input, OnChanges, OnDestroy, OnInit, ViewChild, ChangeDetectorRef, Output, EventEmitter, Inject, Optional } from "@angular/core";
+// import { select, Store } from "@ngrx/store";
+// import { combineLatest, fromEvent, merge, Observable, of, Subscription, timer, asyncScheduler, BehaviorSubject, Subject } from "rxjs";
+// import { buffer, debounceTime, distinctUntilChanged, filter, map, mapTo, scan, shareReplay, skip, startWith, switchMap, switchMapTo, take, tap, withLatestFrom, delayWhen, throttleTime } from "rxjs/operators";
+// import { trigger, state, style, animate, transition } from '@angular/animations'
+// import { MatDrawer } from "@angular/material/sidenav";
+
+// import { LoggingService } from "src/logging";
+// import {
+//   CHANGE_NAVIGATION,
+//   getMultiNgIdsRegionsLabelIndexMap,
+//   getNgIds,
+//   ILandmark,
+//   IOtherLandmarkGeometry,
+//   IPlaneLandmarkGeometry,
+//   IPointLandmarkGeometry,
+//   isDefined,
+//   MOUSE_OVER_LANDMARK,
+//   NgViewerStateInterface
+// } from "src/services/stateStore.service";
+
+// import { getExportNehuba, isSame } from "src/util/fn";
+// import { API_SERVICE_SET_VIEWER_HANDLE_TOKEN, IUserLandmark } from "src/atlasViewer/atlasViewer.apiService.service";
+// import { NehubaViewerUnit } from "./nehubaViewer/nehubaViewer.component";
+// import { compareLandmarksChanged } from "src/util/constants";
+// import { PureContantService } from "src/util";
+// import { ARIA_LABELS, IDS, CONST } from 'common/constants'
+// import { serialiseParcellationRegion } from "common/util"
+// import { ngViewerActionSetPerspOctantRemoval, PANELS, ngViewerActionToggleMax, ngViewerActionAddNgLayer, ngViewerActionRemoveNgLayer } from "src/services/state/ngViewerState.store.helper";
+// import { viewerStateSelectRegionWithIdDeprecated, viewerStateAddUserLandmarks, viewreStateRemoveUserLandmarks, viewerStateCustomLandmarkSelector, viewerStateSelectedParcellationSelector, viewerStateSelectedTemplateSelector, viewerStateSelectedRegionsSelector } from 'src/services/state/viewerState.store.helper'
+// import { SwitchDirective } from "src/util/directives/switch.directive";
+// import {
+//   viewerStateDblClickOnViewer,
+// } from "src/services/state/viewerState.store.helper";
+
+// import { getFourPanel, getHorizontalOneThree, getSinglePanel, getVerticalOneThree, calculateSliceZoomFactor, scanSliceViewRenderFn as scanFn, takeOnePipe } from "./util";
+// import { NehubaViewerContainerDirective } from "./nehubaViewerInterface/nehubaViewerInterface.directive";
+// import { ITunableProp } from "./mobileOverlay/mobileOverlay.component";
+// import { viewerStateMouseOverCustomLandmark } from "src/services/state/viewerState/actions";
+// import { ngViewerSelectorNehubaReady, ngViewerSelectorOctantRemoval, ngViewerSelectorPanelMode, ngViewerSelectorPanelOrder } from "src/services/state/ngViewerState/selectors";
+// import { REGION_OF_INTEREST } from "src/util/interfaces";
+// import { uiActionHideAllDatasets, uiActionHideDatasetWithId } from "src/services/state/uiState/actions";
+
+// const { MESH_LOADING_STATUS } = IDS
+
+// const sortByFreshness: (acc: any[], curr: any[]) => any[] = (acc, curr) => {
+
+//   const getLayerName = ({layer} = {layer: {}}) => {
+//     const { name } = layer as any
+//     return name
+//   }
+
+//   const newEntries = (curr && curr.filter(entry => {
+//     const name = getLayerName(entry)
+//     return acc.map(getLayerName).indexOf(name) < 0
+//   })) || []
+
+//   const entryChanged: (itemPrevState, newArr) => boolean = (itemPrevState, newArr) => {
+//     const layerName = getLayerName(itemPrevState)
+//     const { segment } = itemPrevState
+//     const foundItem = newArr?.find((_item) =>
+//       getLayerName(_item) === layerName)
+
+//     if (foundItem) {
+//       const { segment: foundSegment } = foundItem
+//       return segment !== foundSegment
+//     } else {
+//       /**
+//        * if item was not found in the new array, meaning hovering nothing
+//        */
+//       return segment !== null
+//     }
+//   }
+
+//   const getItemFromLayerName = (item, arr) => {
+//     const foundItem = arr?.find(i => getLayerName(i) === getLayerName(item))
+//     return foundItem
+//       ? foundItem
+//       : {
+//         layer: item.layer,
+//         segment: null,
+//       }
+//   }
+
+//   const getReduceExistingLayers = (newArr) => ([changed, unchanged], _curr) => {
+//     const changedFlag = entryChanged(_curr, newArr)
+//     return changedFlag
+//       ? [ changed.concat( getItemFromLayerName(_curr, newArr) ), unchanged ]
+//       : [ changed, unchanged.concat(_curr) ]
+//   }
+
+//   /**
+//    * now, for all the previous layers, separate into changed and unchanged layers
+//    */
+//   const [changed, unchanged] = acc.reduce(getReduceExistingLayers(curr), [[], []])
+//   return [...newEntries, ...changed, ...unchanged]
+// }
+
+// const {
+//   ZOOM_IN,
+//   ZOOM_OUT,
+//   TOGGLE_FRONTAL_OCTANT,
+//   TOGGLE_SIDE_PANEL,
+//   EXPAND,
+//   COLLAPSE,
+//   ADDITIONAL_VOLUME_CONTROL,
+// } = ARIA_LABELS
+
+// @Component({
+//   selector : 'ui-nehuba-container',
+//   templateUrl : './nehubaContainer.template.html',
+//   styleUrls : [
+//     `./nehubaContainer.style.css`,
+//   ],
+//   animations: [
+//     trigger('openClose', [
+//       state('open', style({
+//         transform: 'translateY(0)',
+//         opacity: 1
+//       })),
+//       state('closed', style({
+//         transform: 'translateY(-100vh)',
+//         opacity: 0
+//       })),
+//       transition('open => closed', [
+//         animate('200ms cubic-bezier(0.35, 0, 0.25, 1)')
+//       ]),
+//       transition('closed => open', [
+//         animate('200ms cubic-bezier(0.35, 0, 0.25, 1)')
+//       ])
+//     ]),
+//     trigger('openCloseAnchor', [
+//       state('open', style({
+//         transform: 'translateY(0)'
+//       })),
+//       state('closed', style({
+//         transform: 'translateY(100vh)'
+//       })),
+//       transition('open => closed', [
+//         animate('200ms cubic-bezier(0.35, 0, 0.25, 1)')
+//       ]),
+//       transition('closed => open', [
+//         animate('200ms cubic-bezier(0.35, 0, 0.25, 1)')
+//       ])
+//     ]),
+//   ],
+//   exportAs: 'uiNehubaContainer',
+//   providers: [
+//     {
+//       provide: REGION_OF_INTEREST,
+//       useFactory: (store: Store<any>) => store.pipe(
+//         select(viewerStateSelectedRegionsSelector),
+//         map(rs => rs[0] || null)
+//       ),
+//       deps: [
+//         Store
+//       ]
+//     }
+//   ]
+// })
+
+// export class NehubaContainer implements OnInit, OnChanges, OnDestroy {
+
+//   public CONST = CONST
+//   public ARIA_LABEL_ZOOM_IN = ZOOM_IN
+//   public ARIA_LABEL_ZOOM_OUT = ZOOM_OUT
+//   public ARIA_LABEL_TOGGLE_FRONTAL_OCTANT = TOGGLE_FRONTAL_OCTANT
+//   public ARIA_LABEL_TOGGLE_SIDE_PANEL = TOGGLE_SIDE_PANEL
+//   public ARIA_LABEL_EXPAND = EXPAND
+//   public ARIA_LABEL_COLLAPSE = COLLAPSE
+//   public ARIA_LABEL_ADDITIONAL_VOLUME_CONTROL = ADDITIONAL_VOLUME_CONTROL
   
-  public ID_MESH_LOADING_STATUS = MESH_LOADING_STATUS
-
-  @ViewChild(NehubaViewerContainerDirective,{static: true})
-  public nehubaContainerDirective: NehubaViewerContainerDirective
-
-  @ViewChild('sideNavMasterSwitch', { static: true })
-  public navSideDrawerMainSwitch: SwitchDirective
-  @ViewChild('sideNavSwitch', { static: true })
-  public navSideDrawerMinorSwitch: SwitchDirective
-
-  @ViewChild('matDrawerMaster', {static: true})
-  public matDrawerMain: MatDrawer
-  @ViewChild('matDrawerMinor', { static: true })
-  public matDrawerMinor: MatDrawer
-
-  @Output()
-  public nehubaViewerLoaded: EventEmitter<boolean> = new EventEmitter()
-
-  @Output()
-  public forceUI$: Observable<{ target: 'perspective:octantRemoval', mode: boolean,  message?: string }>
-
-  public disableOctantRemoval$: Observable<{ message?: string, mode: boolean }>
-
-  public handleViewerLoadedEvent(flag: boolean){
-    this.viewerLoaded = flag
-    this.nehubaViewerLoaded.emit(flag)
-  }
-
-  public viewerLoaded: boolean = false
-
-  private sliceRenderEvent$: Observable<CustomEvent>
-  public sliceViewLoadingMain$: Observable<[boolean, boolean, boolean]>
-  public perspectiveViewLoading$: Observable<string|null>
-  public showPerpsectiveScreen$: Observable<string>
-
-  public templateSelected$: Observable<any> = this.store.pipe(
-    select(viewerStateSelectedTemplateSelector),
-    distinctUntilChanged(isSame),
-  )
-
-  private newViewer$: Observable<any> = this.templateSelected$.pipe(
-    filter(v => !!v),
-  )
-
-  private selectedParcellation$: Observable<any> = this.store.pipe(
-    select(viewerStateSelectedParcellationSelector),
-    distinctUntilChanged(),
-    filter(v => !!v)
-  )
-  public selectedRegions: any[] = []
-  public selectedRegions$: Observable<any[]> = this.store.pipe(
-    select(viewerStateSelectedRegionsSelector),
-    filter(rs => !!rs),
-  )
-
-  public selectedLandmarks$: Observable<any[]>
-  public selectedPtLandmarks$: Observable<any[]>
-  public customLandmarks$: Observable<any> = this.store.pipe(
-    select(viewerStateCustomLandmarkSelector),
-    map(lms => lms.map(lm => ({
-      ...lm,
-      geometry: {
-        position: lm.position
-      }
-    })))
-  )
-  private hideSegmentations$: Observable<boolean>
-
-  private fetchedSpatialDatasets$: Observable<ILandmark[]>
-  private userLandmarks$: Observable<IUserLandmark[]>
-
-  public nehubaViewerPerspectiveOctantRemoval$: Observable<boolean>
-
-  @Input()
-  private currentOnHover: {segments: any, landmark: any, userLandmark: any}
-
-  @Input()
-  currentOnHoverObs$: Observable<{segments: any, landmark: any, userLandmark: any}>
-
-  public iavAdditionalLayers$ = new Subject<any[]>()
-
-  public alwaysHideMinorPanel$: Observable<boolean> = combineLatest(
-    this.selectedRegions$,
-    this.iavAdditionalLayers$.pipe(
-      startWith([])
-    )
-  ).pipe(
-    map(([ regions, layers ]) => regions.length === 0 && layers.length === 0)
-  )
-
-  public onHoverSegments$: BehaviorSubject<any[]> = new BehaviorSubject([])
-  public onHoverSegment$: Observable<any> = this.onHoverSegments$.pipe(
-    scan(sortByFreshness, []),
-    /**
-     * take the first element after sort by freshness
-     */
-    map(arr => arr[0]),
-    /**
-     * map to the older interface
-     */
-    filter(v => !!v),
-    map(({ segment }) => {
-      return {
-        labelIndex: (isNaN(segment) && Number(segment.labelIndex)) || null,
-        foundRegion: (isNaN(segment) && segment) || null,
-      }
-    }),
-  )
-
-  public selectedTemplate: any | null
-  private selectedRegionIndexSet: Set<string> = new Set()
-  public fetchedSpatialData: ILandmark[] = []
-
-  private ngLayersRegister: Partial<NgViewerStateInterface> = {layers : [], forceShowSegment: null}
-  private ngLayers$: Observable<NgViewerStateInterface>
-
-  public selectedParcellation: any | null
-
-  public nehubaViewer: NehubaViewerUnit = null
-  private multiNgIdsRegionsLabelIndexMap: Map<string, Map<number, any>> = new Map()
-  private landmarksLabelIndexMap: Map<number, any> = new Map()
-  private landmarksNameMap: Map<string, number> = new Map()
-
-  private subscriptions: Subscription[] = []
-
-  public nanometersToOffsetPixelsFn: Array<(...arg) => any> = []
-
-  public viewPanels: [HTMLElement, HTMLElement, HTMLElement, HTMLElement] = [null, null, null, null]
-  public panelMode$: Observable<string>
-
-  public panelOrder$: Observable<string>
-  private redrawLayout$: Observable<[string, string]>
-
-  public hoveredPanelIndices$: Observable<number>
-
-  public connectivityNumber: string
-  public connectivityLoadUrl: string
-
-  constructor(
-    private pureConstantService: PureContantService,
-    @Optional() @Inject(API_SERVICE_SET_VIEWER_HANDLE_TOKEN) private setViewerHandle: (arg) => void,
-    private store: Store<any>,
-    private elementRef: ElementRef,
-    private log: LoggingService,
-    private cdr: ChangeDetectorRef,
-    @Optional() @Inject(REGION_OF_INTEREST) public regionOfInterest$: Observable<any>
-  ) {
-
-    this.useMobileUI$ = this.pureConstantService.useTouchUI$
-
-    this.nehubaViewerPerspectiveOctantRemoval$ = this.store.pipe(
-      select(ngViewerSelectorOctantRemoval),
-    )
-
-    this.panelMode$ = this.store.pipe(
-      select(ngViewerSelectorPanelMode),
-      distinctUntilChanged(),
-      shareReplay(1),
-    )
-
-    this.panelOrder$ = this.store.pipe(
-      select(ngViewerSelectorPanelOrder),
-      distinctUntilChanged(),
-      shareReplay(1),
-    )
-
-    this.redrawLayout$ = this.store.pipe(
-      select(ngViewerSelectorNehubaReady),
-      distinctUntilChanged(),
-      filter(v => !!v),
-      switchMapTo(combineLatest([
-        this.panelMode$,
-        this.panelOrder$,
-      ])),
-    )
-
-    this.selectedLandmarks$ = this.store.pipe(
-      select('viewerState'),
-      select('landmarksSelected'),
-    )
-
-    this.selectedPtLandmarks$ = this.selectedLandmarks$.pipe(
-      map(lms => lms.filter(lm => lm.geometry.type === 'point')),
-    )
-
-    this.fetchedSpatialDatasets$ = this.store.pipe(
-      select('dataStore'),
-      select('fetchedSpatialData'),
-      distinctUntilChanged(compareLandmarksChanged),
-      filter(v => !!v),
-      startWith([]),
-      debounceTime(300),
-    )
-
-    this.userLandmarks$ = this.store.pipe(
-      select(viewerStateCustomLandmarkSelector),
-      distinctUntilChanged(),
-    )
-
-    /**
-     * in future, perhaps add other force UI optinos here
-     */
-    this.forceUI$ = this.userLandmarks$.pipe(
-      map(lm => {
-        if (lm.length > 0) {
-          return {
-            target: 'perspective:octantRemoval',
-            mode: false,
-            message: `octant control disabled: showing landmarks.`
-          }
-        } else {
-          return {
-            target: 'perspective:octantRemoval',
-            mode: null
-          }
-        }
-      })
-    )
-
-    this.disableOctantRemoval$ = this.forceUI$.pipe(
-      filter(({ target }) => target === 'perspective:octantRemoval'),
-    )
-
-    this.sliceRenderEvent$ = fromEvent(this.elementRef.nativeElement, 'sliceRenderEvent').pipe(
-      map(ev => ev as CustomEvent)
-    )
-
-    this.sliceViewLoadingMain$ = this.sliceRenderEvent$.pipe(
-      scan(scanFn, [null, null, null]),
-      startWith([true, true, true] as [boolean, boolean, boolean]),
-      shareReplay(1),
-    )
-
-    this.showPerpsectiveScreen$ = this.newViewer$.pipe(
-      switchMapTo(this.sliceRenderEvent$.pipe(
-        scan((acc, curr) => {
-
-          /**
-           * if at any point, all chunks have been loaded, always return loaded state
-           */
-          if (acc.every(v => v === 0)) return [0, 0, 0]
-          const { detail = {}, target } = curr || {}
-          const { missingChunks = -1, missingImageChunks = -1 } = detail
-          const idx = this.findPanelIndex(target as HTMLElement)
-          const returnAcc = [...acc]
-          if (idx >= 0) {
-            returnAcc[idx] = missingChunks + missingImageChunks
-          }
-          return returnAcc
-        }, [-1, -1, -1]),
-        map(arr => {
-          let sum = 0
-          let uncertain = false
-          for (const num of arr) {
-            if (num < 0) {
-              uncertain = true
-            } else {
-              sum += num
-            }
-          }
-          return sum > 0
-            ? `Loading ${sum}${uncertain ? '+' : ''} chunks ...`
-            : null
-        }),
-        distinctUntilChanged(),
-        startWith('Loading ...'),
-        throttleTime(100, asyncScheduler, { leading: true, trailing: true }),
-        shareReplay(1),
-      ))
-    )
-
-    /* missing chunk perspective view */
-    this.perspectiveViewLoading$ = fromEvent(this.elementRef.nativeElement, 'perpspectiveRenderEvent')
-      .pipe(
-        filter(event => isDefined(event) && isDefined((event as any).detail) && isDefined((event as any).detail.lastLoadedMeshId) ),
-        map(event => {
-
-          /**
-           * TODO dig into event detail to see if the exact mesh loaded
-           */
-          const { meshesLoaded, meshFragmentsLoaded, lastLoadedMeshId } = (event as any).detail
-          return meshesLoaded >= this.nehubaViewer.numMeshesToBeLoaded
-            ? null
-            : 'Loading meshes ...'
-        }),
-        distinctUntilChanged()
-      )
-
-    this.ngLayers$ = this.store.pipe(
-      select('ngViewerState'),
-    )
-
-    this.hideSegmentations$ = this.ngLayers$.pipe(
-      map(state => isDefined(state)
-        ? state.layers?.findIndex(l => l.mixability === 'nonmixable') >= 0
-        : false),
-    )
-
-    /**
-     * fixes 
-     * https://github.com/HumanBrainProject/interactive-viewer/issues/800
-     */
-    this.subscriptions.push(
-      this.nehubaViewerLoaded.pipe(
-        debounceTime(500),
-        filter(v => !v),
-      ).subscribe(() => {
-        this.matDrawerMain.close()
-        this.matDrawerMinor.close()
-      })
-    )
-  }
-
-  public useMobileUI$: Observable<boolean>
-
-  private removeExistingPanels() {
-    const element = this.nehubaViewer.nehubaViewer.ngviewer.layout.container.componentValue.element as HTMLElement
-    while (element.childElementCount > 0) {
-      element.removeChild(element.firstElementChild)
-    }
-    return element
-  }
-
-  private findPanelIndex = (panel: HTMLElement) => this.viewPanels?.findIndex(p => p === panel)
-
-  private _exportNehuba: any
-  get exportNehuba() {
-    if (!this._exportNehuba) {
-      this._exportNehuba = getExportNehuba()
-    }
-    return this._exportNehuba
-  }
-
-  public ngOnInit() {
-    this.hoveredPanelIndices$ = fromEvent(this.elementRef.nativeElement, 'mouseover').pipe(
-      switchMap((ev: MouseEvent) => merge(
-        of(this.findPanelIndex(ev.target as HTMLElement)),
-        fromEvent(this.elementRef.nativeElement, 'mouseout').pipe(
-          mapTo(null),
-        ),
-      )),
-      debounceTime(20),
-      shareReplay(1),
-    )
-
-    // TODO deprecate
-    /* each time a new viewer is initialised, take the first event to get the translation function */
-    this.subscriptions.push(
-      this.newViewer$.pipe(
-        switchMapTo(this.sliceRenderEvent$.pipe(
-          takeOnePipe()
-        ))
-      ).subscribe((events) => {
-        for (const idx in [0, 1, 2]) {
-          const ev = events[idx] as CustomEvent
-          this.viewPanels[idx] = ev.target as HTMLElement
-          this.nanometersToOffsetPixelsFn[idx] = ev.detail.nanometersToOffsetPixels
-        }
-      }),
-    )
-
-    this.subscriptions.push(
-      this.newViewer$.pipe(
-        switchMapTo(fromEvent(this.elementRef.nativeElement, 'perpspectiveRenderEvent').pipe(
-          take(1),
-        )),
-      ).subscribe(ev => this.viewPanels[3] = ((ev as CustomEvent).target) as HTMLElement),
-    )
-
-    this.subscriptions.push(
-      this.redrawLayout$.subscribe(([mode, panelOrder]) => {
-        const viewPanels = panelOrder.split('').map(v => Number(v)).map(idx => this.viewPanels[idx]) as [HTMLElement, HTMLElement, HTMLElement, HTMLElement]
-        /**
-         * TODO be smarter with event stream
-         */
-        if (!this.nehubaViewer) { return }
-
-        /**
-         * TODO smarter with event stream
-         */
-        if (!viewPanels.every(v => !!v)) { return }
-
-        switch (mode) {
-        case PANELS.H_ONE_THREE: {
-          const element = this.removeExistingPanels()
-          const newEl = getHorizontalOneThree(viewPanels)
-          element.appendChild(newEl)
-          break;
-        }
-        case PANELS.V_ONE_THREE: {
-          const element = this.removeExistingPanels()
-          const newEl = getVerticalOneThree(viewPanels)
-          element.appendChild(newEl)
-          break;
-        }
-        case PANELS.FOUR_PANEL: {
-          const element = this.removeExistingPanels()
-          const newEl = getFourPanel(viewPanels)
-          element.appendChild(newEl)
-          break;
-        }
-        case PANELS.SINGLE_PANEL: {
-          const element = this.removeExistingPanels()
-          const newEl = getSinglePanel(viewPanels)
-          element.appendChild(newEl)
-          break;
-        }
-        default:
-        }
-        for (const panel of viewPanels) {
-          (panel as HTMLElement).classList.add('neuroglancer-panel')
-        }
-
-        // TODO needed to redraw?
-        // see https://trello.com/c/oJOnlc6v/60-enlarge-panel-allow-user-rearrange-panel-position
-        // further investigaation required
-        this.nehubaViewer.redraw()
-      }),
-    )
-
-    this.subscriptions.push(
-      this.fetchedSpatialDatasets$.subscribe(datasets => {
-        this.landmarksLabelIndexMap = new Map(datasets.map((v, idx) => [idx, v]) as Array<[number, any]>)
-        this.landmarksNameMap = new Map(datasets.map((v, idx) => [v.name, idx] as [string, number]))
-      }),
-    )
-
-    /**
-     * TODO deprecate, but document the method
-     */
-    this.subscriptions.push(
-      combineLatest(
-        this.fetchedSpatialDatasets$,
-      ).subscribe(([fetchedSpatialData]) => {
-        this.fetchedSpatialData = fetchedSpatialData
-
-        if (this.fetchedSpatialData?.length > 0) {
-          this.nehubaViewer.addSpatialSearch3DLandmarks(
-            this.fetchedSpatialData
-              .map(data => data.geometry.type === 'point'
-                ? (data.geometry as IPointLandmarkGeometry).position
-                : data.geometry.type === 'plane'
-                  ? [
-                    (data.geometry as IPlaneLandmarkGeometry).corners,
-                    [[0, 1, 2], [0, 2, 3]],
-                  ]
-                  : data.geometry.type === 'mesh'
-                    ? [
-                      (data.geometry as IOtherLandmarkGeometry).vertices,
-                      (data.geometry as IOtherLandmarkGeometry).meshIdx,
-                    ]
-                    : null),
-          )
-        } else {
-          if (this.nehubaViewer && this.nehubaViewer.removeSpatialSearch3DLandmarks instanceof Function) {
-            this.nehubaViewer.removeSpatialSearch3DLandmarks()
-          }
-        }
-      }),
-    )
-
-    this.subscriptions.push(
-      this.userLandmarks$.pipe(
-        withLatestFrom(
-          this.nehubaViewerPerspectiveOctantRemoval$
-        )
-      ).subscribe(([landmarks, flag]) => {
-        if (this.nehubaContainerDirective) {
-          this.nehubaContainerDirective.toggleOctantRemoval(
-            landmarks.length > 0 ? false : flag
-          )
-        }
-        if (this.nehubaViewer) {
-          this.nehubaViewer.updateUserLandmarks(landmarks)
-        }
-      }),
-    )
-
-    this.subscriptions.push(
-      this.newViewer$.pipe(
-        skip(1),
-      ).subscribe(() => {
-
-        /* on selecting of new template, remove additional nglayers */
-        const baseLayerNames = Object.keys(this.selectedTemplate.nehubaConfig.dataset.initialNgState.layers)
-        this.ngLayersRegister.layers
-          .filter(layer => baseLayerNames?.findIndex(l => l === layer.name) < 0)
-          .map(l => l.name)
-          .forEach(layerName => {
-            this.store.dispatch(ngViewerActionRemoveNgLayer({
-              layer: {
-                name: layerName
-              }
-            }))
-          })
-      }),
-    )
-
-    this.subscriptions.push(
-      this.templateSelected$.subscribe(() => this.destroynehuba()),
-    )
-
-    /* order of subscription will determine the order of execution */
-    this.subscriptions.push(
-      this.newViewer$.pipe(
-        map(templateSelected => {
-          const deepCopiedState = JSON.parse(JSON.stringify(templateSelected))
-          const navigation = deepCopiedState.nehubaConfig.dataset.initialNgState.navigation
-          if (!navigation) {
-            return deepCopiedState
-          }
-          navigation.zoomFactor = calculateSliceZoomFactor(navigation.zoomFactor)
-          deepCopiedState.nehubaConfig.dataset.initialNgState.navigation = navigation
-          return deepCopiedState
-        }),
-        withLatestFrom(
-          this.selectedParcellation$.pipe(
-            startWith(null),
-          )
-        ),
-      ).subscribe(([templateSelected, parcellationSelected]) => {
-
-        this.selectedTemplate = templateSelected
-        this.createNewNehuba(templateSelected)
-        const foundParcellation = parcellationSelected
-          && templateSelected?.parcellations?.find(parcellation => parcellationSelected.name === parcellation.name)
-        this.handleParcellation(foundParcellation || templateSelected.parcellations[0])
-
-        const nehubaConfig = templateSelected.nehubaConfig
-        const initialSpec = nehubaConfig.dataset.initialNgState
-        const {layers} = initialSpec
-
-        const dispatchLayers = Object.keys(layers).map(key => {
-          const layer = {
-            name : key,
-            source : layers[key].source,
-            mixability : layers[key].type === 'image'
-              ? 'base'
-              : 'mixable',
-            visible : typeof layers[key].visible === 'undefined'
-              ? true
-              : layers[key].visible,
-            transform : typeof layers[key].transform === 'undefined'
-              ? null
-              : layers[key].transform,
-          }
-          this.ngLayersRegister.layers.push(layer)
-          return layer
-        })
-
-        this.store.dispatch(ngViewerActionAddNgLayer({
-          layer: dispatchLayers
-        }))
-      })
-    )
-
-    let prevParcellation = null
-
-    this.subscriptions.push(
-
-      combineLatest([
-        this.selectedRegions$.pipe(
-          distinctUntilChanged(),
-        ),
-        this.hideSegmentations$.pipe(
-          distinctUntilChanged(),
-        ),
-        this.ngLayers$.pipe(
-          map(state => state.forceShowSegment),
-          distinctUntilChanged(),
-        ),
-        this.selectedParcellation$,
-        this.store.pipe(
-          select('viewerState'),
-          select('overwrittenColorMap'),
-          distinctUntilChanged()
-        )
-      ]).pipe(
-        delayWhen(() => timer())
-      ).subscribe(([regions, hideSegmentFlag, forceShowSegment, selectedParcellation, overwrittenColorMap]) => {
-        if (!this.nehubaViewer) { return }
-
-        const { ngId: defaultNgId } = selectedParcellation
-
-        /* selectedregionindexset needs to be updated regardless of forceshowsegment */
-        this.selectedRegionIndexSet = !prevParcellation || prevParcellation === selectedParcellation?
-          new Set(regions.map(({ngId = defaultNgId, labelIndex}) => generateLabelIndexId({ ngId, labelIndex }))) : new Set()
-
-        if ( forceShowSegment === false || (forceShowSegment === null && hideSegmentFlag) ) {
-          this.nehubaViewer.hideAllSeg()
-          return
-        }
-
-        this.selectedRegionIndexSet.size > 0 && !overwrittenColorMap
-          ? this.nehubaViewer.showSegs([...this.selectedRegionIndexSet])
-          : this.nehubaViewer.showAllSeg()
-
-        prevParcellation = selectedParcellation
-      }),
-    )
-
-    this.subscriptions.push(
-      this.ngLayers$.subscribe(ngLayersInterface => {
-        if (!this.nehubaViewer) { return }
-
-        const newLayers = ngLayersInterface.layers.filter(l => this.ngLayersRegister.layers?.findIndex(ol => ol.name === l.name) < 0)
-        const removeLayers = this.ngLayersRegister.layers.filter(l => ngLayersInterface.layers?.findIndex(nl => nl.name === l.name) < 0)
-
-        if (newLayers?.length > 0) {
-          const newLayersObj: any = {}
-          newLayers.forEach(({ name, source, ...rest }) => newLayersObj[name] = {
-            ...rest,
-            source,
-            // source: getProxyUrl(source),
-            // ...getProxyOther({source})
-          })
-
-          if (!this.nehubaViewer.nehubaViewer || !this.nehubaViewer.nehubaViewer.ngviewer) {
-            this.nehubaViewer.initNiftiLayers.push(newLayersObj)
-          } else {
-            this.nehubaViewer.loadLayer(newLayersObj)
-          }
-          this.ngLayersRegister.layers = this.ngLayersRegister.layers.concat(newLayers)
-        }
-
-        if (removeLayers?.length > 0) {
-          removeLayers.forEach(l => {
-            if (this.nehubaViewer.removeLayer({
-              name : l.name,
-            })) {
-              this.ngLayersRegister.layers = this.ngLayersRegister.layers.filter(rl => rl.name !== l.name)
-            }
-          })
-        }
-      }),
-    )
-
-    this.subscriptions.push(
-      this.selectedParcellation$.subscribe(this.handleParcellation.bind(this))
-    )
-
-    /* setup init view state */
-
-    this.subscriptions.push(
-      this.selectedRegions$.pipe(
-        filter(() => !!this.nehubaViewer),
-      ).subscribe(regions => {
-        this.nehubaViewer.initRegions = regions.map(({ ngId, labelIndex }) => generateLabelIndexId({ ngId, labelIndex }))
-      })
-    )
-
-    this.subscriptions.push(this.selectedRegions$.subscribe(sr => {
-      this.selectedRegions = sr
-    }))
-
-    /** switch side nav */
-    this.subscriptions.push(
-      this.alwaysHideMinorPanel$.pipe(
-        distinctUntilChanged()
-      ).subscribe(flag => {
-        if (!flag) {
-          this.matDrawerMinor && this.matDrawerMinor.open()
-          this.navSideDrawerMainSwitch && this.navSideDrawerMainSwitch.open()
-        }
-      })
-    )
-
-    this.subscriptions.push(
-      this.selectedRegions$.subscribe(regions => {
-        this.selectedRegions = regions
-      })
-    )
-
-    /* handler to open/select landmark */
-    const clickObs$ = fromEvent(this.elementRef.nativeElement, 'click')
-
-    this.subscriptions.push(
-      clickObs$.pipe(
-        buffer(
-          clickObs$.pipe(
-            debounceTime(200),
-          ),
-        ),
-        filter(arr => arr?.length >= 2),
-      )
-        .subscribe(() => {
-          const { currentOnHover } = this
-          this.store.dispatch(viewerStateDblClickOnViewer({
-            payload: { ...currentOnHover }
-          }))
-        }),
-    )
-
-    this.subscriptions.push(
-      this.selectedLandmarks$.pipe(
-        map(lms => lms.map(lm => this.landmarksNameMap.get(lm.name))),
-        debounceTime(16),
-      ).subscribe(indices => {
-        const filteredIndices = indices.filter(v => typeof v !== 'undefined' && v !== null)
-        if (this.nehubaViewer) {
-          this.nehubaViewer.spatialLandmarkSelectionChanged(filteredIndices)
-        }
-      }),
-    )
-  }
-
-  // datasetViewerRegistry : Set<string> = new Set()
-  public showObliqueScreen$: Observable<boolean>
-  public showObliqueSelection$: Observable<boolean>
-  public showObliqueRotate$: Observable<boolean>
-
-  private currOnHoverObsSub: Subscription
-  public ngOnChanges() {
-    this.currOnHoverObsSub && this.currOnHoverObsSub.unsubscribe()
-    if (this.currentOnHoverObs$) {
-      this.currOnHoverObsSub = this.currentOnHoverObs$.subscribe(({ segments }) => this.onHoverSegments$.next(segments))
-    }
-  }
-
-  public ngOnDestroy() {
-    this.subscriptions.forEach(s => s.unsubscribe())
-  }
-
-  public toggleMaximiseMinimise(index: number) {
-    this.store.dispatch(ngViewerActionToggleMax({
-      payload: { index }
-    }))
-  }
-
-  public tunableMobileProperties: ITunableProp[] = []
-
-
-  public selectedProp = null
-
-  public returnTruePos(quadrant: number, data: any) {
-    const pos = quadrant > 2
-      ? [0, 0, 0]
-      : this.nanometersToOffsetPixelsFn && this.nanometersToOffsetPixelsFn[quadrant]
-        ? this.nanometersToOffsetPixelsFn[quadrant](data.geometry.position.map(n => n * 1e6))
-        : [0, 0, 0]
-    return pos
-  }
-
-  public getPositionX(quadrant: number, data: any) {
-    return this.returnTruePos(quadrant, data)[0]
-  }
-  public getPositionY(quadrant: number, data: any) {
-    return this.returnTruePos(quadrant, data)[1]
-  }
-  public getPositionZ(quadrant: number, data: any) {
-    return this.returnTruePos(quadrant, data)[2]
-  }
-
-  public handleMouseEnterCustomLandmark(lm) {
-    this.store.dispatch(
-      viewerStateMouseOverCustomLandmark({
-        payload: { userLandmark: lm }
-      })
-    )
-  }
-
-  public handleMouseLeaveCustomLandmark(lm) {
-    this.store.dispatch(
-      viewerStateMouseOverCustomLandmark({
-        payload: { userLandmark: null }
-      })
-    )
-  }
-
-  // handles mouse enter/leave landmarks in 2D
-  public handleMouseEnterLandmark(spatialData: any) {
-    spatialData.highlight = true
-    this.store.dispatch({
-      type : MOUSE_OVER_LANDMARK,
-      landmark : spatialData._label,
-    })
-  }
-
-  public handleMouseLeaveLandmark(spatialData: any) {
-    spatialData.highlight = false
-    this.store.dispatch({
-      type : MOUSE_OVER_LANDMARK,
-      landmark : null,
-    })
-  }
-
-  private handleParcellation(parcellation: any) {
-    /**
-     * parcellaiton may be undefined
-     */
-    if ( !(parcellation && parcellation.regions)) {
-      return
-    }
-
-    /**
-     * first, get all all the ngIds, including parent id from parcellation (if defined)
-     */
-    const ngIds = getNgIds(parcellation.regions).concat( parcellation.ngId ? parcellation.ngId : [])
-
-    this.multiNgIdsRegionsLabelIndexMap = getMultiNgIdsRegionsLabelIndexMap(parcellation)
-
-    this.nehubaViewer.multiNgIdsLabelIndexMap = this.multiNgIdsRegionsLabelIndexMap
-    this.nehubaViewer.auxilaryMeshIndices = parcellation.auxillaryMeshIndices || []
-
-    /* TODO replace with proper KG id */
-    /**
-     * need to set unique array of ngIds, or else workers will be overworked
-     */
-    this.nehubaViewer.ngIds = Array.from(new Set(ngIds))
-    this.selectedParcellation = parcellation
-  }
-
-  /* related spatial search */
-  public spatialSearchPagination: number = 0
-
-  private destroynehuba() {
-    /**
-     * TODO if plugin subscribes to viewerHandle, and then new template is selected, changes willl not be be sent
-     * could be considered as a bug.
-     */
-    this.setViewerHandle && this.setViewerHandle(null)
-    this.nehubaContainerDirective.clear()
-
-    this.nehubaViewer = null
-
-    this.cdr.detectChanges()
-  }
-
-  private createNewNehuba(template: any) {
-
-    this.nehubaContainerDirective.createNehubaInstance(template)
-    this.nehubaViewer = this.nehubaContainerDirective.nehubaViewerInstance
-
-    this.setupViewerHandleApi()
-  }
-
-  private setupViewerHandleApi() {
-    const viewerHandle = {
-      setNavigationLoc : (coord, realSpace?) => this.nehubaViewer.setNavigationState({
-        position : coord,
-        positionReal : typeof realSpace !== 'undefined' ? realSpace : true,
-      }),
-      /* TODO introduce animation */
-      moveToNavigationLoc : (coord, realSpace?) => {
-        this.store.dispatch({
-          type: CHANGE_NAVIGATION,
-          navigation: {
-            position: coord,
-            animation: {},
-          },
-        })
-      },
-      setNavigationOri : (quat) => this.nehubaViewer.setNavigationState({
-        orientation : quat,
-      }),
-      /* TODO introduce animation */
-      moveToNavigationOri : (quat) => this.nehubaViewer.setNavigationState({
-        orientation : quat,
-      }),
-      showSegment : (_labelIndex) => {
-        /**
-         * TODO reenable with updated select_regions api
-         */
-        this.log.warn(`showSegment is temporarily disabled`)
-
-        // if(!this.selectedRegionIndexSet.has(labelIndex))
-        //   this.store.dispatch({
-        //     type : SELECT_REGIONS,
-        //     selectRegions :  [labelIndex, ...this.selectedRegionIndexSet]
-        //   })
-      },
-      add3DLandmarks : landmarks => {
-        // TODO check uniqueness of ID
-        if (!landmarks.every(l => isDefined(l.id))) {
-          throw new Error('every landmarks needs to be identified with the id field')
-        }
-        if (!landmarks.every(l => isDefined(l.position))) {
-          throw new Error('every landmarks needs to have position defined')
-        }
-        if (!landmarks.every(l => l.position.constructor === Array) || !landmarks.every(l => l.position.every(v => !isNaN(v))) || !landmarks.every(l => l.position.length == 3)) {
-          throw new Error('position needs to be a length 3 tuple of numbers ')
-        }
-
-        this.store.dispatch(viewerStateAddUserLandmarks({
-          landmarks
-        }))
-      },
-      remove3DLandmarks : landmarkIds => {
-        this.store.dispatch(viewreStateRemoveUserLandmarks({
-          payload: { landmarkIds }
-        }))
-      },
-      hideSegment : (_labelIndex) => {
-        /**
-         * TODO reenable with updated select_regions api
-         */
-        this.log.warn(`hideSegment is temporarily disabled`)
-
-        // if(this.selectedRegionIndexSet.has(labelIndex)){
-        //   this.store.dispatch({
-        //     type :SELECT_REGIONS,
-        //     selectRegions : [...this.selectedRegionIndexSet].filter(num=>num!==labelIndex)
-        //   })
-        // }
-      },
-      showAllSegments : () => {
-        const selectRegionIds = []
-        this.multiNgIdsRegionsLabelIndexMap.forEach((map, ngId) => {
-          Array.from(map.keys()).forEach(labelIndex => {
-            selectRegionIds.push(generateLabelIndexId({ ngId, labelIndex }))
-          })
-        })
-        this.store.dispatch(viewerStateSelectRegionWithIdDeprecated({
-          selectRegionIds
-        }))
-      },
-      hideAllSegments : () => {
-        this.store.dispatch(viewerStateSelectRegionWithIdDeprecated({
-          selectRegionIds: []
-        }))
-      },
-      segmentColourMap : new Map(),
-      getLayersSegmentColourMap: () => {
-        const newMainMap = new Map()
-        for (const [key, colormap] of this.nehubaViewer.multiNgIdColorMap.entries()) {
-          const newColormap = new Map()
-          newMainMap.set(key, newColormap)
-
-          for (const [lableIndex, entry] of colormap.entries()) {
-            newColormap.set(lableIndex, JSON.parse(JSON.stringify(entry)))
-          }
-        }
-        return newMainMap
-      },
-      applyColourMap : (_map) => {
-        throw new Error(`apply color map has been deprecated. use applyLayersColourMap instead`)
-      },
-      applyLayersColourMap: (map) => {
-        this.nehubaViewer.setColorMap(map)
-      },
-      loadLayer : (layerObj) => this.nehubaViewer.loadLayer(layerObj),
-      removeLayer : (condition) => this.nehubaViewer.removeLayer(condition),
-      setLayerVisibility : (condition, visible) => this.nehubaViewer.setLayerVisibility(condition, visible),
-      mouseEvent : merge(
-        fromEvent(this.elementRef.nativeElement, 'click').pipe(
-          map((ev: MouseEvent) => ({eventName : 'click', event: ev})),
-        ),
-        fromEvent(this.elementRef.nativeElement, 'mousemove').pipe(
-          map((ev: MouseEvent) => ({eventName : 'mousemove', event: ev})),
-        ),
-        /**
-         * neuroglancer prevents propagation, so use capture instead
-         */
-        Observable.create(observer => {
-          this.elementRef.nativeElement.addEventListener('mousedown', event => observer.next({eventName: 'mousedown', event}), true)
-        }) as Observable<{eventName: string, event: MouseEvent}>,
-        fromEvent(this.elementRef.nativeElement, 'mouseup').pipe(
-          map((ev: MouseEvent) => ({eventName : 'mouseup', event: ev})),
-        ),
-      ) ,
-      mouseOverNehuba : this.onHoverSegment$.pipe(
-        tap(() => console.warn('mouseOverNehuba observable is becoming deprecated. use mouseOverNehubaLayers instead.')),
-      ),
-      mouseOverNehubaLayers: this.onHoverSegments$,
-      mouseOverNehubaUI: this.currentOnHoverObs$.pipe(
-        map(({ landmark, segments, userLandmark: customLandmark }) => ({ segments, landmark, customLandmark })),
-        shareReplay(1),
-      ),
-      getNgHash : this.nehubaViewer.getNgHash,
-    }
-
-    this.setViewerHandle && this.setViewerHandle(viewerHandle)
-  }
-
-  public setOctantRemoval(octantRemovalFlag: boolean) {
-    this.store.dispatch(
-      ngViewerActionSetPerspOctantRemoval({
-        octantRemovalFlag
-      })
-    )
-  }
-
-  public zoomNgView(panelIndex: number, factor: number) {
-    const ngviewer = this.nehubaViewer?.nehubaViewer?.ngviewer
-    if (!ngviewer) throw new Error(`ngviewer not defined!`)
-
-    /**
-     * panelIndex < 3 === slice view
-     */
-    if (panelIndex < 3) {
-      /**
-       * factor > 1 === zoom out
-       */
-      ngviewer.navigationState.zoomBy(factor)
-    } else {
-      ngviewer.perspectiveNavigationState.zoomBy(factor)
-    }
-  }
-
-  public clearPreviewingDataset(id: string){
-    /**
-     * clear all preview
-     */
-    this.store.dispatch(
-      id
-        ? uiActionHideDatasetWithId({ id })
-        : uiActionHideAllDatasets()
-    )
-  }
-}
+//   public ID_MESH_LOADING_STATUS = MESH_LOADING_STATUS
+
+//   @ViewChild(NehubaViewerContainerDirective,{static: true})
+//   public nehubaContainerDirective: NehubaViewerContainerDirective
+
+//   // @ViewChild('sideNavMasterSwitch', { static: true })
+//   // public navSideDrawerMainSwitch: SwitchDirective
+//   // @ViewChild('sideNavSwitch', { static: true })
+//   // public navSideDrawerMinorSwitch: SwitchDirective
+
+//   @ViewChild('matDrawerMaster', {static: true})
+//   public matDrawerMain: MatDrawer
+//   @ViewChild('matDrawerMinor', { static: true })
+//   public matDrawerMinor: MatDrawer
+
+//   @Output()
+//   public nehubaViewerLoaded: EventEmitter<boolean> = new EventEmitter()
+
+//   @Output()
+//   public forceUI$: Observable<{ target: 'perspective:octantRemoval', mode: boolean,  message?: string }>
+
+//   public disableOctantRemoval$: Observable<{ message?: string, mode: boolean }>
+
+//   public handleViewerLoadedEvent(flag: boolean){
+//     this.viewerLoaded = flag
+//     this.nehubaViewerLoaded.emit(flag)
+//   }
+
+//   public viewerLoaded: boolean = false
+
+//   private sliceRenderEvent$: Observable<CustomEvent>
+//   public sliceViewLoadingMain$: Observable<[boolean, boolean, boolean]>
+//   public perspectiveViewLoading$: Observable<string|null>
+//   public showPerpsectiveScreen$: Observable<string>
+
+//   public templateSelected$: Observable<any> = this.store.pipe(
+//     select(viewerStateSelectedTemplateSelector),
+//     distinctUntilChanged(isSame),
+//   )
+
+//   private newViewer$: Observable<any> = this.templateSelected$.pipe(
+//     filter(v => !!v),
+//   )
+
+//   private selectedParcellation$: Observable<any> = this.store.pipe(
+//     select(viewerStateSelectedParcellationSelector),
+//     distinctUntilChanged(),
+//     filter(v => !!v)
+//   )
+//   public selectedRegions: any[] = []
+//   public selectedRegions$: Observable<any[]> = this.store.pipe(
+//     select(viewerStateSelectedRegionsSelector),
+//     filter(rs => !!rs),
+//   )
+
+//   public selectedLandmarks$: Observable<any[]>
+//   public selectedPtLandmarks$: Observable<any[]>
+//   public customLandmarks$: Observable<any> = this.store.pipe(
+//     select(viewerStateCustomLandmarkSelector),
+//     map(lms => lms.map(lm => ({
+//       ...lm,
+//       geometry: {
+//         position: lm.position
+//       }
+//     })))
+//   )
+//   private hideSegmentations$: Observable<boolean>
+
+//   private fetchedSpatialDatasets$: Observable<ILandmark[]>
+//   private userLandmarks$: Observable<IUserLandmark[]>
+
+//   public nehubaViewerPerspectiveOctantRemoval$: Observable<boolean>
+
+//   @Input()
+//   private currentOnHover: {segments: any, landmark: any, userLandmark: any}
+
+//   @Input()
+//   currentOnHoverObs$: Observable<{segments: any, landmark: any, userLandmark: any}>
+
+//   public iavAdditionalLayers$ = new Subject<any[]>()
+
+//   // public alwaysHideMinorPanel$: Observable<boolean> = combineLatest(
+//   //   this.selectedRegions$,
+//   //   this.iavAdditionalLayers$.pipe(
+//   //     startWith([])
+//   //   )
+//   // ).pipe(
+//   //   map(([ regions, layers ]) => regions.length === 0 && layers.length === 0)
+//   // )
+
+//   public onHoverSegments$: BehaviorSubject<any[]> = new BehaviorSubject([])
+//   public onHoverSegment$: Observable<any> = this.onHoverSegments$.pipe(
+//     scan(sortByFreshness, []),
+//     /**
+//      * take the first element after sort by freshness
+//      */
+//     map(arr => arr[0]),
+//     /**
+//      * map to the older interface
+//      */
+//     filter(v => !!v),
+//     map(({ segment }) => {
+//       return {
+//         labelIndex: (isNaN(segment) && Number(segment.labelIndex)) || null,
+//         foundRegion: (isNaN(segment) && segment) || null,
+//       }
+//     }),
+//   )
+
+//   public selectedTemplate: any | null
+//   private selectedRegionIndexSet: Set<string> = new Set()
+//   public fetchedSpatialData: ILandmark[] = []
+
+//   private ngLayersRegister: Partial<NgViewerStateInterface> = {layers : [], forceShowSegment: null}
+//   private ngLayers$: Observable<NgViewerStateInterface>
+
+//   public selectedParcellation: any | null
+
+//   public nehubaViewer: NehubaViewerUnit = null
+//   private multiNgIdsRegionsLabelIndexMap: Map<string, Map<number, any>> = new Map()
+//   private landmarksLabelIndexMap: Map<number, any> = new Map()
+//   private landmarksNameMap: Map<string, number> = new Map()
+
+//   private subscriptions: Subscription[] = []
+
+//   public nanometersToOffsetPixelsFn: Array<(...arg) => any> = []
+
+//   public viewPanels: [HTMLElement, HTMLElement, HTMLElement, HTMLElement] = [null, null, null, null]
+//   public panelMode$: Observable<string>
+
+//   public panelOrder$: Observable<string>
+//   private redrawLayout$: Observable<[string, string]>
+
+//   public hoveredPanelIndices$: Observable<number>
+
+//   public connectivityNumber: string
+
+//   constructor(
+//     private pureConstantService: PureContantService,
+//     @Optional() @Inject(API_SERVICE_SET_VIEWER_HANDLE_TOKEN) private setViewerHandle: (arg) => void,
+//     private store: Store<any>,
+//     private elementRef: ElementRef,
+//     private log: LoggingService,
+//     private cdr: ChangeDetectorRef,
+//     @Optional() @Inject(REGION_OF_INTEREST) public regionOfInterest$: Observable<any>
+//   ) {
+
+//     this.useMobileUI$ = this.pureConstantService.useTouchUI$
+
+//     // this.nehubaViewerPerspectiveOctantRemoval$ = this.store.pipe(
+//     //   select(ngViewerSelectorOctantRemoval),
+//     // )
+
+//     // this.panelMode$ = this.store.pipe(
+//     //   select(ngViewerSelectorPanelMode),
+//     //   distinctUntilChanged(),
+//     //   shareReplay(1),
+//     // )
+
+//     // this.panelOrder$ = this.store.pipe(
+//     //   select(ngViewerSelectorPanelOrder),
+//     //   distinctUntilChanged(),
+//     //   shareReplay(1),
+//     // )
+
+//     // this.redrawLayout$ = this.store.pipe(
+//     //   select(ngViewerSelectorNehubaReady),
+//     //   distinctUntilChanged(),
+//     //   filter(v => !!v),
+//     //   switchMapTo(combineLatest([
+//     //     this.panelMode$,
+//     //     this.panelOrder$,
+//     //   ])),
+//     // )
+
+//     this.selectedLandmarks$ = this.store.pipe(
+//       select('viewerState'),
+//       select('landmarksSelected'),
+//     )
+
+//     this.selectedPtLandmarks$ = this.selectedLandmarks$.pipe(
+//       map(lms => lms.filter(lm => lm.geometry.type === 'point')),
+//     )
+
+//     this.fetchedSpatialDatasets$ = this.store.pipe(
+//       select('dataStore'),
+//       select('fetchedSpatialData'),
+//       distinctUntilChanged(compareLandmarksChanged),
+//       filter(v => !!v),
+//       startWith([]),
+//       debounceTime(300),
+//     )
+
+//     // this.userLandmarks$ = this.store.pipe(
+//     //   select(viewerStateCustomLandmarkSelector),
+//     //   distinctUntilChanged(),
+//     // )
+
+//     /**
+//      * in future, perhaps add other force UI optinos here
+//      */
+//     // this.forceUI$ = this.userLandmarks$.pipe(
+//     //   map(lm => {
+//     //     if (lm.length > 0) {
+//     //       return {
+//     //         target: 'perspective:octantRemoval',
+//     //         mode: false,
+//     //         message: `octant control disabled: showing landmarks.`
+//     //       }
+//     //     } else {
+//     //       return {
+//     //         target: 'perspective:octantRemoval',
+//     //         mode: null
+//     //       }
+//     //     }
+//     //   })
+//     // )
+
+//     // this.disableOctantRemoval$ = this.forceUI$.pipe(
+//     //   filter(({ target }) => target === 'perspective:octantRemoval'),
+//     // )
+
+//     // this.sliceRenderEvent$ = fromEvent(this.elementRef.nativeElement, 'sliceRenderEvent').pipe(
+//     //   map(ev => ev as CustomEvent)
+//     // )
+
+//     // this.sliceViewLoadingMain$ = this.sliceRenderEvent$.pipe(
+//     //   scan(scanFn, [null, null, null]),
+//     //   startWith([true, true, true] as [boolean, boolean, boolean]),
+//     //   shareReplay(1),
+//     // )
+
+//     // this.showPerpsectiveScreen$ = this.newViewer$.pipe(
+//     //   switchMapTo(this.sliceRenderEvent$.pipe(
+//     //     scan((acc, curr) => {
+
+//     //       /**
+//     //        * if at any point, all chunks have been loaded, always return loaded state
+//     //        */
+//     //       if (acc.every(v => v === 0)) return [0, 0, 0]
+//     //       const { detail = {}, target } = curr || {}
+//     //       const { missingChunks = -1, missingImageChunks = -1 } = detail
+//     //       const idx = this.findPanelIndex(target as HTMLElement)
+//     //       const returnAcc = [...acc]
+//     //       if (idx >= 0) {
+//     //         returnAcc[idx] = missingChunks + missingImageChunks
+//     //       }
+//     //       return returnAcc
+//     //     }, [-1, -1, -1]),
+//     //     map(arr => {
+//     //       let sum = 0
+//     //       let uncertain = false
+//     //       for (const num of arr) {
+//     //         if (num < 0) {
+//     //           uncertain = true
+//     //         } else {
+//     //           sum += num
+//     //         }
+//     //       }
+//     //       return sum > 0
+//     //         ? `Loading ${sum}${uncertain ? '+' : ''} chunks ...`
+//     //         : null
+//     //     }),
+//     //     distinctUntilChanged(),
+//     //     startWith('Loading ...'),
+//     //     throttleTime(100, asyncScheduler, { leading: true, trailing: true }),
+//     //     shareReplay(1),
+//     //   ))
+//     // )
+
+//     /* missing chunk perspective view */
+//     // this.perspectiveViewLoading$ = fromEvent(this.elementRef.nativeElement, 'perpspectiveRenderEvent')
+//     //   .pipe(
+//     //     filter(event => isDefined(event) && isDefined((event as any).detail) && isDefined((event as any).detail.lastLoadedMeshId) ),
+//     //     map(event => {
+
+//     //       /**
+//     //        * TODO dig into event detail to see if the exact mesh loaded
+//     //        */
+//     //       const { meshesLoaded, meshFragmentsLoaded, lastLoadedMeshId } = (event as any).detail
+//     //       return meshesLoaded >= this.nehubaViewer.numMeshesToBeLoaded
+//     //         ? null
+//     //         : 'Loading meshes ...'
+//     //     }),
+//     //     distinctUntilChanged()
+//     //   )
+
+//     this.ngLayers$ = this.store.pipe(
+//       select('ngViewerState'),
+//     )
+
+//     this.hideSegmentations$ = this.ngLayers$.pipe(
+//       map(state => isDefined(state)
+//         ? state.layers?.findIndex(l => l.mixability === 'nonmixable') >= 0
+//         : false),
+//     )
+
+//     /**
+//      * fixes 
+//      * https://github.com/HumanBrainProject/interactive-viewer/issues/800
+//      */
+//     this.subscriptions.push(
+//       this.nehubaViewerLoaded.pipe(
+//         debounceTime(500),
+//         filter(v => !v),
+//       ).subscribe(() => {
+//         this.matDrawerMain.close()
+//         this.matDrawerMinor.close()
+//       })
+//     )
+//   }
+
+//   public useMobileUI$: Observable<boolean>
+
+//   // private removeExistingPanels() {
+//   //   const element = this.nehubaViewer.nehubaViewer.ngviewer.layout.container.componentValue.element as HTMLElement
+//   //   while (element.childElementCount > 0) {
+//   //     element.removeChild(element.firstElementChild)
+//   //   }
+//   //   return element
+//   // }
+
+//   // private findPanelIndex = (panel: HTMLElement) => this.viewPanels?.findIndex(p => p === panel)
+
+//   private _exportNehuba: any
+//   get exportNehuba() {
+//     if (!this._exportNehuba) {
+//       this._exportNehuba = getExportNehuba()
+//     }
+//     return this._exportNehuba
+//   }
+
+//   public ngOnInit() {
+//     // this.hoveredPanelIndices$ = fromEvent(this.elementRef.nativeElement, 'mouseover').pipe(
+//     //   switchMap((ev: MouseEvent) => merge(
+//     //     of(this.findPanelIndex(ev.target as HTMLElement)),
+//     //     fromEvent(this.elementRef.nativeElement, 'mouseout').pipe(
+//     //       mapTo(null),
+//     //     ),
+//     //   )),
+//     //   debounceTime(20),
+//     //   shareReplay(1),
+//     // )
+
+//     // TODO deprecate
+//     /* each time a new viewer is initialised, take the first event to get the translation function */
+//     // this.subscriptions.push(
+//     //   this.newViewer$.pipe(
+//     //     switchMapTo(this.sliceRenderEvent$.pipe(
+//     //       takeOnePipe()
+//     //     ))
+//     //   ).subscribe((events) => {
+//     //     for (const idx in [0, 1, 2]) {
+//     //       const ev = events[idx] as CustomEvent
+//     //       this.viewPanels[idx] = ev.target as HTMLElement
+//     //       this.nanometersToOffsetPixelsFn[idx] = ev.detail.nanometersToOffsetPixels
+//     //     }
+//     //   }),
+//     // )
+
+//     // this.subscriptions.push(
+//     //   this.newViewer$.pipe(
+//     //     switchMapTo(fromEvent(this.elementRef.nativeElement, 'perpspectiveRenderEvent').pipe(
+//     //       take(1),
+//     //     )),
+//     //   ).subscribe(ev => this.viewPanels[3] = ((ev as CustomEvent).target) as HTMLElement),
+//     // )
+
+//     // this.subscriptions.push(
+//     //   this.redrawLayout$.subscribe(([mode, panelOrder]) => {
+//     //     const viewPanels = panelOrder.split('').map(v => Number(v)).map(idx => this.viewPanels[idx]) as [HTMLElement, HTMLElement, HTMLElement, HTMLElement]
+//     //     /**
+//     //      * TODO be smarter with event stream
+//     //      */
+//     //     if (!this.nehubaViewer) { return }
+
+//     //     /**
+//     //      * TODO smarter with event stream
+//     //      */
+//     //     if (!viewPanels.every(v => !!v)) { return }
+
+//     //     switch (mode) {
+//     //     case PANELS.H_ONE_THREE: {
+//     //       const element = this.removeExistingPanels()
+//     //       const newEl = getHorizontalOneThree(viewPanels)
+//     //       element.appendChild(newEl)
+//     //       break;
+//     //     }
+//     //     case PANELS.V_ONE_THREE: {
+//     //       const element = this.removeExistingPanels()
+//     //       const newEl = getVerticalOneThree(viewPanels)
+//     //       element.appendChild(newEl)
+//     //       break;
+//     //     }
+//     //     case PANELS.FOUR_PANEL: {
+//     //       const element = this.removeExistingPanels()
+//     //       const newEl = getFourPanel(viewPanels)
+//     //       element.appendChild(newEl)
+//     //       break;
+//     //     }
+//     //     case PANELS.SINGLE_PANEL: {
+//     //       const element = this.removeExistingPanels()
+//     //       const newEl = getSinglePanel(viewPanels)
+//     //       element.appendChild(newEl)
+//     //       break;
+//     //     }
+//     //     default:
+//     //     }
+//     //     for (const panel of viewPanels) {
+//     //       (panel as HTMLElement).classList.add('neuroglancer-panel')
+//     //     }
+
+//     //     // TODO needed to redraw?
+//     //     // see https://trello.com/c/oJOnlc6v/60-enlarge-panel-allow-user-rearrange-panel-position
+//     //     // further investigaation required
+//     //     this.nehubaViewer.redraw()
+//     //   }),
+//     // )
+
+//     this.subscriptions.push(
+//       this.fetchedSpatialDatasets$.subscribe(datasets => {
+//         this.landmarksLabelIndexMap = new Map(datasets.map((v, idx) => [idx, v]) as Array<[number, any]>)
+//         this.landmarksNameMap = new Map(datasets.map((v, idx) => [v.name, idx] as [string, number]))
+//       }),
+//     )
+
+//     /**
+//      * TODO deprecate, but document the method
+//      */
+//     this.subscriptions.push(
+//       combineLatest(
+//         this.fetchedSpatialDatasets$,
+//       ).subscribe(([fetchedSpatialData]) => {
+//         this.fetchedSpatialData = fetchedSpatialData
+
+//         if (this.fetchedSpatialData?.length > 0) {
+//           this.nehubaViewer.addSpatialSearch3DLandmarks(
+//             this.fetchedSpatialData
+//               .map(data => data.geometry.type === 'point'
+//                 ? (data.geometry as IPointLandmarkGeometry).position
+//                 : data.geometry.type === 'plane'
+//                   ? [
+//                     (data.geometry as IPlaneLandmarkGeometry).corners,
+//                     [[0, 1, 2], [0, 2, 3]],
+//                   ]
+//                   : data.geometry.type === 'mesh'
+//                     ? [
+//                       (data.geometry as IOtherLandmarkGeometry).vertices,
+//                       (data.geometry as IOtherLandmarkGeometry).meshIdx,
+//                     ]
+//                     : null),
+//           )
+//         } else {
+//           if (this.nehubaViewer && this.nehubaViewer.removeSpatialSearch3DLandmarks instanceof Function) {
+//             this.nehubaViewer.removeSpatialSearch3DLandmarks()
+//           }
+//         }
+//       }),
+//     )
+
+//     // this.subscriptions.push(
+//     //   this.userLandmarks$.pipe(
+//     //     withLatestFrom(
+//     //       this.nehubaViewerPerspectiveOctantRemoval$
+//     //     )
+//     //   ).subscribe(([landmarks, flag]) => {
+//     //     if (this.nehubaContainerDirective) {
+//     //       this.nehubaContainerDirective.toggleOctantRemoval(
+//     //         landmarks.length > 0 ? false : flag
+//     //       )
+//     //     }
+//     //     if (this.nehubaViewer) {
+//     //       this.nehubaViewer.updateUserLandmarks(landmarks)
+//     //     }
+//     //   }),
+//     // )
+
+//     // this.subscriptions.push(
+//     //   this.newViewer$.pipe(
+//     //     skip(1),
+//     //   ).subscribe(() => {
+
+//     //     /* on selecting of new template, remove additional nglayers */
+//     //     const baseLayerNames = Object.keys(this.selectedTemplate.nehubaConfig.dataset.initialNgState.layers)
+//     //     this.ngLayersRegister.layers
+//     //       .filter(layer => baseLayerNames?.findIndex(l => l === layer.name) < 0)
+//     //       .map(l => l.name)
+//     //       .forEach(layerName => {
+//     //         this.store.dispatch(ngViewerActionRemoveNgLayer({
+//     //           layer: {
+//     //             name: layerName
+//     //           }
+//     //         }))
+//     //       })
+//     //   }),
+//     // )
+
+//     this.subscriptions.push(
+//       this.templateSelected$.subscribe(() => this.destroynehuba()),
+//     )
+
+//     /* order of subscription will determine the order of execution */
+//     // this.subscriptions.push(
+//     //   this.newViewer$.pipe(
+//     //     map(templateSelected => {
+//     //       const deepCopiedState = JSON.parse(JSON.stringify(templateSelected))
+//     //       const navigation = deepCopiedState.nehubaConfig.dataset.initialNgState.navigation
+//     //       if (!navigation) {
+//     //         return deepCopiedState
+//     //       }
+//     //       navigation.zoomFactor = calculateSliceZoomFactor(navigation.zoomFactor)
+//     //       deepCopiedState.nehubaConfig.dataset.initialNgState.navigation = navigation
+//     //       return deepCopiedState
+//     //     }),
+//     //     withLatestFrom(
+//     //       this.selectedParcellation$.pipe(
+//     //         startWith(null),
+//     //       )
+//     //     ),
+//     //   ).subscribe(([templateSelected, parcellationSelected]) => {
+
+//     //     this.selectedTemplate = templateSelected
+//     //     this.createNewNehuba(templateSelected)
+//     //     const foundParcellation = parcellationSelected
+//     //       && templateSelected?.parcellations?.find(parcellation => parcellationSelected.name === parcellation.name)
+//     //     this.handleParcellation(foundParcellation || templateSelected.parcellations[0])
+
+//     //     const nehubaConfig = templateSelected.nehubaConfig
+//     //     const initialSpec = nehubaConfig.dataset.initialNgState
+//     //     const {layers} = initialSpec
+
+//     //     const dispatchLayers = Object.keys(layers).map(key => {
+//     //       const layer = {
+//     //         name : key,
+//     //         source : layers[key].source,
+//     //         mixability : layers[key].type === 'image'
+//     //           ? 'base'
+//     //           : 'mixable',
+//     //         visible : typeof layers[key].visible === 'undefined'
+//     //           ? true
+//     //           : layers[key].visible,
+//     //         transform : typeof layers[key].transform === 'undefined'
+//     //           ? null
+//     //           : layers[key].transform,
+//     //       }
+//     //       this.ngLayersRegister.layers.push(layer)
+//     //       return layer
+//     //     })
+
+//     //     this.store.dispatch(ngViewerActionAddNgLayer({
+//     //       layer: dispatchLayers
+//     //     }))
+//     //   })
+//     // )
+
+//     let prevParcellation = null
+
+//     // this.subscriptions.push(
+
+//     //   combineLatest([
+//     //     this.selectedRegions$.pipe(
+//     //       distinctUntilChanged(),
+//     //     ),
+//     //     this.hideSegmentations$.pipe(
+//     //       distinctUntilChanged(),
+//     //     ),
+//     //     this.ngLayers$.pipe(
+//     //       map(state => state.forceShowSegment),
+//     //       distinctUntilChanged(),
+//     //     ),
+//     //     this.selectedParcellation$,
+//     //     this.store.pipe(
+//     //       select('viewerState'),
+//     //       select('overwrittenColorMap'),
+//     //       distinctUntilChanged()
+//     //     )
+//     //   ]).pipe(
+//     //     delayWhen(() => timer())
+//     //   ).subscribe(([regions, hideSegmentFlag, forceShowSegment, selectedParcellation, overwrittenColorMap]) => {
+//     //     if (!this.nehubaViewer) { return }
+
+//     //     const { ngId: defaultNgId } = selectedParcellation
+
+//     //     /* selectedregionindexset needs to be updated regardless of forceshowsegment */
+//     //     this.selectedRegionIndexSet = !prevParcellation || prevParcellation === selectedParcellation?
+//     //       new Set(regions.map(({ngId = defaultNgId, labelIndex}) => serialiseParcellationRegion({ ngId, labelIndex }))) : new Set()
+
+//     //     if ( forceShowSegment === false || (forceShowSegment === null && hideSegmentFlag) ) {
+//     //       this.nehubaViewer.hideAllSeg()
+//     //       return
+//     //     }
+
+//     //     this.selectedRegionIndexSet.size > 0 && !overwrittenColorMap
+//     //       ? this.nehubaViewer.showSegs([...this.selectedRegionIndexSet])
+//     //       : this.nehubaViewer.showAllSeg()
+
+//     //     prevParcellation = selectedParcellation
+//     //   }),
+//     // )
+
+//     // this.subscriptions.push(
+//     //   this.ngLayers$.subscribe(ngLayersInterface => {
+//     //     if (!this.nehubaViewer) { return }
+
+//     //     const newLayers = ngLayersInterface.layers.filter(l => this.ngLayersRegister.layers?.findIndex(ol => ol.name === l.name) < 0)
+//     //     const removeLayers = this.ngLayersRegister.layers.filter(l => ngLayersInterface.layers?.findIndex(nl => nl.name === l.name) < 0)
+
+//     //     if (newLayers?.length > 0) {
+//     //       const newLayersObj: any = {}
+//     //       newLayers.forEach(({ name, source, ...rest }) => newLayersObj[name] = {
+//     //         ...rest,
+//     //         source,
+//     //         // source: getProxyUrl(source),
+//     //         // ...getProxyOther({source})
+//     //       })
+
+//     //       if (!this.nehubaViewer.nehubaViewer || !this.nehubaViewer.nehubaViewer.ngviewer) {
+//     //         this.nehubaViewer.initNiftiLayers.push(newLayersObj)
+//     //       } else {
+//     //         this.nehubaViewer.loadLayer(newLayersObj)
+//     //       }
+//     //       this.ngLayersRegister.layers = this.ngLayersRegister.layers.concat(newLayers)
+//     //     }
+
+//     //     if (removeLayers?.length > 0) {
+//     //       removeLayers.forEach(l => {
+//     //         if (this.nehubaViewer.removeLayer({
+//     //           name : l.name,
+//     //         })) {
+//     //           this.ngLayersRegister.layers = this.ngLayersRegister.layers.filter(rl => rl.name !== l.name)
+//     //         }
+//     //       })
+//     //     }
+//     //   }),
+//     // )
+
+//     this.subscriptions.push(
+//       this.selectedParcellation$.subscribe(this.handleParcellation.bind(this))
+//     )
+
+//     /* setup init view state */
+
+//     this.subscriptions.push(
+//       this.selectedRegions$.pipe(
+//         filter(() => !!this.nehubaViewer),
+//       ).subscribe(regions => {
+//         this.nehubaViewer.initRegions = regions.map(({ ngId, labelIndex }) => serialiseParcellationRegion({ ngId, labelIndex }))
+//       })
+//     )
+
+//     this.subscriptions.push(this.selectedRegions$.subscribe(sr => {
+//       this.selectedRegions = sr
+//     }))
+
+//     /** switch side nav */
+//     // this.subscriptions.push(
+//     //   this.alwaysHideMinorPanel$.pipe(
+//     //     distinctUntilChanged()
+//     //   ).subscribe(flag => {
+//     //     if (!flag) {
+//     //       this.matDrawerMinor && this.matDrawerMinor.open()
+//     //       this.navSideDrawerMainSwitch && this.navSideDrawerMainSwitch.open()
+//     //     }
+//     //   })
+//     // )
+
+//     this.subscriptions.push(
+//       this.selectedRegions$.subscribe(regions => {
+//         this.selectedRegions = regions
+//       })
+//     )
+
+//     /* handler to open/select landmark */
+//     const clickObs$ = fromEvent(this.elementRef.nativeElement, 'click')
+
+//     this.subscriptions.push(
+//       clickObs$.pipe(
+//         buffer(
+//           clickObs$.pipe(
+//             debounceTime(200),
+//           ),
+//         ),
+//         filter(arr => arr?.length >= 2),
+//       )
+//         .subscribe(() => {
+//           const { currentOnHover } = this
+//           this.store.dispatch(viewerStateDblClickOnViewer({
+//             payload: { ...currentOnHover }
+//           }))
+//         }),
+//     )
+
+//     // this.subscriptions.push(
+//     //   this.selectedLandmarks$.pipe(
+//     //     map(lms => lms.map(lm => this.landmarksNameMap.get(lm.name))),
+//     //     debounceTime(16),
+//     //   ).subscribe(indices => {
+//     //     const filteredIndices = indices.filter(v => typeof v !== 'undefined' && v !== null)
+//     //     if (this.nehubaViewer) {
+//     //       this.nehubaViewer.spatialLandmarkSelectionChanged(filteredIndices)
+//     //     }
+//     //   }),
+//     // )
+//   }
+
+//   // datasetViewerRegistry : Set<string> = new Set()
+//   public showObliqueScreen$: Observable<boolean>
+//   public showObliqueSelection$: Observable<boolean>
+//   public showObliqueRotate$: Observable<boolean>
+
+//   private currOnHoverObsSub: Subscription
+//   public ngOnChanges() {
+//     this.currOnHoverObsSub && this.currOnHoverObsSub.unsubscribe()
+//     if (this.currentOnHoverObs$) {
+//       this.currOnHoverObsSub = this.currentOnHoverObs$.subscribe(({ segments }) => this.onHoverSegments$.next(segments))
+//     }
+//   }
+
+//   public ngOnDestroy() {
+//     this.subscriptions.forEach(s => s.unsubscribe())
+//   }
+
+//   // public toggleMaximiseMinimise(index: number) {
+//   //   this.store.dispatch(ngViewerActionToggleMax({
+//   //     payload: { index }
+//   //   }))
+//   // }
+
+//   public tunableMobileProperties: ITunableProp[] = []
+
+
+//   public selectedProp = null
+
+//   // public returnTruePos(quadrant: number, data: any) {
+//   //   const pos = quadrant > 2
+//   //     ? [0, 0, 0]
+//   //     : this.nanometersToOffsetPixelsFn && this.nanometersToOffsetPixelsFn[quadrant]
+//   //       ? this.nanometersToOffsetPixelsFn[quadrant](data.geometry.position.map(n => n * 1e6))
+//   //       : [0, 0, 0]
+//   //   return pos
+//   // }
+
+//   // public getPositionX(quadrant: number, data: any) {
+//   //   return this.returnTruePos(quadrant, data)[0]
+//   // }
+//   // public getPositionY(quadrant: number, data: any) {
+//   //   return this.returnTruePos(quadrant, data)[1]
+//   // }
+//   // public getPositionZ(quadrant: number, data: any) {
+//   //   return this.returnTruePos(quadrant, data)[2]
+//   // }
+
+//   // public handleMouseEnterCustomLandmark(lm) {
+//   //   this.store.dispatch(
+//   //     viewerStateMouseOverCustomLandmark({
+//   //       payload: { userLandmark: lm }
+//   //     })
+//   //   )
+//   // }
+
+//   // public handleMouseLeaveCustomLandmark(lm) {
+//   //   this.store.dispatch(
+//   //     viewerStateMouseOverCustomLandmark({
+//   //       payload: { userLandmark: null }
+//   //     })
+//   //   )
+//   // }
+
+//   // handles mouse enter/leave landmarks in 2D
+//   public handleMouseEnterLandmark(spatialData: any) {
+//     spatialData.highlight = true
+//     this.store.dispatch({
+//       type : MOUSE_OVER_LANDMARK,
+//       landmark : spatialData._label,
+//     })
+//   }
+
+//   public handleMouseLeaveLandmark(spatialData: any) {
+//     spatialData.highlight = false
+//     this.store.dispatch({
+//       type : MOUSE_OVER_LANDMARK,
+//       landmark : null,
+//     })
+//   }
+
+//   // private handleParcellation(parcellation: any) {
+//   //   /**
+//   //    * parcellaiton may be undefined
+//   //    */
+//   //   if ( !(parcellation && parcellation.regions)) {
+//   //     return
+//   //   }
+
+//   //   /**
+//   //    * first, get all all the ngIds, including parent id from parcellation (if defined)
+//   //    */
+//   //   const ngIds = getNgIds(parcellation.regions).concat( parcellation.ngId ? parcellation.ngId : [])
+
+//   //   this.multiNgIdsRegionsLabelIndexMap = getMultiNgIdsRegionsLabelIndexMap(parcellation)
+
+//   //   this.nehubaViewer.multiNgIdsLabelIndexMap = this.multiNgIdsRegionsLabelIndexMap
+//   //   this.nehubaViewer.auxilaryMeshIndices = parcellation.auxillaryMeshIndices || []
+
+//   //   /* TODO replace with proper KG id */
+//   //   /**
+//   //    * need to set unique array of ngIds, or else workers will be overworked
+//   //    */
+//   //   this.nehubaViewer.ngIds = Array.from(new Set(ngIds))
+//   //   this.selectedParcellation = parcellation
+//   // }
+
+//   /* related spatial search */
+//   public spatialSearchPagination: number = 0
+
+//   private destroynehuba() {
+//     /**
+//      * TODO if plugin subscribes to viewerHandle, and then new template is selected, changes willl not be be sent
+//      * could be considered as a bug.
+//      */
+//     this.setViewerHandle && this.setViewerHandle(null)
+//     this.nehubaContainerDirective.clear()
+
+//     this.nehubaViewer = null
+
+//     this.cdr.detectChanges()
+//   }
+
+//   private createNewNehuba(template: any) {
+
+//     this.nehubaContainerDirective.createNehubaInstance(template)
+//     this.nehubaViewer = this.nehubaContainerDirective.nehubaViewerInstance
+
+//     this.setupViewerHandleApi()
+//   }
+
+//   private setupViewerHandleApi() {
+//     const viewerHandle = {
+//       setNavigationLoc : (coord, realSpace?) => this.nehubaViewer.setNavigationState({
+//         position : coord,
+//         positionReal : typeof realSpace !== 'undefined' ? realSpace : true,
+//       }),
+//       /* TODO introduce animation */
+//       moveToNavigationLoc : (coord, realSpace?) => {
+//         this.store.dispatch({
+//           type: CHANGE_NAVIGATION,
+//           navigation: {
+//             position: coord,
+//             animation: {},
+//           },
+//         })
+//       },
+//       setNavigationOri : (quat) => this.nehubaViewer.setNavigationState({
+//         orientation : quat,
+//       }),
+//       /* TODO introduce animation */
+//       moveToNavigationOri : (quat) => this.nehubaViewer.setNavigationState({
+//         orientation : quat,
+//       }),
+//       showSegment : (_labelIndex) => {
+//         /**
+//          * TODO reenable with updated select_regions api
+//          */
+//         this.log.warn(`showSegment is temporarily disabled`)
+
+//         // if(!this.selectedRegionIndexSet.has(labelIndex))
+//         //   this.store.dispatch({
+//         //     type : SELECT_REGIONS,
+//         //     selectRegions :  [labelIndex, ...this.selectedRegionIndexSet]
+//         //   })
+//       },
+//       add3DLandmarks : landmarks => {
+//         // TODO check uniqueness of ID
+//         if (!landmarks.every(l => isDefined(l.id))) {
+//           throw new Error('every landmarks needs to be identified with the id field')
+//         }
+//         if (!landmarks.every(l => isDefined(l.position))) {
+//           throw new Error('every landmarks needs to have position defined')
+//         }
+//         if (!landmarks.every(l => l.position.constructor === Array) || !landmarks.every(l => l.position.every(v => !isNaN(v))) || !landmarks.every(l => l.position.length == 3)) {
+//           throw new Error('position needs to be a length 3 tuple of numbers ')
+//         }
+
+//         this.store.dispatch(viewerStateAddUserLandmarks({
+//           landmarks
+//         }))
+//       },
+//       remove3DLandmarks : landmarkIds => {
+//         this.store.dispatch(viewreStateRemoveUserLandmarks({
+//           payload: { landmarkIds }
+//         }))
+//       },
+//       hideSegment : (_labelIndex) => {
+//         /**
+//          * TODO reenable with updated select_regions api
+//          */
+//         this.log.warn(`hideSegment is temporarily disabled`)
+
+//         // if(this.selectedRegionIndexSet.has(labelIndex)){
+//         //   this.store.dispatch({
+//         //     type :SELECT_REGIONS,
+//         //     selectRegions : [...this.selectedRegionIndexSet].filter(num=>num!==labelIndex)
+//         //   })
+//         // }
+//       },
+//       showAllSegments : () => {
+//         const selectRegionIds = []
+//         this.multiNgIdsRegionsLabelIndexMap.forEach((map, ngId) => {
+//           Array.from(map.keys()).forEach(labelIndex => {
+//             selectRegionIds.push(serialiseParcellationRegion({ ngId, labelIndex }))
+//           })
+//         })
+//         this.store.dispatch(viewerStateSelectRegionWithIdDeprecated({
+//           selectRegionIds
+//         }))
+//       },
+//       hideAllSegments : () => {
+//         this.store.dispatch(viewerStateSelectRegionWithIdDeprecated({
+//           selectRegionIds: []
+//         }))
+//       },
+//       segmentColourMap : new Map(),
+//       getLayersSegmentColourMap: () => {
+//         const newMainMap = new Map()
+//         for (const [key, colormap] of this.nehubaViewer.multiNgIdColorMap.entries()) {
+//           const newColormap = new Map()
+//           newMainMap.set(key, newColormap)
+
+//           for (const [lableIndex, entry] of colormap.entries()) {
+//             newColormap.set(lableIndex, JSON.parse(JSON.stringify(entry)))
+//           }
+//         }
+//         return newMainMap
+//       },
+//       applyColourMap : (_map) => {
+//         throw new Error(`apply color map has been deprecated. use applyLayersColourMap instead`)
+//       },
+//       applyLayersColourMap: (map) => {
+//         this.nehubaViewer.setColorMap(map)
+//       },
+//       loadLayer : (layerObj) => this.nehubaViewer.loadLayer(layerObj),
+//       removeLayer : (condition) => this.nehubaViewer.removeLayer(condition),
+//       setLayerVisibility : (condition, visible) => this.nehubaViewer.setLayerVisibility(condition, visible),
+//       mouseEvent : merge(
+//         fromEvent(this.elementRef.nativeElement, 'click').pipe(
+//           map((ev: MouseEvent) => ({eventName : 'click', event: ev})),
+//         ),
+//         fromEvent(this.elementRef.nativeElement, 'mousemove').pipe(
+//           map((ev: MouseEvent) => ({eventName : 'mousemove', event: ev})),
+//         ),
+//         /**
+//          * neuroglancer prevents propagation, so use capture instead
+//          */
+//         Observable.create(observer => {
+//           this.elementRef.nativeElement.addEventListener('mousedown', event => observer.next({eventName: 'mousedown', event}), true)
+//         }) as Observable<{eventName: string, event: MouseEvent}>,
+//         fromEvent(this.elementRef.nativeElement, 'mouseup').pipe(
+//           map((ev: MouseEvent) => ({eventName : 'mouseup', event: ev})),
+//         ),
+//       ) ,
+//       mouseOverNehuba : this.onHoverSegment$.pipe(
+//         tap(() => console.warn('mouseOverNehuba observable is becoming deprecated. use mouseOverNehubaLayers instead.')),
+//       ),
+//       mouseOverNehubaLayers: this.onHoverSegments$,
+//       mouseOverNehubaUI: this.currentOnHoverObs$.pipe(
+//         map(({ landmark, segments, userLandmark: customLandmark }) => ({ segments, landmark, customLandmark })),
+//         shareReplay(1),
+//       ),
+//       getNgHash : this.nehubaViewer.getNgHash,
+//     }
+
+//     this.setViewerHandle && this.setViewerHandle(viewerHandle)
+//   }
+
+//   // public setOctantRemoval(octantRemovalFlag: boolean) {
+//   //   this.store.dispatch(
+//   //     ngViewerActionSetPerspOctantRemoval({
+//   //       octantRemovalFlag
+//   //     })
+//   //   )
+//   // }
+
+//   // public zoomNgView(panelIndex: number, factor: number) {
+//   //   const ngviewer = this.nehubaViewer?.nehubaViewer?.ngviewer
+//   //   if (!ngviewer) throw new Error(`ngviewer not defined!`)
+
+//   //   /**
+//   //    * panelIndex < 3 === slice view
+//   //    */
+//   //   if (panelIndex < 3) {
+//   //     /**
+//   //      * factor > 1 === zoom out
+//   //      */
+//   //     ngviewer.navigationState.zoomBy(factor)
+//   //   } else {
+//   //     ngviewer.perspectiveNavigationState.zoomBy(factor)
+//   //   }
+//   // }
+
+//   // public clearPreviewingDataset(id: string){
+//   //   /**
+//   //    * clear all preview
+//   //    */
+//   //   this.store.dispatch(
+//   //     id
+//   //       ? uiActionHideDatasetWithId({ id })
+//   //       : uiActionHideAllDatasets()
+//   //   )
+//   // }
+// }
diff --git a/src/ui/nehubaContainer/nehubaContainer.template.html b/src/ui/nehubaContainer/nehubaContainer.template.html
index b08904a09ce57f37dfaed22204fba0da53d86d38..921151abb70002e45eda44b4264a9fd4585f9b42 100644
--- a/src/ui/nehubaContainer/nehubaContainer.template.html
+++ b/src/ui/nehubaContainer/nehubaContainer.template.html
@@ -393,7 +393,6 @@
       <!--  regional features-->
       <ng-template #regionalFeaturesTmpl>
         <data-browser
-          [parcellation]="selectedParcellation"
           [disableVirtualScroll]="true"
           [regions]="regions">
         </data-browser>
@@ -572,7 +571,6 @@
             [parcellationId]="selectedParcellation['@id']"
             (setOpenState)="expansionPanel.expanded = $event"
             (connectivityNumberReceived)="connectivityNumber = $event"
-            (connectivityLoadUrl)="connectivityLoadUrl = $event"
             [accordionExpanded]="expansionPanel.expanded">
           </connectivity-browser>
         </ng-container>
@@ -592,13 +590,16 @@
     <div class="w-0 h-0"
       iav-counter
       #connectedCounterDir="iavCounter">
-
-      <hbp-connectivity-matrix-row *ngIf="region && region.name"
-        [region]="region.name + (region.status? ' - ' + region.status : '')"
-        (connectivityDataReceived)="connectedCounterDir.value = $event.detail.length"
-        class="invisible d-block h-0 w-0"
-        [loadurl]="connectivityLoadUrl">
-      </hbp-connectivity-matrix-row>
+      <!-- TODO figure out why conn browser does not work here -->
+      <!-- @fsdavid, can you take a look why this component is not emitting connectivityNumberReceived event? -->
+      <connectivity-browser *ngIf="region && region.name"
+        class="d-block h-0 w-0 overflow-hidden"
+        [region]="region"
+        [parcellationId]="selectedParcellation['@id']"
+        [accordionExpanded]="true"
+        (connectivityNumberReceived)="connectedCounterDir.value = $event">
+        
+      </connectivity-browser>
     </div>
   </mat-accordion>
 </ng-template>
@@ -667,7 +668,7 @@
     <landmark-2d-flat-cmp *ngFor="let spatialData of (selectedPtLandmarks$ | async)"
       (mouseenter)="handleMouseEnterLandmark(spatialData)"
       (mouseleave)="handleMouseLeaveLandmark(spatialData)"
-      [highlight]="spatialData.highlight ? spatialData.highlight : false"
+      [color]="spatialData.highlight ? [255, 0, 0] : [255, 255, 255]"
       [positionX]="getPositionX(panelIndex, spatialData)"
       [positionY]="getPositionY(panelIndex, spatialData)"
       [positionZ]="getPositionZ(panelIndex, spatialData)">
diff --git a/src/ui/templateParcellationCitations/templateParcellationCitations.component.ts b/src/ui/templateParcellationCitations/templateParcellationCitations.component.ts
deleted file mode 100644
index c97715d798fbf1345ee5832cd890d2ebcb0ef477..0000000000000000000000000000000000000000
--- a/src/ui/templateParcellationCitations/templateParcellationCitations.component.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { Component } from "@angular/core";
-import { select, Store } from "@ngrx/store";
-import { Observable } from "rxjs";
-import { map, switchMap } from "rxjs/operators";
-import { safeFilter, IavRootStoreInterface } from "../../services/stateStore.service";
-
-@Component({
-  selector : 'template-parcellation-citation-container',
-  templateUrl : './templateParcellationCitations.template.html',
-  styleUrls : [
-    './templateParcellationCitations.style.css',
-  ],
-})
-
-export class TemplateParcellationCitationsContainer {
-  public selectedTemplate$: Observable<any>
-  public selectedParcellation$: Observable<any>
-
-  constructor(private store: Store<IavRootStoreInterface>) {
-    this.selectedTemplate$ = this.store.pipe(
-      select('viewerState'),
-      safeFilter('templateSelected'),
-      map(state => state.templateSelected),
-    )
-
-    this.selectedParcellation$ = this.selectedTemplate$.pipe(
-      switchMap(() => this.store.pipe(
-        select('viewerState'),
-        safeFilter('parcellationSelected'),
-        map(state => state.parcellationSelected),
-      )),
-    )
-  }
-}
diff --git a/src/ui/templateParcellationCitations/templateParcellationCitations.template.html b/src/ui/templateParcellationCitations/templateParcellationCitations.template.html
deleted file mode 100644
index 48b54d534f9efe9b53f055ccbae85f689afe67d9..0000000000000000000000000000000000000000
--- a/src/ui/templateParcellationCitations/templateParcellationCitations.template.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<citations-component 
-  *ngIf = "selectedTemplate$ | async"
-  [properties] = "(selectedTemplate$ | async).properties"
-  citationContainer>
-
-</citations-component>
-<citations-component
-  *ngIf = "selectedParcellation$ | async"
-  [properties] = "(selectedParcellation$ | async).properties"
-  citationContainer>
-</citations-component>
\ No newline at end of file
diff --git a/src/ui/topMenu/index.ts b/src/ui/topMenu/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/ui/topMenu/module.ts b/src/ui/topMenu/module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a2c6f8a2e211f2952b5cc4f3975adcc27e4f7217
--- /dev/null
+++ b/src/ui/topMenu/module.ts
@@ -0,0 +1,39 @@
+import { CommonModule } from "@angular/common";
+import { NgModule } from "@angular/core";
+import { DatabrowserModule } from "src/atlasComponents/databrowserModule";
+import { AuthModule } from "src/auth";
+import { ComponentsModule } from "src/components";
+import { FabSpeedDialModule } from "src/components/fabSpeedDial";
+import { PluginModule } from "src/plugin";
+import { UtilModule } from "src/util";
+import { ConfigModule } from "../config/module";
+import { CookieModule } from "../cookieAgreement/module";
+import { HelpModule } from "../help/module";
+import { KgTosModule } from "../kgtos/module";
+import { AngularMaterialModule } from "../sharedModules/angularMaterial.module";
+import { TopMenuCmp } from "./topMenuCmp/topMenu.components";
+
+@NgModule({
+  imports: [
+    CommonModule,
+    UtilModule,
+    AngularMaterialModule,
+    DatabrowserModule,
+    FabSpeedDialModule,
+    ComponentsModule,
+    CookieModule,
+    KgTosModule,
+    ConfigModule,
+    HelpModule,
+    PluginModule,
+    AuthModule,
+  ],
+  declarations: [
+    TopMenuCmp
+  ],
+  exports: [
+    TopMenuCmp
+  ]
+})
+
+export class TopMenuModule{}
diff --git a/src/ui/signinBanner/signinBanner.components.ts b/src/ui/topMenu/topMenuCmp/topMenu.components.ts
similarity index 91%
rename from src/ui/signinBanner/signinBanner.components.ts
rename to src/ui/topMenu/topMenuCmp/topMenu.components.ts
index ef5c4e442357fcd684657bb9fb503888d11d5e30..4a78e0d12fb6231da10f7d954c8e6bdaa4bc850d 100644
--- a/src/ui/signinBanner/signinBanner.components.ts
+++ b/src/ui/topMenu/topMenuCmp/topMenu.components.ts
@@ -15,20 +15,19 @@ import { MatBottomSheet } from "@angular/material/bottom-sheet";
 import { CONST } from 'common/constants'
 
 @Component({
-  selector: 'signin-banner',
-  templateUrl: './signinBanner.template.html',
+  selector: 'top-menu-cmp',
+  templateUrl: './topMenu.template.html',
   styleUrls: [
-    './signinBanner.style.css',
-    '../btnShadow.style.css',
+    './topMenu.style.css',
   ],
   changeDetection: ChangeDetectionStrategy.OnPush,
 })
 
-export class SigninBanner {
+export class TopMenuCmp {
 
   public PINNED_DATASETS_BADGE_DESC = CONST.PINNED_DATASETS_BADGE_DESC
 
-  public matBtnStyle = ''
+  public matBtnStyle = 'mat-icon-button'
   public matBtnColor = 'primary'
 
   private _ismobile = false
@@ -43,7 +42,7 @@ export class SigninBanner {
   }
 
   @Input() public darktheme: boolean
-  @Input() public parcellationIsSelected: boolean
+  @Input() public viewerLoaded: boolean
 
   public user$: Observable<any>
   public userBtnTooltip$: Observable<string>
diff --git a/src/ui/signinBanner/signinBanner.style.css b/src/ui/topMenu/topMenuCmp/topMenu.style.css
similarity index 100%
rename from src/ui/signinBanner/signinBanner.style.css
rename to src/ui/topMenu/topMenuCmp/topMenu.style.css
diff --git a/src/ui/signinBanner/signinBanner.template.html b/src/ui/topMenu/topMenuCmp/topMenu.template.html
similarity index 98%
rename from src/ui/signinBanner/signinBanner.template.html
rename to src/ui/topMenu/topMenuCmp/topMenu.template.html
index c4b925620a6ec51a92bb4293bda290706bd8f6c5..f3ef18322bbb703d96c9fbdf2b52980d50c46401 100644
--- a/src/ui/signinBanner/signinBanner.template.html
+++ b/src/ui/topMenu/topMenuCmp/topMenu.template.html
@@ -138,7 +138,7 @@
 <mat-menu #pluginDropdownMenu
   [aria-label]="'Tools and plugins menu'">
   <button mat-menu-item
-    [disabled]="!parcellationIsSelected"
+    [disabled]="!viewerLoaded"
     screenshot-switch
     [matTooltip]="screenshotTooltipText">
     <mat-icon fontSet="fas" fontIcon="fa-camera">
@@ -179,8 +179,8 @@
   <mat-dialog-content>
     <mat-tab-group>
       <mat-tab label="About">
-        <help-component>
-        </help-component>
+        <iav-about>
+        </iav-about>
       </mat-tab>
       <mat-tab label="Privacy Policy">
         <!-- TODO make tab container scrollable -->
diff --git a/src/ui/ui.module.ts b/src/ui/ui.module.ts
index e58bd77ba1c134fad099b3c439e73b425f7cc1c4..ac11d02f3cd101e9033e64ade8d0d2616d7cd556 100644
--- a/src/ui/ui.module.ts
+++ b/src/ui/ui.module.ts
@@ -1,11 +1,9 @@
-import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from "@angular/core";
+import { NgModule } from "@angular/core";
 import { ComponentsModule } from "src/components/components.module";
 
 import { FormsModule, ReactiveFormsModule } from "@angular/forms";
 import { LayoutModule } from "src/layouts/layout.module";
-import { NehubaContainer } from "./nehubaContainer/nehubaContainer.component";
-import { IMPORT_NEHUBA_INJECT_TOKEN } from "./nehubaContainer/nehubaViewer/nehubaViewer.component";
-import { GetTemplateImageSrcPipe, ImgSrcSetPipe, SplashScreen } from "./nehubaContainer/splashScreen/splashScreen.component";
+// import { NehubaContainer } from "./nehubaContainer/nehubaContainer.component";
 
 import { FilterRegionDataEntries } from "src/util/pipes/filterRegionDataEntries.pipe";
 import { GroupDatasetByRegion } from "src/util/pipes/groupDataEntriesByRegion.pipe";
@@ -13,9 +11,6 @@ import { GroupDatasetByRegion } from "src/util/pipes/groupDataEntriesByRegion.pi
 import { GetLayerNameFromDatasets } from "../util/pipes/getLayerNamePipe.pipe";
 import { SortDataEntriesToRegion } from "../util/pipes/sortDataEntriesIntoRegion.pipe";
 import { CitationsContainer } from "./citation/citations.component";
-import { KgEntryViewer } from "./kgEntryViewer/kgentry.component";
-import { SubjectViewer } from "./kgEntryViewer/subjectViewer/subjectViewer.component";
-import { PluginBannerUI } from "./pluginBanner/pluginBanner.component";
 
 import { ScrollingModule } from "@angular/cdk/scrolling"
 import { HttpClientModule } from "@angular/common/http";
@@ -26,66 +21,36 @@ import { GetFileExtension } from "src/util/pipes/getFileExt.pipe";
 import { UtilModule } from "src/util";
 import { DownloadDirective } from "../util/directives/download.directive";
 import { SpatialLandmarksToDataBrowserItemPipe } from "../util/pipes/spatialLandmarksToDatabrowserItem.pipe";
-import { ConfigComponent } from './config/config.component'
-import { CurrentLayout } from "./config/currentLayout/currentLayout.component";
-import { FourPanelLayout } from "./config/layouts/fourPanel/fourPanel.component";
-import { HorizontalOneThree } from "./config/layouts/h13/h13.component";
-import { SinglePanel } from "./config/layouts/single/single.component";
-import { VerticalOneThree } from "./config/layouts/v13/v13.component";
-import { CookieAgreement } from "./cookieAgreement/cookieAgreement.component";
-import { DatabrowserModule } from "./databrowserModule/databrowser.module";
-import { HelpComponent } from "./help/help.component";
-import { KGToS } from "./kgtos/kgtos.component";
+
+
+import { DatabrowserModule } from "../atlasComponents/databrowserModule/databrowser.module";
+
 import { LogoContainer } from "./logoContainer/logoContainer.component";
 import { MobileOverlay } from "./nehubaContainer/mobileOverlay/mobileOverlay.component";
 import { MobileControlNubStylePipe } from "./nehubaContainer/pipes/mobileControlNubStyle.pipe";
-import { StatusCardComponent } from "./nehubaContainer/statusCard/statusCard.component";
-import { SigninBanner } from "./signinBanner/signinBanner.components";
-
-import { TemplateParcellationCitationsContainer } from "./templateParcellationCitations/templateParcellationCitations.component";
-import { FilterNameBySearch } from "./viewerStateController/regionHierachy/filterNameBySearch.pipe";
-
-import { ViewerStateMini } from 'src/ui/viewerStateController/viewerStateCMini/viewerStateMini.component'
+// import { StatusCardComponent } from "./nehubaContainer/statusCard/statusCard.component";
 
 import { HumanReadableFileSizePipe } from "src/util/pipes/humanReadableFileSize.pipe";
 import { KgSearchBtnColorPipe } from "src/util/pipes/kgSearchBtnColor.pipe";
 import { PluginBtnFabColorPipe } from "src/util/pipes/pluginBtnFabColor.pipe";
 import { TemplateParcellationHasMoreInfo } from "src/util/pipes/templateParcellationHasMoreInfo.pipe";
-import { MaximmisePanelButton } from "./nehubaContainer/maximisePanelButton/maximisePanelButton.component";
+
 import { ReorderPanelIndexPipe } from "./nehubaContainer/reorderPanelIndex.pipe";
-import { TouchSideClass } from "./nehubaContainer/touchSideClass.directive";
-import { BinSavedRegionsSelectionPipe, SavedRegionsSelectionBtnDisabledPipe } from "./viewerStateController/viewerState.pipes";
 
 import { FixedMouseContextualContainerDirective } from "src/util/directives/FixedMouseContextualContainerDirective.directive";
-import { RegionHierarchy } from './viewerStateController/regionHierachy/regionHierarchy.component'
-import { RegionTextSearchAutocomplete } from "./viewerStateController/regionSearch/regionSearch.component";
 
-import { ConnectivityBrowserComponent } from "src/ui/connectivityBrowser/connectivityBrowser.component";
-import { RegionMenuComponent } from 'src/ui/parcellationRegion/regionMenu/regionMenu.component'
-import { RegionListSimpleViewComponent } from "./parcellationRegion/regionListSimpleView/regionListSimpleView.component";
-import { SimpleRegionComponent } from "./parcellationRegion/regionSimple/regionSimple.component";
-import { LandmarkUIComponent } from "./landmarkUI/landmarkUI.component";
-import { NehubaModule } from "./nehubaContainer/nehuba.module";
 import { ShareModule } from "src/share";
-import { StateModule } from "src/state";
 import { AuthModule } from "src/auth";
-import { FabSpeedDialModule } from "src/components/fabSpeedDial";
 import { ActionDialog } from "./actionDialog/actionDialog.component";
-import { NehubaViewerTouchDirective } from "./nehubaContainer/nehubaViewerInterface/nehubaViewerTouch.directive";
-import { importNehubaFactory } from "./nehubaContainer/util";
 import { APPEND_SCRIPT_TOKEN, appendScriptFactory } from "src/util/constants";
 import { DOCUMENT } from "@angular/common";
-import { AtlasDropdownSelector } from './atlasDropdown/atlasDropdown.component'
-import { AtlasLayerSelector } from "src/ui/atlasLayerSelector/atlasLayerSelector.component";
 import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
-import { RegionDirective } from "./parcellationRegion/region.directive";
-import { RenderViewOriginDatasetLabelPipe } from "./parcellationRegion/region.base";
-import { RegionAccordionTooltipTextPipe } from './util'
-import { HelpOnePager } from "./helpOnePager/helpOnePager.component";
-import { RegionalFeaturesModule } from "./regionalFeatures";
+import { RegionalFeaturesModule } from "../atlasComponents/regionalFeatures";
 import { Landmark2DModule } from "./nehubaContainer/2dLandmarks/module";
-import { PluginCspCtrlCmp } from "./config/pluginCsp/pluginCsp.component";
 import { ScreenshotModule, HANDLE_SCREENSHOT_PROMISE, TypeHandleScrnShotPromise } from "./screenshot";
+import { ParcellationRegionModule } from "src/atlasComponents/parcellationRegion";
+import { AtlasCmpParcellationModule } from "src/atlasComponents/parcellation";
+import { AtlasCmptConnModule } from "src/atlasComponents/connectivity";
 
 @NgModule({
   imports : [
@@ -99,52 +64,23 @@ import { ScreenshotModule, HANDLE_SCREENSHOT_PROMISE, TypeHandleScrnShotPromise
     UtilModule,
     ScrollingModule,
     AngularMaterialModule,
-    NehubaModule,
     ShareModule,
-    StateModule,
     AuthModule,
-    FabSpeedDialModule,
     RegionalFeaturesModule,
     Landmark2DModule,
     ScreenshotModule,
+    ParcellationRegionModule,
+    AtlasCmpParcellationModule,
+    AtlasCmptConnModule,
   ],
   declarations : [
-    NehubaContainer,
+    // NehubaContainer,
     
-    SplashScreen,
-    PluginBannerUI,
     CitationsContainer,
-    KgEntryViewer,
-    SubjectViewer,
     LogoContainer,
-    TemplateParcellationCitationsContainer,
     MobileOverlay,
-    HelpComponent,
-    ConfigComponent,
-    SigninBanner,
-    AtlasDropdownSelector,
-    AtlasLayerSelector,
-    AtlasDropdownSelector,
-    PluginCspCtrlCmp,
 
-    StatusCardComponent,
-    CookieAgreement,
-    KGToS,
-    FourPanelLayout,
-    HorizontalOneThree,
-    VerticalOneThree,
-    SinglePanel,
-    CurrentLayout,
-    ViewerStateMini,
-    RegionHierarchy,
-    MaximmisePanelButton,
-    RegionTextSearchAutocomplete,
-    RegionMenuComponent,
-    ConnectivityBrowserComponent,
-    SimpleRegionComponent,
-    RegionListSimpleViewComponent,
-    LandmarkUIComponent,
-    HelpOnePager,
+    // StatusCardComponent,
 
     ActionDialog,
 
@@ -155,36 +91,21 @@ import { ScreenshotModule, HANDLE_SCREENSHOT_PROMISE, TypeHandleScrnShotPromise
     GetLayerNameFromDatasets,
     SortDataEntriesToRegion,
     SpatialLandmarksToDataBrowserItemPipe,
-    FilterNameBySearch,
     AppendtooltipTextPipe,
     MobileControlNubStylePipe,
-    GetTemplateImageSrcPipe,
-    ImgSrcSetPipe,
     PluginBtnFabColorPipe,
     KgSearchBtnColorPipe,
     GetFileExtension,
-    BinSavedRegionsSelectionPipe,
-    SavedRegionsSelectionBtnDisabledPipe,
 
     TemplateParcellationHasMoreInfo,
     HumanReadableFileSizePipe,
     ReorderPanelIndexPipe,
-    RenderViewOriginDatasetLabelPipe,
-    RegionAccordionTooltipTextPipe,
 
     /* directive */
     DownloadDirective,
-    TouchSideClass,
     FixedMouseContextualContainerDirective,
-    NehubaViewerTouchDirective,
-    RegionDirective
   ],
   providers: [
-    {
-      provide: IMPORT_NEHUBA_INJECT_TOKEN,
-      useFactory: importNehubaFactory,
-      deps: [ APPEND_SCRIPT_TOKEN ]
-    },
     {
       provide: APPEND_SCRIPT_TOKEN,
       useFactory: appendScriptFactory,
@@ -249,39 +170,18 @@ import { ScreenshotModule, HANDLE_SCREENSHOT_PROMISE, TypeHandleScrnShotPromise
 
     /* dynamically created components needs to be declared here */
     
-    PluginBannerUI,
     ActionDialog,
   ],
   exports : [
-    SubjectViewer,
-    KgEntryViewer,
     CitationsContainer,
-    PluginBannerUI,
-    NehubaContainer,
+    // NehubaContainer,
     
     LogoContainer,
-    TemplateParcellationCitationsContainer,
     MobileOverlay,
-    HelpComponent,
-    ConfigComponent,
-    SigninBanner,
-    AtlasLayerSelector,
-    RegionDirective,
     
-    CookieAgreement,
-    KGToS,
-    StatusCardComponent,
-    ViewerStateMini,
-    RegionMenuComponent,
+    // StatusCardComponent,
     FixedMouseContextualContainerDirective,
-    LandmarkUIComponent,
-    NehubaViewerTouchDirective,
-    AtlasDropdownSelector,
-    RenderViewOriginDatasetLabelPipe,
-  ],
-  schemas: [
-    CUSTOM_ELEMENTS_SCHEMA,
-  ],
+  ]
 })
 
 export class UIModule {
diff --git a/src/ui/viewerStateController/viewerState.base.ts b/src/ui/viewerStateController/viewerState.base.ts
deleted file mode 100644
index 70a67c226bec656ba46429e5d9cd203605a5fcd9..0000000000000000000000000000000000000000
--- a/src/ui/viewerStateController/viewerState.base.ts
+++ /dev/null
@@ -1,201 +0,0 @@
-import { OnInit, TemplateRef, ViewChild } from "@angular/core";
-import { select, Store } from "@ngrx/store";
-import { Observable, Subscription } from "rxjs";
-import { distinctUntilChanged, filter, shareReplay } from "rxjs/operators";
-import { DialogService } from "src/services/dialogService.service";
-import { RegionSelection } from "src/services/state/userConfigState.store";
-import { IavRootStoreInterface, SELECT_REGIONS, USER_CONFIG_ACTION_TYPES } from "src/services/stateStore.service";
-import { MatSelectChange } from "@angular/material/select";
-import { MatBottomSheet, MatBottomSheetRef } from "@angular/material/bottom-sheet";
-import { viewerStateSelectTemplateWithName } from "src/services/state/viewerState/actions";
-
-const ACTION_TYPES = {
-  SELECT_PARCELLATION_WITH_NAME: 'SELECT_PARCELLATION_WITH_NAME',
-
-}
-
-export class ViewerStateBase implements OnInit {
-
-  @ViewChild('savedRegionBottomSheetTemplate', {read: TemplateRef}) public savedRegionBottomSheetTemplate: TemplateRef<any>
-
-  public focused: boolean = false
-
-  private subscriptions: Subscription[] = []
-
-  public standaloneVolumes$: Observable<any[]>
-
-  public availableTemplates$: Observable<any[]>
-  public availableParcellations$: Observable<any[]>
-
-  public templateSelected$: Observable<any>
-  public parcellationSelected$: Observable<any>
-  public regionsSelected$: Observable<any>
-
-  public savedRegionsSelections$: Observable<any[]>
-
-  private savedRegionBottomSheetRef: MatBottomSheetRef
-
-  constructor(
-    private store$: Store<IavRootStoreInterface>,
-    private dialogService: DialogService,
-    private bottomSheet: MatBottomSheet,
-  ) {
-    const viewerState$ = this.store$.pipe(
-      select('viewerState'),
-      shareReplay(1),
-    )
-
-    this.savedRegionsSelections$ = this.store$.pipe(
-      select('userConfigState'),
-      select('savedRegionsSelection'),
-      shareReplay(1),
-    )
-
-    this.templateSelected$ = viewerState$.pipe(
-      select('templateSelected'),
-      distinctUntilChanged(),
-    )
-
-    this.parcellationSelected$ = viewerState$.pipe(
-      select('parcellationSelected'),
-      distinctUntilChanged(),
-      shareReplay(1),
-    )
-
-    this.regionsSelected$ = viewerState$.pipe(
-      select('regionsSelected'),
-      distinctUntilChanged(),
-      shareReplay(1),
-    )
-
-    this.standaloneVolumes$ = viewerState$.pipe(
-      select('standaloneVolumes'),
-      distinctUntilChanged(),
-      shareReplay(1)
-    )
-
-    this.availableTemplates$ = viewerState$.pipe(
-      select('fetchedTemplates'),
-      distinctUntilChanged()
-    )
-
-    this.availableParcellations$ = this.templateSelected$.pipe(
-      select('parcellations'),
-    )
-
-  }
-
-  public ngOnInit() {
-    this.subscriptions.push(
-      this.savedRegionsSelections$.pipe(
-        filter(srs => srs.length === 0),
-      ).subscribe(() => this.savedRegionBottomSheetRef && this.savedRegionBottomSheetRef.dismiss()),
-    )
-  }
-
-  public handleTemplateChange(event: MatSelectChange) {
-    this.store$.dispatch(
-      viewerStateSelectTemplateWithName({
-        payload: { name: event.value }
-      })
-    )
-  }
-
-  public handleParcellationChange(event: MatSelectChange) {
-    if (!event.value) { return }
-    this.store$.dispatch({
-      type: ACTION_TYPES.SELECT_PARCELLATION_WITH_NAME,
-      payload: {
-        name: event.value,
-      },
-    })
-  }
-
-  public loadSavedRegion(event: MouseEvent, savedRegionsSelection: RegionSelection) {
-    this.store$.dispatch({
-      type: USER_CONFIG_ACTION_TYPES.LOAD_REGIONS_SELECTION,
-      payload: {
-        savedRegionsSelection,
-      },
-    })
-  }
-
-  public editSavedRegion(event: MouseEvent, savedRegionsSelection: RegionSelection) {
-    event.preventDefault()
-    event.stopPropagation()
-    this.dialogService.getUserInput({
-      defaultValue: savedRegionsSelection.name,
-      placeholder: `Enter new name`,
-      title: 'Edit name',
-      iconClass: null,
-    }).then(name => {
-      if (!name) { throw new Error('user cancelled') }
-      this.store$.dispatch({
-        type: USER_CONFIG_ACTION_TYPES.UPDATE_REGIONS_SELECTION,
-        payload: {
-          ...savedRegionsSelection,
-          name,
-        },
-      })
-    }).catch(e => {
-      // TODO catch user cancel
-    })
-  }
-  public removeSavedRegion(event: MouseEvent, savedRegionsSelection: RegionSelection) {
-    event.preventDefault()
-    event.stopPropagation()
-    this.store$.dispatch({
-      type: USER_CONFIG_ACTION_TYPES.DELETE_REGIONS_SELECTION,
-      payload: {
-        ...savedRegionsSelection,
-      },
-    })
-  }
-
-  public trackByFn = ({ name }) => name
-
-  public loadSelection(_event: MouseEvent) {
-    this.focused = true
-
-    this.savedRegionBottomSheetRef = this.bottomSheet.open(this.savedRegionBottomSheetTemplate)
-    this.savedRegionBottomSheetRef.afterDismissed()
-      .subscribe(null, null, () => {
-        this.focused = false
-        this.savedRegionBottomSheetRef = null
-      })
-  }
-
-  public saveSelection(_event: MouseEvent) {
-    this.focused = true
-    this.dialogService.getUserInput({
-      defaultValue: `Saved Region`,
-      placeholder: `Name the selection`,
-      title: 'Save region selection',
-      iconClass: 'far fa-bookmark',
-    })
-      .then(name => {
-        if (!name) { throw new Error('User cancelled') }
-        this.store$.dispatch({
-          type: USER_CONFIG_ACTION_TYPES.SAVE_REGIONS_SELECTION,
-          payload: { name },
-        })
-      })
-      .catch(e => {
-        /**
-         * TODO USER CANCELLED, HANDLE
-         */
-      })
-      .finally(() => this.focused = false)
-  }
-
-  public deselectAllRegions(_event: MouseEvent) {
-    this.store$.dispatch({
-      type: SELECT_REGIONS,
-      selectRegions: [],
-    })
-  }
-
-}
-
-export const VIEWERSTATE_CONTROLLER_ACTION_TYPES = ACTION_TYPES
-
diff --git a/src/ui/viewerStateController/viewerState.pipes.ts b/src/ui/viewerStateController/viewerState.pipes.ts
deleted file mode 100644
index 400ed875be821b17776f5623d11a3e7ebbed2159..0000000000000000000000000000000000000000
--- a/src/ui/viewerStateController/viewerState.pipes.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import { Pipe, PipeTransform } from "@angular/core";
-import { RegionSelection } from "src/services/state/userConfigState.store";
-
-@Pipe({
-  name: 'binSavedRegionsSelectionPipe',
-})
-
-export class BinSavedRegionsSelectionPipe implements PipeTransform {
-  public transform(regionSelections: RegionSelection[]): Array<{parcellationSelected: any, templateSelected: any, regionSelections: RegionSelection[]}> {
-    const returnMap = new Map()
-    for (const regionSelection of regionSelections) {
-      const key = `${regionSelection.templateSelected.name}\n${regionSelection.parcellationSelected.name}`
-      const existing = returnMap.get(key)
-      if (existing) { existing.push(regionSelection) } else { returnMap.set(key, [regionSelection]) }
-    }
-    return Array.from(returnMap)
-      .map(([_unused, regionSelections]) => {
-        const {parcellationSelected = null, templateSelected = null} = regionSelections[0] || {}
-        return {
-          regionSelections,
-          parcellationSelected,
-          templateSelected,
-        }
-      })
-  }
-}
-
-@Pipe({
-  name: 'savedRegionsSelectionBtnDisabledPipe',
-})
-
-export class SavedRegionsSelectionBtnDisabledPipe implements PipeTransform {
-  public transform(regionSelection: RegionSelection, templateSelected: any, parcellationSelected: any): boolean {
-    return regionSelection.parcellationSelected.name !== parcellationSelected.name
-      || regionSelection.templateSelected.name !== templateSelected.name
-  }
-}
diff --git a/src/ui/viewerStateController/viewerStateCMini/viewerStateMini.component.ts b/src/ui/viewerStateController/viewerStateCMini/viewerStateMini.component.ts
deleted file mode 100644
index 66ff71b0c37b93d3ecba2c26980e90b1fa4f22f5..0000000000000000000000000000000000000000
--- a/src/ui/viewerStateController/viewerStateCMini/viewerStateMini.component.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { Component } from "@angular/core";
-import { Store } from "@ngrx/store";
-import { DialogService } from "src/services/dialogService.service";
-
-import { IavRootStoreInterface } from "src/services/stateStore.service";
-import { ViewerStateBase } from '../viewerState.base'
-import {MatBottomSheet} from "@angular/material/bottom-sheet";
-
-@Component({
-  selector: 'viewer-state-mini',
-  templateUrl: './viewerStateMini.template.html',
-  styleUrls: [
-    './viewerStateMini.style.css',
-  ],
-})
-
-export class ViewerStateMini extends ViewerStateBase {
-
-  constructor(
-    store$: Store<IavRootStoreInterface>,
-    dialogService: DialogService,
-    bottomSheet: MatBottomSheet,
-  ) {
-    super(store$, dialogService, bottomSheet)
-  }
-}
diff --git a/src/ui/viewerStateController/viewerStateCMini/viewerStateMini.template.html b/src/ui/viewerStateController/viewerStateCMini/viewerStateMini.template.html
deleted file mode 100644
index 2604321cb2f7ec6f857ab83acaff064338a19284..0000000000000000000000000000000000000000
--- a/src/ui/viewerStateController/viewerStateCMini/viewerStateMini.template.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!-- selected template and parcellation -->
-<div *ngIf="templateSelected$ | async as templateSelected">
-  {{ templateSelected.name }}
-</div>
-<div *ngIf="parcellationSelected$ | async as parcellationSelected">
-  {{ (parcellationSelected.displayName || parcellationSelected.name) | tmpParcNamePipe }}
-</div>
-
-<!-- selected parcellation regions -->
-<ng-container *ngIf="regionsSelected$ | async as regionsSelected">
-  <ng-container *ngIf="regionsSelected.length > 0">
-    <div class="mt-2">
-      {{ regionsSelected.length }} region{{ regionsSelected.length > 1 ? 's' : '' }} selected
-    </div>
-  </ng-container>
-</ng-container>
-
-<ng-container *ngIf="standaloneVolumes$ | async as standaloneVolumes">
-  <div *ngFor="let vol of standaloneVolumes">
-    {{ vol }}
-  </div>
-</ng-container>
\ No newline at end of file
diff --git a/src/util/fn.spec.ts b/src/util/fn.spec.ts
index 98f60a54cb0b71f9e5de4c38db0f8b6a8d95f6e2..f17d211b79c3b363eb7da40c9e517817a66db4a5 100644
--- a/src/util/fn.spec.ts
+++ b/src/util/fn.spec.ts
@@ -1,7 +1,28 @@
 import {} from 'jasmine'
-import { isSame } from './fn'
+import { isSame, getGetRegionFromLabelIndexId } from './fn'
 
 describe(`util/fn.ts`, () => {
+
+  describe('getGetRegionFromLabelIndexId', () => {
+    const colinsJson = require('!json-loader!../res/ext/colin.json')
+    
+    const COLIN_JULICHBRAIN_LAYER_NAME = `COLIN_V25_LEFT_NG_SPLIT_HEMISPHERE`
+    const COLIN_V25_ID = 'minds/core/parcellationatlas/v1.0.0/94c1125b-b87e-45e4-901c-00daee7f2579-25'
+    
+    it('translateds hoc1 from labelIndex to region', () => {
+
+      const getRegionFromlabelIndexId = getGetRegionFromLabelIndexId({
+        parcellation: {
+          ...colinsJson.parcellations.find(p => p['@id'] === COLIN_V25_ID),
+          updated: true,
+        },
+      })
+      const fetchedRegion = getRegionFromlabelIndexId({ labelIndexId: `${COLIN_JULICHBRAIN_LAYER_NAME}#116` })
+      expect(fetchedRegion).toBeTruthy()
+      expect(fetchedRegion.fullId.kg.kgId).toEqual('c9753e82-80ca-4074-a704-9dd2c4c0d58b')
+      
+    })
+  })
   describe(`#isSame`, () => {
     it('should return true with null, null', () => {
       expect(isSame(null, null)).toBe(true)
diff --git a/src/util/fn.ts b/src/util/fn.ts
index 827aec4f0e872df3433aacc123066f6707ce2f72..a62dd546b99b936a4f2a74d6b947b99a1f6b2659 100644
--- a/src/util/fn.ts
+++ b/src/util/fn.ts
@@ -55,3 +55,10 @@ export function recursiveFindRegionWithLabelIndexId({ regions, labelIndexId, inh
 export function getUuid(){
   return crypto.getRandomValues(new Uint32Array(1))[0].toString(16)
 }
+
+export const getGetRegionFromLabelIndexId = ({ parcellation }) => {
+  const { ngId: defaultNgId, regions } = parcellation
+  // if (!updated) throw new Error(`parcellation not yet updated`)
+  return ({ labelIndexId }) =>
+    recursiveFindRegionWithLabelIndexId({ regions, labelIndexId, inheritedNgId: defaultNgId })
+}
diff --git a/src/viewerModule/index.ts b/src/viewerModule/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6e5c74fbe55be040c17b54d98c7b6f29cd66a513
--- /dev/null
+++ b/src/viewerModule/index.ts
@@ -0,0 +1 @@
+export { ViewerModule } from "./module"
\ No newline at end of file
diff --git a/src/viewerModule/module.ts b/src/viewerModule/module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b9359cbf6fce7c4d6d204b3bd71e08d0adc27d36
--- /dev/null
+++ b/src/viewerModule/module.ts
@@ -0,0 +1,349 @@
+import { CommonModule } from "@angular/common";
+import { NgModule } from "@angular/core";
+import { AtlasCmptConnModule } from "src/atlasComponents/connectivity";
+import { DatabrowserModule } from "src/atlasComponents/databrowserModule";
+import { AtlasCmpParcellationModule } from "src/atlasComponents/parcellation";
+import { ParcellationRegionModule } from "src/atlasComponents/parcellationRegion";
+import { SplashUiModule } from "src/atlasComponents/splashScreen";
+import { AtlasCmpUiSelectorsModule } from "src/atlasComponents/uiSelectors";
+import { ComponentsModule } from "src/components";
+import { LayoutModule } from "src/layouts/layout.module";
+import { AngularMaterialModule } from "src/ui/sharedModules/angularMaterial.module";
+import { TopMenuModule } from "src/ui/topMenu/module";
+import { UtilModule } from "src/util";
+import { NehubaModule } from "./nehuba";
+import { RegionAccordionTooltipTextPipe } from "./util/regionAccordionTooltipText.pipe";
+import { ViewerCmp } from "./viewerCmp/viewerCmp.component";
+
+@NgModule({
+  imports: [
+    CommonModule,
+    NehubaModule,
+    LayoutModule,
+    DatabrowserModule,
+    AtlasCmpUiSelectorsModule,
+    AngularMaterialModule,
+    SplashUiModule,
+    TopMenuModule,
+    ParcellationRegionModule,
+    UtilModule,
+    AtlasCmpParcellationModule,
+    AtlasCmptConnModule,
+    ComponentsModule,
+  ],
+  declarations: [
+    ViewerCmp,
+
+    RegionAccordionTooltipTextPipe,
+  ],
+  exports: [
+    ViewerCmp,
+  ],
+})
+
+export class ViewerModule{}
+
+/**
+    <ui-nehuba-container
+      class="z-index-10"
+      #uiNehubaContainer="uiNehubaContainer"
+      iav-mouse-hover
+      #iavMouseHoverEl="iavMouseHover"
+      [currentOnHoverObs$]="iavMouseHoverEl.currentOnHoverObs$"
+      [currentOnHover]="iavMouseHoverEl.currentOnHoverObs$ | async"
+      iav-captureClickListenerDirective
+      [iav-captureClickListenerDirective-captureDocument]="true"
+      (iav-captureClickListenerDirective-onUnmovedClick)="mouseClickDocument($event)"
+      (drag-drop)="localFileService.handleFileDrop($event)">
+
+      <!-- top right content transclusion -->
+      <div ui-nehuba-container-overlay-top-right class="d-inline-flex flex-row justify-content-end align-items-start z-index-6 position-absolute pe-none w-100 h-100">
+
+        <top-menu-cmp
+          class="mt-3 mr-2"
+          [parcellationIsSelected]="!!selectedParcellation"
+          [ismobile]="(media.mediaBreakPoint$ | async) > 3">
+        </top-menu-cmp>
+
+        <!-- atlas selector -->
+        <div *ngIf="uiNehubaContainer.viewerLoaded"
+          class="iv-custom-comp bg card m-2 mat-elevation-z2">
+          <atlas-dropdown-selector class="pe-all mt-2">
+          </atlas-dropdown-selector>
+        </div>
+
+      </div>
+
+      <!-- bottom left content transclusion -->
+      <div ui-nehuba-container-overlay-bottom-left class="d-inline-flex pe-none w-100 align-items-end m-2 mb-4">
+
+        <!-- only load atlas layer selector and chips if viewer is loaded -->
+        <ng-template [ngIf]="uiNehubaContainer.viewerLoaded  && !(isStandaloneVolumes$ | async)">
+
+          <!-- Viewer Selector Container-->
+          <atlas-layer-selector
+            #alSelector="atlasLayerSelector"
+            class="pe-all"
+            (iav-outsideClick)="alSelector.selectorExpanded = false">
+          </atlas-layer-selector>
+          <mat-chip-list class="mb-2">
+            <!-- additional layer -->
+
+            <ng-container>
+              <ng-container *ngTemplateOutlet="currParcellationTmpl; context: { addParc: (selectedAdditionalLayers$ | async), parc: selectedParcellation }">
+              </ng-container>
+            </ng-container>
+
+            <!-- any selected region(s) -->
+            <ng-container>
+              <ng-container *ngTemplateOutlet="selectedRegionTmpl">
+              </ng-container>
+            </ng-container>
+
+            <!-- controls for iav volumes -->
+            <div class="hidden" iav-shown-previews #previews="iavShownPreviews"></div>
+            <ng-container *ngTemplateOutlet="selectedDatasetPreview; context: { layers: previews.iavAdditionalLayers$ | async | filterPreviewByType : [previews.FILETYPES.VOLUMES] }">
+            </ng-container>
+
+          </mat-chip-list>
+
+          <!-- current layer tmpl -->
+
+          <ng-template #currParcellationTmpl let-parc="parc" let-addParc="addParc">
+
+            <div [matMenuTriggerFor]="layerVersionMenu"
+              [matMenuTriggerData]="{ layerVersionMenuTrigger: layerVersionMenuTrigger }"
+              #layerVersionMenuTrigger="matMenuTrigger">
+
+              <ng-template [ngIf]="addParc.length > 0" [ngIfElse]="defaultParcTmpl">
+                <ng-container *ngFor="let p of addParc">
+                  <ng-container *ngTemplateOutlet="chipTmpl; context: {
+                    parcel: p,
+                    selected: true,
+                    dismissable: true,
+                    onclick: layerVersionMenuTrigger.toggleMenu.bind(layerVersionMenuTrigger)
+                  }">
+                  </ng-container>
+                </ng-container>
+              </ng-template>
+              <ng-template #defaultParcTmpl>
+                <ng-container *ngTemplateOutlet="chipTmpl; context: {
+                  parcel: parc,
+                  selected: false,
+                  dismissable: false,
+                  onclick: layerVersionMenuTrigger.toggleMenu.bind(layerVersionMenuTrigger)
+                }">
+                </ng-container>
+              </ng-template>
+            </div>
+          </ng-template>
+
+          <!-- render parc templ -->
+          <ng-template #chipTmpl
+            let-parcel="parcel"
+            let-selected="selected"
+            let-dismissable="dismissable"
+            let-chipClass="class"
+            let-onclick="onclick">
+            <mat-chip class="pe-all position-relative z-index-2 d-inline-flex justify-content-between"
+              [ngClass]="chipClass"
+              (click)="onclick && onclick()"
+              [selected]="selected">
+
+              <span>
+                {{ parcel?.groupName ? (parcel?.groupName + ' - ') : '' }}{{ parcel && (parcel.displayName || parcel.name) }}
+              </span>
+
+              <!-- info icon -->
+              <ng-template [ngIf]="parcel?.originDatasets?.length > 0" [ngIfElse]="infoIconBasic">
+
+                <mat-icon
+                  *ngFor="let ds of parcel.originDatasets"
+                  fontSet="fas"
+                  fontIcon="fa-info-circle"
+                  iav-stop="click"
+                  iav-dataset-show-dataset-dialog
+                  [iav-dataset-show-dataset-dialog-kgid]="ds['kgId']"
+                  [iav-dataset-show-dataset-dialog-kgschema]="ds['kgSchema']"
+                  [iav-dataset-show-dataset-dialog-name]="parcel?.properties?.name"
+                  [iav-dataset-show-dataset-dialog-description]="parcel?.properties?.description">
+                </mat-icon>
+
+              </ng-template>
+
+              <ng-template #infoIconBasic>
+                <mat-icon *ngIf="parcel?.properties?.name && parcel?.properties?.description"
+                  fontSet="fas"
+                  fontIcon="fa-info-circle"
+                  iav-stop="click"
+                  iav-dataset-show-dataset-dialog
+                  [iav-dataset-show-dataset-dialog-name]="parcel.properties.name"
+                  [iav-dataset-show-dataset-dialog-description]="parcel.properties.description">
+
+                </mat-icon>
+              </ng-template>
+
+              <!-- dismiss icon -->
+              <mat-icon
+                *ngIf="dismissable"
+                (click)="clearAdditionalLayer(parcel); $event.stopPropagation()"
+                fontSet="fas"
+                fontIcon="fa-times">
+              </mat-icon>
+            </mat-chip>
+          </ng-template>
+
+          <!-- layer version selector -->
+          <mat-menu #layerVersionMenu
+            class="bg-none box-shadow-none"
+            [hasBackdrop]="false">
+            <ng-template matMenuContent let-layerVersionMenuTrigger="layerVersionMenuTrigger">
+              <div (iav-outsideClick)="layerVersionMenuTrigger.closeMenu()">
+                <ng-container *ngFor="let parcVer of selectedLayerVersions$ | async">
+                  <ng-container *ngTemplateOutlet="chipTmpl; context: {
+                    parcel: parcVer,
+                    selected: selectedParcellation && selectedParcellation['@id'] === parcVer['@id'],
+                    dismissable: false,
+                    class: 'w-100',
+                    onclick: bindFns([
+                      [ selectParcellation.bind(this), parcVer ],
+                      [ layerVersionMenuTrigger.closeMenu.bind(layerVersionMenuTrigger) ]
+                    ])
+                  }">
+                  </ng-container>
+                  <div class="mt-1"></div>
+                </ng-container>
+              </div>
+            </ng-template>
+          </mat-menu>
+
+          <ng-template #selectedRegionTmpl>
+
+            <!-- regions chip -->
+            <ng-template [ngIf]="selectedRegions$ | async" let-selectedRegions="ngIf">
+              <!-- if regions.length > 1 -->
+              <!-- use group chip -->
+              <ng-template [ngIf]="selectedRegions.length > 1" [ngIfElse]="singleRegionTmpl">
+                <mat-chip
+                  color="primary"
+                  selected
+                  (click)="uiNehubaContainer.matDrawerMinor.open() && uiNehubaContainer.navSideDrawerMainSwitch.open()"
+                  class="pe-all position-relative z-index-1 ml-8-n">
+                  <span class="iv-custom-comp text text-truncate d-inline pl-4">
+                    {{ CONST.MULTI_REGION_SELECTION }}
+                  </span>
+                  <mat-icon
+                    (click)="clearSelectedRegions()"
+                    fontSet="fas"
+                    iav-stop="click"
+                    fontIcon="fa-times">
+                  </mat-icon>
+                </mat-chip>
+              </ng-template>
+
+              <!-- if reginos.lengt === 1 -->
+              <!-- use single region chip -->
+              <ng-template #singleRegionTmpl>
+                <ng-container *ngFor="let r of selectedRegions">
+
+                  <!-- region chip for discrete map -->
+                  <mat-chip
+                    iav-region
+                    (click)="uiNehubaContainer.matDrawerMinor.open() && uiNehubaContainer.navSideDrawerMainSwitch.open()"
+                    [region]="r"
+                    class="pe-all position-relative z-index-1 ml-8-n"
+                    [ngClass]="{
+                      'darktheme':regionDirective.rgbDarkmode === true,
+                      'lighttheme': regionDirective.rgbDarkmode === false
+                    }"
+                    [style.backgroundColor]="regionDirective.rgbString"
+                    #regionDirective="iavRegion">
+                    <span class="iv-custom-comp text text-truncate d-inline pl-4">
+                      {{ r.name }}
+                    </span>
+                    <mat-icon
+                      class="iv-custom-comp text"
+                      (click)="clearSelectedRegions()"
+                      fontSet="fas"
+                      iav-stop="click"
+                      fontIcon="fa-times">
+                    </mat-icon>
+                  </mat-chip>
+    
+                  <!-- chips for previewing origin datasets/continous map -->
+                  <ng-container *ngFor="let originDataset of (r.originDatasets || []); let index = index">
+                    <div class="hidden"
+                      iav-dataset-preview-dataset-file
+                      [iav-dataset-preview-dataset-file-kgid]="originDataset.kgId"
+                      [iav-dataset-preview-dataset-file-filename]="originDataset.filename"
+                      #previewDirective="iavDatasetPreviewDatasetFile">
+                    </div>
+                    <mat-chip *ngIf="previewDirective.active"
+                      (click)="uiNehubaContainer.matDrawerMinor.open() && uiNehubaContainer.navSideDrawerMainSwitch.open()"
+                      class="pe-all position-relative ml-8-n">
+                      <span class="pl-4">
+                        {{ regionDirective.regionOriginDatasetLabels$ | async | renderViewOriginDatasetlabel : index }}
+                      </span>
+                      <mat-icon (click)="previewDirective.onClick()"
+                        fontSet="fas"
+                        iav-stop="click"
+                        fontIcon="fa-times">
+                      </mat-icon>
+                    </mat-chip>
+    
+                    <mat-chip *ngFor="let key of clearViewKeys$ | async"
+                      (click)="uiNehubaContainer.matDrawerMinor.open() && uiNehubaContainer.navSideDrawerMainSwitch.open()"
+                      class="pe-all position-relative ml-8-n">
+                      <span class="pl-4">
+                        {{ key }}
+                      </span>
+                      <mat-icon (click)="unsetClearViewByKey(key)"
+                        fontSet="fas"
+                        iav-stop="click"
+                        fontIcon="fa-times">
+    
+                      </mat-icon>
+                    </mat-chip>
+                  </ng-container>
+    
+                </ng-container>
+              </ng-template>
+            </ng-template>
+
+          </ng-template>
+
+          <ng-template #selectedDatasetPreview let-layers="layers">
+
+            <ng-container *ngFor="let layer of layers">
+              <div class="hidden"
+                iav-dataset-preview-dataset-file
+                [iav-dataset-preview-dataset-file-kgid]="layer.datasetId"
+                [iav-dataset-preview-dataset-file-filename]="layer.filename"
+                #preview="iavDatasetPreviewDatasetFile">
+
+              </div>
+              <mat-chip class="pe-all"
+                (click)="uiNehubaContainer.matDrawerMinor.open() && uiNehubaContainer.navSideDrawerMainSwitch.open()">
+                {{ layer.file?.name || layer.filename || 'Unknown data preview' }}
+                <mat-icon fontSet="fas" fontIcon="fa-times"
+                  (click)="preview.onClick()"
+                  iav-stop="click">
+                </mat-icon>
+              </mat-chip>
+            </ng-container>
+          </ng-template>
+
+        </ng-template>
+      </div>
+
+      <!-- top left content transclusion -->
+      <div ui-nehuba-container-overlay-top-left class="d-inline-flex pe-none w-100 align-items-start m-2">
+        <ui-status-card
+          *ngIf="uiNehubaContainer.viewerLoaded"
+          class="pe-all muted-7"
+          [selectedTemplateName]="uiNehubaContainer?.selectedTemplate?.name"
+          [nehubaViewer]="uiNehubaContainer?.nehubaViewer">
+        </ui-status-card>
+      </div>
+    </ui-nehuba-container>
+ */
\ No newline at end of file
diff --git a/src/viewerModule/nehuba/actions.ts b/src/viewerModule/nehuba/actions.ts
new file mode 100644
index 0000000000000000000000000000000000000000..979a485f1694ed7586d2326a5a286703d4610522
--- /dev/null
+++ b/src/viewerModule/nehuba/actions.ts
@@ -0,0 +1,10 @@
+import { createAction, props } from "@ngrx/store";
+import { INgLayerInterface } from "src/services/state/ngViewerState.store";
+import { NEHUBA_VIEWER_FEATURE_KEY } from "./constants";
+
+export const actionAddNgLayer = createAction(
+  `[${NEHUBA_VIEWER_FEATURE_KEY}] [addNgLayer]`,
+  props<{
+    layers: INgLayerInterface[]
+  }>()
+)
\ No newline at end of file
diff --git a/src/viewerModule/nehuba/constants.ts b/src/viewerModule/nehuba/constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5dd2cd2c51eb1146d8769bfe0025d93644d33c6c
--- /dev/null
+++ b/src/viewerModule/nehuba/constants.ts
@@ -0,0 +1,59 @@
+export { getNgIds } from 'src/util/fn'
+export const NEHUBA_VIEWER_FEATURE_KEY = 'ngViewerFeature'
+
+export interface INgLayerInterface {
+  name: string // displayName
+  source: string
+  mixability: string // base | mixable | nonmixable
+  annotation?: string //
+  id?: string // unique identifier
+  visible?: boolean
+  shader?: string
+  transform?: any
+}
+
+export function getMultiNgIdsRegionsLabelIndexMap(parcellation: any = {}, inheritAttrsOpt: any = { ngId: 'root' }): Map<string, Map<number, any>> {
+  const map: Map<string, Map<number, any>> = new Map()
+  
+  const inheritAttrs = Object.keys(inheritAttrsOpt)
+  if (inheritAttrs.indexOf('children') >=0 ) throw new Error(`children attr cannot be inherited`)
+
+  const processRegion = (region: any) => {
+    const { ngId: rNgId } = region
+    const existingMap = map.get(rNgId)
+    const labelIndex = Number(region.labelIndex)
+    if (labelIndex) {
+      if (!existingMap) {
+        const newMap = new Map()
+        newMap.set(labelIndex, region)
+        map.set(rNgId, newMap)
+      } else {
+        existingMap.set(labelIndex, region)
+      }
+    }
+
+    if (region.children && Array.isArray(region.children)) {
+      for (const r of region.children) {
+        const copiedRegion = { ...r }
+        for (const attr of inheritAttrs){
+          copiedRegion[attr] = copiedRegion[attr] || region[attr] || parcellation[attr]
+        }
+        processRegion(copiedRegion)
+      }
+    }
+  }
+
+  if (!parcellation) throw new Error(`parcellation needs to be defined`)
+  if (!parcellation.regions) throw new Error(`parcellation.regions needs to be defined`)
+  if (!Array.isArray(parcellation.regions)) throw new Error(`parcellation.regions needs to be an array`)
+
+  for (const region of parcellation.regions){
+    const copiedregion = { ...region }
+    for (const attr of inheritAttrs){
+      copiedregion[attr] = copiedregion[attr] || parcellation[attr]
+    }
+    processRegion(copiedregion)
+  }
+
+  return map
+}
diff --git a/src/viewerModule/nehuba/index.ts b/src/viewerModule/nehuba/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..65cb900d6d7293034929898b2515f02082d04b37
--- /dev/null
+++ b/src/viewerModule/nehuba/index.ts
@@ -0,0 +1,4 @@
+export { NehubaGlueCmp } from "./nehubaViewerGlue/nehubaViewerGlue.component"
+export { NehubaViewerTouchDirective } from "./nehubaViewerInterface/nehubaViewerTouch.directive"
+export { NehubaModule } from "./module"
+export { NehubaViewerUnit } from "./nehubaViewer/nehubaViewer.component"
diff --git a/src/ui/nehubaContainer/maximisePanelButton/maximisePanelButton.component.ts b/src/viewerModule/nehuba/maximisePanelButton/maximisePanelButton.component.ts
similarity index 97%
rename from src/ui/nehubaContainer/maximisePanelButton/maximisePanelButton.component.ts
rename to src/viewerModule/nehuba/maximisePanelButton/maximisePanelButton.component.ts
index b3e5745f92e2ea7e9dbb2d95cc2298375b3a49b3..7aab44ac4156b05454a3d7bce915068cdf24a07e 100644
--- a/src/ui/nehubaContainer/maximisePanelButton/maximisePanelButton.component.ts
+++ b/src/viewerModule/nehuba/maximisePanelButton/maximisePanelButton.component.ts
@@ -19,7 +19,7 @@ const {
   ],
 })
 
-export class MaximmisePanelButton {
+export class MaximisePanelButton {
 
   public ARIA_LABEL_MAXIMISE_VIEW = MAXIMISE_VIEW
   public ARIA_LABEL_UNMAXIMISE_VIEW = UNMAXIMISE_VIEW
diff --git a/src/viewerModule/nehuba/maximisePanelButton/maximisePanelButton.style.css b/src/viewerModule/nehuba/maximisePanelButton/maximisePanelButton.style.css
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/ui/nehubaContainer/maximisePanelButton/maximisePanelButton.template.html b/src/viewerModule/nehuba/maximisePanelButton/maximisePanelButton.template.html
similarity index 100%
rename from src/ui/nehubaContainer/maximisePanelButton/maximisePanelButton.template.html
rename to src/viewerModule/nehuba/maximisePanelButton/maximisePanelButton.template.html
diff --git a/src/viewerModule/nehuba/module.ts b/src/viewerModule/nehuba/module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..061d73c27f32a9a1793d0d398292a02155c44aa3
--- /dev/null
+++ b/src/viewerModule/nehuba/module.ts
@@ -0,0 +1,79 @@
+import { ComponentRef, NgModule } from "@angular/core";
+import { NehubaViewerContainerDirective } from './nehubaViewerInterface/nehubaViewerInterface.directive'
+import { IMPORT_NEHUBA_INJECT_TOKEN, NehubaViewerUnit } from "./nehubaViewer/nehubaViewer.component";
+import { CommonModule } from "@angular/common";
+import { APPEND_SCRIPT_TOKEN } from "src/util/constants";
+import { importNehubaFactory, NEHUBA_INSTANCE_INJTKN } from "./util";
+import { NehubaViewerTouchDirective } from "./nehubaViewerInterface/nehubaViewerTouch.directive";
+import { StoreModule } from "@ngrx/store";
+import { NEHUBA_VIEWER_FEATURE_KEY } from "./constants";
+import { reducer } from "./store";
+import { NehubaGlueCmp } from "./nehubaViewerGlue/nehubaViewerGlue.component";
+import { UtilModule } from "src/util";
+import { LayoutModule } from "src/layouts/layout.module";
+import { TouchSideClass } from "./touchSideClass.directive";
+import { ComponentsModule } from "src/components";
+import { AngularMaterialModule } from "src/ui/sharedModules/angularMaterial.module";
+import { MaximisePanelButton } from "./maximisePanelButton/maximisePanelButton.component";
+import { Landmark2DModule } from "src/ui/nehubaContainer/2dLandmarks/module";
+import { MouseoverModule } from "src/mouseoverModule";
+import { StatusCardComponent } from "./statusCard/statusCard.component";
+import { ShareModule } from "src/share";
+import { FormsModule, ReactiveFormsModule } from "@angular/forms";
+import { Subject } from "rxjs";
+import { StateModule } from "src/state";
+import { AuthModule } from "src/auth";
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    ReactiveFormsModule,
+    UtilModule,
+    LayoutModule,
+    AngularMaterialModule,
+    Landmark2DModule,
+    ComponentsModule,
+    MouseoverModule,
+    ShareModule,
+
+    /**
+     * should probably break this into its own...
+     * share url module or something?
+     */
+    StateModule,
+    AuthModule,
+    StoreModule.forFeature(
+      NEHUBA_VIEWER_FEATURE_KEY,
+      reducer
+    )
+  ],
+  declarations: [
+    NehubaViewerContainerDirective,
+    NehubaViewerUnit,
+    NehubaViewerTouchDirective,
+    NehubaGlueCmp,
+    TouchSideClass,
+    MaximisePanelButton,
+    StatusCardComponent,
+  ],
+  exports: [
+    NehubaViewerUnit,
+    NehubaViewerTouchDirective,
+    NehubaGlueCmp,
+    StatusCardComponent,
+  ],
+  providers: [
+    {
+      provide: IMPORT_NEHUBA_INJECT_TOKEN,
+      useFactory: importNehubaFactory,
+      deps: [ APPEND_SCRIPT_TOKEN ]
+    },
+    {
+      provide: NEHUBA_INSTANCE_INJTKN,
+      useValue: new Subject()
+    }
+  ]
+})
+
+export class NehubaModule{}
diff --git a/src/viewerModule/nehuba/nehubaContainer.component.spec.ts b/src/viewerModule/nehuba/nehubaContainer.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..61bb83b5671bbfe3366c0a5ae2450bfa0f4c5711
--- /dev/null
+++ b/src/viewerModule/nehuba/nehubaContainer.component.spec.ts
@@ -0,0 +1,688 @@
+
+// const { 
+//   TOGGLE_SIDE_PANEL,
+//   EXPAND,
+//   COLLAPSE,
+//   ZOOM_IN,
+//   ZOOM_OUT,
+//   TOGGLE_FRONTAL_OCTANT
+// } = ARIA_LABELS
+
+// const _bigbrainJson = require('!json-loader!src/res/ext/bigbrain.json')
+// const _bigbrainNehubaConfigJson = require('!json-loader!src/res/ext/bigbrainNehubaConfig.json')
+// const bigbrainJson = {
+//   ..._bigbrainJson,
+//   nehubaConfig: _bigbrainNehubaConfigJson
+// }
+// const humanAtlas = require('!json-loader!src/res/ext/atlas/atlas_multiLevelHuman.json')
+// const importNehubaSpy = jasmine.createSpy('importNehubaSpy').and.returnValue(Promise.reject())
+
+describe('> nehubaContainer.component.ts', () => {
+
+  describe('> NehubaContainer', () => {
+
+    // beforeEach(async(() => {
+
+    //   TestBed.configureTestingModule({
+    //     imports: [
+    //       NoopAnimationsModule,
+    //       WidgetModule,
+    //       AngularMaterialModule,
+    //       LayoutModule,
+    //       UtilModule,
+    //       DatabrowserModule,
+    //       NehubaModule,
+    //       AuthModule,
+    //       StateModule,
+    //       FormsModule,
+    //       ReactiveFormsModule,
+    //       HttpClientModule,
+    //       CommonModule,
+    //       RegionalFeaturesModule,
+    //       ParcellationRegionModule,
+    //       AtlasCmpParcellationModule,
+
+    //       /**
+    //        * because the change done to pureconstant service, need to intercept http call to avoid crypto error message
+    //        * so and so components needs to be compiled first. make sure you call compileComponents
+    //        */
+    //       HttpClientTestingModule,
+    //       Landmark2DModule,
+    //     ],
+    //     declarations: [
+    //       NehubaContainer,
+    //       TouchSideClass,
+    //       MaximisePanelButton,
+    //       AtlasLayerSelector,
+    //       StatusCardComponent,
+    //       NehubaViewerTouchDirective,
+    //       MobileOverlay,
+          
+    //       SplashScreen,
+    //       CurrentLayout,
+  
+    //       // pipes
+    //       MobileControlNubStylePipe,
+    //       ReorderPanelIndexPipe,
+          
+    //       RegionAccordionTooltipTextPipe,
+    //     ],
+    //     providers: [
+    //       provideMockStore({ initialState: defaultRootState }),
+    //       {
+    //         provide: IMPORT_NEHUBA_INJECT_TOKEN,
+    //         useValue: importNehubaSpy
+    //       },
+    //       PureContantService,
+    //     ],
+    //     schemas: [
+    //       CUSTOM_ELEMENTS_SCHEMA
+    //     ],
+    //   }).compileComponents()
+      
+    // }))
+
+    
+    // const fixture = TestBed.createComponent(NehubaContainer)
+    // fixture.componentInstance.currentOnHoverObs$ = hot('')
+    // const el = fixture.debugElement.componentInstance
+    // expect(el).toBeTruthy()
+    it('> component can be created')
+
+    describe('> on selectedTemplatechange', () => {
+
+      // const fixture = TestBed.createComponent(NehubaContainer)
+      // fixture.componentInstance.currentOnHoverObs$ = hot('')
+
+      // const mockStore = TestBed.inject(MockStore)
+      // const newState = {
+      //   ...defaultRootState,
+      //   viewerState: {
+      //     ...defaultRootState.viewerState,
+      //     fetchedTemplates: [ bigbrainJson ],
+      //     templateSelected: bigbrainJson,
+      //     parcellationSelected: bigbrainJson.parcellations[0]
+      //   },
+      //   [viewerStateHelperStoreName]: {
+      //     fetchedAtlases: [ humanAtlas ],
+      //     selectedAtlasId: humanAtlas['@id']
+      //   }
+      // }
+
+      // mockStore.setState(newState)
+      // fixture.detectChanges()
+      // expect(importNehubaSpy).toHaveBeenCalled()
+      it('> calls importNehubaPr')
+
+      /**
+       * TODO perhaps move this to e2e?
+       */
+      it('> drag handle reattaches properly')
+    })
+
+    describe('> on selectedparcellation change', () => {
+
+
+      // const fixture = TestBed.createComponent(NehubaContainer)
+      // fixture.componentInstance.currentOnHoverObs$ = hot('')
+      // const el = fixture.debugElement.componentInstance as NehubaContainer
+      // const mockStore = TestBed.inject(MockStore)
+      // const newState = {
+      //   ...defaultRootState,
+      //   viewerState: {
+      //     ...defaultRootState.viewerState,
+      //     fetchedTemplates: [ bigbrainJson ],
+      //     templateSelected: bigbrainJson,
+      //     parcellationSelected: bigbrainJson.parcellations[0]
+      //   },
+      //   [viewerStateHelperStoreName]: {
+      //     fetchedAtlases: [ humanAtlas ],
+      //     selectedAtlasId: humanAtlas['@id']
+      //   }
+      // }
+
+      // mockStore.setState(newState)
+      // fixture.detectChanges()
+
+      // const setSpy = spyOnProperty(el.nehubaViewer, 'ngIds', 'set')
+
+      // const newState2 = {
+      //   ...defaultRootState,
+      //   viewerState: {
+      //     ...defaultRootState.viewerState,
+      //     fetchedTemplates: [ bigbrainJson ],
+      //     templateSelected: bigbrainJson,
+      //     parcellationSelected: bigbrainJson.parcellations[1]
+      //   },
+      //   [viewerStateHelperStoreName]: {
+      //     fetchedAtlases: [ humanAtlas ],
+      //     selectedAtlasId: humanAtlas['@id']
+      //   }
+      // }
+
+      // mockStore.setState(newState2)
+      // fixture.detectChanges()
+
+      // expect(setSpy).toHaveBeenCalled()
+      it('> should set ngId of nehubaViewer')
+    })
+
+    describe('> extended sidepanel hides and shows as expected', () => {
+      describe('> on start, if nothing is selected', () => {
+        // beforeEach(() => {
+        //   const mockStore = TestBed.inject(MockStore)
+        //   const newState = {
+        //     ...defaultRootState,
+        //     viewerState: {
+        //       ...defaultRootState.viewerState,
+        //       fetchedTemplates: [ bigbrainJson ],
+        //       templateSelected: bigbrainJson,
+        //       parcellationSelected: bigbrainJson.parcellations[0]
+        //     },
+        //     [viewerStateHelperStoreName]: {
+        //       fetchedAtlases: [ humanAtlas ],
+        //       selectedAtlasId: humanAtlas['@id']
+        //     }
+        //   }
+
+        //   mockStore.setState(newState)
+        // })
+
+
+
+        // const fixture = TestBed.createComponent(NehubaContainer)
+        // fixture.componentInstance.currentOnHoverObs$ = hot('')
+        // fixture.detectChanges()
+        // expect(
+        //   fixture.componentInstance.matDrawerMain.opened
+        // ).toEqual(false)
+        // expect(
+        //   fixture.componentInstance.matDrawerMinor.opened
+        // ).toEqual(false)
+        it('> both should be shut')
+
+
+        // const fixture = TestBed.createComponent(NehubaContainer)
+        // fixture.componentInstance.currentOnHoverObs$ = hot('')
+        // fixture.detectChanges()
+        // const toggleBtn = fixture.debugElement.query( By.css(`[aria-label="${TOGGLE_SIDE_PANEL}"]`) )
+        // toggleBtn.triggerEventHandler('click', null)
+        // fixture.detectChanges()
+        
+        // expect(
+        //   fixture.componentInstance.matDrawerMain.opened
+        // ).toEqual(true)
+        // expect(
+        //   fixture.componentInstance.matDrawerMinor.opened
+        // ).toEqual(false)
+        it('> opening via tab should result in only top drawer open')
+
+
+
+        // const fixture = TestBed.createComponent(NehubaContainer)
+        // fixture.componentInstance.currentOnHoverObs$ = hot('')
+        // fixture.detectChanges()
+        // const toggleBtn = fixture.debugElement.query( By.css(`[aria-label="${TOGGLE_SIDE_PANEL}"]`) )
+        // toggleBtn.triggerEventHandler('click', null)
+        // fixture.detectChanges()
+        // const expandRegionFeatureBtn = fixture.debugElement.query( By.css(`mat-drawer[data-mat-drawer-secondary-open="true"] [aria-label="${EXPAND}"]`) )
+        // expect(expandRegionFeatureBtn).toBeNull()
+        it('> on opening top drawer, explore features should not be present')
+
+
+        // const fixture = TestBed.createComponent(NehubaContainer)
+        // fixture.componentInstance.currentOnHoverObs$ = hot('')
+        // fixture.detectChanges()
+        // const toggleBtn = fixture.debugElement.query( By.css(`[aria-label="${TOGGLE_SIDE_PANEL}"]`) )
+        // toggleBtn.triggerEventHandler('click', null)
+        // fixture.detectChanges()
+        // const expandRegionFeatureBtn = fixture.debugElement.query( By.css(`mat-drawer[data-mat-drawer-secondary-open="true"] [aria-label="${COLLAPSE}"]`) )
+        // expect(expandRegionFeatureBtn).toBeNull()
+        it('> collapse btn should not be visible')
+      })
+
+      describe('> on start, if something is selected', () => {
+        // beforeEach(() => {
+        //   const mockStore = TestBed.inject(MockStore)
+        //   const newState = {
+        //     ...defaultRootState,
+        //     viewerState: {
+        //       ...defaultRootState.viewerState,
+        //       fetchedTemplates: [ bigbrainJson ],
+        //       templateSelected: bigbrainJson,
+        //       parcellationSelected: bigbrainJson.parcellations[0],
+        //       regionsSelected: [{
+        //         name: "foobar",
+        //         ngId: 'untitled',
+        //         labelIndex: 15
+        //       }]
+        //     },
+        //     [viewerStateHelperStoreName]: {
+        //       fetchedAtlases: [ humanAtlas ],
+        //       selectedAtlasId: humanAtlas['@id']
+        //     }
+        //   }
+
+        //   mockStore.setState(newState)
+        // })
+
+
+        // const fixture = TestBed.createComponent(NehubaContainer)
+        // fixture.componentInstance.currentOnHoverObs$ = hot('')
+        // fixture.detectChanges()
+        // expect(
+        //   fixture.componentInstance.matDrawerMain.opened
+        // ).toEqual(true)
+        // expect(
+        //   fixture.componentInstance.matDrawerMinor.opened
+        // ).toEqual(true)
+
+        // expect(
+        //   fixture.componentInstance.navSideDrawerMainSwitch.switchState
+        // ).toEqual(true)
+        // expect(
+        //   fixture.componentInstance.navSideDrawerMinorSwitch.switchState
+        // ).toEqual(true)
+        it('> both should be open')
+
+
+        // () => {
+        //   const fixture = TestBed.createComponent(NehubaContainer)
+        //   fixture.componentInstance.currentOnHoverObs$ = hot('')
+        //   fixture.detectChanges()
+        //   const toggleBtn = fixture.debugElement.query( By.css(`[aria-label="${TOGGLE_SIDE_PANEL}"]`) )
+        //   toggleBtn.triggerEventHandler('click', null)
+        //   fixture.detectChanges()
+        //   expect(
+        //     fixture.componentInstance.matDrawerMain.opened
+        //   ).toEqual(false)
+
+        //   /**
+        //    * TODO investigate why openedStart/closedStart events fail to fire
+        //    */
+        //   // expect(
+        //   //   fixture.componentInstance.matDrawerMinor.opened
+        //   // ).toEqual(false)
+
+        //   // expect(
+        //   //   fixture.componentInstance.navSideDrawerMainSwitch.switchState
+        //   // ).toEqual(false)
+        //   // expect(
+        //   //   fixture.componentInstance.navSideDrawerMinorSwitch.switchState
+        //   // ).toEqual(false)
+        // }
+        it('> closing main drawer via tag should close both')
+
+
+        // () => {
+
+        //   const fixture = TestBed.createComponent(NehubaContainer)
+        //   fixture.componentInstance.currentOnHoverObs$ = hot('')
+        //   fixture.detectChanges()
+        //   const collapseRegionFeatureBtn = fixture.debugElement.query( By.css(`mat-drawer[data-mat-drawer-secondary-open="true"] [aria-label="${COLLAPSE}"]`) )
+        //   expect(collapseRegionFeatureBtn).not.toBeNull()
+        // }
+        it('> collapse btn should be visible')
+
+        // () => {
+
+        //   const fixture = TestBed.createComponent(NehubaContainer)
+        //   fixture.componentInstance.currentOnHoverObs$ = hot('')
+        //   fixture.detectChanges()
+        //   const collapseRegionFeatureBtn = fixture.debugElement.query( By.css(`mat-drawer[data-mat-drawer-secondary-open="true"] [aria-label="${COLLAPSE}"]`) )
+        //   collapseRegionFeatureBtn.triggerEventHandler('click', null)
+        //   fixture.detectChanges()
+        //   expect(
+        //     fixture.componentInstance.matDrawerMain.opened
+        //   ).toEqual(true)
+
+        //   /**
+        //    * TODO investigate why property does not get updated
+        //    */
+        //   // expect(
+        //   //   fixture.componentInstance.matDrawerMinor.opened
+        //   // ).toEqual(false)
+
+        //   expect(
+        //     fixture.componentInstance.navSideDrawerMainSwitch.switchState
+        //   ).toEqual(true)
+        //   expect(
+        //     fixture.componentInstance.navSideDrawerMinorSwitch.switchState
+        //   ).toEqual(false)
+        // }
+        it('> clicking on collapse btn should minimize 1 drawer')
+
+        // () => {
+        //   const fixture = TestBed.createComponent(NehubaContainer)
+        //   fixture.componentInstance.currentOnHoverObs$ = hot('')
+        //   fixture.detectChanges()
+        //   const collapseRegionFeatureBtn = fixture.debugElement.query( By.css(`mat-drawer[data-mat-drawer-secondary-open="true"] [aria-label="${COLLAPSE}"]`) )
+        //   collapseRegionFeatureBtn.triggerEventHandler('click', null)
+        //   fixture.detectChanges()
+        //   const expandRegionFeatureBtn = fixture.debugElement.query( By.css(`mat-drawer[data-mat-drawer-primary-open="true"] [aria-label="${EXPAND}"]`) )
+        //   expandRegionFeatureBtn.triggerEventHandler('click', null)
+        //   fixture.detectChanges()
+
+        //   expect(
+        //     fixture.componentInstance.matDrawerMain.opened
+        //   ).toEqual(true)
+        //   expect(
+        //     fixture.componentInstance.matDrawerMinor.opened
+        //   ).toEqual(true)
+
+        //   expect(
+        //     fixture.componentInstance.navSideDrawerMainSwitch.switchState
+        //   ).toEqual(true)
+        //   /**
+        //    * TODO figoure out why switch state is updated async, and karma can't force update state
+        //    */
+        //   // expect(
+        //   //   fixture.componentInstance.navSideDrawerMinorSwitch.switchState
+        //   // ).toEqual(true)
+        // }
+        it('> on minimize drawer, clicking expand btn should expand everything')
+      })
+
+      describe('> side bar content', () => {
+
+        /**
+         * TODO
+         */
+        it('> if nothing is shown, it should show place holder text')
+
+        /**
+         * TODO
+         */
+        it('> if something (region features/connectivity) exists, placeh holder text should be hdiden')
+      })
+    })
+  
+    describe('> panelCtrl', () => {
+      // let fixture: ComponentFixture<NehubaContainer>
+      // const setViewerLoaded = () => {
+      //   fixture.componentInstance.viewerLoaded = true
+      // }
+      // const ctrlElementIsVisible = (el: DebugElement) => {
+      //   const visible = (el.nativeElement as HTMLElement).getAttribute('data-viewer-controller-visible')
+      //   return visible === 'true'
+      // }
+      // beforeEach(() => {
+      //   fixture = TestBed.createComponent(NehubaContainer)
+      // })
+
+      // () => {
+      //   fixture.detectChanges()
+      //   setViewerLoaded()
+      //   fixture.detectChanges()
+      //   for (const idx of [0, 1, 2, 3]) {
+      //     const el = fixture.debugElement.query(
+      //       By.css(`[data-viewer-controller-index="${idx}"]`)
+      //     )
+      //     expect(el).toBeTruthy()
+      //   }
+      // }
+      it('> on start, all four ctrl panels exists')
+
+      // () => {
+        
+      //   fixture.detectChanges()
+      //   setViewerLoaded()
+      //   fixture.detectChanges()
+      //   for (const idx of [0, 1, 2, 3]) {
+      //     const el = fixture.debugElement.query(
+      //       By.css(`[data-viewer-controller-index="${idx}"]`)
+      //     )
+      //     expect(ctrlElementIsVisible(el)).toBeFalsy()
+      //   }
+      // }
+      it('> on start all four ctrl panels are invisible')
+
+      describe('> on hover, only the hovered panel have ctrl shown', () => {
+
+        for (const idx of [0, 1, 2, 3]) {
+          
+          // fakeAsync(() => {
+          //   fixture.detectChanges()
+          //   const findPanelIndexSpy = spyOn<any>(fixture.componentInstance, 'findPanelIndex').and.callFake(() => {
+          //     return idx
+          //   })
+          //   setViewerLoaded()
+          //   fixture.detectChanges()
+          //   const nativeElement = fixture.componentInstance['elementRef'].nativeElement
+          //   nativeElement.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }))
+  
+          //   /**
+          //    * assert findPanelIndex called with event.target, i.e. native element in thsi case
+          //    */
+          //   expect(findPanelIndexSpy).toHaveBeenCalledWith(nativeElement)
+          //   tick(200)
+          //   fixture.detectChanges()
+            
+          //   /**
+          //    * every panel index should be non visible
+          //    * only when idx matches, it can be visible
+          //    * n.b. this does not test visual visibility (which is controlled by extra-style.css)
+          //    * (which is also affected by global [ismobile] configuration)
+          //    * 
+          //    * this merely test the unit logic, and sets the flag appropriately
+          //    */
+          //   for (const iterativeIdx of [0, 1, 2, 3]) {
+          //     const el = fixture.debugElement.query(
+          //       By.css(`[data-viewer-controller-index="${iterativeIdx}"]`)
+          //     )
+          //     if (iterativeIdx === idx) {
+          //       expect(ctrlElementIsVisible(el)).toBeTruthy()
+          //     } else {
+          //       expect(ctrlElementIsVisible(el)).toBeFalsy()
+          //     }
+          //   }
+          //   discardPeriodicTasks()
+          // })
+          it(`> on hoveredPanelIndices$ emit ${idx}, the panel index ${idx} ctrl becomes visible`)
+        }
+  
+      })
+
+      describe('> on maximise top right slice panel (idx 1)', () => {
+        // beforeEach(() => {
+        //   const mockStore = TestBed.inject(MockStore)
+        //   mockStore.overrideSelector(ngViewerSelectorPanelMode, PANELS.SINGLE_PANEL)
+        //   mockStore.overrideSelector(ngViewerSelectorPanelOrder, '1230')
+
+        //   fixture.detectChanges()
+        //   setViewerLoaded()
+        //   fixture.detectChanges()
+        // })
+
+
+        // () => {
+
+        //   const toggleBtn = fixture.debugElement.query(
+        //     By.css(`[cell-i] [aria-label="${TOGGLE_FRONTAL_OCTANT}"]`)
+        //   )
+        //   expect(toggleBtn).toBeFalsy()
+        // }
+        it('> toggle front octant btn not visible')
+
+        // () => {
+
+        //   const zoomInBtn = fixture.debugElement.query(
+        //     By.css(`[cell-i] [aria-label="${ZOOM_IN}"]`)
+        //   )
+
+        //   const zoomOutBtn = fixture.debugElement.query(
+        //     By.css(`[cell-i] [aria-label="${ZOOM_OUT}"]`)
+        //   )
+
+        //   expect(zoomInBtn).toBeTruthy()
+        //   expect(zoomOutBtn).toBeTruthy()
+        // }
+        it('> zoom in and out btns are visible')
+
+        // () => {
+        //   const zoomViewSpy = spyOn(fixture.componentInstance, 'zoomNgView')
+
+        //   const zoomInBtn = fixture.debugElement.query(
+        //     By.css(`[cell-i] [aria-label="${ZOOM_IN}"]`)
+        //   )
+        //   zoomInBtn.triggerEventHandler('click', null)
+        //   expect(zoomViewSpy).toHaveBeenCalled()
+        //   const { args } = zoomViewSpy.calls.first()
+        //   expect(args[0]).toEqual(1)
+        //   /**
+        //    * zoom in < 1
+        //    */
+        //   expect(args[1]).toBeLessThan(1)
+        // }
+        it('> zoom in btn calls fn with right param')
+
+        // () => {
+        //   const zoomViewSpy = spyOn(fixture.componentInstance, 'zoomNgView')
+
+        //   const zoomOutBtn = fixture.debugElement.query(
+        //     By.css(`[cell-i] [aria-label="${ZOOM_OUT}"]`)
+        //   )
+        //   zoomOutBtn.triggerEventHandler('click', null)
+        //   expect(zoomViewSpy).toHaveBeenCalled()
+        //   const { args } = zoomViewSpy.calls.first()
+        //   expect(args[0]).toEqual(1)
+        //   /**
+        //    * zoom out > 1
+        //    */
+        //   expect(args[1]).toBeGreaterThan(1)
+        // }
+        it('> zoom out btn calls fn with right param')
+      })
+
+      describe('> on maximise perspective panel', () => {
+        // beforeEach(() => {
+        //   const mockStore = TestBed.inject(MockStore)
+        //   mockStore.overrideSelector(ngViewerSelectorPanelMode, PANELS.SINGLE_PANEL)
+        //   mockStore.overrideSelector(ngViewerSelectorPanelOrder, '3012')
+
+        //   fixture.detectChanges()
+        //   setViewerLoaded()
+        //   fixture.detectChanges()
+        // })
+
+
+        // () => {
+        //   const setOctantRemovalSpy = spyOn(fixture.componentInstance, 'setOctantRemoval')
+
+        //   const toggleBtn = fixture.debugElement.query(
+        //     By.css(`[cell-i] [aria-label="${TOGGLE_FRONTAL_OCTANT}"]`)
+        //   )
+        //   expect(toggleBtn).toBeTruthy()
+        //   toggleBtn.nativeElement.dispatchEvent(
+        //     new MouseEvent('click', { bubbles: true })
+        //   )
+        //   expect(setOctantRemovalSpy).toHaveBeenCalled()
+        // }
+        it('> toggle octant btn visible and functional')
+
+        // () => {
+        //   const zoomViewSpy = spyOn(fixture.componentInstance, 'zoomNgView')
+
+        //   const zoomInBtn = fixture.debugElement.query(
+        //     By.css(`[cell-i] [aria-label="${ZOOM_IN}"]`)
+        //   )
+        //   expect(zoomInBtn).toBeTruthy()
+
+        //   zoomInBtn.triggerEventHandler('click', null)
+        //   expect(zoomViewSpy).toHaveBeenCalled()
+        //   const { args } = zoomViewSpy.calls.first()
+        //   expect(args[0]).toEqual(3)
+        //   /**
+        //    * zoom in < 1
+        //    */
+        //   expect(args[1]).toBeLessThan(1)
+        // }
+        it('> zoom in btn visible and functional')
+
+        // () => {
+        //   const zoomViewSpy = spyOn(fixture.componentInstance, 'zoomNgView')
+
+        //   const zoomOutBtn = fixture.debugElement.query(
+        //     By.css(`[cell-i] [aria-label="${ZOOM_OUT}"]`)
+        //   )
+        //   expect(zoomOutBtn).toBeTruthy()
+
+        //   zoomOutBtn.triggerEventHandler('click', null)
+        //   expect(zoomViewSpy).toHaveBeenCalled()
+        //   const { args } = zoomViewSpy.calls.first()
+        //   expect(args[0]).toEqual(3)
+        //   /**
+        //    * zoom in < 1
+        //    */
+        //   expect(args[1]).toBeGreaterThan(1)
+        // }
+        it('> zoom out btn visible and functional')
+      
+      })
+    })
+  
+    describe('> on userLandmarks change', () => {
+      const lm1 = {
+        id: 'test-1',
+        position: [0, 0, 0]
+      }
+      const lm2 = {
+        id: 'test-2',
+        position: [1, 1,1 ]
+      }
+
+      // () => {
+      //   const fixture = TestBed.createComponent(NehubaContainer)
+
+      //   fixture.componentInstance.nehubaViewer = {
+      //     updateUserLandmarks: () => {}
+      //   } as any
+
+      //   const updateUserLandmarksSpy = spyOn(
+      //     fixture.componentInstance.nehubaViewer,
+      //     'updateUserLandmarks'
+      //   )
+
+      //   const mockStore = TestBed.inject(MockStore)
+      //   mockStore.overrideSelector(viewerStateCustomLandmarkSelector, [
+      //     lm1, 
+      //     lm2
+      //   ])
+      //   fixture.detectChanges()
+      //   expect(
+      //     updateUserLandmarksSpy
+      //   ).toHaveBeenCalledWith([
+      //     lm1, lm2
+      //   ])
+      // }
+      it('> calls nehubaViewer.updateUserLandmarks')
+    
+      // () => {
+        
+      //   const fixture = TestBed.createComponent(NehubaContainer)
+
+      //   fixture.componentInstance.nehubaContainerDirective = {
+      //     toggleOctantRemoval: () => {},
+      //     clear: () => {}
+      //   } as any
+
+      //   const toggleOctantRemovalSpy = spyOn(
+      //     fixture.componentInstance.nehubaContainerDirective,
+      //     'toggleOctantRemoval'
+      //   )
+
+      //   const mockStore = TestBed.inject(MockStore)
+      //   mockStore.overrideSelector(viewerStateCustomLandmarkSelector, [
+      //     lm1, 
+      //     lm2
+      //   ])
+      //   mockStore.overrideSelector(ngViewerSelectorOctantRemoval, true)
+      //   fixture.detectChanges()
+      //   expect(
+      //     toggleOctantRemovalSpy
+      //   ).toHaveBeenCalledWith(false)
+      // }
+      it('> calls togglecotantREmoval')
+    })
+  })
+})
diff --git a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.spec.ts b/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.spec.ts
similarity index 100%
rename from src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.spec.ts
rename to src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.spec.ts
diff --git a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts b/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.ts
similarity index 98%
rename from src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts
rename to src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.ts
index d1edab5e0f9fa80aa6347906b43c5d4ccceef803..57f4f526ff7651ce098ed165f73e7c835b4a7f2d 100644
--- a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts
+++ b/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.ts
@@ -3,7 +3,6 @@ import { fromEvent, Subscription, ReplaySubject, BehaviorSubject, Observable, ra
 import { debounceTime, filter, map, scan, startWith, mapTo, switchMap, take, skip } from "rxjs/operators";
 import { AtlasWorkerService } from "src/atlasViewer/atlasViewer.workerService.service";
 import { StateInterface as ViewerConfiguration } from "src/services/state/viewerConfig.store";
-import { getNgIdLabelIndexFromId } from "src/services/stateStore.service";
 
 import { LoggingService } from "src/logging";
 import { getExportNehuba, getViewer, setNehubaViewer } from "src/util/fn";
@@ -11,7 +10,7 @@ import { getExportNehuba, getViewer, setNehubaViewer } from "src/util/fn";
 import '!!file-loader?context=third_party&name=main.bundle.js!export-nehuba/dist/min/main.bundle.js'
 import '!!file-loader?context=third_party&name=chunk_worker.bundle.js!export-nehuba/dist/min/chunk_worker.bundle.js'
 import { scanSliceViewRenderFn } from "../util";
-import { intToRgb as intToColour } from 'common/util'
+import { intToRgb as intToColour, deserialiseParcRegionId } from 'common/util'
 
 const NG_LANDMARK_LAYER_NAME = 'spatial landmark layer'
 const NG_USER_LANDMARK_LAYER_NAME = 'user landmark layer'
@@ -637,6 +636,8 @@ export class NehubaViewerUnit implements OnInit, OnDestroy {
   }
 
   public hideAllSeg() {
+    // console.log('hideallseg')
+    // debugger
     if (!this.nehubaViewer) { return }
     Array.from(this.multiNgIdsLabelIndexMap.keys()).forEach(ngId => {
 
@@ -681,9 +682,13 @@ export class NehubaViewerUnit implements OnInit, OnDestroy {
     const reduceFn: (acc: Map<string, number[]>, curr: string) => Map<string, number[]> = (acc, curr) => {
 
       const newMap = new Map(acc)
-      const { ngId, labelIndex } = getNgIdLabelIndexFromId({ labelIndexId: curr })
+      const { ngId, labelIndex } = deserialiseParcRegionId(curr)
       const exist = newMap.get(ngId)
-      if (!exist) { newMap.set(ngId, [Number(labelIndex)]) } else { newMap.set(ngId, [...exist, Number(labelIndex)]) }
+      if (!exist) {
+        newMap.set(ngId, [Number(labelIndex)])
+      } else {
+        newMap.set(ngId, [...exist, Number(labelIndex)])
+      }
       return newMap
     }
 
diff --git a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.style.css b/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.style.css
similarity index 100%
rename from src/ui/nehubaContainer/nehubaViewer/nehubaViewer.style.css
rename to src/viewerModule/nehuba/nehubaViewer/nehubaViewer.style.css
diff --git a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.template.html b/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.template.html
similarity index 100%
rename from src/ui/nehubaContainer/nehubaViewer/nehubaViewer.template.html
rename to src/viewerModule/nehuba/nehubaViewer/nehubaViewer.template.html
diff --git a/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.component.ts b/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d9b52d1dc806f239a1638c084256f04577a0a1e1
--- /dev/null
+++ b/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.component.ts
@@ -0,0 +1,793 @@
+import { Component, ElementRef, Inject, Input, OnChanges, OnDestroy, Optional, SimpleChanges, ViewChild } from "@angular/core";
+import { select, Store } from "@ngrx/store";
+import { asyncScheduler, combineLatest, fromEvent, interval, merge, Observable, of, Subject, timer } from "rxjs";
+import { ngViewerActionAddNgLayer, ngViewerActionRemoveNgLayer, ngViewerActionSetPerspOctantRemoval, ngViewerActionToggleMax } from "src/services/state/ngViewerState/actions";
+import { ClickInterceptor, CLICK_INTERCEPTOR_INJECTOR } from "src/util";
+import { uiStateMouseOverSegmentsSelector } from "src/services/state/uiState/selectors";
+import { debounceTime, distinctUntilChanged, filter, map, mapTo, scan, shareReplay, startWith, switchMap, switchMapTo, take, tap, throttleTime, withLatestFrom } from "rxjs/operators";
+import { viewerStateAddUserLandmarks, viewerStateChangeNavigation, viewerStateMouseOverCustomLandmark, viewerStateSelectRegionWithIdDeprecated, viewerStateSetSelectedRegions, viewreStateRemoveUserLandmarks } from "src/services/state/viewerState/actions";
+import { ngViewerSelectorLayers, ngViewerSelectorClearView, ngViewerSelectorPanelOrder, ngViewerSelectorOctantRemoval, ngViewerSelectorPanelMode } from "src/services/state/ngViewerState/selectors";
+import { viewerStateCustomLandmarkSelector, viewerStateSelectedRegionsSelector } from "src/services/state/viewerState/selectors";
+import { serialiseParcellationRegion } from 'common/util'
+import { ARIA_LABELS, IDS } from 'common/constants'
+import { PANELS } from "src/services/state/ngViewerState/constants";
+import { LoggingService } from "src/logging";
+
+import { getNgIds, getMultiNgIdsRegionsLabelIndexMap } from "../constants";
+import { IViewer, TViewerEvent } from "../../viewer.interface";
+import { NehubaViewerUnit } from "../nehubaViewer/nehubaViewer.component";
+import { NehubaViewerContainerDirective } from "../nehubaViewerInterface/nehubaViewerInterface.directive";
+import { calculateSliceZoomFactor, getFourPanel, getHorizontalOneThree, getSinglePanel, getVerticalOneThree, NEHUBA_INSTANCE_INJTKN, scanSliceViewRenderFn, takeOnePipe } from "../util";
+import { API_SERVICE_SET_VIEWER_HANDLE_TOKEN, IUserLandmark, TSetViewerHandle } from "src/atlasViewer/atlasViewer.apiService.service";
+import { MouseHoverDirective } from "src/mouseoverModule";
+
+interface INgLayerInterface {
+  name: string // displayName
+  source: string
+  mixability: string // base | mixable | nonmixable
+  annotation?: string //
+  id?: string // unique identifier
+  visible?: boolean
+  shader?: string
+  transform?: any
+}
+
+@Component({
+  selector: 'iav-cmp-viewer-nehuba-glue',
+  templateUrl: './nehubaViewerGlue.template.html',
+  styleUrls: [
+    './nehubaViewerGlue.style.css'
+  ],
+  exportAs: 'iavCmpViewerNehubaGlue'
+})
+
+export class NehubaGlueCmp implements IViewer, OnChanges, OnDestroy{
+
+  public ARIA_LABELS = ARIA_LABELS
+  public IDS = IDS
+
+  @ViewChild(NehubaViewerContainerDirective, { static: true })
+  public nehubaContainerDirective: NehubaViewerContainerDirective
+
+  @ViewChild(MouseHoverDirective, { static: true })
+  private mouseoverDirective: MouseHoverDirective
+
+  public viewerEvents$ = new Subject<TViewerEvent>()
+  public viewerLoaded$ = this.viewerEvents$.pipe(
+    filter(ev => ev.type === 'VIEWERLOADED'),
+    map(ev => ev.data)
+  )
+
+  private onhoverSegments = []
+  private onDestroyCb: Function[] = []
+  private viewerUnit: NehubaViewerUnit
+  private ngLayersRegister: {layers: INgLayerInterface[]} = {
+    layers: []
+  }
+  private multiNgIdsRegionsLabelIndexMap: Map<string, Map<number, any>>
+
+  @Input()
+  public selectedParcellation: any
+
+  @Input()
+  public selectedTemplate: any
+
+  private newViewer$ = new Subject()
+
+  public showPerpsectiveScreen$: Observable<string>
+  public sliceViewLoadingMain$: Observable<[boolean, boolean, boolean]>
+  private sliceRenderEvent$: Observable<CustomEvent>
+  public perspectiveViewLoading$: Observable<string|null>
+  public hoveredPanelIndices$: Observable<number>
+  private viewPanelWeakMap = new WeakMap<HTMLElement, number>()
+  private viewPanels: [HTMLElement, HTMLElement, HTMLElement, HTMLElement] = [null, null, null, null]
+  private findPanelIndex = (panel: HTMLElement) => this.viewPanelWeakMap.get(panel)
+  public nanometersToOffsetPixelsFn: Array<(...arg) => any> = []
+
+  public customLandmarks$: Observable<any> = this.store$.pipe(
+    select(viewerStateCustomLandmarkSelector),
+    map(lms => lms.map(lm => ({
+      ...lm,
+      geometry: {
+        position: lm.position
+      }
+    }))),
+  )
+
+  private forceUI$ = this.customLandmarks$.pipe(
+    map(lm => {
+      if (lm.length > 0) {
+        return {
+          target: 'perspective:octantRemoval',
+          mode: false,
+          message: `octant control disabled: showing landmarks.`
+        }
+      } else {
+        return {
+          target: 'perspective:octantRemoval',
+          mode: null
+        }
+      }
+    })
+  )
+
+  public disableOctantRemovalCtrl$ = this.forceUI$.pipe(
+    filter(({ target }) => target === 'perspective:octantRemoval'),
+  )
+
+  public nehubaViewerPerspectiveOctantRemoval$ = this.store$.pipe(
+    select(ngViewerSelectorOctantRemoval),
+  )
+
+  public panelOrder$ = this.store$.pipe(
+    select(ngViewerSelectorPanelOrder),
+    distinctUntilChanged(),
+    shareReplay(1),
+  )
+
+  ngOnChanges(sc: SimpleChanges){
+    const {
+      selectedParcellation,
+      selectedTemplate
+    } = sc
+    if (selectedTemplate?.previousValue) {
+      this.unloadTmpl(selectedTemplate?.previousValue)
+    }
+    if (selectedTemplate && selectedTemplate.currentValue !== selectedTemplate.previousValue) {
+      this.loadTmpl(selectedTemplate.currentValue, selectedParcellation.currentValue)
+    } else if (selectedParcellation && selectedParcellation.currentValue !== selectedParcellation.previousValue) {
+      this.loadParc(selectedParcellation.currentValue)
+    }
+  }
+
+  ngOnDestroy() {
+    while (this.onDestroyCb.length) this.onDestroyCb.pop()()
+  }
+
+  private loadParc(parcellation: any) {
+    /**
+     * parcellaiton may be undefined
+     */
+    if ( !(parcellation && parcellation.regions)) {
+      return
+    }
+
+    /**
+     * first, get all all the ngIds, including parent id from parcellation (if defined)
+     */
+    const ngIds = getNgIds(parcellation.regions).concat( parcellation.ngId ? parcellation.ngId : [])
+
+    this.multiNgIdsRegionsLabelIndexMap = getMultiNgIdsRegionsLabelIndexMap(parcellation)
+
+    this.viewerUnit.multiNgIdsLabelIndexMap = this.multiNgIdsRegionsLabelIndexMap
+    this.viewerUnit.auxilaryMeshIndices = parcellation.auxillaryMeshIndices || []
+
+    /* TODO replace with proper KG id */
+    /**
+     * need to set unique array of ngIds, or else workers will be overworked
+     */
+    this.viewerUnit.ngIds = Array.from(new Set(ngIds))
+  }
+
+  private unloadTmpl(tmpl: any) {
+    /**
+     * clear existing container
+     */
+    this.viewerUnit = null
+    this.nehubaContainerDirective.clear()
+
+    /* on selecting of new template, remove additional nglayers */
+    const baseLayerNames = Object.keys(tmpl.nehubaConfig.dataset.initialNgState.layers)
+    this.ngLayersRegister.layers
+      .filter(layer => baseLayerNames?.findIndex(l => l === layer.name) >= 0)
+      .map(l => l.name)
+      .forEach(layerName => {
+        this.store$.dispatch(ngViewerActionRemoveNgLayer({
+          layer: {
+            name: layerName
+          }
+        }))
+      })
+  }
+
+  private async loadTmpl(_template: any, parcellation: any) {
+
+    if (!_template) return
+    /**
+     * recalcuate zoom
+     */
+    const template = (() => {
+
+      const deepCopiedState = JSON.parse(JSON.stringify(_template))
+      const navigation = deepCopiedState.nehubaConfig.dataset.initialNgState.navigation
+      if (!navigation) {
+        return deepCopiedState
+      }
+      navigation.zoomFactor = calculateSliceZoomFactor(navigation.zoomFactor)
+      deepCopiedState.nehubaConfig.dataset.initialNgState.navigation = navigation
+      return deepCopiedState
+    })()
+
+    this.nehubaContainerDirective.createNehubaInstance(template)
+    this.viewerUnit = this.nehubaContainerDirective.nehubaViewerInstance
+    this.sliceRenderEvent$.pipe(
+      takeOnePipe()
+    ).subscribe(ev => {
+
+      for (const idx of [0, 1, 2]) {
+        const e = ev[idx] as CustomEvent
+        const el = e.target as HTMLElement
+        this.viewPanelWeakMap.set(el, idx)
+        this.viewPanels[idx] = el
+        this.nanometersToOffsetPixelsFn[idx] = e.detail.nanometersToOffsetPixels
+      }
+    })
+    const foundParcellation = parcellation
+      && template?.parcellations?.find(p => parcellation.name === p.name)
+    this.loadParc(foundParcellation || template.parcellations[0])
+
+    const nehubaConfig = template.nehubaConfig
+    const initialSpec = nehubaConfig.dataset.initialNgState
+    const {layers} = initialSpec
+
+    const dispatchLayers = Object.keys(layers).map(key => {
+      const layer = {
+        name : key,
+        source : layers[key].source,
+        mixability : layers[key].type === 'image'
+          ? 'base'
+          : 'mixable',
+        visible : typeof layers[key].visible === 'undefined'
+          ? true
+          : layers[key].visible,
+        transform : typeof layers[key].transform === 'undefined'
+          ? null
+          : layers[key].transform,
+      }
+      this.ngLayersRegister.layers.push(layer)
+      return layer
+    })
+
+    this.newViewer$.next(true)
+    this.store$.dispatch(ngViewerActionAddNgLayer({
+      layer: dispatchLayers
+    }))
+  }
+
+  constructor(
+    private store$: Store<any>,
+    private el: ElementRef,
+    private log: LoggingService,
+    @Optional() @Inject(CLICK_INTERCEPTOR_INJECTOR) clickInterceptor: ClickInterceptor,
+    @Optional() @Inject(API_SERVICE_SET_VIEWER_HANDLE_TOKEN) setViewerHandle: TSetViewerHandle,
+    @Optional() @Inject(NEHUBA_INSTANCE_INJTKN) nehubaViewer$: Subject<NehubaViewerUnit>,
+  ){
+    this.viewerEvents$.next({
+      type: 'MOUSEOVER_ANNOTATION',
+      data: {}
+    })
+    /**
+     * define onclick behaviour
+     */
+    if (clickInterceptor) {
+      const { deregister, register } = clickInterceptor
+      const selOnhoverRegion = this.selectHoveredRegion.bind(this)
+      register(selOnhoverRegion)
+      this.onDestroyCb.push(() => deregister(selOnhoverRegion)) 
+    }
+
+    const nehubaViewerSub = this.newViewer$.pipe(
+      tap(() => nehubaViewer$.next(null)),
+      switchMap(this.waitForNehuba.bind(this)),
+      map(() => this.nehubaContainerDirective.nehubaViewerInstance)
+    ).subscribe(viewer => nehubaViewer$.next(viewer))
+    this.onDestroyCb.push(() => nehubaViewerSub.unsubscribe())
+
+    /**
+     * on layout change
+     */
+    const redrawLayoutSub = combineLatest([
+      this.store$.pipe(
+        select(ngViewerSelectorPanelMode),
+        distinctUntilChanged(),
+        shareReplay(1),
+      ),
+      this.panelOrder$,
+    ]).pipe(
+      switchMap(this.waitForNehuba.bind(this))
+    ).subscribe(([mode, panelOrder]) => {
+      const viewPanels = panelOrder.split('').map(v => Number(v)).map(idx => this.viewPanels[idx]) as [HTMLElement, HTMLElement, HTMLElement, HTMLElement]
+
+      /**
+       * TODO smarter with event stream
+       */
+      if (!viewPanels.every(v => !!v)) { 
+        this.log.error(`on relayout, not every view panel is populated. This should not occur!`)
+        return
+      }
+
+      switch (mode) {
+      case PANELS.H_ONE_THREE: {
+        const element = this.removeExistingPanels()
+        const newEl = getHorizontalOneThree(viewPanels)
+        element.appendChild(newEl)
+        break;
+      }
+      case PANELS.V_ONE_THREE: {
+        const element = this.removeExistingPanels()
+        const newEl = getVerticalOneThree(viewPanels)
+        element.appendChild(newEl)
+        break;
+      }
+      case PANELS.FOUR_PANEL: {
+        const element = this.removeExistingPanels()
+        const newEl = getFourPanel(viewPanels)
+        element.appendChild(newEl)
+        break;
+      }
+      case PANELS.SINGLE_PANEL: {
+        const element = this.removeExistingPanels()
+        const newEl = getSinglePanel(viewPanels)
+        element.appendChild(newEl)
+        break;
+      }
+      default:
+      }
+      for (const panel of viewPanels) {
+        (panel as HTMLElement).classList.add('neuroglancer-panel')
+      }
+
+      // TODO needed to redraw?
+      // see https://trello.com/c/oJOnlc6v/60-enlarge-panel-allow-user-rearrange-panel-position
+      // further investigaation required
+      this.nehubaContainerDirective.nehubaViewerInstance.redraw()
+    })
+    this.onDestroyCb.push(() => redrawLayoutSub.unsubscribe())
+
+    /**
+     * on hover segment
+     */
+    const onhovSegSub = this.store$.pipe(
+      select(uiStateMouseOverSegmentsSelector),
+      distinctUntilChanged(),
+    ).subscribe(arr => {
+      const segments = arr.map(({ segment }) => segment).filter(v => !!v)
+      this.onhoverSegments = segments
+    })
+    this.onDestroyCb.push(() => onhovSegSub.unsubscribe())
+
+    /**
+     * subscribe to when ngLayer gets updated, and add/remove layer as necessary
+     */
+    const addRemoveAdditionalLayerSub = this.store$.pipe(
+      select(ngViewerSelectorLayers),
+      switchMap(this.waitForNehuba.bind(this)),
+    ).subscribe((ngLayers: INgLayerInterface[]) => {
+
+      const newLayers = ngLayers.filter(l => this.ngLayersRegister.layers?.findIndex(ol => ol.name === l.name) < 0)
+      const removeLayers = this.ngLayersRegister.layers.filter(l => ngLayers?.findIndex(nl => nl.name === l.name) < 0)
+      
+      if (newLayers?.length > 0) {
+        const newLayersObj: any = {}
+        newLayers.forEach(({ name, source, ...rest }) => newLayersObj[name] = {
+          ...rest,
+          source,
+          // source: getProxyUrl(source),
+          // ...getProxyOther({source})
+        })
+
+        this.nehubaContainerDirective.nehubaViewerInstance.loadLayer(newLayersObj)
+
+        /**
+         * previous miplementation... if nehubaViewer has not yet be instantiated, add it to the queue
+         * may no longer be necessary
+         * or implement proper queue'ing rather than ... this... half assed queue'ing
+         */
+        // if (!this.nehubaViewer.nehubaViewer || !this.nehubaViewer.nehubaViewer.ngviewer) {
+        //   this.nehubaViewer.initNiftiLayers.push(newLayersObj)
+        // } else {
+        //   this.nehubaViewer.loadLayer(newLayersObj)
+        // }
+        this.ngLayersRegister.layers = this.ngLayersRegister.layers.concat(newLayers)
+      }
+
+      if (removeLayers?.length > 0) {
+        removeLayers.forEach(l => {
+          if (this.nehubaContainerDirective.nehubaViewerInstance.removeLayer({
+            name : l.name,
+          })) {
+            this.ngLayersRegister.layers = this.ngLayersRegister.layers.filter(rl => rl.name !== l.name)
+          }
+        })
+      }
+    })
+    this.onDestroyCb.push(() => addRemoveAdditionalLayerSub.unsubscribe())
+
+    /**
+     * define when shown segments should be updated
+     */
+    const regSelectSub = combineLatest([
+      /**
+       * selectedRegions
+       */
+      this.store$.pipe(
+        select(viewerStateSelectedRegionsSelector)
+      ),
+      /**
+       * if layer contains non mixable layer
+       */
+      this.store$.pipe(
+        select(ngViewerSelectorLayers),
+        map(layers => layers.findIndex(l => l.mixability === 'nonmixable') >= 0),
+      ),
+      /**
+       * clearviewqueue, indicating something is controlling colour map
+       * show all seg
+       */
+      this.store$.pipe(
+        select(ngViewerSelectorClearView),
+        distinctUntilChanged()
+      )
+    ]).pipe(
+      switchMap(this.waitForNehuba.bind(this)),
+    ).subscribe(([ regions, nonmixableLayerExists, clearViewFlag ]) => {
+      if (nonmixableLayerExists) {
+        this.nehubaContainerDirective.nehubaViewerInstance.hideAllSeg()
+        return
+      }
+      const { ngId: defaultNgId } = this.selectedParcellation || {}
+
+      /* selectedregionindexset needs to be updated regardless of forceshowsegment */
+      const selectedRegionIndexSet = new Set<string>(regions.map(({ngId = defaultNgId, labelIndex}) => serialiseParcellationRegion({ ngId, labelIndex })))
+
+      if (selectedRegionIndexSet.size > 0 && !clearViewFlag) {
+        this.nehubaContainerDirective.nehubaViewerInstance.showSegs([...selectedRegionIndexSet])
+      } else {
+        this.nehubaContainerDirective.nehubaViewerInstance.showAllSeg()
+      }
+    })
+    this.onDestroyCb.push(() => regSelectSub.unsubscribe())
+
+    const perspectiveRenderEvSub = this.newViewer$.pipe(
+      switchMapTo(fromEvent<CustomEvent>(this.el.nativeElement, 'perpspectiveRenderEvent').pipe(
+        take(1)
+      ))
+    ).subscribe(ev => {
+      const perspPanel = ev.target as HTMLElement
+      this.viewPanels[3] = perspPanel
+      this.viewPanelWeakMap.set(perspPanel, 3)
+    })
+    this.onDestroyCb.push(() => perspectiveRenderEvSub.unsubscribe())
+
+    const perspOctCtrlSub = this.customLandmarks$.pipe(
+      withLatestFrom(
+        this.nehubaViewerPerspectiveOctantRemoval$
+      ),
+      switchMap(this.waitForNehuba.bind(this))
+    ).subscribe(([ landmarks, flag ]) => {
+      this.nehubaContainerDirective.toggleOctantRemoval(
+        landmarks.length > 0 ? false : flag
+      )
+      this.nehubaContainerDirective.nehubaViewerInstance.updateUserLandmarks(landmarks)
+    })
+    this.onDestroyCb.push(() => perspOctCtrlSub.unsubscribe())
+
+    this.sliceRenderEvent$ = fromEvent<CustomEvent>(this.el.nativeElement, 'sliceRenderEvent')
+    this.sliceViewLoadingMain$ = this.sliceRenderEvent$.pipe(
+      scan(scanSliceViewRenderFn, [null, null, null]),
+      startWith([true, true, true] as [boolean, boolean, boolean]),
+      shareReplay(1),
+    )
+
+    this.perspectiveViewLoading$ = fromEvent(this.el.nativeElement, 'perpspectiveRenderEvent').pipe(
+      filter((event: CustomEvent) => event?.detail?.lastLoadedMeshId ),
+      map(event => {
+
+        /**
+         * TODO dig into event detail to see if the exact mesh loaded
+         */
+        const { meshesLoaded, meshFragmentsLoaded, lastLoadedMeshId } = (event as any).detail
+        return meshesLoaded >= this.nehubaContainerDirective.nehubaViewerInstance.numMeshesToBeLoaded
+          ? null
+          : 'Loading meshes ...'
+      }),
+      distinctUntilChanged()
+    )
+
+    this.showPerpsectiveScreen$ = this.newViewer$.pipe(
+      switchMapTo(this.sliceRenderEvent$.pipe(
+        scan((acc, curr) => {
+
+          /**
+           * if at any point, all chunks have been loaded, always return loaded state
+           */
+          if (acc.every(v => v === 0)) return [0, 0, 0]
+          const { detail = {}, target } = curr || {}
+          const { missingChunks = -1, missingImageChunks = -1 } = detail
+          const idx = this.findPanelIndex(target as HTMLElement)
+          const returnAcc = [...acc]
+          if (idx >= 0) {
+            returnAcc[idx] = missingChunks + missingImageChunks
+          }
+          return returnAcc
+        }, [-1, -1, -1]),
+        map(arr => {
+          let sum = 0
+          let uncertain = false
+          for (const num of arr) {
+            if (num < 0) {
+              uncertain = true
+            } else {
+              sum += num
+            }
+          }
+          return sum > 0
+            ? `Loading ${sum}${uncertain ? '+' : ''} chunks ...`
+            : null
+        }),
+        distinctUntilChanged(),
+        startWith('Loading ...'),
+        throttleTime(100, asyncScheduler, { leading: true, trailing: true }),
+        shareReplay(1),
+      ))
+    )
+
+    this.hoveredPanelIndices$ = fromEvent(this.el.nativeElement, 'mouseover').pipe(
+      switchMap((ev: MouseEvent) => merge(
+        of(this.findPanelIndex(ev.target as HTMLElement)),
+        fromEvent(this.el.nativeElement, 'mouseout').pipe(
+          mapTo(null),
+        ),
+      )),
+      debounceTime(20),
+      shareReplay(1),
+    )
+
+    const setupViewerApiSub = this.newViewer$.pipe(
+      tap(() => {
+        setViewerHandle(null)
+      }),
+      switchMap(this.waitForNehuba.bind(this))
+    ).subscribe(() => {
+      setViewerHandle({
+        setNavigationLoc : (coord, realSpace?) => this.nehubaContainerDirective.nehubaViewerInstance.setNavigationState({
+          position : coord,
+          positionReal : typeof realSpace !== 'undefined' ? realSpace : true,
+        }),
+        /* TODO introduce animation */
+        moveToNavigationLoc : (coord, realSpace?) => {
+          this.store$.dispatch(
+            viewerStateChangeNavigation({
+              navigation: {
+                position: coord,
+                animation: {},
+              }
+            })
+          )
+        },
+        setNavigationOri : (quat) => this.nehubaContainerDirective.nehubaViewerInstance.setNavigationState({
+          orientation : quat,
+        }),
+        /* TODO introduce animation */
+        moveToNavigationOri : (quat) => this.nehubaContainerDirective.nehubaViewerInstance.setNavigationState({
+          orientation : quat,
+        }),
+        showSegment : (_labelIndex) => {
+          /**
+           * TODO reenable with updated select_regions api
+           */
+          this.log.warn(`showSegment is temporarily disabled`)
+  
+          // if(!this.selectedRegionIndexSet.has(labelIndex))
+          //   this.store.dispatch({
+          //     type : SELECT_REGIONS,
+          //     selectRegions :  [labelIndex, ...this.selectedRegionIndexSet]
+          //   })
+        },
+        add3DLandmarks : landmarks => {
+          // TODO check uniqueness of ID
+          if (!landmarks.every(l => !!l.id)) {
+            throw new Error('every landmarks needs to be identified with the id field')
+          }
+          if (!landmarks.every(l => !!l.position)) {
+            throw new Error('every landmarks needs to have position defined')
+          }
+          if (!landmarks.every(l => l.position.constructor === Array) || !landmarks.every(l => l.position.every(v => !isNaN(v))) || !landmarks.every(l => l.position.length == 3)) {
+            throw new Error('position needs to be a length 3 tuple of numbers ')
+          }
+  
+          this.store$.dispatch(viewerStateAddUserLandmarks({
+            landmarks
+          }))
+        },
+        remove3DLandmarks : landmarkIds => {
+          this.store$.dispatch(viewreStateRemoveUserLandmarks({
+            payload: { landmarkIds }
+          }))
+        },
+        hideSegment : (_labelIndex) => {
+          /**
+           * TODO reenable with updated select_regions api
+           */
+          this.log.warn(`hideSegment is temporarily disabled`)
+  
+          // if(this.selectedRegionIndexSet.has(labelIndex)){
+          //   this.store.dispatch({
+          //     type :SELECT_REGIONS,
+          //     selectRegions : [...this.selectedRegionIndexSet].filter(num=>num!==labelIndex)
+          //   })
+          // }
+        },
+        showAllSegments : () => {
+          const selectRegionIds = []
+          this.multiNgIdsRegionsLabelIndexMap.forEach((map, ngId) => {
+            Array.from(map.keys()).forEach(labelIndex => {
+              selectRegionIds.push(serialiseParcellationRegion({ ngId, labelIndex }))
+            })
+          })
+          this.store$.dispatch(viewerStateSelectRegionWithIdDeprecated({
+            selectRegionIds
+          }))
+        },
+        hideAllSegments : () => {
+          this.store$.dispatch(viewerStateSelectRegionWithIdDeprecated({
+            selectRegionIds: []
+          }))
+        },
+        segmentColourMap : new Map(),
+        getLayersSegmentColourMap: () => {
+          const newMainMap = new Map()
+          for (const [key, colormap] of this.nehubaContainerDirective.nehubaViewerInstance.multiNgIdColorMap.entries()) {
+            const newColormap = new Map()
+            newMainMap.set(key, newColormap)
+  
+            for (const [lableIndex, entry] of colormap.entries()) {
+              newColormap.set(lableIndex, JSON.parse(JSON.stringify(entry)))
+            }
+          }
+          return newMainMap
+        },
+        applyColourMap : (_map) => {
+          throw new Error(`apply color map has been deprecated. use applyLayersColourMap instead`)
+        },
+        applyLayersColourMap: (map) => {
+          this.nehubaContainerDirective.nehubaViewerInstance.setColorMap(map)
+        },
+        loadLayer : (layerObj) => this.nehubaContainerDirective.nehubaViewerInstance.loadLayer(layerObj),
+        removeLayer : (condition) => this.nehubaContainerDirective.nehubaViewerInstance.removeLayer(condition),
+        setLayerVisibility : (condition, visible) => this.nehubaContainerDirective.nehubaViewerInstance.setLayerVisibility(condition, visible),
+        mouseEvent : merge(
+          fromEvent(this.el.nativeElement, 'click').pipe(
+            map((ev: MouseEvent) => ({eventName : 'click', event: ev})),
+          ),
+          fromEvent(this.el.nativeElement, 'mousemove').pipe(
+            map((ev: MouseEvent) => ({eventName : 'mousemove', event: ev})),
+          ),
+          /**
+           * neuroglancer prevents propagation, so use capture instead
+           */
+          Observable.create(observer => {
+            this.el.nativeElement.addEventListener('mousedown', event => observer.next({eventName: 'mousedown', event}), true)
+          }) as Observable<{eventName: string, event: MouseEvent}>,
+          fromEvent(this.el.nativeElement, 'mouseup').pipe(
+            map((ev: MouseEvent) => ({eventName : 'mouseup', event: ev})),
+          ),
+        ) ,
+        mouseOverNehuba : of(null).pipe(
+          tap(() => console.warn('mouseOverNehuba observable is becoming deprecated. use mouseOverNehubaLayers instead.')),
+        ),
+        mouseOverNehubaLayers: this.mouseoverDirective.currentOnHoverObs$.pipe(
+          map(({ segments }) => segments)
+        ),
+        mouseOverNehubaUI: this.mouseoverDirective.currentOnHoverObs$.pipe(
+          map(({ landmark, segments, userLandmark: customLandmark }) => ({ segments, landmark, customLandmark })),
+          shareReplay(1),
+        ),
+        getNgHash : this.nehubaContainerDirective.nehubaViewerInstance.getNgHash,
+      })
+    })
+    this.onDestroyCb.push(() => setupViewerApiSub.unsubscribe())
+  
+  }
+
+  handleViewerLoadedEvent(flag: boolean) {
+    this.viewerEvents$.next({
+      type: 'VIEWERLOADED',
+      data: flag
+    })
+  }
+
+  private selectHoveredRegion(ev: any, next: Function){
+    if (!this.onhoverSegments || !(this.onhoverSegments.length)) return next()
+    this.store$.dispatch(
+      viewerStateSetSelectedRegions({
+        selectRegions: this.onhoverSegments.slice(0, 1)
+      })
+    )
+    next()
+  }
+
+  private waitForNehuba(arg: unknown) {
+    return interval(16).pipe(
+      filter(() => !!(this.nehubaContainerDirective?.isReady())),
+      take(1),
+      mapTo(arg),
+    )
+  }
+
+  public setOctantRemoval(octantRemovalFlag: boolean) {
+    this.store$.dispatch(
+      ngViewerActionSetPerspOctantRemoval({
+        octantRemovalFlag
+      })
+    )
+  }
+
+  public toggleMaximiseMinimise(index: number) {
+    this.store$.dispatch(ngViewerActionToggleMax({
+      payload: { index }
+    }))
+  }
+
+  public zoomNgView(panelIndex: number, factor: number) {
+    const ngviewer = this.nehubaContainerDirective?.nehubaViewerInstance?.nehubaViewer?.ngviewer
+    if (!ngviewer) throw new Error(`ngviewer not defined!`)
+
+    /**
+     * panelIndex < 3 === slice view
+     */
+    if (panelIndex < 3) {
+      /**
+       * factor > 1 === zoom out
+       */
+      ngviewer.navigationState.zoomBy(factor)
+    } else {
+      ngviewer.perspectiveNavigationState.zoomBy(factor)
+    }
+  }
+
+  private removeExistingPanels() {
+    const element = this.nehubaContainerDirective.nehubaViewerInstance.nehubaViewer.ngviewer.layout.container.componentValue.element as HTMLElement
+    while (element.childElementCount > 0) {
+      element.removeChild(element.firstElementChild)
+    }
+    return element
+  }
+
+
+  public returnTruePos(quadrant: number, data: any) {
+    const pos = quadrant > 2
+      ? [0, 0, 0]
+      : this.nanometersToOffsetPixelsFn && this.nanometersToOffsetPixelsFn[quadrant]
+        ? this.nanometersToOffsetPixelsFn[quadrant](data.geometry.position.map(n => n * 1e6))
+        : [0, 0, 0]
+    return pos
+  }
+
+  public getPositionX(quadrant: number, data: any) {
+    return this.returnTruePos(quadrant, data)[0]
+  }
+  public getPositionY(quadrant: number, data: any) {
+    return this.returnTruePos(quadrant, data)[1]
+  }
+  public getPositionZ(quadrant: number, data: any) {
+    return this.returnTruePos(quadrant, data)[2]
+  }
+
+  public handleMouseEnterCustomLandmark(lm) {
+    this.store$.dispatch(
+      viewerStateMouseOverCustomLandmark({
+        payload: { userLandmark: lm }
+      })
+    )
+  }
+
+  public handleMouseLeaveCustomLandmark(lm) {
+    this.store$.dispatch(
+      viewerStateMouseOverCustomLandmark({
+        payload: { userLandmark: null }
+      })
+    )
+  }
+
+}
\ No newline at end of file
diff --git a/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.style.css b/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.style.css
new file mode 100644
index 0000000000000000000000000000000000000000..a03d05dd199a30e712eb7062ee253473ae894552
--- /dev/null
+++ b/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.style.css
@@ -0,0 +1,31 @@
+
+.opacity-crossfade
+{
+  transition: opacity 170ms ease-in-out,
+    transform 250ms ease-in-out;
+}
+
+.opacity-crossfade
+{
+
+  opacity: 0.0;
+  pointer-events: none;
+}
+
+.opacity-crossfade.onHover,
+.opacity-crossfade:hover,
+:host-context([ismobile="true"]) .opacity-crossfade.always-show-touchdevice
+{
+  opacity: 1.0 !important;
+  pointer-events: all !important;
+}
+
+.screen-overlay
+{
+  background-color: rgba(255, 255, 255, 0.7);
+}
+
+:host-context([darktheme="true"]) .screen-overlay
+{
+  background-color: rgba(0, 0, 0, 0.7);
+}
diff --git a/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.template.html b/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.template.html
new file mode 100644
index 0000000000000000000000000000000000000000..45b20af1f7ffc74a0a2315ccd1e7643b07802ddc
--- /dev/null
+++ b/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.template.html
@@ -0,0 +1,161 @@
+<div class="d-block"
+  iav-nehuba-viewer-container
+  iav-mouse-hover
+  (iavNehubaViewerContainerViewerLoading)="handleViewerLoadedEvent($event)">
+
+</div>
+
+<current-layout *ngIf="viewerLoaded$ | async" class="position-absolute w-100 h-100 d-block pe-none top-0 left-0">
+  <div class="w-100 h-100 position-relative" cell-i>
+    <ng-content *ngTemplateOutlet="ngPanelOverlayTmpl; context: { panelIndex: panelOrder$ | async | getNthElement : 0 | parseAsNumber }"></ng-content>
+  </div>
+  <div class="w-100 h-100 position-relative" cell-ii>
+    <ng-content *ngTemplateOutlet="ngPanelOverlayTmpl; context: { panelIndex: panelOrder$ | async | getNthElement : 1 | parseAsNumber }"></ng-content>
+  </div>
+  <div class="w-100 h-100 position-relative" cell-iii>
+    <ng-content *ngTemplateOutlet="ngPanelOverlayTmpl; context: { panelIndex: panelOrder$ | async | getNthElement : 2 | parseAsNumber }"></ng-content>
+  </div>
+  <div class="w-100 h-100 position-relative" cell-iv>
+    <ng-content *ngTemplateOutlet="ngPanelOverlayTmpl; context: { panelIndex: panelOrder$ | async | getNthElement : 3 | parseAsNumber }"></ng-content>
+  </div>
+</current-layout>
+
+<!-- slice view overlay tmpl -->
+<ng-template #ngPanelOverlayTmpl let-panelIndex="panelIndex">
+
+  <!-- perspective view tmpl -->
+  <ng-template #overlayPerspectiveTmpl>
+    <layout-floating-container landmarkContainer>
+
+      <div class="d-flex flex-column justify-content-center align-items-center w-100 h-100 position-absolute opacity-crossfade screen-overlay pe-none"
+        [ngClass]="{onHover: !!(showPerpsectiveScreen$ | async)}"
+        [attr.id]="IDS.MESH_LOADING_STATUS"
+        role="status">
+
+        <spinner-cmp *ngIf="showPerpsectiveScreen$ | async">
+        </spinner-cmp>
+        
+        <mat-list>
+          <mat-list-item>
+            {{ showPerpsectiveScreen$ | async }}
+          </mat-list-item>
+        </mat-list>
+      </div>
+
+      <!-- mesh loading is still weird -->
+      <!-- if the precomputed server does not have the necessary fragment file, then the numberws will not collate -->
+      <div *ngIf="false && (perspectiveViewLoading$ | async)" class="loadingIndicator">
+        <spinner-cmp></spinner-cmp>
+
+        <div *ngIf="false" perspectiveLoadingText>
+          {{ perspectiveViewLoading$ | async }}
+        </div>
+      </div>
+    </layout-floating-container>
+  </ng-template>
+
+  <iav-layout-fourcorners class="w-100 h-100 d-block">
+    <layout-floating-container *ngIf="panelIndex < 3; else overlayPerspectiveTmpl"
+      class="overflow-hidden"
+      iavLayoutFourCornersContent>
+      <!-- TODO add landmarks here -->
+
+
+      <!-- customLandmarks -->
+      <!-- only show landmarks in slice views -->
+      <landmark-2d-flat-cmp *ngFor="let lm of (customLandmarks$ | async | filterByProperty : 'showInSliceView')"
+        (mouseenter)="handleMouseEnterCustomLandmark(lm)"
+        (mouseleave)="handleMouseLeaveCustomLandmark(lm)"
+        [color]="lm.color || [255, 255, 255]"
+        [positionX]="getPositionX(panelIndex, lm)"
+        [positionY]="getPositionY(panelIndex, lm)"
+        [positionZ]="getPositionZ(panelIndex, lm)">
+
+      </landmark-2d-flat-cmp>
+    </layout-floating-container>
+
+    <!-- panel controller -->
+    <div iavLayoutFourCornersBottomRight>
+
+      <ng-container *ngTemplateOutlet="panelCtrlTmpl; context: {
+        panelIndex: panelIndex,
+        visible: (hoveredPanelIndices$ | async) === panelIndex
+      }">
+      </ng-container>
+
+      <div *ngIf="(sliceViewLoadingMain$ | async)[panelIndex]">
+        <spinner-cmp></spinner-cmp>
+      </div>
+    </div>
+  </iav-layout-fourcorners>
+
+</ng-template>
+
+<!-- panel control template -->
+<ng-template
+  #panelCtrlTmpl
+  let-panelIndex="panelIndex"
+  let-visible="visible">
+
+  <div class="opacity-crossfade always-show-touchdevice pe-all overlay-btn-container"
+    [ngClass]="{ onHover: visible }"
+    [attr.data-viewer-controller-visible]="visible"
+    [attr.data-viewer-controller-index]="panelIndex">
+
+    <!-- perspective specific control -->
+    <ng-container *ngIf="panelIndex === 3">
+      <ng-container *ngTemplateOutlet="perspectiveOctantRemovalTmpl; context: {
+        state: (nehubaViewerPerspectiveOctantRemoval$ | async),
+        disableOctantRemovalCtrl: disableOctantRemovalCtrl$ | async
+      }">
+
+      </ng-container>
+    </ng-container>
+
+    <!-- factor < 1.0 === zoom in -->
+    <button mat-icon-button color="primary"
+      (click)="zoomNgView(panelIndex, 0.9)"
+      [attr.aria-label]="ARIA_LABELS.ZOOM_IN">
+      <i class="fas fa-search-plus"></i>
+    </button>
+
+    <!-- factor > 1.0 === zoom out -->
+    <button mat-icon-button color="primary"
+      (click)="zoomNgView(panelIndex, 1.1)"
+      [attr.aria-label]="ARIA_LABELS.ZOOM_OUT">
+      <i class="fas fa-search-minus"></i>
+    </button>
+
+    <maximise-panel-button
+      (click)="toggleMaximiseMinimise(panelIndex)"
+      [touch-side-class]="panelIndex">
+    </maximise-panel-button>
+  </div>
+
+</ng-template>
+
+<!-- tmpl for toggling perspective frontal octant -->
+<ng-template #perspectiveOctantRemovalTmpl
+  let-state="state"
+  let-disableOctantRemovalCtrl="disableOctantRemovalCtrl">
+  <div class="d-inline-block"
+    [matTooltip]="disableOctantRemovalCtrl?.mode !== null ? disableOctantRemovalCtrl.message : null">
+    <button
+      (click)="setOctantRemoval(!state)"
+      mat-icon-button
+      [disabled]="disableOctantRemovalCtrl?.mode !== null"
+      [attr.aria-label]="ARIA_LABELS.TOGGLE_FRONTAL_OCTANT"
+      color="primary">
+
+      <!-- octant removal is true -->
+      <ng-template [ngIf]="disableOctantRemovalCtrl?.mode !== null ? disableOctantRemovalCtrl.mode : state" [ngIfElse]="octantRemovalOffTmpl">
+        <i class="fas fa-eye-slash"></i>
+      </ng-template>
+
+      <!-- octant removal is false -->
+      <ng-template #octantRemovalOffTmpl>
+        <i class="fas fa-eye"></i>
+      </ng-template>
+    </button>
+  </div>
+</ng-template>
\ No newline at end of file
diff --git a/src/ui/nehubaContainer/nehubaViewerInterface/nehubaViewerInterface.directive.spec.ts b/src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerInterface.directive.spec.ts
similarity index 100%
rename from src/ui/nehubaContainer/nehubaViewerInterface/nehubaViewerInterface.directive.spec.ts
rename to src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerInterface.directive.spec.ts
diff --git a/src/ui/nehubaContainer/nehubaViewerInterface/nehubaViewerInterface.directive.ts b/src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerInterface.directive.ts
similarity index 98%
rename from src/ui/nehubaContainer/nehubaViewerInterface/nehubaViewerInterface.directive.ts
rename to src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerInterface.directive.ts
index f4a1973ae240f4235f441159dc0892456c381f2f..e0f0678a4d20ff05f1dee4ce9f8d9d21e6b5e685 100644
--- a/src/ui/nehubaContainer/nehubaViewerInterface/nehubaViewerInterface.directive.ts
+++ b/src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerInterface.directive.ts
@@ -3,7 +3,7 @@ import { NehubaViewerUnit, INehubaLifecycleHook } from "../nehubaViewer/nehubaVi
 import { Store, select } from "@ngrx/store";
 import { IavRootStoreInterface } from "src/services/stateStore.service";
 import { Subscription, Observable, fromEvent } from "rxjs";
-import { distinctUntilChanged, filter, debounceTime, shareReplay, scan, map, throttleTime, switchMapTo } from "rxjs/operators";
+import { distinctUntilChanged, filter, debounceTime, scan, map, throttleTime, switchMapTo } from "rxjs/operators";
 import { StateInterface as ViewerConfigStateInterface } from "src/services/state/viewerConfig.store";
 import { getNavigationStateFromConfig, takeOnePipe } from "../util";
 import { NEHUBA_LAYER_CHANGED, CHANGE_NAVIGATION } from "src/services/state/viewerState.store";
@@ -437,7 +437,7 @@ export class NehubaViewerContainerDirective implements OnInit, OnDestroy{
 
       this.nehubaViewerInstance.mouseoverSegmentEmitter.pipe(
         scan(accumulatorFn, new Map()),
-        map(map => Array.from(map.entries()).filter(([_ngId, { segmentId }]) => segmentId)),
+        map((map: Map<string, any>) => Array.from(map.entries()).filter(([_ngId, { segmentId }]) => segmentId)),
       ).subscribe(arrOfArr => {
         this.store$.dispatch({
           type: MOUSE_OVER_SEGMENTS,
@@ -501,6 +501,10 @@ export class NehubaViewerContainerDirective implements OnInit, OnDestroy{
     return this.cr && this.cr.instance
   }
 
+  isReady() {
+    return !!(this.cr?.instance?.nehubaViewer?.ngviewer)
+  }
+
   /* because the navigation can be changed from two sources,
     either dynamically (e.g. navigation panel in the UI or plugins etc)
     or actively (via user interaction with the viewer)
diff --git a/src/ui/nehubaContainer/nehubaViewerInterface/nehubaViewerTouch.directive.ts b/src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerTouch.directive.ts
similarity index 100%
rename from src/ui/nehubaContainer/nehubaViewerInterface/nehubaViewerTouch.directive.ts
rename to src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerTouch.directive.ts
diff --git a/src/ui/nehubaContainer/statusCard/statusCard.component.spec.ts b/src/viewerModule/nehuba/statusCard/statusCard.component.spec.ts
similarity index 98%
rename from src/ui/nehubaContainer/statusCard/statusCard.component.spec.ts
rename to src/viewerModule/nehuba/statusCard/statusCard.component.spec.ts
index 8db6d1a4e195ec1c5f7cb08a6b163c4773d232e6..bf9068df5e635e014f21a875fbd9a133cf5db5db 100644
--- a/src/ui/nehubaContainer/statusCard/statusCard.component.spec.ts
+++ b/src/viewerModule/nehuba/statusCard/statusCard.component.spec.ts
@@ -18,7 +18,7 @@ import * as util from '../util'
 import { viewerStateChangeNavigation } from "src/services/state/viewerState/actions"
 
 @Directive({
-  selector: '[iav-auth-authState]',
+  selector: '[iav-auth-auth-state]',
   exportAs: 'iavAuthAuthState'
 })
 
@@ -107,7 +107,7 @@ describe('> statusCard.component.ts', () => {
         it('> takes into account of statusPanelRealSpace panel', () => {
           const setNavigationStateSpy = jasmine.createSpy('setNavigationState')
           fixture.componentInstance.nehubaViewer = {
-            setNavigationState: setNavigationStateSpy
+            setNavigationState: setNavigationStateSpy,
           } as any
   
           fixture.componentInstance.statusPanelRealSpace = true
diff --git a/src/ui/nehubaContainer/statusCard/statusCard.component.ts b/src/viewerModule/nehuba/statusCard/statusCard.component.ts
similarity index 68%
rename from src/ui/nehubaContainer/statusCard/statusCard.component.ts
rename to src/viewerModule/nehuba/statusCard/statusCard.component.ts
index 8f14652f75394e561bf700fa7a26f006d1129da5..c4158fe7c92ff939940e84ddceb2eb6b5149fb2a 100644
--- a/src/ui/nehubaContainer/statusCard/statusCard.component.ts
+++ b/src/viewerModule/nehuba/statusCard/statusCard.component.ts
@@ -1,7 +1,6 @@
-import { Component, Input, OnInit, OnChanges, TemplateRef, HostBinding } from "@angular/core";
+import { Component, OnInit, OnChanges, TemplateRef, HostBinding, Optional, Inject } from "@angular/core";
 import { select, Store } from "@ngrx/store";
 import { LoggingService } from "src/logging";
-import { IavRootStoreInterface } from "src/services/stateStore.service";
 import { NehubaViewerUnit } from "../nehubaViewer/nehubaViewer.component";
 import { Observable, Subscription, of, combineLatest } from "rxjs";
 import { map, filter, startWith } from "rxjs/operators";
@@ -11,18 +10,26 @@ import { ARIA_LABELS } from 'common/constants'
 import { PureContantService } from "src/util";
 import { FormControl } from "@angular/forms";
 import { viewerStateNavigationStateSelector, viewerStateSelectedTemplatePureSelector } from "src/services/state/viewerState/selectors";
-import { getNavigationStateFromConfig } from "../util";
+
 import { viewerStateChangeNavigation } from "src/services/state/viewerState/actions";
+import { getNavigationStateFromConfig, NEHUBA_INSTANCE_INJTKN } from '../util'
 
 @Component({
-  selector : 'ui-status-card',
+  selector : 'iav-cmp-viewer-nehuba-status',
   templateUrl : './statusCard.template.html',
   styleUrls : ['./statusCard.style.css'],
 })
 export class StatusCardComponent implements OnInit, OnChanges{
 
-  @Input() public selectedTemplateName: string;
-  @Input() public nehubaViewer: NehubaViewerUnit;
+  private _nehubaViewer: NehubaViewerUnit;
+
+  get nehubaViewer(){
+    return this._nehubaViewer
+  }
+  set nehubaViewer(v: NehubaViewerUnit) {
+    this._nehubaViewer = v
+    this.ngOnChanges()
+  }
 
   @HostBinding('attr.aria-label')
   public arialabel = ARIA_LABELS.STATUS_PANEL
@@ -44,13 +51,24 @@ export class StatusCardComponent implements OnInit, OnChanges{
   public SHOW_FULL_STATUS_PANEL_ARIA_LABEL = ARIA_LABELS.SHOW_FULL_STATUS_PANEL
   public HIDE_FULL_STATUS_PANEL_ARIA_LABEL = ARIA_LABELS.HIDE_FULL_STATUS_PANEL
   constructor(
-    private store$: Store<IavRootStoreInterface>,
+    private store$: Store<any>,
     private log: LoggingService,
     private bottomSheet: MatBottomSheet,
     private dialog: MatDialog,
-    private pureConstantService: PureContantService
+    //private pureConstantService: PureContantService,
+    @Optional() @Inject(NEHUBA_INSTANCE_INJTKN) nehubaViewer$: Observable<NehubaViewerUnit>
   ) {
-    this.useTouchInterface$ = this.pureConstantService.useTouchUI$
+    this.useTouchInterface$ = of(true) //this.pureConstantService.useTouchUI$
+
+    if (nehubaViewer$) {
+      this.subscriptions.push(
+        nehubaViewer$.subscribe(
+          viewer => this.nehubaViewer = viewer
+        )
+      )
+    } else {
+      this.log.warn(`NEHUBA_INSTANCE_INJTKN not injected!`)
+    }
   }
 
   ngOnInit(): void {
@@ -74,40 +92,45 @@ export class StatusCardComponent implements OnInit, OnChanges{
   }
 
   ngOnChanges() {
-    if (!this.nehubaViewer) {
+    if (this.nehubaViewer?.viewerPosInReal$ && this.nehubaViewer?.viewerPosInVoxel$) {
+      this.navVal$ = combineLatest([
+        this.statusPanelRealSpace$,
+        this.nehubaViewer.viewerPosInReal$.pipe(
+          filter(v => !!v)
+        ),
+        this.nehubaViewer.viewerPosInVoxel$.pipe(
+          filter(v => !!v)
+        )
+      ]).pipe(
+        map(([realFlag, real, voxel]) => realFlag
+          ? real.map(v => `${ (v / 1e6).toFixed(3) }mm`).join(', ')
+          : voxel.map(v => v.toFixed(3)).join(', ') ),
+        startWith(`nehubaViewer initialising`)
+      )
+    } else {
       this.navVal$ = of(`neubaViewer is undefined`)
-      this.mouseVal$ = of(`neubaViewer is undefined`)
-      return
     }
-    this.navVal$ = combineLatest([
-      this.statusPanelRealSpace$,
-      this.nehubaViewer.viewerPosInReal$.pipe(
-        filter(v => !!v)
-      ),
-      this.nehubaViewer.viewerPosInVoxel$.pipe(
-        filter(v => !!v)
-      )
-    ]).pipe(
-      map(([realFlag, real, voxel]) => realFlag
-        ? real.map(v => `${ (v / 1e6).toFixed(3) }mm`).join(', ')
-        : voxel.map(v => v.toFixed(3)).join(', ') ),
-      startWith(`nehubaViewer initialising`)
-    )
 
-    this.mouseVal$ = combineLatest([
-      this.statusPanelRealSpace$,
-      this.nehubaViewer.mousePosInReal$.pipe(
-        filter(v => !!v)
-      ),
-      this.nehubaViewer.mousePosInVoxel$.pipe(
-        filter(v => !!v)
+    if ( this.nehubaViewer?.mousePosInReal$ && this.nehubaViewer?.mousePosInVoxel$ ) {
+
+      this.mouseVal$ = combineLatest([
+        this.statusPanelRealSpace$,
+        this.nehubaViewer.mousePosInReal$.pipe(
+          filter(v => !!v)
+        ),
+        this.nehubaViewer.mousePosInVoxel$.pipe(
+          filter(v => !!v)
+        )
+      ]).pipe(
+        map(([realFlag, real, voxel]) => realFlag
+          ? real.map(v => `${ (v/1e6).toFixed(3) }mm`).join(', ')
+          : voxel.map(v => v.toFixed(3)).join(', ')),
+        startWith(``)
       )
-    ]).pipe(
-      map(([realFlag, real, voxel]) => realFlag
-        ? real.map(v => `${ (v/1e6).toFixed(3) }mm`).join(', ')
-        : voxel.map(v => v.toFixed(3)).join(', ')),
-      startWith(``)
-    )
+    } else {
+      this.mouseVal$ = of(`neubaViewer is undefined`)
+    }
+
   }
 
   public statusPanelFormCtrl = new FormControl(true, [])
diff --git a/src/ui/nehubaContainer/statusCard/statusCard.style.css b/src/viewerModule/nehuba/statusCard/statusCard.style.css
similarity index 100%
rename from src/ui/nehubaContainer/statusCard/statusCard.style.css
rename to src/viewerModule/nehuba/statusCard/statusCard.style.css
diff --git a/src/ui/nehubaContainer/statusCard/statusCard.template.html b/src/viewerModule/nehuba/statusCard/statusCard.template.html
similarity index 99%
rename from src/ui/nehubaContainer/statusCard/statusCard.template.html
rename to src/viewerModule/nehuba/statusCard/statusCard.template.html
index 17d4fe7cfd9f6c5c18cedd1f3471b320934b1e62..0489d088a7818527404627c3f230661d3dd30408 100644
--- a/src/ui/nehubaContainer/statusCard/statusCard.template.html
+++ b/src/viewerModule/nehuba/statusCard/statusCard.template.html
@@ -170,7 +170,7 @@
   </h2>
 
   <div mat-dialog-content>
-    <div iav-auth-authState
+    <div iav-auth-auth-state
       #authState="iavAuthAuthState">
 
       <!-- Logged in. Explain that links will not expire, offer to logout -->
diff --git a/src/viewerModule/nehuba/store.ts b/src/viewerModule/nehuba/store.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f00a217031ac76ef8bb50ba0a7e30b0e47963e22
--- /dev/null
+++ b/src/viewerModule/nehuba/store.ts
@@ -0,0 +1,36 @@
+import { createReducer } from "@ngrx/store";
+import { INgLayerInterface } from "src/services/state/ngViewerState.store";
+
+
+/**
+ * TODO port from global store to feature store
+ */
+
+enum EnumPanelMode {
+  FOUR_PANEL = 'FOUR_PANEL',
+  V_ONE_THREE = 'V_ONE_THREE',
+  H_ONE_THREE = 'H_ONE_THREE',
+  SINGLE_PANEL = 'SINGLE_PANEL',
+}
+
+interface INehubaFeature {
+  layers: INgLayerInterface[]
+  panelMode: string
+  panelOrder: string
+  octantRemoval: boolean
+  clearViewQueue: {
+    [key: string]: boolean
+  }
+}
+
+const defaultState: INehubaFeature = {
+  layers: [],
+  panelMode: EnumPanelMode.FOUR_PANEL,
+  panelOrder: '0123',
+  octantRemoval: true,
+  clearViewQueue: {}
+}
+
+export const reducer = createReducer(
+  defaultState
+)
\ No newline at end of file
diff --git a/src/ui/nehubaContainer/touchSideClass.directive.ts b/src/viewerModule/nehuba/touchSideClass.directive.ts
similarity index 93%
rename from src/ui/nehubaContainer/touchSideClass.directive.ts
rename to src/viewerModule/nehuba/touchSideClass.directive.ts
index edaa9823ff6af39756e0f51e16c91cee40d91022..44cdac937990acc2b79bb03a70d545fb8030af1b 100644
--- a/src/ui/nehubaContainer/touchSideClass.directive.ts
+++ b/src/viewerModule/nehuba/touchSideClass.directive.ts
@@ -4,7 +4,8 @@ import { Observable, Subscription } from "rxjs";
 import { distinctUntilChanged, tap } from "rxjs/operators";
 import { ngViewerSelectorPanelMode } from "src/services/state/ngViewerState/selectors";
 import { IavRootStoreInterface } from "src/services/stateStore.service";
-import { addTouchSideClasses, removeTouchSideClasses } from "./util";
+import { addTouchSideClasses, removeTouchSideClasses } from "src/viewerModule/nehuba/util";
+
 
 @Directive({
   selector: '[touch-side-class]',
diff --git a/src/ui/nehubaContainer/util.ts b/src/viewerModule/nehuba/util.ts
similarity index 96%
rename from src/ui/nehubaContainer/util.ts
rename to src/viewerModule/nehuba/util.ts
index 49d7136412e6d19d67bdf6774d7e6f81e9832988..3849713a6681f396d24ab5daf804351c479462b8 100644
--- a/src/ui/nehubaContainer/util.ts
+++ b/src/viewerModule/nehuba/util.ts
@@ -1,7 +1,9 @@
-import { pipe } from 'rxjs'
+import { InjectionToken } from '@angular/core'
+import { Observable, pipe } from 'rxjs'
 import { filter, scan, take } from 'rxjs/operators'
 import { PANELS } from 'src/services/state/ngViewerState.store.helper'
 import { getViewer } from 'src/util/fn'
+import { NehubaViewerUnit } from './nehubaViewer/nehubaViewer.component'
 
 const flexContCmnCls = ['w-100', 'h-100', 'd-flex', 'justify-content-center', 'align-items-stretch']
 
@@ -285,3 +287,5 @@ export const takeOnePipe = () => {
     take(1),
   )
 }
+
+export const NEHUBA_INSTANCE_INJTKN = new InjectionToken<Observable<NehubaViewerUnit>>('NEHUBA_INSTANCE_INJTKN')
\ No newline at end of file
diff --git a/src/ui/util.ts b/src/viewerModule/util/regionAccordionTooltipText.pipe.ts
similarity index 100%
rename from src/ui/util.ts
rename to src/viewerModule/util/regionAccordionTooltipText.pipe.ts
diff --git a/src/viewerModule/viewer.interface.ts b/src/viewerModule/viewer.interface.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4e4eada8942a3b563f036b4566b73e42be452d3e
--- /dev/null
+++ b/src/viewerModule/viewer.interface.ts
@@ -0,0 +1,48 @@
+import { Observable } from "rxjs";
+
+type TLayersColorMap = Map<string, Map<number, { red: number, green: number, blue: number }>>
+
+interface IViewerCtrl {
+
+  // navigation control
+  setNavigationLoc(coord: number[], realSpace?: boolean): void
+  moveToNavigationLoc(coord: number[], realSpace?: boolean): void
+  setNavigationOri(quat: number[]): void
+  moveToNavigationOri(quat: number[]): void
+
+  // segment control
+  showSegment(segment: any): void
+  hideSegment(segment: any): void
+  showAllSegments(): void
+  hideAllSegments(): void
+
+  // landmark control
+  addLandmarks(landmarks: any[]): void
+  removeLandmarks(landmarks: any[]): void
+
+  // layer control
+  addLayer(layerSpec: any): void
+  removeLayer(layerId: string): void
+  applyLayersColourMap(map: TLayersColorMap): void
+  getLayersColourMap(): TLayersColorMap
+}
+
+type TViewerEventMOAnno = {
+  type: "MOUSEOVER_ANNOTATION"
+  data: any
+}
+
+type TViewerEventViewerLoaded = {
+  type: "VIEWERLOADED"
+  data: boolean
+}
+
+export type TViewerEvent = TViewerEventMOAnno | TViewerEventViewerLoaded
+
+export type IViewer = {
+  
+  selectedTemplate: any
+  selectedParcellation: any
+  viewerCtrlHandler?: IViewerCtrl
+  viewerEvents$: Observable<TViewerEvent>
+}
\ No newline at end of file
diff --git a/src/viewerModule/viewerCmp/viewerCmp.component.ts b/src/viewerModule/viewerCmp/viewerCmp.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..82d5bf98ea4e58e5b59dd05a47b41a30730167c1
--- /dev/null
+++ b/src/viewerModule/viewerCmp/viewerCmp.component.ts
@@ -0,0 +1,232 @@
+import { AfterViewInit, Component, Inject, Input, OnDestroy, Optional, ViewChild } from "@angular/core";
+import { select, Store } from "@ngrx/store";
+import { combineLatest, Observable, Subject, Subscription } from "rxjs";
+import { distinctUntilChanged, filter, map, startWith } from "rxjs/operators";
+import { viewerStateHelperSelectParcellationWithId, viewerStateRemoveAdditionalLayer, viewerStateSetSelectedRegions } from "src/services/state/viewerState/actions";
+import { viewerStateGetOverlayingAdditionalParcellations, viewerStateParcVersionSelector, viewerStateSelectedParcellationSelector, viewerStateSelectedRegionsSelector, viewerStateSelectedTemplateSelector, viewerStateStandAloneVolumes } from "src/services/state/viewerState/selectors"
+import { NehubaGlueCmp } from "../nehuba";
+import { IViewer } from "../viewer.interface";
+import { CONST, ARIA_LABELS } from 'common/constants'
+import { ngViewerActionClearView } from "src/services/state/ngViewerState/actions";
+import { ngViewerSelectorClearViewEntries } from "src/services/state/ngViewerState/selectors";
+import { uiActionHideAllDatasets, uiActionHideDatasetWithId } from "src/services/state/uiState/actions";
+import { REGION_OF_INTEREST } from "src/util/interfaces";
+import { animate, state, style, transition, trigger } from "@angular/animations";
+import { SwitchDirective } from "src/util/directives/switch.directive";
+
+@Component({
+  selector: 'iav-cmp-viewer-container',
+  templateUrl: './viewerCmp.template.html',
+  styleUrls: [
+    './viewerCmp.style.css'
+  ],
+  exportAs: 'iavCmpViewerCntr',
+  animations: [
+    trigger('openClose', [
+      state('open', style({
+        transform: 'translateY(0)',
+        opacity: 1
+      })),
+      state('closed', style({
+        transform: 'translateY(-100vh)',
+        opacity: 0
+      })),
+      transition('open => closed', [
+        animate('200ms cubic-bezier(0.35, 0, 0.25, 1)')
+      ]),
+      transition('closed => open', [
+        animate('200ms cubic-bezier(0.35, 0, 0.25, 1)')
+      ])
+    ]),
+    trigger('openCloseAnchor', [
+      state('open', style({
+        transform: 'translateY(0)'
+      })),
+      state('closed', style({
+        transform: 'translateY(100vh)'
+      })),
+      transition('open => closed', [
+        animate('200ms cubic-bezier(0.35, 0, 0.25, 1)')
+      ]),
+      transition('closed => open', [
+        animate('200ms cubic-bezier(0.35, 0, 0.25, 1)')
+      ])
+    ]),
+  ],
+  providers: [
+    {
+      provide: REGION_OF_INTEREST,
+      useFactory: (store: Store<any>) => store.pipe(
+        select(viewerStateSelectedRegionsSelector),
+        map(rs => rs[0] || null)
+      ),
+      deps: [
+        Store
+      ]
+    }
+  ]
+})
+
+export class ViewerCmp implements OnDestroy, AfterViewInit{
+
+  public CONST = CONST
+  public ARIA_LABELS = ARIA_LABELS
+
+  @ViewChild(NehubaGlueCmp) viewerCmp: IViewer
+  @ViewChild('sideNavTopSwitch', { static: true })
+  private sidenavTopSwitch: SwitchDirective
+
+  @ViewChild('sideNavFullLeftSwitch', { static: true })
+  private sidenavLeftSwitch: SwitchDirective
+
+  @Input() ismobile = false
+
+  private subscriptions: Subscription[] = []
+  public viewerLoaded: boolean = false
+
+  public templateSelected$ = this.store$.pipe(
+    select(viewerStateSelectedTemplateSelector),
+    distinctUntilChanged(),
+  )
+  public parcellationSelected$ = this.store$.pipe(
+    select(viewerStateSelectedParcellationSelector),
+    distinctUntilChanged(),
+  )
+
+  public selectedRegions$ = this.store$.pipe(
+    select(viewerStateSelectedRegionsSelector),
+    distinctUntilChanged(),
+  )
+
+  public isStandaloneVolumes$ = this.store$.pipe(
+    select(viewerStateStandAloneVolumes),
+    map(v => v.length > 0)
+  )
+
+  public selectedLayerVersions$ = this.store$.pipe(
+    select(viewerStateParcVersionSelector),
+    map(arr => arr.map(item => {
+      const overwrittenName = item['@version'] && item['@version']['name']
+      return overwrittenName
+        ? { ...item, displayName: overwrittenName }
+        : item
+    }))
+  )
+
+  public selectedAdditionalLayers$ = this.store$.pipe(
+    select(viewerStateGetOverlayingAdditionalParcellations),
+  )
+
+  public clearViewKeys$ = this.store$.pipe(
+    select(ngViewerSelectorClearViewEntries)
+  )
+
+  /**
+   * TODO may need to be deprecated
+   * in favour of regional feature/data feature
+   */
+  public iavAdditionalLayers$ = new Subject<any[]>()
+
+  /**
+   * if no regions are selected, nor any additional layers (being deprecated)
+   * then the "explore" btn should not show
+   * and the full left side bar should not be expandable
+   * if it is already expanded, it should collapse
+   */
+  public alwaysHideMinorPanel$: Observable<boolean> = combineLatest([
+    this.selectedRegions$,
+    this.iavAdditionalLayers$.pipe(
+      startWith([])
+    )
+  ]).pipe(
+    map(([ regions, layers ]) => regions.length === 0 && layers.length === 0)
+  )
+
+  constructor(
+    private store$: Store<any>,
+    @Optional() @Inject(REGION_OF_INTEREST) public regionOfInterest$: Observable<any>
+  ){
+    this.subscriptions.push(
+      this.alwaysHideMinorPanel$.pipe(
+        distinctUntilChanged(),
+        filter(flag => !flag),
+      ).subscribe(() => {
+        this.openSideNavs()
+      })
+    )
+  }
+
+  ngAfterViewInit(){
+    this.subscriptions.push(
+      this.viewerCmp.viewerEvents$.pipe(
+        filter(ev => ev.type === 'VIEWERLOADED'),
+      ).subscribe(ev => {
+        this.viewerLoaded = ev.data
+      })
+    )
+  }
+
+  ngOnDestroy() {
+    while (this.subscriptions.length) this.subscriptions.pop().unsubscribe()
+  }
+
+
+  public bindFns(fns){
+    return () => {
+      for (const [ fn, ...arg] of fns) {
+        fn(...arg)
+      }
+    }
+  }
+  
+  public clearAdditionalLayer(layer: { ['@id']: string }){
+    this.store$.dispatch(
+      viewerStateRemoveAdditionalLayer({
+        payload: layer
+      })
+    )
+  }
+
+  public clearSelectedRegions(){
+    this.store$.dispatch(
+      viewerStateSetSelectedRegions({
+        selectRegions: []
+      })
+    )
+  }
+  
+  public selectParcellation(parc: any) {
+    this.store$.dispatch(
+      viewerStateHelperSelectParcellationWithId({
+        payload: parc
+      })
+    )
+  }
+
+  public handleChipClick(){
+    this.openSideNavs()
+  }
+
+  private openSideNavs() {
+    this.sidenavLeftSwitch && this.sidenavLeftSwitch.open()
+    this.sidenavTopSwitch && this.sidenavTopSwitch.open()
+  }
+
+  public unsetClearViewByKey(key: string){
+    this.store$.dispatch(
+      ngViewerActionClearView({ payload: {
+        [key]: false
+      }})
+    )
+  }
+  public clearPreviewingDataset(id: string){
+    /**
+     * clear all preview
+     */
+    this.store$.dispatch(
+      id
+        ? uiActionHideDatasetWithId({ id })
+        : uiActionHideAllDatasets()
+    )
+  }
+}
\ No newline at end of file
diff --git a/src/viewerModule/viewerCmp/viewerCmp.style.css b/src/viewerModule/viewerCmp/viewerCmp.style.css
new file mode 100644
index 0000000000000000000000000000000000000000..a3960f1d7ea97425a512e78a0d7396801e28cf8b
--- /dev/null
+++ b/src/viewerModule/viewerCmp/viewerCmp.style.css
@@ -0,0 +1,42 @@
+:host
+{
+  position: relative;
+}
+
+.explore-btn
+{
+  margin-top: 4.5rem;
+}
+
+.region-text-search-autocomplete-position
+{
+  z-index: 10;
+  position: sticky;
+  top: 0.5rem;
+}
+
+.tab-toggle-container
+{
+  margin-top: 1.5rem;
+}
+
+
+.tab-toggle
+{
+  margin-left: -2rem;
+  padding-right: 0.75rem;
+  margin-right: 1rem;
+  text-align: right;
+}
+
+.accordion-icon
+{
+  width:1.5rem;
+}
+
+.collapse-position
+{
+  z-index: 10;
+  position: sticky;
+  bottom: 0.5rem;
+}
diff --git a/src/viewerModule/viewerCmp/viewerCmp.template.html b/src/viewerModule/viewerCmp/viewerCmp.template.html
new file mode 100644
index 0000000000000000000000000000000000000000..2df56a69fd5e00480757e94a6514be539c574790
--- /dev/null
+++ b/src/viewerModule/viewerCmp/viewerCmp.template.html
@@ -0,0 +1,946 @@
+<div class="position-absolute w-100 h-100">
+  <ng-container *ngTemplateOutlet="viewerTmpl">
+  </ng-container>
+</div>
+
+<layout-floating-container [zIndex]="10">
+
+  <!-- top drawer -->
+  <mat-drawer-container
+    [iav-switch-initstate]="false"
+    iav-switch
+    #sideNavTopSwitch="iavSwitch"
+    class="mat-drawer-content-overflow-visible w-100 h-100 position-absolute invisible"
+    [hasBackdrop]="false">
+
+    <!-- sidenav-content -->
+
+    <!-- (closedStart)="sideNavFullLeftSwitch.switchState && matDrawerLeft.close()"
+    (openedStart)="sideNavFullLeftSwitch.switchState && matDrawerLeft.open()" -->
+    <mat-drawer class="box-shadow-none border-0 pe-none bg-none col-10 col-sm-10 col-md-5 col-lg-4 col-xl-3 col-xxl-2"
+      mode="side"
+      [attr.data-mat-drawer-top-open]="matDrawerTop.opened"
+      [opened]="sideNavTopSwitch.switchState"
+      [autoFocus]="false"
+      [disableClose]="true"
+      #matDrawerTop="matDrawer">
+
+      <div class="h-0 w-100 region-text-search-autocomplete-position">
+        <ng-container *ngTemplateOutlet="autocompleteTmpl">
+        </ng-container>
+      </div>
+
+      <button mat-raised-button
+        *ngIf="!(alwaysHideMinorPanel$ | async)"
+        [attr.aria-label]="ARIA_LABELS.EXPAND"
+        (click)="sideNavFullLeftSwitch && sideNavFullLeftSwitch.open()"
+        class="explore-btn pe-all w-100"
+        [ngClass]="{
+          'darktheme': iavRegion.rgbDarkmode === true,
+          'lighttheme': iavRegion.rgbDarkmode === false
+        }"
+        [style.backgroundColor]="iavRegion?.rgbString || 'accent'">
+        <span class="text iv-custom-comp">
+          Explore
+        </span>
+
+        <div class="hidden"
+          iav-region
+          [region]="(selectedRegions$ | async) && (selectedRegions$ | async)[0]"
+          #iavRegion="iavRegion">
+        </div>
+
+      </button>
+    </mat-drawer>
+
+    <mat-drawer-content class="visible position-relative pe-none">
+      
+      <iav-layout-fourcorners>
+
+        <!-- pullable tab top right corner -->
+        <div iavLayoutFourCornersTopLeft class="d-inline-flex">
+
+          <div *ngIf="viewerLoaded"
+            class="pe-all tab-toggle-container"
+            (click)="sideNavTopSwitch && sideNavTopSwitch.toggle()">
+            <ng-container *ngTemplateOutlet="tabTmpl; context: {
+              isOpen: sideNavTopSwitch.switchState,
+              regionSelected: selectedRegions$ | async,
+              iavAdditionallayers: iavAdditionalLayers$ | async
+            }">
+            </ng-container>
+          </div>
+
+          <iav-cmp-viewer-nehuba-status *ngIf="viewerLoaded"
+            class="pe-all mt-2 muted-7">
+          </iav-cmp-viewer-nehuba-status>
+        </div>
+
+        <!-- signin banner at top right corner -->
+        <div iavLayoutFourCornersTopRight
+          class="d-inline-flex align-items-start">
+
+          <top-menu-cmp class="mt-3 mr-2 d-inline-block"
+            [ismobile]="ismobile"
+            [viewerLoaded]="viewerLoaded">
+          </top-menu-cmp>
+
+          <div *ngIf="viewerLoaded"
+            class="iv-custom-comp bg card m-2 mat-elevation-z2">
+            <atlas-dropdown-selector class="pe-all mt-2">
+            </atlas-dropdown-selector>
+          </div>
+        </div>
+      </iav-layout-fourcorners>
+
+    </mat-drawer-content>
+  </mat-drawer-container>
+
+  <!-- full left drawer -->
+  <mat-drawer-container
+    [iav-switch-initstate]="!(alwaysHideMinorPanel$ | async)"
+    iav-switch
+    #sideNavFullLeftSwitch="iavSwitch"
+    class="mat-drawer-content-overflow-visible w-100 h-100 position-absolute invisible"
+    [hasBackdrop]="false">
+
+    <!-- sidenav-content -->
+    <mat-drawer class="darker-bg iv-custom-comp visible col-10 col-sm-10 col-md-5 col-lg-4 col-xl-3 col-xxl-2 d-flex flex-column pe-all"
+      mode="push"
+      [opened]="sideNavTopSwitch.switchState && sideNavFullLeftSwitch.switchState"
+      [attr.data-mat-drawer-fullleft-open]="matDrawerLeft.opened"
+      [autoFocus]="false"
+      #matDrawerLeft="matDrawer"
+      (openedChange)="$event && sideNavFullLeftSwitch.open()"
+      [@openClose]="sideNavTopSwitch.switchState && sideNavFullLeftSwitch.switchState ? 'open' : 'closed'"
+      (@openClose.done)="$event.toState === 'closed' && matDrawerLeft.close()"
+      [disableClose]="true">
+
+      <div class="position-relative d-flex flex-column h-100">
+
+        <!-- TODO dataset preview will become deprecated in the future.
+        Regional feature/data feature will replace it -->
+
+        <div class="hidden"
+          iav-shown-dataset
+          #iavShownDataset="iavShownDataset">
+        </div>
+      
+        <div class="hidden"
+          iav-shown-previews
+          (emitter)="iavAdditionalLayers$.next($event)"
+          #previews="iavShownPreviews">
+        </div>
+
+        <!-- sidenav datasets -->
+        <ng-container *ngIf="iavShownDataset.shownDatasetId$ | async as shownDatasetId">
+          <ng-template [ngIf]="shownDatasetId.length > 0" [ngIfElse]="sideNavVolumePreview">
+            
+            <!-- single dataset side nav panel -->
+            <single-dataset-sidenav-view *ngFor="let id of shownDatasetId"
+              (clear)="clearPreviewingDataset(id)"
+              [fullId]="id"
+              class="bs-border-box ml-15px-n mr-15px-n">
+              <mat-chip *ngIf="regionOfInterest$ && regionOfInterest$ | async as region"
+                region-of-interest
+                iav-region
+                [region]="region"
+                [ngClass]="{
+                  'darktheme':regionDirective.rgbDarkmode === true,
+                  'lighttheme': regionDirective.rgbDarkmode === false
+                }"
+                [style.backgroundColor]="regionDirective.rgbString"
+                #regionDirective="iavRegion">
+                <span class="iv-custom-comp text text-truncate d-inline">
+                  {{ region.name }}
+                </span>
+              </mat-chip>
+            </single-dataset-sidenav-view>
+          </ng-template>
+        </ng-container>
+
+        <!-- preview volumes -->
+        <ng-template #sideNavVolumePreview>
+          <ng-container *ngIf="previews.iavAdditionalLayers$ | async | filterPreviewByType : [previews.FILETYPES.VOLUMES] as volumePreviews">
+            <ng-template [ngIf]="volumePreviews.length > 0" [ngIfElse]="sidenavRegionTmpl">
+              <ng-container *ngFor="let vPreview of volumePreviews">
+                <ng-container *ngTemplateOutlet="sidenavDsPreviewTmpl; context: vPreview">
+
+                </ng-container>
+              </ng-container>
+            </ng-template>
+          </ng-container>
+        </ng-template>
+
+      </div>
+    </mat-drawer>
+
+    <!-- main-content -->
+    <mat-drawer-content class="visible position-relative">
+
+      <iav-layout-fourcorners>
+    
+        <!-- bottom left corner (atlas selector and currently selected) -->
+        <div iavLayoutFourCornersBottomLeft class="d-inline-flex align-items-center mb-4 ml-2">
+    
+          <!-- atlas selector -->
+          <atlas-layer-selector *ngIf="viewerLoaded && !(isStandaloneVolumes$ | async)"
+            #alSelector="atlasLayerSelector"
+            (iav-outsideClick)="alSelector.selectorExpanded = false">
+          </atlas-layer-selector>
+    
+          <!-- chips -->
+          <mat-chip-list>
+            <!-- additional layer -->
+    
+            <ng-container>
+              <ng-container *ngTemplateOutlet="currParcellationTmpl; context: { addParc: (selectedAdditionalLayers$ | async), parc: (parcellationSelected$ | async) }">
+              </ng-container>
+            </ng-container>
+    
+            <!-- any selected region(s) -->
+            <ng-container>
+              <ng-container *ngTemplateOutlet="selectedRegionTmpl">
+              </ng-container>
+            </ng-container>
+    
+            <!-- controls for iav volumes -->
+            <div class="hidden" iav-shown-previews #previews="iavShownPreviews"></div>
+            <ng-container *ngTemplateOutlet="selectedDatasetPreview; context: { layers: previews.iavAdditionalLayers$ | async | filterPreviewByType : [previews.FILETYPES.VOLUMES] }">
+            </ng-container>
+    
+          </mat-chip-list>
+        </div>
+    
+      </iav-layout-fourcorners>
+
+    </mat-drawer-content>
+  </mat-drawer-container>
+
+</layout-floating-container>
+
+<!-- viewer tmpl -->
+<ng-template #viewerTmpl>
+
+  <iav-layout-fourcorners>
+    <div iavLayoutFourCornersContent
+      class="w-100 h-100 position-absolute">
+      <ui-splashscreen *ngIf="!viewerLoaded"
+        class="position-absolute left-0 top-0">
+      </ui-splashscreen>
+      <div class="h-100 w-100 overflow-hidden position-relative"
+        [ngClass]="{'pe-none': !viewerLoaded}">
+        <iav-cmp-viewer-nehuba-glue class="d-block w-100 h-100 position-absolute left-0 top-0"
+          [selectedTemplate]="templateSelected$ | async"
+          [selectedParcellation]="parcellationSelected$ | async"
+          #iavCmpViewerNehubaGlue="iavCmpViewerNehubaGlue">
+        </iav-cmp-viewer-nehuba-glue>
+      
+      </div>
+    </div>
+  </iav-layout-fourcorners>
+</ng-template>
+
+<!-- parcellation chip / region chip -->
+<!-- TODO maybe migrate to atlas cmp... later? -->
+<ng-template #currParcellationTmpl let-parc="parc" let-addParc="addParc">
+  <div [matMenuTriggerFor]="layerVersionMenu"
+    [matMenuTriggerData]="{ layerVersionMenuTrigger: layerVersionMenuTrigger }"
+    #layerVersionMenuTrigger="matMenuTrigger">
+
+    <ng-template [ngIf]="addParc.length > 0" [ngIfElse]="defaultParcTmpl">
+      <ng-container *ngFor="let p of addParc">
+        <ng-container *ngTemplateOutlet="chipTmpl; context: {
+          parcel: p,
+          selected: true,
+          dismissable: true,
+          onclick: layerVersionMenuTrigger.toggleMenu.bind(layerVersionMenuTrigger)
+        }">
+        </ng-container>
+      </ng-container>
+    </ng-template>
+    <ng-template #defaultParcTmpl>
+      <ng-container *ngTemplateOutlet="chipTmpl; context: {
+        parcel: parc,
+        selected: false,
+        dismissable: false,
+        onclick: layerVersionMenuTrigger.toggleMenu.bind(layerVersionMenuTrigger)
+      }">
+      </ng-container>
+    </ng-template>
+  </div>
+</ng-template>
+
+
+<!-- layer version selector -->
+<mat-menu #layerVersionMenu
+  class="bg-none box-shadow-none"
+  [hasBackdrop]="false">
+  <ng-template matMenuContent let-layerVersionMenuTrigger="layerVersionMenuTrigger">
+    <div (iav-outsideClick)="layerVersionMenuTrigger.closeMenu()">
+      <ng-container *ngFor="let parcVer of selectedLayerVersions$ | async">
+        <ng-container *ngIf="parcellationSelected$ | async as selectedParcellation">
+
+          <ng-container *ngTemplateOutlet="chipTmpl; context: {
+            parcel: parcVer,
+            selected: selectedParcellation['@id'] === parcVer['@id'],
+            dismissable: false,
+            class: 'w-100',
+            onclick: bindFns([
+              [ selectParcellation.bind(this), parcVer ],
+              [ layerVersionMenuTrigger.closeMenu.bind(layerVersionMenuTrigger) ]
+            ])
+          }">
+          </ng-container>
+        </ng-container>
+        <div class="mt-1"></div>
+      </ng-container>
+    </div>
+  </ng-template>
+</mat-menu>
+
+<!-- chip tmpl -->
+<ng-template #chipTmpl
+  let-parcel="parcel"
+  let-selected="selected"
+  let-dismissable="dismissable"
+  let-chipClass="class"
+  let-onclick="onclick">
+  <mat-chip class="pe-all position-relative z-index-2 d-inline-flex justify-content-between"
+    [ngClass]="chipClass"
+    (click)="onclick && onclick()"
+    [selected]="selected">
+
+    <span>
+      {{ parcel?.groupName ? (parcel?.groupName + ' - ') : '' }}{{ parcel && (parcel.displayName || parcel.name) }}
+    </span>
+
+    <!-- info icon -->
+    <ng-template [ngIf]="parcel?.originDatasets?.length > 0" [ngIfElse]="infoIconBasic">
+
+      <mat-icon
+        *ngFor="let ds of parcel.originDatasets"
+        fontSet="fas"
+        fontIcon="fa-info-circle"
+        iav-stop="click"
+        iav-dataset-show-dataset-dialog
+        [iav-dataset-show-dataset-dialog-kgid]="ds['kgId']"
+        [iav-dataset-show-dataset-dialog-kgschema]="ds['kgSchema']"
+        [iav-dataset-show-dataset-dialog-name]="parcel?.properties?.name"
+        [iav-dataset-show-dataset-dialog-description]="parcel?.properties?.description">
+      </mat-icon>
+
+    </ng-template>
+
+    <ng-template #infoIconBasic>
+      <mat-icon *ngIf="parcel?.properties?.name && parcel?.properties?.description"
+        fontSet="fas"
+        fontIcon="fa-info-circle"
+        iav-stop="click"
+        iav-dataset-show-dataset-dialog
+        [iav-dataset-show-dataset-dialog-name]="parcel.properties.name"
+        [iav-dataset-show-dataset-dialog-description]="parcel.properties.description">
+
+      </mat-icon>
+    </ng-template>
+
+    <!-- dismiss icon -->
+    <mat-icon
+      *ngIf="dismissable"
+      (click)="clearAdditionalLayer(parcel); $event.stopPropagation()"
+      fontSet="fas"
+      fontIcon="fa-times">
+    </mat-icon>
+  </mat-chip>
+</ng-template>
+
+
+<ng-template #selectedRegionTmpl>
+
+  <!-- regions chip -->
+  <ng-template [ngIf]="selectedRegions$ | async" let-selectedRegions="ngIf">
+    <!-- if regions.length > 1 -->
+    <!-- use group chip -->
+    <ng-template [ngIf]="selectedRegions.length > 1" [ngIfElse]="singleRegionChipTmpl">
+      <mat-chip
+        color="primary"
+        selected
+        (click)="handleChipClick()"
+        class="pe-all position-relative z-index-1 ml-8-n">
+        <span class="iv-custom-comp text text-truncate d-inline pl-4">
+          {{ CONST.MULTI_REGION_SELECTION }}
+        </span>
+        <mat-icon
+          (click)="clearSelectedRegions()"
+          fontSet="fas"
+          iav-stop="click"
+          fontIcon="fa-times">
+        </mat-icon>
+      </mat-chip>
+    </ng-template>
+
+    <!-- if reginos.lengt === 1 -->
+    <!-- use single region chip -->
+    <ng-template #singleRegionChipTmpl>
+      <ng-container *ngFor="let r of selectedRegions">
+
+        <!-- region chip for discrete map -->
+        <mat-chip
+          iav-region
+          (click)="handleChipClick()"
+          [region]="r"
+          class="pe-all position-relative z-index-1 ml-8-n"
+          [ngClass]="{
+            'darktheme':regionDirective.rgbDarkmode === true,
+            'lighttheme': regionDirective.rgbDarkmode === false
+          }"
+          [style.backgroundColor]="regionDirective.rgbString"
+          #regionDirective="iavRegion">
+          <span class="iv-custom-comp text text-truncate d-inline pl-4">
+            {{ r.name }}
+          </span>
+          <mat-icon
+            class="iv-custom-comp text"
+            (click)="clearSelectedRegions()"
+            fontSet="fas"
+            iav-stop="click"
+            fontIcon="fa-times">
+          </mat-icon>
+        </mat-chip>
+
+        <!-- chips for previewing origin datasets/continous map -->
+        <ng-container *ngFor="let originDataset of (r.originDatasets || []); let index = index">
+          <div class="hidden"
+            iav-dataset-preview-dataset-file
+            [iav-dataset-preview-dataset-file-kgid]="originDataset.kgId"
+            [iav-dataset-preview-dataset-file-filename]="originDataset.filename"
+            #previewDirective="iavDatasetPreviewDatasetFile">
+          </div>
+          <mat-chip *ngIf="previewDirective.active"
+            (click)="handleChipClick()"
+            class="pe-all position-relative ml-8-n">
+            <span class="pl-4">
+              {{ regionDirective.regionOriginDatasetLabels$ | async | renderViewOriginDatasetlabel : index }}
+            </span>
+            <mat-icon (click)="previewDirective.onClick()"
+              fontSet="fas"
+              iav-stop="click"
+              fontIcon="fa-times">
+            </mat-icon>
+          </mat-chip>
+
+          <mat-chip *ngFor="let key of clearViewKeys$ | async"
+            (click)="handleChipClick()"
+            class="pe-all position-relative ml-8-n">
+            <span class="pl-4">
+              {{ key }}
+            </span>
+            <mat-icon (click)="unsetClearViewByKey(key)"
+              fontSet="fas"
+              iav-stop="click"
+              fontIcon="fa-times">
+
+            </mat-icon>
+          </mat-chip>
+        </ng-container>
+
+      </ng-container>
+    </ng-template>
+  </ng-template>
+
+</ng-template>
+
+
+<ng-template #selectedDatasetPreview let-layers="layers">
+
+  <ng-container *ngFor="let layer of layers">
+    <div class="hidden"
+      iav-dataset-preview-dataset-file
+      [iav-dataset-preview-dataset-file-kgid]="layer.datasetId"
+      [iav-dataset-preview-dataset-file-filename]="layer.filename"
+      #preview="iavDatasetPreviewDatasetFile">
+
+    </div>
+    <mat-chip class="pe-all"
+      (click)="handleChipClick()">
+      {{ layer.file?.name || layer.filename || 'Unknown data preview' }}
+      <mat-icon fontSet="fas" fontIcon="fa-times"
+        (click)="preview.onClick()"
+        iav-stop="click">
+      </mat-icon>
+    </mat-chip>
+  </ng-container>
+</ng-template>
+
+<!-- auto complete search box -->
+
+<ng-template #autocompleteTmpl>
+  <div class="iv-custom-comp bg card w-100 mat-elevation-z8 pe-all">
+    <region-text-search-autocomplete class="w-100 pt-2 flex-shrink-0 flex-grow-0">
+    </region-text-search-autocomplete>
+  </div>
+</ng-template>
+
+
+<!-- template for rendering tab -->
+<ng-template #tabTmpl
+  let-isOpen="isOpen"
+  let-regionSelected="regionSelected"
+  let-iavAdditionallayers="iavAdditionallayers">
+
+  <!-- if mat drawer is open -->
+  <ng-template [ngIf]="isOpen" [ngIfElse]="tabTmpl_closedTmpl">
+    <ng-container *ngTemplateOutlet="tabTmpl_defaultTmpl; context: {
+      matColor: 'basic',
+      fontIcon: 'fa-chevron-left'
+    }">
+    </ng-container>
+  </ng-template>
+
+  <!-- if matdrawer is closed -->
+  <ng-template #tabTmpl_closedTmpl>
+
+    <!-- if additional layers are being shown -->
+    <ng-template [ngIf]="iavAdditionallayers?.length > 0" [ngIfElse]="tabTmpl_noAdditionalLayers">
+      <ng-container *ngTemplateOutlet="tabTmpl_defaultTmpl; context: {
+        matColor: 'accent',
+        fontIcon: 'fa-database',
+        tooltip: 'Explore dataset preview'
+      }">
+      </ng-container>
+    </ng-template>
+
+    <!-- if additional layers not not being shown -->
+    <ng-template #tabTmpl_noAdditionalLayers>
+
+      <!-- if region selected > 0 -->
+      <ng-template [ngIf]="regionSelected?.length > 0" [ngIfElse]="tabTmpl_nothingSelected">
+        <div class="hidden"
+          iav-region
+          [region]="regionSelected[0]"
+          #tabTmpl_iavRegion="iavRegion">
+        </div>
+
+        <ng-container *ngTemplateOutlet="tabTmpl_defaultTmpl; context: {
+          matColor: 'accent',
+          customColor: tabTmpl_iavRegion.rgbString,
+          customColorDarkmode: tabTmpl_iavRegion.rgbDarkmode,
+          fontIcon: 'fa-brain',
+          tooltip: 'Explore ' + tabTmpl_iavRegion.region.name
+        }">
+
+        </ng-container>
+      </ng-template>
+
+      <!-- nothing is selected -->
+      <ng-template #tabTmpl_nothingSelected>
+        <ng-container *ngTemplateOutlet="tabTmpl_defaultTmpl; context: {
+          matColor: 'primary',
+          fontIcon: 'fa-sitemap',
+          tooltip: 'Explore regions'
+        }">
+        </ng-container>
+      </ng-template>
+    </ng-template>
+  </ng-template>
+
+  <ng-template #tabTmpl_defaultTmpl
+    let-matColor="matColor"
+    let-fontIcon="fontIcon"
+    let-customColor="customColor"
+    let-customColorDarkmode="customColorDarkmode"
+    let-tooltip="tooltip">
+    <!-- (click)="sideNavMasterSwitch.toggle()" -->
+    <button mat-raised-button
+      [attr.aria-label]="ARIA_LABELS.TOGGLE_SIDE_PANEL"
+      [matTooltip]="tooltip"
+      class="pe-all tab-toggle"
+      [ngClass]="{
+        'darktheme': customColorDarkmode === true,
+        'lighttheme': customColorDarkmode === false
+      }"
+      [style.backgroundColor]="customColor"
+      
+      [color]="(!customColor && matColor) ? matColor : null">
+
+      <span [ngClass]="{'iv-custom-comp  text': !!customColor}">
+        <i class="fas" [ngClass]="fontIcon || 'fa-question'"></i>
+      </span>
+    </button>
+  </ng-template>
+</ng-template>
+
+
+<!-- region sidenav tmpl -->
+<ng-template #sidenavRegionTmpl>
+
+  <!-- region search autocomplete  -->
+  <!-- [@openCloseAnchor]="sideNavFullLeftSwitch.switchState ? 'open' : 'closed'" -->
+  <div class="h-0 w-100 region-text-search-autocomplete-position">
+    <ng-container *ngTemplateOutlet="autocompleteTmpl">
+    </ng-container>
+  </div>
+
+  <div class="flex-shrink-1 flex-grow-1 d-flex flex-column"
+    [ngClass]="{'region-populated': (selectedRegions$ | async).length > 0 }">
+    <!-- region detail -->
+    <ng-container *ngIf="selectedRegions$ | async as selectedRegions; else selectRegionErrorTmpl">
+
+      <!-- single-region-wrapper -->
+      <ng-template [ngIf]="selectedRegions.length === 1" [ngIfElse]="multiRegionWrapperTmpl">
+        <!-- a series of bugs result in requiring this hacky -->
+        <!-- see https://github.com/HumanBrainProject/interactive-viewer/issues/698 -->
+        <ng-container *ngFor="let region of selectedRegions">
+          <ng-container *ngTemplateOutlet="singleRegionTmpl; context: { region: region }">
+          </ng-container>
+        </ng-container>
+      </ng-template>
+      
+      <!-- multi region wrapper -->
+      <ng-template #multiRegionWrapperTmpl>
+        <ng-container *ngTemplateOutlet="multiRegionTmpl; context: {
+          regions: selectedRegions
+        }">
+        </ng-container>
+        <!-- This is a wrapper for multiregion consisting of {{ selectedRegions.length }} regions -->
+      </ng-template>
+
+      <!-- place holder if length === 0 -->
+      <ng-container *ngIf="selectedRegions.length === 0">
+        <ng-container *ngTemplateOutlet="singleRegionTmpl; context: { region: false }">
+        </ng-container>
+      </ng-container>
+    </ng-container>
+
+    <div class="spacer">
+    </div>
+  </div>
+
+  <!-- collapse btn -->
+  <ng-container *ngTemplateOutlet="collapseBtn">
+  </ng-container>
+</ng-template>
+
+
+<!-- single region tmpl -->
+<ng-template #singleRegionTmpl let-region="region">
+  <!-- region detail -->
+  <ng-container *ngIf="region; else regionPlaceholderTmpl">
+    <region-menu
+      [showRegionInOtherTmpl]="false"
+      [region]="region"
+      class="bs-border-box ml-15px-n mr-15px-n mat-elevation-z4">
+    </region-menu>
+  </ng-container>
+
+  <!-- other region detail accordion -->
+  <mat-accordion *ngIf="region"
+    class="bs-border-box ml-15px-n mr-15px-n mt-2"
+    iav-region
+    [region]="region"
+    #iavRegion="iavRegion">
+
+    <!-- desc -->
+    <ng-container *ngFor="let ods of (region.originDatasets || [])">
+      <ng-template #regionDescTmpl>
+        <single-dataset-view
+          [hideTitle]="true"
+          [hideExplore]="true"
+          [hidePreview]="true"
+          [hidePinBtn]="true"
+          [hideDownloadBtn]="true"
+          [kgSchema]="ods.kgSchema"
+          [kgId]="ods.kgId">
+
+        </single-dataset-view>
+      </ng-template>
+      <ng-container *ngTemplateOutlet="ngMatAccordionTmpl; context: {
+        title: 'Description',
+        iconClass: 'fas fa-info',
+        iavNgIf: true,
+        content: regionDescTmpl
+      }">
+
+      </ng-container>
+    </ng-container>
+
+    <!-- Explore in other template -->
+    <ng-container *ngIf="iavRegion.regionInOtherTemplates$ | async as regionInOtherTemplates">
+
+      <ng-template #exploreInOtherTmpl>
+        <mat-card *ngFor="let sameRegion of regionInOtherTemplates"
+          class="p-0 border-0 box-shadow-none mt-1 tb-1 cursor-pointer" 
+          (click)="iavRegion.changeView(sameRegion)"
+          [matTooltip]="sameRegion.template.name + (sameRegion.hemisphere ? (' - ' + sameRegion.hemisphere) : '')"
+          mat-ripple>
+          <small>
+            {{ sameRegion.template.name + (sameRegion.hemisphere ? (' - ' + sameRegion.hemisphere) : '') }}
+          </small>
+        </mat-card>
+      </ng-template>
+
+      <ng-container *ngTemplateOutlet="ngMatAccordionTmpl; context: {
+        title: 'Explore in other templates',
+        desc: regionInOtherTemplates.length,
+        iconClass: 'fas fa-brain',
+        iconTooltip: regionInOtherTemplates.length | regionAccordionTooltipTextPipe : 'regionInOtherTmpl',
+        iavNgIf: regionInOtherTemplates.length,
+        content: exploreInOtherTmpl
+      }">
+
+
+      </ng-container>
+    </ng-container>
+
+    <!--  regional features-->
+    <ng-template #regionalFeaturesTmpl let-expansionPanel="expansionPanel">
+
+      <data-browser
+        *ngIf="expansionPanel.expanded" 
+        [disableVirtualScroll]="true"
+        [regions]="[region]">
+      </data-browser>
+    </ng-template>
+
+    <div class="hidden" iav-databrowser-directive
+      [regions]="[region]"
+      #iavDbDirective="iavDatabrowserDirective">
+    </div>
+
+    <!-- if dataset is loading -->
+    <ng-template
+      [ngIf]="iavDbDirective?.fetchingFlag"
+      [ngIfElse]="featureLoadedTmpl">
+      <div class="d-flex justify-content-center">
+        <spinner-cmp></spinner-cmp>
+      </div>
+    </ng-template>
+
+    <ng-template #featureLoadedTmpl>
+
+      <!-- place holder content, if no regional features or connectivity or change ref space options are available -->
+      <ng-template [ngIf]="iavDbDirective?.dataentries?.length === 0">
+        <ng-container *ngIf="parcellationSelected$ | async as selectedParcellation">
+          <ng-template [ngIf]="selectedParcellation?.hasAdditionalViewMode?.includes('connectivity')">
+            <div class="p-4">
+              {{ CONST.NO_ADDIONTAL_INFO_AVAIL }}
+            </div>
+          </ng-template>
+        </ng-container>
+      </ng-template>
+
+    </ng-template>
+
+
+    <ng-container *ngTemplateOutlet="ngMatAccordionTmpl; context: {
+      title: CONST.REGIONAL_FEATURES,
+      desc: iavDbDirective?.dataentries?.length,
+      iconClass: 'fas fa-database',
+      iconTooltip: iavDbDirective?.dataentries?.length | regionAccordionTooltipTextPipe : 'regionalFeatures',
+      iavNgIf: iavDbDirective?.dataentries?.length,
+      content: regionalFeaturesTmpl
+    }">
+    </ng-container>
+
+    <!-- Connectivity -->
+    <ng-container  *ngIf="parcellationSelected$ | async as selectedParcellation">
+
+      <ng-template #connectivityContentTmpl let-expansionPanel="expansionPanel">
+        <mat-card-content class="flex-grow-1 flex-shrink-1 w-100">
+          <ng-container *ngFor="let region of selectedRegions$ | async">
+            <connectivity-browser class="pe-all flex-shrink-1"
+              [region]="region"
+              [parcellationId]="selectedParcellation['@id']"
+              (setOpenState)="expansionPanel.expanded = $event"
+              [accordionExpanded]="expansionPanel.expanded">
+            </connectivity-browser>
+          </ng-container>
+        </mat-card-content>
+      </ng-template>
+  
+      <ng-container *ngTemplateOutlet="ngMatAccordionTmpl; context: {
+        title: 'Connectivity',
+        desc: connectedCounterDir.value,
+        iconClass: 'fas fa-braille',
+        iconTooltip: connectedCounterDir.value | regionAccordionTooltipTextPipe : 'connectivity',
+        iavNgIf: selectedParcellation?.hasAdditionalViewMode?.includes('connectivity'),
+        content: connectivityContentTmpl
+      }">
+      </ng-container>
+
+      <div class="w-0 h-0"
+        iav-counter
+        #connectedCounterDir="iavCounter">
+        <!-- TODO figure out why conn browser does not work here -->
+        <!-- @fsdavid, can you take a look why this component is not emitting connectivityNumberReceived event? -->
+        <connectivity-browser *ngIf="region && region.name"
+          class="d-block h-0 w-0 overflow-hidden"
+          [region]="region"
+          [parcellationId]="selectedParcellation['@id']"
+          [accordionExpanded]="true"
+          (connectivityNumberReceived)="connectedCounterDir.value = $event">
+          
+        </connectivity-browser>
+      </div>
+    </ng-container>
+
+  </mat-accordion>
+</ng-template>
+
+
+<!-- expansion tmpl -->
+<ng-template #ngMatAccordionTmpl
+  let-title="title"
+  let-desc="desc"
+  let-iconClass="iconClass"
+  let-iconTooltip="iconTooltip"
+  let-iavNgIf="iavNgIf"
+  let-content="content">
+  <mat-expansion-panel
+    [attr.data-opened]="expansionPanel.expanded"
+    [attr.data-mat-expansion-title]="title"
+    hideToggle
+    *ngIf="iavNgIf"
+    #expansionPanel="matExpansionPanel">
+
+    <mat-expansion-panel-header>
+
+      <!-- title -->
+      <mat-panel-title>
+        {{ title }}
+      </mat-panel-title>
+
+      <!-- desc + icon -->
+      <mat-panel-description class="d-flex align-items-center justify-content-end"
+        [matTooltip]="iconTooltip">
+        <span class="mr-3">{{ desc }}</span>
+        <span class="accordion-icon d-inline-flex justify-content-center">
+          <i [class]="iconClass"></i>
+        </span>
+      </mat-panel-description>
+
+    </mat-expansion-panel-header>
+
+    <!-- content -->
+    <ng-container *ngTemplateOutlet="content; context: { expansionPanel: expansionPanel }">
+    </ng-container>
+  </mat-expansion-panel>
+</ng-template>
+
+<!-- TODO deprecate in favour of dedicated dataset preview side nav -->
+<ng-template #sidenavDsPreviewTmpl let-file="file" let-filename="filename" let-datasetId="datasetId">
+  <div class="w-100 flex-grow-1 d-flex flex-column">
+
+    <preview-card class="d-block bs-border-box ml-15px-n mr-15px-n flex-grow-1"
+      [attr.aria-label]="ARIA_LABELS.ADDITIONAL_VOLUME_CONTROL"
+      [datasetId]="datasetId"
+      [filename]="filename">
+    </preview-card>
+
+    <!-- collapse btn -->
+    <ng-container *ngTemplateOutlet="collapseBtn">
+    </ng-container>
+  </div>
+</ng-template>
+
+<!-- select region error... for whatever reason -->
+<ng-template #selectRegionErrorTmpl>
+  SELECT REGION ERROR
+</ng-template>
+
+
+<!-- multi region tmpl -->
+<ng-template #multiRegionTmpl let-regions="regions">
+  <ng-template [ngIf]="regions.length > 0" [ngIfElse]="regionPlaceholderTmpl">
+    <region-menu
+      [showRegionInOtherTmpl]="false"
+      [region]="{
+        name: CONST.MULTI_REGION_SELECTION
+      }"
+      class="bs-border-box ml-15px-n mr-15px-n mat-elevation-z4">
+    </region-menu>
+
+    <!-- other regions detail accordion -->
+    <mat-accordion class="bs-border-box ml-15px-n mr-15px-n mt-2">
+
+      <!--  regional features-->
+      <ng-template #regionalFeaturesTmpl>
+        <data-browser
+          [disableVirtualScroll]="true"
+          [regions]="regions">
+        </data-browser>
+      </ng-template>
+
+      <div class="hidden"
+        iav-databrowser-directive
+        [regions]="regions"
+        #iavDbDirective="iavDatabrowserDirective">
+      </div>
+  
+      <ng-container *ngTemplateOutlet="ngMatAccordionTmpl; context: {
+        title: CONST.REGIONAL_FEATURES,
+        desc: iavDbDirective?.dataentries?.length,
+        iconClass: 'fas fa-database',
+        iconTooltip: iavDbDirective?.dataentries?.length | regionAccordionTooltipTextPipe : 'regionalFeatures',
+        iavNgIf: iavDbDirective?.dataentries?.length,
+        content: regionalFeaturesTmpl
+      }">
+      </ng-container>
+
+      <!-- Multi regions include -->
+      <ng-template #multiRegionInclTmpl>
+        <mat-chip-list>
+          <mat-chip *ngFor="let r of regions"
+            iav-region
+            [region]="r"
+            [ngClass]="{
+              'darktheme':regionDirective.rgbDarkmode === true,
+              'lighttheme': regionDirective.rgbDarkmode === false
+            }"
+            [style.backgroundColor]="regionDirective.rgbString"
+            #regionDirective="iavRegion">
+            <span class="iv-custom-comp text text-truncate d-inline pl-4">
+              {{ r.name }}
+            </span>
+          </mat-chip>
+        </mat-chip-list>
+      </ng-template>
+      
+      <ng-container *ngTemplateOutlet="ngMatAccordionTmpl; context: {
+        title: 'Brain regions',
+        desc: regions.length,
+        iconClass: 'fas fa-brain',
+        iavNgIf: true,
+        content: multiRegionInclTmpl
+      }">
+      </ng-container>
+
+    </mat-accordion>
+  </ng-template>
+</ng-template>
+
+<!-- collapse btn -->
+<ng-template #collapseBtn>
+
+  <div class="h-0 w-100 collapse-position d-flex flex-column justify-content-end align-items-center">
+    
+    <button mat-raised-button class="mat-elevation-z8"
+      [attr.aria-label]="ARIA_LABELS.COLLAPSE"
+      (click)="sideNavFullLeftSwitch.close()"  
+      color="basic">
+      <i class="fas fa-chevron-up"></i>
+      <span>
+        collapse
+      </span>
+    </button>
+  </div>
+</ng-template>
+
+<!-- region tmpl placeholder -->
+<ng-template #regionPlaceholderTmpl>
+  <div class="placeholder-region-detail bs-border-box ml-15px-n mr-15px-n mat-elevation-z4">
+    <span class="text-muted">
+      Select a region by clicking on the viewer or search from above
+    </span>
+  </div>
+</ng-template>
\ No newline at end of file
diff --git a/webpack.aot.js b/webpack/webpack.aot.js
similarity index 92%
rename from webpack.aot.js
rename to webpack/webpack.aot.js
index f11f39b77e09aed04a563bfc245221c1c4b14491..15b1f95e5e5e1b658e16caf3361cf30b2161bda5 100644
--- a/webpack.aot.js
+++ b/webpack/webpack.aot.js
@@ -16,7 +16,7 @@ module.exports = merge(staticAssets, {
   },
   output : {
     filename : '[name].js',
-    path : path.resolve(__dirname,'dist/aot')
+    path : path.resolve(__dirname,'../dist/aot')
   },
   module: {
     rules: [
@@ -83,8 +83,8 @@ module.exports = merge(staticAssets, {
       '.json'
     ],
     alias : {
-      "third_party" : path.resolve(__dirname,'third_party'),
-      "src" : path.resolve(__dirname,'src')
+      "third_party" : path.resolve(__dirname,'../third_party'),
+      "src" : path.resolve(__dirname,'../src')
     }
   }
 })
\ No newline at end of file
diff --git a/webpack.common.js b/webpack/webpack.common.js
similarity index 72%
rename from webpack.common.js
rename to webpack/webpack.common.js
index 52e987bddbf7f90d2b16f55ff9b4a16b0b221953..a84b8489c97ef4b52e9350d7bf04f1643f22ae55 100644
--- a/webpack.common.js
+++ b/webpack/webpack.common.js
@@ -21,7 +21,7 @@ module.exports = {
     ]
   },
   plugins : [
-    new webpack.ContextReplacementPlugin(/@angular(\\|\/)core(\\|\/)/,path.join(__dirname,'src'))
+    new webpack.ContextReplacementPlugin(/@angular(\\|\/)core(\\|\/)/,path.join(__dirname, '../src'))
   ],
   resolve : {
     extensions : [
@@ -30,10 +30,10 @@ module.exports = {
       '.json'
     ],
     alias : {
-      "third_party" : path.resolve(__dirname,'third_party'),
-      "src" : path.resolve(__dirname,'src'),
-      "common": path.resolve(__dirname, 'common'),
-      "spec": path.resolve(__dirname, 'spec')
+      "third_party" : path.resolve(__dirname, '../third_party'),
+      "src" : path.resolve(__dirname, '../src'),
+      "common": path.resolve(__dirname, '../common'),
+      "spec": path.resolve(__dirname, '../spec')
     }
   },
 }
\ No newline at end of file
diff --git a/webpack.dev-aot.js b/webpack/webpack.dev-aot.js
similarity index 92%
rename from webpack.dev-aot.js
rename to webpack/webpack.dev-aot.js
index 6ddd24edaa01173f6394865aa80b944a11bba63d..ca332572fe1a3347891d966cd05052ec5949987f 100644
--- a/webpack.dev-aot.js
+++ b/webpack/webpack.dev-aot.js
@@ -16,7 +16,7 @@ module.exports = merge(staticAssets, {
   },
   output : {
     filename : '[name].js',
-    path : path.resolve(__dirname,'dist/aot')
+    path : path.resolve(__dirname,'../dist/aot')
   },
   devtool:'source-map',
   module: {
@@ -77,8 +77,8 @@ module.exports = merge(staticAssets, {
       '.json'
     ],
     alias : {
-      "third_party" : path.resolve(__dirname,'third_party'),
-      "src" : path.resolve(__dirname,'src')
+      "third_party" : path.resolve(__dirname, '../third_party'),
+      "src" : path.resolve(__dirname, '../src')
     }
   }
 })
diff --git a/webpack.dev.js b/webpack/webpack.dev.js
similarity index 92%
rename from webpack.dev.js
rename to webpack/webpack.dev.js
index d32be20fe85174ca5ae969f2d1b99ca43d87558b..2a4fcf203ea57027ecfc6f8c5e0b3ccdb58453cd 100644
--- a/webpack.dev.js
+++ b/webpack/webpack.dev.js
@@ -12,7 +12,7 @@ module.exports = merge(common,ngAssets,staticAssets,{
   mode : 'development',
   output : {
     filename : '[name].js',
-    path : path.resolve(__dirname,'dist/dev')
+    path : path.resolve(__dirname,'../dist/dev')
   },
   devtool:'source-map',
 
diff --git a/webpack.export.aot.js b/webpack/webpack.export.aot.js
similarity index 94%
rename from webpack.export.aot.js
rename to webpack/webpack.export.aot.js
index fda5c27b38cc2f8a9208ea0db0b72110359510ab..2612d09449efa54b3a1e4f3bbbd16aceb4744c4b 100644
--- a/webpack.export.aot.js
+++ b/webpack/webpack.export.aot.js
@@ -10,7 +10,7 @@ module.exports = {
   entry : './src/main-aot.ts',
   output : {
     filename : 'main.js',
-    path : path.resolve(__dirname,'dist/export-aot')
+    path : path.resolve(__dirname,'../dist/export-aot')
   },
   module: {
     rules: [
diff --git a/webpack.export.js b/webpack/webpack.export.js
similarity index 93%
rename from webpack.export.js
rename to webpack/webpack.export.js
index d6cc210c905ec7c59a9a8dd123019e407e3a69c5..1276bc1b5a12de4d22e98f5f17ffed32c6a38c25 100644
--- a/webpack.export.js
+++ b/webpack/webpack.export.js
@@ -10,7 +10,7 @@ module.exports = merge(common,ngAssets,{
   mode : 'development',
   output : {
     filename : 'export.js',
-    path : path.resolve(__dirname,'dist/export')
+    path : path.resolve(__dirname,'../dist/export')
   },
   devtool:'source-map',
   plugins : [
diff --git a/webpack.export.min.js b/webpack/webpack.export.min.js
similarity index 92%
rename from webpack.export.min.js
rename to webpack/webpack.export.min.js
index eff53e1cc79c6f71a3a5eb7ce80ba546cdaa02c9..deefdbceeb145418c988df256b4fb85606dd4e7a 100644
--- a/webpack.export.min.js
+++ b/webpack/webpack.export.min.js
@@ -9,7 +9,7 @@ module.exports = merge(common,ngAssets,{
   entry : './src/atlasViewerExports/main.export.ts',
   output : {
     filename : 'export.js',
-    path : path.resolve(__dirname,'dist/export-min')
+    path : path.resolve(__dirname,'../dist/export-min')
   },
   plugins : [
     new ClosureCompilerPlugin({
diff --git a/webpack.ngassets.js b/webpack/webpack.ngassets.js
similarity index 100%
rename from webpack.ngassets.js
rename to webpack/webpack.ngassets.js
diff --git a/webpack.prod.js b/webpack/webpack.prod.js
similarity index 93%
rename from webpack.prod.js
rename to webpack/webpack.prod.js
index 1119c6948c84f0b87eeb626acd7a1b4ba779f97d..325cdd3de8dfd4631952fe887994ab13bd5000f5 100644
--- a/webpack.prod.js
+++ b/webpack/webpack.prod.js
@@ -11,7 +11,7 @@ module.exports = merge(common,ngAssets,staticAssets,{
   entry : './src/main.ts',
   output : {
     filename : 'main.js',
-    path : path.resolve(__dirname,'dist/prod')
+    path : path.resolve(__dirname,'../dist/prod')
   },
   plugins : [
     new ClosureCompilerPlugin({
diff --git a/webpack.staticassets.js b/webpack/webpack.staticassets.js
similarity index 100%
rename from webpack.staticassets.js
rename to webpack/webpack.staticassets.js
diff --git a/webpack.test.js b/webpack/webpack.test.js
similarity index 100%
rename from webpack.test.js
rename to webpack/webpack.test.js