diff --git a/src/atlasViewer/atlasViewer.component.ts b/src/atlasViewer/atlasViewer.component.ts
index c220280cf6e8e3619d89bbb45e5f0d6251beae87..aad2b38644b0bc369b83e60917b576fc7adda7c5 100644
--- a/src/atlasViewer/atlasViewer.component.ts
+++ b/src/atlasViewer/atlasViewer.component.ts
@@ -67,8 +67,8 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit {
   private showHelp$: Observable<any>
 
   public dedicatedView$: Observable<string | null>
-  public onhoverSegment$: Observable<string>
-  public onhoverSegmentForFixed$: Observable<string>
+  public onhoverSegments$: Observable<string[]>
+  public onhoverSegmentsForFixed$: Observable<string[]>
   public onhoverLandmark$ : Observable<string | null>
   private subscriptions: Subscription[] = []
 
@@ -179,23 +179,23 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit {
     )
 
     // TODO temporary hack. even though the front octant is hidden, it seems if a mesh is present, hover will select the said mesh
-    this.onhoverSegment$ = combineLatest(
+    this.onhoverSegments$ = combineLatest(
       this.store.pipe(
         select('uiState'),
+        select('mouseOverSegments'),
+        filter(v => !!v),
+        distinctUntilChanged((o, n) => o.length === n.length && n.every(segment => o.find(oSegment => oSegment.layer.name === segment.layer.name && oSegment.segment === segment.segment) ) )
         /* cannot filter by state, as the template expects a default value, or it will throw ExpressionChangedAfterItHasBeenCheckedError */
-        map(state => state
-            && state.mouseOverSegment
-            && (isNaN(state.mouseOverSegment)
-              ? state.mouseOverSegment
-              : state.mouseOverSegment.toString())),
-        distinctUntilChanged((o, n) => o === n || (o && n && o.name && n.name && o.name === n.name))
+
       ),
       this.onhoverLandmark$
     ).pipe(
-      map(([segment, onhoverLandmark]) => onhoverLandmark ? null : segment )
+      map(([segments, onhoverLandmark]) => onhoverLandmark ? null : segments ),
+      map(segments => segments.length === 0
+          ? null
+          : segments.map(s => s.segment) )
     )
 
-
     this.selectedParcellation$ = this.store.pipe(
       select('viewerState'),
       safeFilter('parcellationSelected'),
@@ -338,9 +338,9 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit {
       })
     })
 
-    this.onhoverSegmentForFixed$ = this.rClContextualMenu.onShow.pipe(
-      withLatestFrom(this.onhoverSegment$),
-      map(([_flag, onhoverSegment]) => onhoverSegment)
+    this.onhoverSegmentsForFixed$ = this.rClContextualMenu.onShow.pipe(
+      withLatestFrom(this.onhoverSegments$),
+      map(([_flag, onhoverSegments]) => onhoverSegments || [])
     )
   }
 
diff --git a/src/atlasViewer/atlasViewer.template.html b/src/atlasViewer/atlasViewer.template.html
index c3828d3a89c7e36849915a581753ce76de76ac34..caab40d3ed81ca5eeba00e6160ffaaeac90ed258 100644
--- a/src/atlasViewer/atlasViewer.template.html
+++ b/src/atlasViewer/atlasViewer.template.html
@@ -142,7 +142,7 @@
         </div>
         <div body>
           <div
-            *ngIf="onhoverSegmentForFixed$ | async; let onhoverSegmentFixed"
+            *ngFor="let onhoverSegmentFixed of (onhoverSegmentsForFixed$ | async)"
             (click)="searchRegion([onhoverSegmentFixed])"
             class="ws-no-wrap text-left pe-all btn btn-sm btn-secondary btn-block"
             data-toggle="tooltip" 
@@ -160,7 +160,7 @@
           
           <div
             class="p-2 text-muted"
-            *ngIf="!(onhoverSegmentForFixed$ | async) && (selectedRegions$ | async)?.length === 0">
+            *ngIf="(onhoverSegmentsForFixed$ | async)?.length === 0 && (selectedRegions$ | async)?.length === 0">
             Right click on a parcellation region or select parcellation regions to search KG for associated datasets.
           </div>
   
@@ -182,9 +182,12 @@
           {{ onhoverLandmark$ | async }} <i><small class = "mute-text">{{ toggleMessage }}</small></i>
         </div>
         <div 
-          *ngIf="onhoverSegment$ | async; let onhoverSegment" 
+          *ngIf="onhoverSegments$ | async; let onhoverSegments"
           contextualBlock>
-          {{ onhoverSegment.name }} <i><small class = "mute-text">{{ toggleMessage }}</small></i>
+          <div *ngFor="let segment of onhoverSegments">
+            {{ segment.name || segment }}
+          </div>
+          <i><small class = "mute-text">{{ toggleMessage }}</small></i>
         </div>
         <!-- TODO Potentially implementing plugin contextual info -->
       </div>
diff --git a/src/atlasViewer/atlasViewer.urlService.service.ts b/src/atlasViewer/atlasViewer.urlService.service.ts
index 5cd06b1ba499e34537cce32dc2caa872250c53a3..b548c96f292bfa89fa808beccd7b2c5b16778a2a 100644
--- a/src/atlasViewer/atlasViewer.urlService.service.ts
+++ b/src/atlasViewer/atlasViewer.urlService.service.ts
@@ -1,12 +1,13 @@
 import { Injectable } from "@angular/core";
 import { Store, select } from "@ngrx/store";
-import { ViewerStateInterface, isDefined, NEWVIEWER, getLabelIndexMap, SELECT_REGIONS, CHANGE_NAVIGATION, ADD_NG_LAYER } from "../services/stateStore.service";
+import { ViewerStateInterface, isDefined, NEWVIEWER, CHANGE_NAVIGATION, ADD_NG_LAYER, generateLabelIndexId } from "../services/stateStore.service";
 import { PluginInitManifestInterface } from 'src/services/state/pluginState.store'
 import { Observable,combineLatest } from "rxjs";
 import { filter, map, scan, distinctUntilChanged, skipWhile, take } from "rxjs/operators";
 import { PluginServices } from "./atlasViewer.pluginService.service";
 import { AtlasViewerConstantsServices } from "./atlasViewer.constantService.service";
 import { ToastService } from "src/services/toastService.service";
+import { SELECT_REGIONS_WITH_ID } from "src/services/state/viewerState.store";
 
 declare var window
 
@@ -147,14 +148,13 @@ export class AtlasViewerURLService{
         /**
          * either or both parcellationToLoad and .regions maybe empty
          */
-        const labelIndexMap = getLabelIndexMap(parcellationToLoad.regions)
-        const selectedRegions = searchparams.get('regionsSelected')
-        if(selectedRegions){
+        const selectedRegionsParam = searchparams.get('regionsSelected')
+        if(selectedRegionsParam){
+          const ids = selectedRegionsParam.split('_')
+
           this.store.dispatch({
-            type : SELECT_REGIONS,
-            selectRegions : selectedRegions.split('_')
-              .map(labelIndex=>labelIndexMap.get(Number(labelIndex)))
-              .filter(region => !!region)
+            type : SELECT_REGIONS_WITH_ID,
+            selectRegionIds: ids
           })
         }
       }
@@ -223,7 +223,7 @@ export class AtlasViewerURLService{
                   }
                   break;
                 case 'regionsSelected':
-                  _[key] = state[key].map(region=>region.labelIndex).join('_')
+                  _[key] = state[key].map(({ ngId, labelIndex })=> generateLabelIndexId({ ngId,labelIndex })).join('_')
                   break;
                 case 'templateSelected':
                 case 'parcellationSelected':
diff --git a/src/services/state/uiState.store.ts b/src/services/state/uiState.store.ts
index bdf52506daf64fe0cc2d9da4352dad9fe25fbcee..fadd5b87fcc506e504ff011a429675648d85c303 100644
--- a/src/services/state/uiState.store.ts
+++ b/src/services/state/uiState.store.ts
@@ -4,6 +4,7 @@ const agreedCookieKey = 'agreed-cokies'
 const aggredKgTosKey = 'agreed-kg-tos'
 
 const defaultState : UIStateInterface = {
+  mouseOverSegments: [],
   mouseOverSegment: null,
   mouseOverLandmark: null,
   focusedSidePanel: null,
@@ -18,6 +19,12 @@ const defaultState : UIStateInterface = {
 
 export function uiState(state:UIStateInterface = defaultState,action:UIAction){
   switch(action.type){
+    case MOUSE_OVER_SEGMENTS:
+      const { segments } = action
+      return {
+        ...state,
+        mouseOverSegments: segments
+      }
     case MOUSE_OVER_SEGMENT:
       return {
         ...state,
@@ -71,6 +78,12 @@ export function uiState(state:UIStateInterface = defaultState,action:UIAction){
 }
 
 export interface UIStateInterface{
+  mouseOverSegments: {
+    layer: {
+      name: string
+    }
+    segment: any | null
+  }[]
   sidePanelOpen : boolean
   mouseOverSegment : any | number
   mouseOverLandmark : any 
@@ -81,12 +94,19 @@ export interface UIStateInterface{
 }
 
 export interface UIAction extends Action{
-  segment : any | number
-  landmark : any
+  segment: any | number
+  landmark: any
   focusedSidePanel? : string
+  segments?:{
+    layer: {
+      name: string
+    }
+    segment: any | null
+  }[]
 }
 
 export const MOUSE_OVER_SEGMENT = `MOUSE_OVER_SEGMENT`
+export const MOUSE_OVER_SEGMENTS = `MOUSE_OVER_SEGMENTS`
 export const MOUSE_OVER_LANDMARK = `MOUSE_OVER_LANDMARK`
 
 export const TOGGLE_SIDE_PANEL = 'TOGGLE_SIDE_PANEL'
diff --git a/src/services/state/viewerState.store.ts b/src/services/state/viewerState.store.ts
index a8ff3fdaade1c41dbd7b6f46215f7caabc400526..2911c629efca453118989b70ec484730ccc530dd 100644
--- a/src/services/state/viewerState.store.ts
+++ b/src/services/state/viewerState.store.ts
@@ -1,5 +1,6 @@
 import { Action } from '@ngrx/store'
 import { UserLandmark } from 'src/atlasViewer/atlasViewer.apiService.service';
+import { getNgIdLabelIndexFromId, generateLabelIndexId, recursiveFindRegionWithLabelIndexId, propagateNgId } from '../stateStore.service';
 
 export interface ViewerStateInterface{
   fetchedTemplates : any[]
@@ -20,7 +21,8 @@ export interface AtlasAction extends Action{
 
   selectTemplate? : any
   selectParcellation? : any
-  selectRegions? : any[]
+  selectRegions?: any[]
+  selectRegionIds: string[]
   deselectRegions? : any[]
   dedicatedView? : string
 
@@ -57,10 +59,12 @@ export function viewerState(
           : []
       }
     case NEWVIEWER:
+      const { selectParcellation } = action
+      const parcellation = propagateNgId( selectParcellation )
       return {
         ...state,
         templateSelected : action.selectTemplate,
-        parcellationSelected : action.selectParcellation,
+        parcellationSelected : parcellation,
         regionsSelected : [],
         landmarksSelected : [],
         navigation : {},
@@ -79,27 +83,53 @@ export function viewerState(
       }
     }
     case SELECT_PARCELLATION : {
+      const { selectParcellation } = action
+      const parcellation = propagateNgId( selectParcellation )
       return {
         ...state,
-        parcellationSelected : action.selectParcellation,
-        regionsSelected : []
+        parcellationSelected: parcellation,
+        regionsSelecteds: []
       }
     }
-    case DESELECT_REGIONS : {
+    case SELECT_REGIONS:
+      const { selectRegions } = action
       return {
         ...state,
-        regionsSelected : state.regionsSelected.filter(re => action.deselectRegions.findIndex(dRe => dRe.name === re.name) < 0)
+        regionsSelected: selectRegions
       }
-    }
-    case SELECT_REGIONS : {
-      return {
-        ...state,
-        regionsSelected : action.selectRegions.map(region => {
+    case SELECT_REGIONS_WITH_ID : {
+      const { parcellationSelected } = state
+      const { selectRegionIds } = action
+      const { ngId: defaultNgId } = parcellationSelected
+
+      /**
+       * for backwards compatibility.
+       * older versions of atlas viewer may only have labelIndex as region identifier
+       */
+      const regionsSelected = selectRegionIds
+        .map(labelIndexId => getNgIdLabelIndexFromId({ labelIndexId }))
+        .map(({ ngId, labelIndex }) => {
           return {
-            ...region,
-            labelIndex: Number(region.labelIndex)
+            labelIndexId: generateLabelIndexId({
+              ngId: ngId || defaultNgId,
+              labelIndex 
+            })
           }
         })
+        .map(({ labelIndexId }) => {
+          return recursiveFindRegionWithLabelIndexId({ 
+            regions: parcellationSelected.regions,
+            labelIndexId,
+            inheritedNgId: defaultNgId
+          })
+        })
+        .filter(v => {
+          if (!v) console.log(`SELECT_REGIONS_WITH_ID, some ids cannot be parsed intto label index`)
+          return !!v
+        })
+      return {
+        ...state,
+        regionsSelected
       }
     }
     case DESELECT_LANDMARKS : {
@@ -135,7 +165,7 @@ export const CHANGE_NAVIGATION = 'CHANGE_NAVIGATION'
 
 export const SELECT_PARCELLATION = `SELECT_PARCELLATION`
 export const SELECT_REGIONS = `SELECT_REGIONS`
-export const DESELECT_REGIONS = `DESELECT_REGIONS`
+export const SELECT_REGIONS_WITH_ID = `SELECT_REGIONS_WITH_ID`
 export const SELECT_LANDMARKS = `SELECT_LANDMARKS`
 export const DESELECT_LANDMARKS = `DESELECT_LANDMARKS`
 export const USER_LANDMARKS = `USER_LANDMARKS`
diff --git a/src/services/stateStore.service.ts b/src/services/stateStore.service.ts
index 18c1a547e5f963ab03db7be7f92e79b0ffc37649..5bcd42ed9acd371ec4f5bc1ce223308ee44bdc9f 100644
--- a/src/services/stateStore.service.ts
+++ b/src/services/stateStore.service.ts
@@ -3,7 +3,7 @@ import { filter } from 'rxjs/operators';
 export { viewerConfigState } from './state/viewerConfig.store'
 export { pluginState } from './state/pluginState.store'
 export { NgViewerAction, NgViewerStateInterface, ngViewerState, ADD_NG_LAYER, FORCE_SHOW_SEGMENT, HIDE_NG_LAYER, REMOVE_NG_LAYER, SHOW_NG_LAYER } from './state/ngViewerState.store'
-export { CHANGE_NAVIGATION, AtlasAction, DESELECT_LANDMARKS, DESELECT_REGIONS, FETCHED_TEMPLATE, NEWVIEWER, SELECT_LANDMARKS, SELECT_PARCELLATION, SELECT_REGIONS, USER_LANDMARKS, ViewerStateInterface, viewerState } from './state/viewerState.store'
+export { CHANGE_NAVIGATION, AtlasAction, DESELECT_LANDMARKS, FETCHED_TEMPLATE, NEWVIEWER, SELECT_LANDMARKS, SELECT_PARCELLATION, SELECT_REGIONS, USER_LANDMARKS, ViewerStateInterface, viewerState } from './state/viewerState.store'
 export { DataEntry, ParcellationRegion, DataStateInterface, DatasetAction, FETCHED_DATAENTRIES, FETCHED_METADATA, FETCHED_SPATIAL_DATA, Landmark, OtherLandmarkGeometry, PlaneLandmarkGeometry, PointLandmarkGeometry, Property, Publication, ReferenceSpace, dataStore, File, FileSupplementData } from './state/dataStore.store'
 export { CLOSE_SIDE_PANEL, MOUSE_OVER_LANDMARK, MOUSE_OVER_SEGMENT, OPEN_SIDE_PANEL, TOGGLE_SIDE_PANEL, UIAction, UIStateInterface, uiState } from './state/uiState.store'
 export { SPATIAL_GOTO_PAGE, SpatialDataEntries, SpatialDataStateInterface, UPDATE_SPATIAL_DATA, spatialSearchState } from './state/spatialSearchState.store'
@@ -25,6 +25,63 @@ export function extractLabelIdx(region:any):number[]{
   },[]).concat( region.labelIndex ? Number(region.labelIndex) : [] )
 }
 
+const inheritNgId = (region:any) => {
+  const {ngId = 'root', children = []} = region
+  return {
+    ngId,
+    ...region,
+    ...(children && children.map
+      ? {
+        children: children.map(c => inheritNgId({
+          ngId,
+          ...c
+        }))
+      }
+      : {})
+  }
+}
+
+export function getMultiNgIdsRegionsLabelIndexMap(parcellation: any = {}):Map<string,Map<number, any>>{
+  const map:Map<string,Map<number, any>> = new Map()
+  const { ngId = 'root'} = parcellation
+
+  const processRegion = (region:any) => {
+    const { ngId } = region
+    const existingMap = map.get(ngId)
+    const labelIndex = Number(region.labelIndex)
+    if (labelIndex) {
+      if (!existingMap) {
+        const newMap = new Map()
+        newMap.set(labelIndex, region)
+        map.set(ngId, newMap)
+      } else {
+        existingMap.set(labelIndex, region)
+      }
+    }
+
+    if (region.children && region.children.forEach) {
+      region.children.forEach(child => {
+        processRegion({
+          ngId,
+          ...child
+        })
+      })
+    }
+  }
+
+  if (parcellation && parcellation.regions && parcellation.regions.forEach) {
+    parcellation.regions.forEach(r => processRegion({
+      ngId,
+      ...r
+    }))
+  }
+
+  return map
+}
+
+/**
+ * labelIndexMap maps label index to region
+ */
 export function getLabelIndexMap(regions:any[]):Map<number,any>{
   const returnMap = new Map()
 
@@ -38,7 +95,16 @@ export function getLabelIndexMap(regions:any[]):Map<number,any>{
 
   reduceRegions(regions)
   return returnMap
-} 
+}
+
+export function getNgIds(regions: any[]): string[]{
+  return regions && regions.map
+    ? regions
+        .map(r => [r.ngId, ...getNgIds(r.children)])
+        .reduce((acc, item) => acc.concat(item), [])
+        .filter(ngId => !!ngId)
+    : []
+}
 
 export interface DedicatedViewState{
   dedicatedView : string | null
@@ -47,3 +113,61 @@ export interface DedicatedViewState{
 export function isDefined(obj){
   return typeof obj !== 'undefined' && obj !== null
 }
+
+export function generateLabelIndexId({ ngId, labelIndex }) {
+  return `${ngId}#${labelIndex}`
+}
+
+export function getNgIdLabelIndexFromId({ labelIndexId } = {labelIndexId: ''}) {
+  const _ = labelIndexId && labelIndexId.split && labelIndexId.split('#') || []
+  const ngId = _.length > 1
+    ? _[0]
+    : null
+  const labelIndex = _.length > 1
+    ? Number(_[1])
+    : _.length === 0
+      ? null
+      : Number(_[0])
+  return { ngId, labelIndex }
+}
+
+const recursiveFlatten = (region, {ngId}) => {
+  return [{
+    ngId,
+    ...region
+  }].concat(
+    ...((region.children && region.children.map && region.children.map(c => recursiveFlatten(c, { ngId : region.ngId || ngId })) )|| [])
+  )
+}
+
+export function recursiveFindRegionWithLabelIndexId({ regions, labelIndexId, inheritedNgId = 'root' }: {regions: any[], labelIndexId: string, inheritedNgId:string}) {
+  const { ngId, labelIndex } = getNgIdLabelIndexFromId({ labelIndexId })
+  const fr1 = regions.map(r => recursiveFlatten(r,{ ngId: inheritedNgId }))
+  const fr2 = fr1.reduce((acc, curr) => acc.concat(...curr), [])
+  const found = fr2.find(r => r.ngId === ngId && Number(r.labelIndex) === Number(labelIndex))
+  if (found) return found
+  debugger
+  return null
+}
+
+export function propagateNgId(parcellation) {
+  const recursivePropagateNgId = (region, {ngId}) => {
+    return {
+      ngId,
+      ...region,
+      ...( region.children && region.children.map
+        ? {
+          children: region.children.map(c => recursivePropagateNgId(c, { ngId: region.ngId || ngId }))
+        }
+        : {} )
+    }
+  }
+  const regions = parcellation.regions && parcellation.regions.map
+    ? parcellation.regions.map(r => recursivePropagateNgId(r, { ngId: parcellation.ngId }))
+    : []
+
+  return {
+    ...parcellation,
+    regions
+  }
+}
\ No newline at end of file
diff --git a/src/ui/nehubaContainer/nehubaContainer.component.ts b/src/ui/nehubaContainer/nehubaContainer.component.ts
index 146d7a44649df836cdbbc57bf6b93d38e3fcda59..21cf79327d3d41222895e53c0f4e6f737cff494c 100644
--- a/src/ui/nehubaContainer/nehubaContainer.component.ts
+++ b/src/ui/nehubaContainer/nehubaContainer.component.ts
@@ -1,16 +1,17 @@
 import { Component, ViewChild, ViewContainerRef, ComponentFactoryResolver, ComponentFactory, ComponentRef, OnInit, OnDestroy, ElementRef } from "@angular/core";
 import { NehubaViewerUnit } from "./nehubaViewer/nehubaViewer.component";
 import { Store, select } from "@ngrx/store";
-import { ViewerStateInterface, safeFilter, SELECT_REGIONS, getLabelIndexMap, CHANGE_NAVIGATION, isDefined, MOUSE_OVER_SEGMENT, USER_LANDMARKS, ADD_NG_LAYER, REMOVE_NG_LAYER, NgViewerStateInterface, MOUSE_OVER_LANDMARK, SELECT_LANDMARKS, Landmark, PointLandmarkGeometry, PlaneLandmarkGeometry, OtherLandmarkGeometry } from "../../services/stateStore.service";
+import { ViewerStateInterface, safeFilter, CHANGE_NAVIGATION, isDefined, USER_LANDMARKS, ADD_NG_LAYER, REMOVE_NG_LAYER, NgViewerStateInterface, MOUSE_OVER_LANDMARK, SELECT_LANDMARKS, Landmark, PointLandmarkGeometry, PlaneLandmarkGeometry, OtherLandmarkGeometry, getNgIds, getMultiNgIdsRegionsLabelIndexMap, generateLabelIndexId } from "../../services/stateStore.service";
 import { Observable, Subscription, fromEvent, combineLatest, merge } from "rxjs";
 import { filter,map, take, scan, debounceTime, distinctUntilChanged, switchMap, skip, withLatestFrom, buffer, tap } from "rxjs/operators";
 import { AtlasViewerAPIServices, UserLandmark } from "../../atlasViewer/atlasViewer.apiService.service";
 import { timedValues } from "../../util/generator";
-import { AtlasViewerDataService } from "../../atlasViewer/atlasViewer.dataService.service";
 import { AtlasViewerConstantsServices } from "../../atlasViewer/atlasViewer.constantService.service";
 import { ViewerConfiguration } from "src/services/state/viewerConfig.store";
 import { pipeFromArray } from "rxjs/internal/util/pipe";
 import { NEHUBA_READY } from "src/services/state/ngViewerState.store";
+import { MOUSE_OVER_SEGMENTS } from "src/services/state/uiState.store";
+import { SELECT_REGIONS_WITH_ID } from "src/services/state/viewerState.store";
 
 @Component({
   selector : 'ui-nehuba-container',
@@ -57,7 +58,7 @@ export class NehubaContainer implements OnInit, OnDestroy{
   private spatialResultsVisible : boolean = false
 
   private selectedTemplate : any | null
-  private selectedRegionIndexSet : Set<number> = new Set()
+  private selectedRegionIndexSet : Set<string> = new Set()
   public fetchedSpatialData : Landmark[] = []
 
   private ngLayersRegister : Partial<NgViewerStateInterface> = {layers : [], forceShowSegment: null}
@@ -67,7 +68,7 @@ export class NehubaContainer implements OnInit, OnDestroy{
 
   private cr : ComponentRef<NehubaViewerUnit>
   public nehubaViewer : NehubaViewerUnit
-  private regionsLabelIndexMap : Map<number,any> = new Map()
+  private multiNgIdsRegionsLabelIndexMap: Map<string, Map<number, any>> = new Map()
   private landmarksLabelIndexMap : Map<number, any> = new Map()
   private landmarksNameMap : Map<string,number> = new Map()
   
@@ -81,7 +82,6 @@ export class NehubaContainer implements OnInit, OnDestroy{
 
   constructor(
     private constantService : AtlasViewerConstantsServices,
-    private atlasViewerDataService : AtlasViewerDataService,
     private apiService :AtlasViewerAPIServices,
     private csf:ComponentFactoryResolver,
     private store : Store<ViewerStateInterface>,
@@ -118,8 +118,8 @@ export class NehubaContainer implements OnInit, OnDestroy{
 
     this.selectedRegions$ = this.store.pipe(
       select('viewerState'),
-      safeFilter('regionsSelected'),
-      map(state=>state.regionsSelected)
+      select('regionsSelected'),
+      filter(rs => !!rs)
     )
 
     this.selectedLandmarks$ = this.store.pipe(
@@ -267,15 +267,18 @@ export class NehubaContainer implements OnInit, OnDestroy{
           const e = (event as any)
           const lastLoadedIdString = e.detail.lastLoadedMeshId.split(',')[0]
           const lastLoadedIdNum = Number(lastLoadedIdString)
+          /**
+           * TODO dig into event detail to see if the exact mesh loaded
+           */
           return e.detail.meshesLoaded >= this.nehubaViewer.numMeshesToBeLoaded
             ? null
             : isNaN(lastLoadedIdNum)
               ? 'Loading unknown chunk'
               : lastLoadedIdNum >= 65500
                 ? 'Loading auxiliary chunk'
-                : this.regionsLabelIndexMap.get(lastLoadedIdNum)
-                  ? `Loading ${this.regionsLabelIndexMap.get(lastLoadedIdNum).name}`
-                  : 'Loading unknown chunk ...'
+                // : this.regionsLabelIndexMap.get(lastLoadedIdNum)
+                //   ? `Loading ${this.regionsLabelIndexMap.get(lastLoadedIdNum).name}`
+                  : 'Loading meshes ...'
         })
       )
 
@@ -452,7 +455,7 @@ export class NehubaContainer implements OnInit, OnDestroy{
           if(!this.nehubaViewer) return
 
           /* selectedregionindexset needs to be updated regardless of forceshowsegment */
-          this.selectedRegionIndexSet = new Set(regions.map(r=>Number(r.labelIndex)))
+          this.selectedRegionIndexSet = new Set(regions.map(({ngId, labelIndex})=>generateLabelIndexId({ ngId, labelIndex })))
 
           if( forceShowSegment === false || (forceShowSegment === null && hideSegmentFlag) ){
             this.nehubaViewer.hideAllSeg()
@@ -506,7 +509,7 @@ export class NehubaContainer implements OnInit, OnDestroy{
         Object.assign({},navigation,{
           positionReal : true
         })
-      this.nehubaViewer.initRegions = regions.map(re=>re.labelIndex)
+      this.nehubaViewer.initRegions = regions.map(({ ngId, labelIndex }) =>generateLabelIndexId({ ngId, labelIndex }))
     })
 
     this.subscriptions.push(
@@ -652,11 +655,18 @@ export class NehubaContainer implements OnInit, OnDestroy{
     if ( !(parcellation && parcellation.regions)) {
       return
     }
-    this.regionsLabelIndexMap = getLabelIndexMap(parcellation.regions)
-    this.nehubaViewer.regionsLabelIndexMap = this.regionsLabelIndexMap
+
+    /**
+     * 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
 
     /* TODO replace with proper KG id */
-    this.nehubaViewer.parcellationId = parcellation.ngId
+    this.nehubaViewer.ngIds = [...ngIds]
     this.selectedParcellation = parcellation
   }
 
@@ -718,11 +728,34 @@ export class NehubaContainer implements OnInit, OnDestroy{
       ).subscribe(this.handleNavigationPositionAndNavigationZoomChange.bind(this))
     )
 
+    const accumulatorFn: (
+      acc:Map<string, { segment: string | null, segmentId: number | null }>,
+      arg: {layer: {name: string}, segmentId: number|null, segment: string | null}
+    ) => Map<string, {segment: string | null, segmentId: number|null}>
+    = (acc, arg) => {
+      const { layer, segment, segmentId } = arg
+      const { name } = layer
+      const newMap = new Map(acc)
+      newMap.set(name, {segment, segmentId})
+      return newMap
+    }
+
     this.nehubaViewerSubscriptions.push(
-      this.nehubaViewer.mouseoverSegmentEmitter.subscribe(emitted => {
+      
+      this.nehubaViewer.mouseoverSegmentEmitter.pipe(
+        scan(accumulatorFn, new Map()),
+        map(map => Array.from(map.entries()).filter(([_ngId, { segmentId }]) => segmentId))
+      ).subscribe(arrOfArr => {
         this.store.dispatch({
-          type : MOUSE_OVER_SEGMENT,
-          segment : emitted
+          type: MOUSE_OVER_SEGMENTS,
+          segments: arrOfArr.map( ([ngId, {segment, segmentId}]) => {
+            return {
+              layer: {
+                name: ngId,
+              },
+              segment: segment || `${ngId}#${segmentId}`
+            }
+          } )
         })
       })
     )
@@ -736,26 +769,41 @@ export class NehubaContainer implements OnInit, OnDestroy{
       })
     )
 
+    const onhoverSegments$ = this.store.pipe(
+      select('uiState'),
+      select('mouseOverSegments'),
+      filter(v => !!v),
+      distinctUntilChanged((o, n) => o.length === n.length && n.every(segment => o.find(oSegment => oSegment.layer.name === segment.layer.name && oSegment.segment === segment.segment) ) )
+    )
+
     // TODO hack, even though octant is hidden, it seems with vtk one can mouse on hover
     this.nehubaViewerSubscriptions.push(
       this.nehubaViewer.regionSelectionEmitter.pipe(
         withLatestFrom(this.onHoverLandmark$),
         filter(results => results[1] === null),
-        map(results => results[0])
-      ).subscribe((region:any) => {
-        /**
-         * TODO
-         * region may have labelIndex as well as children
-         */
-        this.selectedRegionIndexSet.has(region.labelIndex) ?
-          this.store.dispatch({
-            type : SELECT_REGIONS,
-            selectRegions : [...this.selectedRegionIndexSet].filter(idx=>idx!==region.labelIndex).map(idx=>this.regionsLabelIndexMap.get(idx))
-          }) :
-          this.store.dispatch({
-            type : SELECT_REGIONS,
-            selectRegions : [...this.selectedRegionIndexSet].map(idx=>this.regionsLabelIndexMap.get(idx)).concat(region)
+        withLatestFrom(onhoverSegments$),
+        map(results => results[1]),
+        filter(arr => arr.length > 0),
+        map(arr => {
+          return arr.map(({ layer, segment }) => {
+            const ngId = segment.ngId || layer.name
+            const labelIndex = segment.labelIndex
+            return generateLabelIndexId({ ngId, labelIndex })
           })
+        })
+      ).subscribe((ids:string[]) => {
+        const deselectFlag = ids.some(id => this.selectedRegionIndexSet.has(id))
+
+        const set = new Set(this.selectedRegionIndexSet)
+        if (deselectFlag) {
+          ids.forEach(id => set.delete(id))
+        } else {
+          ids.forEach(id => set.add(id))
+        }
+        this.store.dispatch({
+          type: SELECT_REGIONS_WITH_ID,
+          selectRegionIds: [...set]
+        })
       })
     )
 
@@ -781,11 +829,16 @@ export class NehubaContainer implements OnInit, OnDestroy{
         orientation : quat
       }),
       showSegment : (labelIndex) => {
-        if(!this.selectedRegionIndexSet.has(labelIndex)) 
-          this.store.dispatch({
-            type : SELECT_REGIONS,
-            selectRegions :  [labelIndex, ...this.selectedRegionIndexSet]
-          })
+        /**
+         * TODO reenable with updated select_regions api
+         */
+        console.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
@@ -807,22 +860,33 @@ export class NehubaContainer implements OnInit, OnDestroy{
         })
       },
       hideSegment : (labelIndex) => {
-        if(this.selectedRegionIndexSet.has(labelIndex)){
-          this.store.dispatch({
-            type :SELECT_REGIONS,
-            selectRegions : [...this.selectedRegionIndexSet].filter(num=>num!==labelIndex)
-          })
-        }
+        /**
+         * TODO reenable with updated select_regions api
+         */
+        console.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({
-          type : SELECT_REGIONS,
-          selectRegions : this.regionsLabelIndexMap.keys()
+          type : SELECT_REGIONS_WITH_ID,
+          selectRegionIds 
         })
       },
       hideAllSegments : () => {
         this.store.dispatch({
-          type : SELECT_REGIONS,
+          type : SELECT_REGIONS_WITH_ID,
           selectRegions : []
         })
       },
diff --git a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts b/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts
index a15fd44271abe3d06b0db3fcd667ce6ae0a6b6b2..76de48f81207eb0951fc598f322bdfca9f59ce05 100644
--- a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts
+++ b/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts
@@ -8,7 +8,11 @@ import { AtlasViewerConstantsServices } from "../../../atlasViewer/atlasViewer.c
 import { takeOnePipe, identifySrcElement } from "../nehubaContainer.component";
 import { ViewerConfiguration } from "src/services/state/viewerConfig.store";
 import { pipeFromArray } from "rxjs/internal/util/pipe";
+import { getNgIdLabelIndexFromId } from "src/services/stateStore.service";
 
+/**
+ * no selector is needed, as currently, nehubaviewer is created dynamically
+ */
 @Component({
   templateUrl : './nehubaViewer.template.html',
   styleUrls : [
@@ -20,9 +24,17 @@ export class NehubaViewerUnit implements OnDestroy{
   
   @Output() nehubaReady: EventEmitter<null> = new EventEmitter()
   @Output() debouncedViewerPositionChange : EventEmitter<any> = new EventEmitter()
-  @Output() mouseoverSegmentEmitter : EventEmitter<any | number | null> = new EventEmitter()
+  @Output() mouseoverSegmentEmitter: 
+    EventEmitter<{
+      segmentId: number | null,
+      segment:string | null,
+      layer:{
+        name?: string,
+        url?: string
+      }
+    }> = new EventEmitter()
   @Output() mouseoverLandmarkEmitter : EventEmitter<number | null> = new EventEmitter()
-  @Output() regionSelectionEmitter : EventEmitter<any> = new EventEmitter()
+  @Output() regionSelectionEmitter : EventEmitter<{segment:number, layer:{name?: string, url?: string}}> = new EventEmitter()
   @Output() errorEmitter : EventEmitter<any> = new EventEmitter()
 
   /* only used to set initial navigation state */
@@ -47,6 +59,7 @@ export class NehubaViewerUnit implements OnDestroy{
   _s6$ : any
   _s7$ : any
   _s8$ : any
+  _s9$ : any
 
   _s$ : any[] = [
     this._s1$,
@@ -56,7 +69,8 @@ export class NehubaViewerUnit implements OnDestroy{
     this._s5$,
     this._s6$,
     this._s7$,
-    this._s8$
+    this._s8$,
+    this._s9$
   ]
 
   ondestroySubscriptions: any[] = []
@@ -223,9 +237,11 @@ export class NehubaViewerUnit implements OnDestroy{
           }
   
           /* if the active parcellation is the current parcellation, load the said mesh */
-          if(baseUrl === this._baseUrl){
-            this.nehubaViewer.setMeshesToLoad([...this.workerService.safeMeshSet.get(this._baseUrl)], {
-              name : this.parcellationId
+          const baseUrlIsInLoadedBaseUrlList = new Set([...this._baseUrls]).has(baseUrl)
+          const baseUrlParcellationId = this._baseUrlToParcellationIdMap.get(baseUrl)
+          if( baseUrlIsInLoadedBaseUrlList && baseUrlParcellationId){
+            this.nehubaViewer.setMeshesToLoad([...this.workerService.safeMeshSet.get(baseUrl)], {
+              name : baseUrlParcellationId
             })
           }
         })
@@ -233,15 +249,17 @@ export class NehubaViewerUnit implements OnDestroy{
     )
   }
 
-  private _baseUrl : string 
+  private _baseUrlToParcellationIdMap:Map<string, string> = new Map()
+  private _baseUrls: string[] = []
+
   get numMeshesToBeLoaded():number{
-    if(!this._baseUrl)
+    if(!this._baseUrls || this._baseUrls.length === 0)
       return 0
 
-    const set = this.workerService.safeMeshSet.get(this._baseUrl)
-    return set
-      ? set.size
-      : 0
+    return this._baseUrls.reduce((acc, curr) => {
+      const mappedSet = this.workerService.safeMeshSet.get(curr)
+      return acc + ((mappedSet && mappedSet.size) || 0)
+    } ,0)
   }
 
   public applyPerformanceConfig ({ gpuLimit }: Partial<ViewerConfiguration>) {
@@ -262,20 +280,23 @@ export class NehubaViewerUnit implements OnDestroy{
     this._templateId = id
   }
 
-  /* required to check if the correct meshes are being loaded */
-  private _parcellationId : string
-  get parcellationId(){
-    return this._parcellationId
+  /** compatible with multiple parcellation id selection */
+  private _ngIds: string[] = []
+  get ngIds(){
+    return this._ngIds
   }
-  set parcellationId(id:string){
 
-    if(this._parcellationId && this.nehubaViewer){
-      const oldlayer = this.nehubaViewer.ngviewer.layerManager.getLayerByName(this._parcellationId)
-      if(oldlayer)oldlayer.setVisible(false)
-      else console.warn('could not find old layer',this.parcellationId)
+  set ngIds(val:string[]){
+
+    if(this.nehubaViewer){
+      this._ngIds.forEach(id => {
+        const oldlayer = this.nehubaViewer.ngviewer.layerManager.getLayerByName(id)
+        if(oldlayer)oldlayer.setVisible(false)
+        else console.warn('could not find old layer', id)
+      })
     }
 
-    this._parcellationId = id
+    this._ngIds = val
     
     if(this.nehubaViewer)
       this.loadNewParcellation()
@@ -302,7 +323,7 @@ export class NehubaViewerUnit implements OnDestroy{
     }
   }
 
-  regionsLabelIndexMap : Map<number,any>
+  multiNgIdsLabelIndexMap: Map<string, Map<number, any>>
 
   navPosReal : [number,number,number] = [0,0,0]
   navPosVoxel : [number,number,number] = [0,0,0]
@@ -312,8 +333,9 @@ export class NehubaViewerUnit implements OnDestroy{
 
   viewerState : ViewerState
 
-  private defaultColormap : Map<number,{red:number,green:number,blue:number}>
-  public mouseOverSegment : number | null
+  private multiNgIdColorMap: Map<string, Map<number, {red: number, green:number, blue: number}>>
+  public mouseOverSegment: number | null
+  public mouseOverLayer: {name:string,url:string}| null
 
   private viewportToDatas : [any, any, any] = [null, null, null]
 
@@ -327,11 +349,18 @@ export class NehubaViewerUnit implements OnDestroy{
       console.log(err)
     })
 
-    if(this.regionsLabelIndexMap){
-      const managedLayers = this.nehubaViewer.ngviewer.layerManager.managedLayers
-      managedLayers.slice(1).forEach(layer=>layer.setVisible(false))
-      this.nehubaViewer.redraw()
-    }
+    /**
+     * Hide all layers except the base layer (template)
+     * Then show the layers referenced in multiNgIdLabelIndexMap
+     */
+    const managedLayers = this.nehubaViewer.ngviewer.layerManager.managedLayers
+    managedLayers.slice(1).forEach(layer=>layer.setVisible(false))
+    Array.from(this.multiNgIdsLabelIndexMap.keys()).forEach(ngId => {
+      const layer = this.nehubaViewer.ngviewer.layerManager.getLayerByName(ngId)
+      if (layer) layer.setVisible(true)
+      else console.log('layer unavailable', ngId)
+    })
+    this.nehubaViewer.redraw()
 
     /* creation of the layout is done on next frame, hence the settimeout */
     setTimeout(() => {
@@ -470,9 +499,15 @@ export class NehubaViewerUnit implements OnDestroy{
     
     /* TODO find a more permanent fix to disable double click */
     LayerManager.prototype.invokeAction = (arg) => {
-      const region = this.regionsLabelIndexMap.get(this.mouseOverSegment)
-      if (arg === 'select' && region) {
-        this.regionSelectionEmitter.emit(region)
+
+      /**
+       * The emitted value does not affect the region selection
+       * the region selection is taken care of in nehubaContainer
+       */
+      const map = this.multiNgIdsLabelIndexMap.get(this.mouseOverLayer.name)
+      const region = map && map.get(this.mouseOverSegment)
+      if (arg === 'select') {
+        this.regionSelectionEmitter.emit({ segment: region, layer: this.mouseOverLayer })
       }
     }
 
@@ -582,35 +617,78 @@ export class NehubaViewerUnit implements OnDestroy{
 
   public hideAllSeg(){
     if(!this.nehubaViewer) return
-    Array.from(this.regionsLabelIndexMap.keys()).forEach(idx=>
-      this.nehubaViewer.hideSegment(idx,{
-        name : this.parcellationId
-      }))
-    this.nehubaViewer.showSegment(0,{
-      name : this.parcellationId
+    Array.from(this.multiNgIdsLabelIndexMap.keys()).forEach(ngId => {
+      
+      Array.from(this.multiNgIdsLabelIndexMap.get(ngId).keys()).forEach(idx => {
+        this.nehubaViewer.hideSegment(idx, {
+          name: ngId
+        })
+      })
+      this.nehubaViewer.showSegment(0, {
+        name: ngId
+      })
     })
   }
 
   public showAllSeg(){
     if(!this.nehubaViewer) return
     this.hideAllSeg()
-    this.nehubaViewer.hideSegment(0,{
-      name : this.parcellationId
+    Array.from(this.multiNgIdsLabelIndexMap.keys()).forEach(ngId => {
+      this.nehubaViewer.hideSegment(0,{
+        name: ngId
+      })
     })
   }
 
-  public showSegs(array:number[]){
+  public showSegs(array: number[] | string[]){
+
     if(!this.nehubaViewer) return
+
     this.hideAllSeg()
 
-    this.nehubaViewer.hideSegment(0,{
-      name : this.parcellationId
-    })
+    
+    if (array.length === 0) return
+
+    /**
+     * TODO tobe deprecated
+     */
+
+    if (typeof array[0] === 'number') {
+      console.warn(`show seg with number indices has been deprecated`)
+      return
+    } 
+
+    const reduceFn:(acc:Map<string,number[]>,curr:string)=>Map<string,number[]> = (acc, curr) => {
 
-    array.forEach(idx=>
-      this.nehubaViewer.showSegment(idx,{
-        name : this.parcellationId
-      }))
+      const newMap = new Map(acc)
+      const { ngId, labelIndex } = getNgIdLabelIndexFromId({ labelIndexId: curr })
+      const exist = newMap.get(ngId)
+      if (!exist) newMap.set(ngId, [Number(labelIndex)])
+      else newMap.set(ngId, [...exist, Number(labelIndex)])
+      return newMap
+    }
+    
+    /**
+     * TODO 
+     * AAAAAAARG TYPESCRIPT WHY YOU SO MAD
+     */
+    //@ts-ignore
+    const newMap:Map<string, number[]> = array.reduce(reduceFn, new Map())
+    
+    /**
+     * TODO
+     * ugh, ugly code. cleanify
+     */
+    newMap.forEach((segs, ngId) => {
+      this.nehubaViewer.hideSegment(0, {
+        name: ngId
+      })
+      segs.forEach(seg => {
+        this.nehubaViewer.showSegment(seg, {
+          name: ngId
+        })
+      })
+    })
   }
 
   private vec3(pos:[number,number,number]){
@@ -658,17 +736,22 @@ export class NehubaViewerUnit implements OnDestroy{
     this.nehubaViewer.ngviewer.navigationState.pose.rotateRelative(this.vec3([0, 0, 1]), amount / 4.0 * Math.PI / 180.0)
   }
 
-  private updateColorMap(arrayIdx:number[]){
+  /**
+   * 
+   * @param arrayIdx label indices of the shown segment(s)
+   * @param ngId segmentation layer name
+   */
+  private updateColorMap(arrayIdx:number[], ngId: string){
     const set = new Set(arrayIdx)
     const newColorMap = new Map(
-      Array.from(this.defaultColormap.entries())
+      Array.from(this.multiNgIdColorMap.get(ngId).entries())
         .map(v=> set.has(v[0]) || set.size === 0 ? 
           v :
           [v[0],{red:255,green:255,blue:255}]) as any
     )
 
     this.nehubaViewer.batchAddAndUpdateSegmentColors(newColorMap,{
-      name:this.parcellationId
+      name: ngId
     })
   }
 
@@ -677,7 +760,10 @@ export class NehubaViewerUnit implements OnDestroy{
     /* isn't this layer specific? */
     /* TODO this is layer specific. need a way to distinguish between different segmentation layers */
     this._s2$ = this.nehubaViewer.mouseOver.segment
-      .subscribe(obj=>this.mouseOverSegment = obj.segment)
+      .subscribe(({ segment, layer })=>{
+        this.mouseOverSegment = segment
+        this.mouseOverLayer = { ...layer }
+      })
 
     if(this.initNav){
       this.setNavigationState(this.initNav)
@@ -693,12 +779,23 @@ export class NehubaViewerUnit implements OnDestroy{
       this.hideAllSeg()
     }
 
-    this._s8$ = this.nehubaViewer.mouseOver.segment.subscribe(({segment, ...rest})=>{
-      if( segment && segment < 65500 ) {
-        const region = this.regionsLabelIndexMap.get(segment)
-        this.mouseoverSegmentEmitter.emit(region ? region : segment)
+    this._s8$ = this.nehubaViewer.mouseOver.segment.subscribe(({segment: segmentId, layer, ...rest})=>{
+      
+      const {name = 'unnamed'} = layer
+      if( segmentId && segmentId < 65500 ) {
+        const map = this.multiNgIdsLabelIndexMap.get(name)
+        const region = map && map.get(segmentId)
+        this.mouseoverSegmentEmitter.emit({
+          layer,
+          segment: region,
+          segmentId
+        })
       }else{
-        this.mouseoverSegmentEmitter.emit(null)
+        this.mouseoverSegmentEmitter.emit({
+          layer,
+          segment: null,
+          segmentId
+        })
       }
     })
 
@@ -770,72 +867,97 @@ export class NehubaViewerUnit implements OnDestroy{
   private loadNewParcellation(){
 
     /* show correct segmentation layer */
-
-    const newlayer = this.nehubaViewer.ngviewer.layerManager.getLayerByName(this.parcellationId)
-    if(newlayer)newlayer.setVisible(true)
-    else console.warn('could not find new layer',this.parcellationId)
-
-    const regex = /^(\S.*?)\:\/\/(.*?)$/.exec(newlayer.sourceUrl)
-    
-    if(!regex || !regex[2]){
-      console.error('could not parse baseUrl')
-      return
-    }
-    if(regex[1] !== 'precomputed'){
-      console.error('sourceUrl is not precomputed')
-      return
-    }
-    
-    const baseUrl = regex[2]
-    this._baseUrl = baseUrl
-
-    /* load meshes */
-    /* TODO could be a bug where user loads new parcellation, but before the worker could completely populate the list */
-    const set = this.workerService.safeMeshSet.get(baseUrl)
-    if(set){
-      this.nehubaViewer.setMeshesToLoad([...set],{
-        name : this.parcellationId
-      })
-    }else{
-      if(newlayer){
-        this.zone.runOutsideAngular(() => 
-          this.workerService.worker.postMessage({
-            type : 'CHECK_MESHES',
-            parcellationId : this.parcellationId,
-            baseUrl,
-            indices : [
-              ...Array.from(this.regionsLabelIndexMap.keys()),
-              ...getAuxilliaryLabelIndices()
-            ]
-          })
-        )
+    this._baseUrls = []
+
+    this.ngIds.map(id => {
+      const newlayer = this.nehubaViewer.ngviewer.layerManager.getLayerByName(id)
+      if(newlayer)newlayer.setVisible(true)
+      else console.warn('could not find new layer',id)
+
+      const regex = /^(\S.*?)\:\/\/(.*?)$/.exec(newlayer.sourceUrl)
+      
+      if(!regex || !regex[2]){
+        console.error('could not parse baseUrl')
+        return
       }
-    }
+      if(regex[1] !== 'precomputed'){
+        console.error('sourceUrl is not precomputed')
+        return
+      }
+      
+      const baseUrl = regex[2]
+      this._baseUrls.push(baseUrl)
+      this._baseUrlToParcellationIdMap.set(baseUrl, id)
+
+      /* load meshes */
+      /* TODO could be a bug where user loads new parcellation, but before the worker could completely populate the list */
+      const set = this.workerService.safeMeshSet.get(baseUrl)
+      if(set){
+        this.nehubaViewer.setMeshesToLoad([...set],{
+          name : id
+        })
+      }else{
+        if(newlayer){
+          this.zone.runOutsideAngular(() => 
+            this.workerService.worker.postMessage({
+              type : 'CHECK_MESHES',
+              parcellationId : id,
+              baseUrl,
+              indices : [
+                ...Array.from(this.multiNgIdsLabelIndexMap.get(id).keys()),
+                ...getAuxilliaryLabelIndices()
+              ]
+            })
+          )
+        }
+      }
+    })
 
-    this.defaultColormap = new Map(
-      Array.from(
-        [
-          ...this.regionsLabelIndexMap.entries(),
-          ...getAuxilliaryLabelIndices().map(i=>([
-              i, {}
-            ]))
-          
-        ]
-      ).map((val:[number,any])=>([val[0],this.getRgb(val[0],val[1].rgb)])) as any)
+    const obj = Array.from(this.multiNgIdsLabelIndexMap.keys()).map(ngId => {
+      return [
+        ngId, 
+        new Map(Array.from(
+          [
+            ...this.multiNgIdsLabelIndexMap.get(ngId).entries(),
+            ...getAuxilliaryLabelIndices().map(i => {
+              return [i, {}]
+            })
+          ]
+        ).map((val:[number,any])=>([val[0],this.getRgb(val[0],val[1].rgb)])) as any)
+      ]
+    }) as [string, Map<number, {red:number, green: number, blue: number}>][]
+
+    this.multiNgIdColorMap = new Map(obj)
 
     /* load colour maps */
-    this.nehubaViewer.batchAddAndUpdateSegmentColors(
-      this.defaultColormap,
-      { name : this.parcellationId })
+
+    Array.from(this.multiNgIdColorMap.entries()).forEach(([ngId, map]) => {
+
+      this.nehubaViewer.batchAddAndUpdateSegmentColors(
+        map,
+        { name : ngId })
+    })
 
     this._s$.forEach(_s$=>{
       if(_s$) _s$.unsubscribe()
     })
 
     if(this._s1$)this._s1$.unsubscribe()
-    this._s1$ = this.nehubaViewer.getShownSegmentsObservable({
-      name : this.parcellationId
-    }).subscribe(arrayIdx=>this.updateColorMap(arrayIdx))
+    if(this._s9$)this._s9$.unsubscribe()
+
+    const arr = Array.from(this.multiNgIdsLabelIndexMap.keys()).map(ngId => {
+      return this.nehubaViewer.getShownSegmentsObservable({
+        name: ngId
+      }).subscribe(arrayIdx => this.updateColorMap(arrayIdx, ngId))
+    })
+
+    this._s9$ = {
+      unsubscribe: () => {
+        while(arr.length > 0) {
+          arr.pop().unsubscribe()
+        }
+      }
+    }
   }
 
   private getRgb(labelIndex:number,rgb?:number[]):{red:number,green:number,blue:number}{
diff --git a/src/ui/regionHierachy/regionHierarchy.component.ts b/src/ui/regionHierachy/regionHierarchy.component.ts
index 0555327a6837ba8b66db4e4d1d934f06803cc02e..d5992b28c0ed7503d144de66f96fc0de9c211277 100644
--- a/src/ui/regionHierachy/regionHierarchy.component.ts
+++ b/src/ui/regionHierachy/regionHierarchy.component.ts
@@ -2,6 +2,7 @@ import { EventEmitter, Component, ElementRef, ViewChild, HostListener, OnInit, C
 import {  Subscription, Subject, fromEvent } from "rxjs";
 import { buffer, debounceTime } from "rxjs/operators";
 import { FilterNameBySearch } from "./filterNameBySearch.pipe";
+import { generateLabelIndexId } from "src/services/stateStore.service";
 
 const insertHighlight :(name:string, searchTerm:string) => string = (name:string, searchTerm:string = '') => {
   const regex = new RegExp(searchTerm, 'gi')
@@ -10,10 +11,14 @@ const insertHighlight :(name:string, searchTerm:string) => string = (name:string
     name.replace(regex, (s) => `<span class = "highlight">${s}</span>`)
 }
 
-const getDisplayTreeNode : (searchTerm:string, selectedRegions:any[]) => (item:any) => string = (searchTerm:string = '', selectedRegions:any[] = []) => (item:any) =>  {
-  return typeof item.labelIndex !== 'undefined' && selectedRegions.findIndex(re => re.labelIndex === Number(item.labelIndex)) >= 0 ?
-    `<span class = "regionSelected">${insertHighlight(item.name, searchTerm)}</span>` :
-    `<span class = "regionNotSelected">${insertHighlight(item.name, searchTerm)}</span>`
+const getDisplayTreeNode : (searchTerm:string, selectedRegions:any[]) => (item:any) => string = (searchTerm:string = '', selectedRegions:any[] = []) => ({ ngId, name, labelIndex }) =>  {
+  return !!labelIndex
+    && !!ngId
+    && selectedRegions.findIndex(re =>
+      generateLabelIndexId({ labelIndex: re.labelIndex, ngId: re.ngId }) === generateLabelIndexId({ ngId, labelIndex })
+    ) >= 0
+      ? `<span class="regionSelected">${insertHighlight(name, searchTerm)}</span>`
+      : `<span class="regionNotSelected">${insertHighlight(name, searchTerm)}</span>`
 }
 
 const getFilterTreeBySearch = (pipe:FilterNameBySearch, searchTerm:string) => (node:any) => pipe.transform([node.name], searchTerm)