diff --git a/common/constants.js b/common/constants.js
index c5f7c056767d940539781b8a96efeee7d321fb6f..580136b22ef41d52cd3abebd38c0de8853ac7a6f 100644
--- a/common/constants.js
+++ b/common/constants.js
@@ -14,6 +14,9 @@
     SHOW_ORIGIN_DATASET: `Show probabilistic map`,
     SHOW_CONNECTIVITY_DATA: `Show connectivity data`,
     SHOW_IN_OTHER_REF_SPACE: `Show in other reference space`,
-    AVAILABILITY_IN_OTHER_REF_SPACE: 'Availability in other reference spaces'
+    AVAILABILITY_IN_OTHER_REF_SPACE: 'Availability in other reference spaces',
+
+    // additional volumes
+    TOGGLE_SHOW_LAYER_CONTROL: `Show layer control`,
   }
 })(typeof exports === 'undefined' ? module.exports : exports)
diff --git a/docs/releases/v2.2.1.md b/docs/releases/v2.2.1.md
new file mode 100644
index 0000000000000000000000000000000000000000..1934dc90e4a65c5cc990c948d392076602d4e490
--- /dev/null
+++ b/docs/releases/v2.2.1.md
@@ -0,0 +1,7 @@
+# v2.2.1
+
+26 May 2020
+
+## Bugfixes
+
+- fixed connectivity menu showing non existent connectivity data
diff --git a/e2e/src/advanced/browsingForDatasets.prod.e2e-spec.js b/e2e/src/advanced/browsingForDatasets.prod.e2e-spec.js
index b5cb270a7850655d8b580fa9f3f5ab7ff31935fb..42969809b7a962b46ac912fdcfeec99af8bec2ae 100644
--- a/e2e/src/advanced/browsingForDatasets.prod.e2e-spec.js
+++ b/e2e/src/advanced/browsingForDatasets.prod.e2e-spec.js
@@ -67,7 +67,7 @@ const area = 'Area hOc1 (V1, 17, CalcS)'
 
 const receptorName = `Density measurements of different receptors for Area hOc1 (V1, 17, CalcS) [human, v1.0]`
 
-describe('> dataset previews', () => {
+describe('> receptor dataset previews', () => {
   let iavPage
   beforeEach(async () => {
     iavPage = new AtlasPage()
@@ -121,4 +121,41 @@ describe('> dataset previews', () => {
     const modalHasImage = await iavPage.modalHasChild('div[data-img-src]')
     expect(modalHasImage).toEqual(true)
   })
-})
\ No newline at end of file
+})
+
+describe('> pmap dataset preview', () => {
+  let iavPage
+
+  beforeAll(async () => {
+    // loads pmap and centers on hot spot
+    const url = `/?templateSelected=MNI+152+ICBM+2009c+Nonlinear+Asymmetric&parcellationSelected=JuBrain+Cytoarchitectonic+Atlas&cNavigation=0.0.0.-W000..2_ZG29.-ASCS.2-8jM2._aAY3..BSR0..dABI~.525x0~.7iMV..1EPC&niftiLayers=https%3A%2F%2Fneuroglancer.humanbrainproject.eu%2Fprecomputed%2FJuBrain%2F17%2Ficbm152casym%2Fpmaps%2FVisual_hOc1_l_N10_nlin2MNI152ASYM2009C_2.4_publicP_d3045ee3c0c4de9820eb1516d2cc72bb.nii.gz&previewingDatasetFiles=%5B%7B"datasetId"%3A"minds%2Fcore%2Fdataset%2Fv1.0.0%2F5c669b77-c981-424a-858d-fe9f527dbc07"%2C"filename"%3A"Area+hOc1+%28V1%2C+17%2C+CalcS%29+%5Bv2.4%2C+ICBM+2009c+Asymmetric%2C+left+hemisphere%5D"%7D%5D`
+    iavPage = new AtlasPage()
+    await iavPage.init()
+    await iavPage.goto(url)
+    await iavPage.waitUntilAllChunksLoaded()
+  })
+
+  it('> can display pmap', async () => {
+    const { red, green, blue } = await iavPage.getRgbAt({position: [200, 597]})
+    expect(red).toBeGreaterThan(green)
+    expect(red).toBeGreaterThan(blue)
+  })
+
+  it('> on update of layer control, pmap retains', async () => {
+    // by default, additional layer control is collapsed
+    await iavPage.toggleLayerControl()
+    await iavPage.wait(500)
+    await iavPage.toggleNthLayerControl(0)
+    await iavPage.wait(5500)
+
+    // interact with control
+    await iavPage.click(`[aria-label="Remove background"]`)
+    await iavPage.wait(500)
+
+    // color map should be unchanged
+    const { red, green, blue } = await iavPage.getRgbAt({position: [200, 597]})
+    expect(red).toBeGreaterThan(green)
+    expect(red).toBeGreaterThan(blue)
+    
+  })
+})
diff --git a/e2e/src/advanced/urlParsing.prod.e2e-spec.js b/e2e/src/advanced/urlParsing.prod.e2e-spec.js
index 944dce4faf6e16b829a2496118803bac1150180a..21c9c6b33183574cd811e128e22fbd80b6ba2175 100644
--- a/e2e/src/advanced/urlParsing.prod.e2e-spec.js
+++ b/e2e/src/advanced/urlParsing.prod.e2e-spec.js
@@ -67,35 +67,7 @@ describe('> url parsing', () => {
     await iavPage.goto(url)
     await iavPage.clearAlerts()
 
-    // TODO use screenshot API when merg v2.3.0
-    const screenshotData = await iavPage._driver.takeScreenshot()
-    const [ red, green, blue ] = await iavPage._driver.executeAsyncScript(() => {
-      
-      const dataUri = arguments[0]
-      const pos = arguments[1]
-      const dim = arguments[2]
-      const cb = arguments[arguments.length - 1]
-
-      const img = new Image()
-      img.onload = () => {
-        const canvas = document.createElement('canvas')
-        canvas.width = dim[0]
-        canvas.height = dim[1]
-
-        const ctx = canvas.getContext('2d')
-        ctx.drawImage(img, 0, 0)
-        const imgData = ctx.getImageData(0, 0, dim[0], dim[1])
-
-        const idx = (dim[0] * pos[1] + pos[0]) * 4
-        const red = imgData.data[idx]
-        const green = imgData.data[idx + 1]
-        const blue = imgData.data[idx + 2]
-        cb([red, green, blue])
-      }
-      img.src = dataUri
-
-    }, `data:image/png;base64,${screenshotData}`, [600, 490], [800, 796])
-    
+    const { red, green, blue } = await iavPage.getRgbAt({ position: [600, 490] })
     expect(red).toBeGreaterThan(0)
     expect(red).toEqual(green)
     expect(red).toEqual(blue)
@@ -106,34 +78,7 @@ describe('> url parsing', () => {
     await iavPage.goto(url)
     await iavPage.clearAlerts()
 
-    // TODO use screenshot API when merg v2.3.0
-    const screenshotData = await iavPage._driver.takeScreenshot()
-    const [ red, green, blue ] = await iavPage._driver.executeAsyncScript(() => {
-      
-      const dataUri = arguments[0]
-      const pos = arguments[1]
-      const dim = arguments[2]
-      const cb = arguments[arguments.length - 1]
-
-      const img = new Image()
-      img.onload = () => {
-        const canvas = document.createElement('canvas')
-        canvas.width = dim[0]
-        canvas.height = dim[1]
-
-        const ctx = canvas.getContext('2d')
-        ctx.drawImage(img, 0, 0)
-        const imgData = ctx.getImageData(0, 0, dim[0], dim[1])
-
-        const idx = (dim[0] * pos[1] + pos[0]) * 4
-        const red = imgData.data[idx]
-        const green = imgData.data[idx + 1]
-        const blue = imgData.data[idx + 2]
-        cb([red, green, blue])
-      }
-      img.src = dataUri
-
-    }, `data:image/png;base64,${screenshotData}`, [600, 490], [800, 796])
+    const { red, green, blue } = await iavPage.getRgbAt({ position: [600, 490] })
     
     expect(red).toBeGreaterThan(0)
     expect(red).toEqual(green)
diff --git a/e2e/src/layout/scrollDatasetContainer.prod.e2e-spec.js b/e2e/src/layout/scrollDatasetContainer.prod.e2e-spec.js
index 7d80e04fcb7edce754ba20e99afcd28c562c2b19..198be8f230c3c3acddcad6e70dd7123cd57221cf 100644
--- a/e2e/src/layout/scrollDatasetContainer.prod.e2e-spec.js
+++ b/e2e/src/layout/scrollDatasetContainer.prod.e2e-spec.js
@@ -37,6 +37,8 @@ describe('> scroll dataset container', () => {
       countdown --
     }while(countdown > 0)
 
+    await iavPage.wait(500)
+
     const val = await iavPage.getScrollStatus(scrollContainerCssSelector)
     expect(val).toBeGreaterThanOrEqual(10000)
   })
diff --git a/e2e/src/material-util.js b/e2e/src/material-util.js
new file mode 100644
index 0000000000000000000000000000000000000000..04f9c994fac5310b6d1c50ab915ec3f1ddcc215f
--- /dev/null
+++ b/e2e/src/material-util.js
@@ -0,0 +1,19 @@
+const { By } = require('selenium-webdriver')
+
+async function polyFillClick(cssSelector){
+  if (!cssSelector) throw new Error(`click method needs to define a css selector`)
+  const webEl = this._browser.findElement( By.css(cssSelector) )
+  try {
+    await webEl.click()
+  } catch (e) {
+    const id = await webEl.getAttribute('id')
+    const newId = id.replace(/-input$/, '')
+    await this._browser.findElement(
+      By.id(newId)
+    ).click()
+  }
+}
+
+module.exports = {
+  polyFillClick
+}
diff --git a/e2e/src/util.js b/e2e/src/util.js
index 134ca978f603c656f3b11210ea8984e2615d1219..2830aad1c7c81f861237514157ed24cb3db95917 100644
--- a/e2e/src/util.js
+++ b/e2e/src/util.js
@@ -6,6 +6,9 @@ if (ATLAS_URL.length === 0) throw new Error(`ATLAS_URL must either be left unset
 if (ATLAS_URL[ATLAS_URL.length - 1] === '/') throw new Error(`ATLAS_URL should not trail with a slash: ${ATLAS_URL}`)
 const { By, WebDriver, Key } = require('selenium-webdriver')
 const CITRUS_LIGHT_URL = `https://unpkg.com/citruslight@0.1.0/citruslight.js`
+const { polyFillClick } = require('./material-util')
+
+const { ARIA_LABELS } = require('../../common/constants')
 
 function getActualUrl(url) {
   return /^http\:\/\//.test(url) ? url : `${ATLAS_URL}/${url.replace(/^\//, '')}`
@@ -92,6 +95,40 @@ class WdBase{
     return result
   }
 
+  async getRgbAt({ position } = {}, cssSelector = null){
+    if (!position) throw new Error(`position is required for getRgbAt`)
+    const { x, y } = verifyPosition(position)
+    const screenshotData = await this.takeScreenshot(cssSelector)
+    const [ red, green, blue ] = await this._driver.executeAsyncScript(() => {
+      
+      const dataUri = arguments[0]
+      const pos = arguments[1]
+      const dim = arguments[2]
+      const cb = arguments[arguments.length - 1]
+
+      const img = new Image()
+      img.onload = () => {
+        const canvas = document.createElement('canvas')
+        canvas.width = dim[0]
+        canvas.height = dim[1]
+
+        const ctx = canvas.getContext('2d')
+        ctx.drawImage(img, 0, 0)
+        const imgData = ctx.getImageData(0, 0, dim[0], dim[1])
+
+        const idx = (dim[0] * pos[1] + pos[0]) * 4
+        const red = imgData.data[idx]
+        const green = imgData.data[idx + 1]
+        const blue = imgData.data[idx + 2]
+        cb([red, green, blue])
+      }
+      img.src = dataUri
+
+    }, `data:image/png;base64,${screenshotData}`, [x, y], [800, 796])
+
+    return { red, green, blue }
+  }
+
   async switchIsChecked(cssSelector){
     if (!cssSelector) throw new Error(`switchChecked method requies css selector`)
     const checked = await this._browser
@@ -101,8 +138,7 @@ class WdBase{
   }
 
   async click(cssSelector){
-    if (!cssSelector) throw new Error(`click method needs to define a css selector`)
-    await this._browser.findElement( By.css(cssSelector) ).click()
+    return await polyFillClick.bind(this)(cssSelector)
   }
 
   async getText(cssSelector){
@@ -561,6 +597,13 @@ class WdLayoutPage extends WdBase{
       .click()
   }
 
+  async toggleNthLayerControl(idx) {
+    const els = await this._getAdditionalLayerControl()
+      .findElements( By.css(`[aria-label="${ARIA_LABELS.TOGGLE_SHOW_LAYER_CONTROL}"]`))
+    if (!els[idx]) throw new Error(`toggleNthLayerControl index out of bound: accessor ${idx} with length ${els.length}`)
+    await els[idx].click()
+  }
+
   // Signin banner
   _getToolsIcon(){
     return this._driver
diff --git a/mkdocs.yml b/mkdocs.yml
index e2436413086040713a7cc5eef21856c5a5d2ae8b..25324af62f39c497367e7fa3f87218518c948af8 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -40,6 +40,7 @@ pages:
     - Fetching datasets: 'advanced/datasets.md'
     - Display non-atlas volumes: 'advanced/otherVolumes.md'
   - Release notes:
+    - v2.2.1: 'releases/v2.2.1.md'
     - v2.2.0: 'releases/v2.2.0.md'
     - v2.1.3: 'releases/v2.1.3.md'
     - v2.1.2: 'releases/v2.1.2.md'
diff --git a/src/atlasViewer/atlasViewer.constantService.service.ts b/src/atlasViewer/atlasViewer.constantService.service.ts
index 30cde5aded6877e7df1624f37333c1e17135d61b..ce7645f1ee5fa466f61470866c3a92b2fd1b1463 100644
--- a/src/atlasViewer/atlasViewer.constantService.service.ts
+++ b/src/atlasViewer/atlasViewer.constantService.service.ts
@@ -9,8 +9,6 @@ import { IavRootStoreInterface } from "../services/stateStore.service";
 import { AtlasWorkerService } from "./atlasViewer.workerService.service";
 
 export const CM_THRESHOLD = `0.05`
-export const CM_MATLAB_JET = `float r;if( x < 0.7 ){r = 4.0 * x - 1.5;} else {r = -4.0 * x + 4.5;}float g;if (x < 0.5) {g = 4.0 * x - 0.5;} else {g = -4.0 * x + 3.5;}float b;if (x < 0.3) {b = 4.0 * x + 0.5;} else {b = -4.0 * x + 2.5;}float a = 1.0;`
-export const GLSL_COLORMAP_JET = `void main(){float x = toNormalized(getDataValue());${CM_MATLAB_JET}if(x>${CM_THRESHOLD}){emitRGB(vec3(r,g,b));}else{emitTransparent();}}`
 
 const getUniqueId = () => Math.round(Math.random() * 1e16).toString(16)
 
diff --git a/src/atlasViewer/atlasViewer.urlUtil.ts b/src/atlasViewer/atlasViewer.urlUtil.ts
index 025980709189be5ae41b6189e782011ecd9976ea..6447f1f7fb7b7d8860121eb3ef573cbe1a64f524 100644
--- a/src/atlasViewer/atlasViewer.urlUtil.ts
+++ b/src/atlasViewer/atlasViewer.urlUtil.ts
@@ -2,8 +2,9 @@ import { getGetRegionFromLabelIndexId } from "src/services/effect/effect";
 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, GLSL_COLORMAP_JET, separator } from "./atlasViewer.constantService.service";
+import { decodeToNumber, encodeNumber, separator } from "./atlasViewer.constantService.service";
 import { GetKgSchemaIdFromFullIdPipe } from "src/ui/databrowserModule/util/getKgSchemaIdFromFullId.pipe";
+import { getShader, PMAP_DEFAULT_CONFIG } from "src/util/constants";
 
 const getKgSchemaIdFromFullIdPipe = new GetKgSchemaIdFromFullIdPipe()
 
@@ -304,7 +305,7 @@ export const cvtSearchParamToState = (searchparams: URLSearchParams, state: IavR
           name : layer,
           source : `nifti://${layer}`,
           mixability : 'nonmixable',
-          shader : GLSL_COLORMAP_JET,
+          shader : getShader(PMAP_DEFAULT_CONFIG),
         } as any
       })
     const { ngViewerState } = returnState
diff --git a/src/ui/cookieAgreement/data/readmore.md b/src/ui/cookieAgreement/data/readmore.md
index 243cfe802f6e3ea3bef24c0238b5e6c12308e54a..6692141e5199aa2c7270c70e1ba7dce9f302ea2b 100644
--- a/src/ui/cookieAgreement/data/readmore.md
+++ b/src/ui/cookieAgreement/data/readmore.md
@@ -1,6 +1,6 @@
 **Data controller(s)**: HBP Atlas Viewer is the data controller for your login information.
 **List of partners responsible**: HBP Atlas Viewer is the data controller for your login information.
-**HBP Data Protection Officer (HBP DPO)**: FZJ-INM1 <inm1-bda@fz-juelich.de>
+**HBP Data Protection Officer (HBP DPO)**: <data.protection@humanbrainproject.eu>
 **Legal basis for data processing**: You can find out about HBP Data Protection policies here: <https://www.humanbrainproject.eu/en/social-ethical-reflective/ethics-support/data-protection/> and you can contact HBP Data Protection Officer at <data.protection@humanbrainproject.eu>
 **General categories of personal data collected**: consent
 **Data shared within the HBP Consortium**: Name, ORC ID, JWT ID Token
diff --git a/src/ui/databrowserModule/databrowser.useEffect.ts b/src/ui/databrowserModule/databrowser.useEffect.ts
index 7a55fe649643910505bf5c09e541e1740f6137ab..74eb19f0218e1df91ddd40d81f50b28a4b868d12 100644
--- a/src/ui/databrowserModule/databrowser.useEffect.ts
+++ b/src/ui/databrowserModule/databrowser.useEffect.ts
@@ -6,10 +6,9 @@ import { filter, map, scan, switchMap, withLatestFrom, mapTo, shareReplay, start
 import { LoggingService } from "src/logging";
 import { DATASETS_ACTIONS_TYPES, IDataEntry, ViewerPreviewFile, DatasetPreview } from "src/services/state/dataStore.store";
 import { IavRootStoreInterface, ADD_NG_LAYER, CHANGE_NAVIGATION } from "src/services/stateStore.service";
-import { LOCAL_STORAGE_CONST, DS_PREVIEW_URL } from "src/util/constants";
+import { LOCAL_STORAGE_CONST, DS_PREVIEW_URL, getShader, PMAP_DEFAULT_CONFIG } from "src/util/constants";
 import { KgSingleDatasetService } from "./kgSingleDatasetService.service";
 import { determinePreviewFileType, PREVIEW_FILE_TYPES, PREVIEW_FILE_TYPES_NO_UI } from "./preview/previewFileIcon.pipe";
-import { GLSL_COLORMAP_JET } from "src/atlasViewer/atlasViewer.constantService.service";
 import { SHOW_BOTTOM_SHEET } from "src/services/state/uiState.store";
 import { MatSnackBar } from "@angular/material/snack-bar";
 import { MatDialog } from "@angular/material/dialog";
@@ -293,7 +292,7 @@ export class DataBrowserUseEffect implements OnDestroy {
           name: filename,
           source : `nifti://${url}`,
           mixability : 'nonmixable',
-          shader : GLSL_COLORMAP_JET,
+          shader : getShader(PMAP_DEFAULT_CONFIG),
           annotation: `${DATASET_PREVIEW_ANNOTATION} ${filename}`
         }
         return {
diff --git a/src/ui/layerbrowser/layerDetail/layerDetail.component.spec.ts b/src/ui/layerbrowser/layerDetail/layerDetail.component.spec.ts
index 9d88ec67995546615a0a3e9d6c261b11495460cb..c628d46e0476638c993a44d86a6975d2b17041aa 100644
--- a/src/ui/layerbrowser/layerDetail/layerDetail.component.spec.ts
+++ b/src/ui/layerbrowser/layerDetail/layerDetail.component.spec.ts
@@ -1,8 +1,9 @@
-import { LayerDetailComponent } from './layerDetail.component'
+import { LayerDetailComponent, VIEWER_INJECTION_TOKEN } from './layerDetail.component'
 import { async, TestBed } from '@angular/core/testing'
 import { NgLayersService } from '../ngLayerService.service'
 import { UIModule } from 'src/ui/ui.module'
 import { By } from '@angular/platform-browser'
+import * as CONSTANT from 'src/util/constants'
 
 const getSpies = (service: NgLayersService) => {
   const lowThMapGetSpy = spyOn(service.lowThresholdMap, 'get').and.callThrough()
@@ -65,8 +66,19 @@ const getSliderChangeTest = ctrlName => describe(`testing: ${ctrlName}`, () => {
   })
 })
 
-describe('layerDetail.component.ts', () => {
-  describe('LayerDetailComponent', () => {
+const fragmentMainSpy = {
+  value: `test value`,
+  restoreState: () => {}
+}
+
+const defaultViewer = {
+  layerManager: {
+    getLayerByName: jasmine.createSpy('getLayerByName').and.returnValue({layer: {fragmentMain: fragmentMainSpy}})
+  }
+}
+
+describe('> layerDetail.component.ts', () => {
+  describe('> LayerDetailComponent', () => {
 
     beforeEach(async(() => {
       TestBed.configureTestingModule({
@@ -74,21 +86,28 @@ describe('layerDetail.component.ts', () => {
           UIModule
         ],
         providers: [
-          NgLayersService
+          NgLayersService,
+          {
+            provide: VIEWER_INJECTION_TOKEN,
+            useValue: defaultViewer
+          }
         ]
       }).compileComponents()
     }))
 
-    describe('basic', () => {
+    describe('> basic funcitonalities', () => {
 
-      it('should be created', () => {
+      it('> it should be created', () => {
         const fixture = TestBed.createComponent(LayerDetailComponent)
         const element = fixture.debugElement.componentInstance
         expect(element).toBeTruthy()
       })
   
-      it('on bind input, if input is truthy, calls get on layerService maps', () => {
+      it('> on bind input, if input is truthy, calls get on layerService maps', () => {
         const service = TestBed.inject(NgLayersService)
+        TestBed.overrideProvider(VIEWER_INJECTION_TOKEN, {
+          useValue: {}
+        })
         const {
           brightnessMapGetSpy,
           contractMapGetSpy,
@@ -109,7 +128,7 @@ describe('layerDetail.component.ts', () => {
         expect(removeBgMapGetSpy).toHaveBeenCalledWith(layerName)
       })
   
-      it('on bind input, if input is falsy, does not call layerService map get', () => {
+      it('> on bind input, if input is falsy, does not call layerService map get', () => {
         const service = TestBed.inject(NgLayersService)
         const {
           brightnessMapGetSpy,
@@ -144,8 +163,6 @@ describe('layerDetail.component.ts', () => {
       getSliderChangeTest(sliderCtrl)
     }
 
-    // TODO test remove bg toggle
-
     describe('testing: removeBG toggle', () => {
       it('on change, calls window', () => {
 
@@ -177,6 +194,9 @@ describe('layerDetail.component.ts', () => {
 
     describe('triggerChange', () => {
       it('should throw if viewer is not defined', () => {
+        TestBed.overrideProvider(VIEWER_INJECTION_TOKEN, {
+          useValue: null
+        })
         const fixutre = TestBed.createComponent(LayerDetailComponent)
         expect(function(){
           fixutre.componentInstance.triggerChange()
@@ -184,16 +204,21 @@ describe('layerDetail.component.ts', () => {
       })
 
       it('should throw if layer is not found', () => {
-        const fixutre = TestBed.createComponent(LayerDetailComponent)
-        const layerName = `test-kitty`
         const fakeGetLayerByName = jasmine.createSpy().and.returnValue(undefined)
         const fakeNgInstance = {
           layerManager: {
             getLayerByName: fakeGetLayerByName
           }
         }
+
+        TestBed.overrideProvider(VIEWER_INJECTION_TOKEN, {
+          useValue: fakeNgInstance
+        })
+
+        const fixutre = TestBed.createComponent(LayerDetailComponent)
+        const layerName = `test-kitty`
+
         fixutre.componentInstance.layerName = layerName
-        fixutre.componentInstance.ngViewerInstance = fakeNgInstance
 
         expect(function(){
           fixutre.componentInstance.triggerChange()
@@ -201,8 +226,6 @@ describe('layerDetail.component.ts', () => {
       })
 
       it('should throw if layer.layer.fragmentMain is undefined', () => {
-
-        const fixutre = TestBed.createComponent(LayerDetailComponent)
         const layerName = `test-kitty`
 
         const fakeLayer = {
@@ -214,8 +237,14 @@ describe('layerDetail.component.ts', () => {
             getLayerByName: fakeGetLayerByName
           }
         }
+
+        TestBed.overrideProvider(VIEWER_INJECTION_TOKEN, {
+          useValue: fakeNgInstance
+        })
+
+        const fixutre = TestBed.createComponent(LayerDetailComponent)
+
         fixutre.componentInstance.layerName = layerName
-        fixutre.componentInstance.ngViewerInstance = fakeNgInstance
 
         expect(function(){
           fixutre.componentInstance.triggerChange()
@@ -225,13 +254,12 @@ describe('layerDetail.component.ts', () => {
       it('should call getShader and restoreState if all goes right', () => {
 
         const replacementShader = `blabla ahder`
-
-        const service = TestBed.inject(NgLayersService)
-        const getShaderSpy = spyOn(service, 'getShader').and.returnValue(replacementShader)
-        const fixutre = TestBed.createComponent(LayerDetailComponent)
+        const getShaderSpy = jasmine.createSpy('getShader').and.returnValue(replacementShader)
+        spyOnProperty(CONSTANT, 'getShader').and.returnValue(getShaderSpy)
+        
         const layerName = `test-kitty`
 
-        const fakeRestoreState = jasmine.createSpy()
+        const fakeRestoreState = jasmine.createSpy('fakeGetLayerByName')
         const fakeLayer = {
           layer: {
             fragmentMain: {
@@ -239,14 +267,19 @@ describe('layerDetail.component.ts', () => {
             }
           }
         }
-        const fakeGetLayerByName = jasmine.createSpy().and.returnValue(fakeLayer)
+        const fakeGetLayerByName = jasmine.createSpy('fakeGetLayerByName').and.returnValue(fakeLayer)
         const fakeNgInstance = {
           layerManager: {
             getLayerByName: fakeGetLayerByName
           }
         }
+        TestBed.overrideProvider(VIEWER_INJECTION_TOKEN, {
+          useValue: fakeNgInstance
+        })
+        
+        const fixutre = TestBed.createComponent(LayerDetailComponent)
         fixutre.componentInstance.layerName = layerName
-        fixutre.componentInstance.ngViewerInstance = fakeNgInstance
+        fixutre.detectChanges()
 
         fixutre.componentInstance.triggerChange()
         
diff --git a/src/ui/layerbrowser/layerDetail/layerDetail.component.ts b/src/ui/layerbrowser/layerDetail/layerDetail.component.ts
index ea6efeafc863f1d4a9db30254b31c9d3de5249d4..ce525450d66af85854ae715723c14ff6ad6ffd35 100644
--- a/src/ui/layerbrowser/layerDetail/layerDetail.component.ts
+++ b/src/ui/layerbrowser/layerDetail/layerDetail.component.ts
@@ -1,7 +1,10 @@
-import { Component, Input, OnChanges, ChangeDetectionStrategy } from "@angular/core";
+import { Component, Input, OnChanges, ChangeDetectionStrategy, Optional, Inject } from "@angular/core";
 import { NgLayersService } from "../ngLayerService.service";
 import { MatSliderChange } from "@angular/material/slider";
 import { MatSlideToggleChange } from "@angular/material/slide-toggle";
+import { COLORMAP_IS_JET, getShader, PMAP_DEFAULT_CONFIG } from "src/util/constants";
+
+export const VIEWER_INJECTION_TOKEN = `VIEWER_INJECTION_TOKEN`
 
 @Component({
   selector: 'layer-detail-cmp',
@@ -13,15 +16,26 @@ export class LayerDetailComponent implements OnChanges{
   @Input() 
   layerName: string
 
-  @Input()
-  ngViewerInstance: any
+  private colormap = null 
 
-  constructor(private layersService: NgLayersService){
+  constructor(
+    private layersService: NgLayersService,
+    @Optional() @Inject(VIEWER_INJECTION_TOKEN) private injectedViewer
+  ){
 
   }
 
   ngOnChanges(){
     if (!this.layerName) return
+
+    const isPmap = (this.fragmentMain.value as string).includes(COLORMAP_IS_JET)
+    const { colormap, lowThreshold, removeBg } = PMAP_DEFAULT_CONFIG
+    if (isPmap) {
+      this.colormap = colormap
+      this.lowThreshold = lowThreshold
+      this.removeBg = removeBg
+    }
+
     this.lowThreshold = this.layersService.lowThresholdMap.get(this.layerName) || this.lowThreshold
     this.highThreshold = this.layersService.highThresholdMap.get(this.layerName) || this.highThreshold
     this.brightness = this.layersService.brightnessMap.get(this.layerName) || this.brightness
@@ -65,21 +79,29 @@ export class LayerDetailComponent implements OnChanges{
   }
 
   triggerChange(){
+    const { lowThreshold, highThreshold, brightness, contrast, removeBg, colormap } = this
+    const shader = getShader({
+      lowThreshold,
+      highThreshold, 
+      colormap,
+      brightness,
+      contrast,
+      removeBg
+    })
+    this.fragmentMain.restoreState(shader)
+  }
+
+  private get viewer(){
+    return this.injectedViewer || (window as any).viewer
+  }
+
+  private get fragmentMain(){
+
     if (!this.viewer) throw new Error(`viewer is not defined`)
     const layer = this.viewer.layerManager.getLayerByName(this.layerName)
     if (!layer) throw new Error(`layer with name: ${this.layerName}, not found.`)
     if (! (layer.layer?.fragmentMain?.restoreState) ) throw new Error(`layer.fragmentMain is not defined... is this an image layer?`)
-    const shader = this.layersService.getShader(
-      this.lowThreshold,
-      this.highThreshold,
-      this.brightness,
-      this.contrast,
-      this.removeBg
-    )
-    layer.layer.fragmentMain.restoreState(shader)
-  }
 
-  get viewer(){
-    return this.ngViewerInstance || (window as any).viewer
+    return layer.layer.fragmentMain
   }
 }
diff --git a/src/ui/layerbrowser/layerDetail/layerDetail.template.html b/src/ui/layerbrowser/layerDetail/layerDetail.template.html
index ef47a9b904dcd3a1c72d9380b21073d4df62965b..376b875c3ffd924a5a69166d2555104cae0c0390 100644
--- a/src/ui/layerbrowser/layerDetail/layerDetail.template.html
+++ b/src/ui/layerbrowser/layerDetail/layerDetail.template.html
@@ -72,7 +72,7 @@
     <mat-slide-toggle
       aria-label="Remove background"
       (change)="handleToggleBg($event)"
-      [value]="removeBg">
+      [(ngModel)]="removeBg">
 
     </mat-slide-toggle>
   </div>
diff --git a/src/ui/layerbrowser/layerbrowser.component.ts b/src/ui/layerbrowser/layerbrowser.component.ts
index 91121d8f27731c516768eadbc6dc62de728a2c8b..aa6e069a4e53d763030bd53989ab89ff6cc762dc 100644
--- a/src/ui/layerbrowser/layerbrowser.component.ts
+++ b/src/ui/layerbrowser/layerbrowser.component.ts
@@ -9,6 +9,7 @@ import { getViewer } from "src/util/fn";
 import { INgLayerInterface } from "../../atlasViewer/atlasViewer.component";
 import { FORCE_SHOW_SEGMENT, getNgIds, isDefined, REMOVE_NG_LAYER, safeFilter, ViewerStateInterface, IavRootStoreInterface } from "../../services/stateStore.service";
 import { MatSliderChange } from "@angular/material/slider";
+import { ARIA_LABELS } from 'common/constants'
 
 @Component({
   selector : 'layer-browser',
@@ -21,6 +22,8 @@ import { MatSliderChange } from "@angular/material/slider";
 
 export class LayerBrowser implements OnInit, OnDestroy {
 
+  public TOGGLE_SHOW_LAYER_CONTROL_ARIA_LABEL = ARIA_LABELS.TOGGLE_SHOW_LAYER_CONTROL
+
   @Output() public nonBaseLayersChanged: EventEmitter<INgLayerInterface[]> = new EventEmitter()
 
   /**
diff --git a/src/ui/layerbrowser/layerbrowser.template.html b/src/ui/layerbrowser/layerbrowser.template.html
index 4c50cf9506371c4c236dc8d89dfd10e6cd1d6942..f34b2ea8b77315f7a2b54f39d237c21b469c4a5d 100644
--- a/src/ui/layerbrowser/layerbrowser.template.html
+++ b/src/ui/layerbrowser/layerbrowser.template.html
@@ -13,7 +13,7 @@
       class="layer-expansion-unit"
       #expansionPanel>
       <mat-expansion-panel-header>
-        <div class="align-items-center d-flex flex-nowrap pr-4">
+        <div class="align-items-center d-flex flex-nowrap pr-4 w-100">
           <!-- toggle opacity -->
           <div matTooltip="opacity">
 
@@ -70,11 +70,12 @@
           <mat-label
             [matTooltipPosition]="matTooltipPosition"
             [matTooltip]="ngLayer.name | getFilenamePipe "
-            [class]="((darktheme$ | async) ? 'text-light' : 'text-dark') + ' text-truncate'">
+            [class]="((darktheme$ | async) ? 'text-light' : 'text-dark') + ' text-truncate flex-grow-1 flex-shrink-1'">
             {{ ngLayer.name | getFilenamePipe }}
           </mat-label>
 
           <button mat-icon-button
+            [attr.aria-label]="TOGGLE_SHOW_LAYER_CONTROL_ARIA_LABEL"
             (click)="expansionPanel.toggle()">
             <ng-container *ngIf="expansionPanel.expanded; else btnIconAlt">
               <i class="fas fa-chevron-up"></i>
diff --git a/src/ui/layerbrowser/ngLayerService.service.ts b/src/ui/layerbrowser/ngLayerService.service.ts
index fefb5b7c4675cfac110a02c5008f462c0de5592f..baf59a9a4191c27ea5ddffb72629148cdb1a1ab9 100644
--- a/src/ui/layerbrowser/ngLayerService.service.ts
+++ b/src/ui/layerbrowser/ngLayerService.service.ts
@@ -1,22 +1,5 @@
 import { Injectable } from "@angular/core";
 
-const setGetShaderFn = (normalizedIncomingColor) => (lowerThreshold, upperThreshold, brightness, contrast, removeBg: boolean) => `
-void main() {
-  float raw_x = toNormalized(getDataValue());
-  float x = (raw_x - ${lowerThreshold.toFixed(5)}) / (${(upperThreshold - lowerThreshold).toFixed(5)}) ${brightness > 0 ? '+' : '-'} ${Math.abs(brightness).toFixed(5)};
-
-  ${ removeBg ? 'if(x>1.0){ emitTransparent(); }else if (x<0.0){ emitTransparent(); }else{' : '' }
-  
-    emitRGB(vec3(
-      x * ${normalizedIncomingColor[0].toFixed(5)}, x * ${normalizedIncomingColor[1].toFixed(5)}, x * ${normalizedIncomingColor[2].toFixed(5)})
-      * exp(${contrast.toFixed(5)})
-    );
-
-  ${ removeBg ? '}' : '' }
-  
-}
-`
-
 @Injectable({
   providedIn: 'root'
 })
@@ -27,5 +10,4 @@ export class NgLayersService{
   public brightnessMap: Map<string, number> = new Map()
   public contrastMap: Map<string, number> = new Map()
   public removeBgMap: Map<string, boolean> = new Map()
-  public getShader: (low: number, high: number, brightness: number, contrast: number, removeBg: boolean) => string = setGetShaderFn([1, 1, 1])
 }
diff --git a/src/ui/parcellationRegion/regionMenu/regionMenu.template.html b/src/ui/parcellationRegion/regionMenu/regionMenu.template.html
index 4d538936d97e6f385673e486683d3f263b06ca5f..d4f008803fae1a52450fa862010319c168e7a609 100644
--- a/src/ui/parcellationRegion/regionMenu/regionMenu.template.html
+++ b/src/ui/parcellationRegion/regionMenu/regionMenu.template.html
@@ -138,7 +138,7 @@
       </mat-list-item>
 
       <!-- connectivity -->
-      <div iav-switch #connectivitySwitch="iavSwitch">
+      <div *ngIf="hasConnectivity" iav-switch #connectivitySwitch="iavSwitch">
 
         <mat-list-item mat-ripple
           (click)="connectivitySwitch.toggle()"
diff --git a/src/util/constants.ts b/src/util/constants.ts
index bfb83d130f37e87b74f201971016e38012127395..8a56a7ceaa97c2c654be25e3d49df77dd191d1f4 100644
--- a/src/util/constants.ts
+++ b/src/util/constants.ts
@@ -66,4 +66,39 @@ export const getHttpHeader: () => HttpHeaders = () => {
   const header = new HttpHeaders()
   header.set('referrer', getScopedReferer())
   return header
-}
\ No newline at end of file
+}
+
+const CM_MATLAB_JET = `float r;if( x < 0.7 ){r = 4.0 * x - 1.5;} else {r = -4.0 * x + 4.5;}float g;if (x < 0.5) {g = 4.0 * x - 0.5;} else {g = -4.0 * x + 3.5;}float b;if (x < 0.3) {b = 4.0 * x + 0.5;} else {b = -4.0 * x + 2.5;}float a = 1.0;`
+const CM_DEFAULT = `float r = x; float g = x; float b = x;`
+export const COLORMAP_IS_JET = `// iav-colormap-is-jet`
+export const COLORMAP_IS_DEFAULT = `// iav-colormap-default`
+
+export const getShader = ({
+  colormap = null, 
+  lowThreshold = 0,
+  highThreshold = 1,
+  brightness = 0, 
+  contrast = 0,
+  removeBg = false
+} = {}): string => {
+  const header = colormap === 'jet' ? COLORMAP_IS_JET : COLORMAP_IS_DEFAULT
+  const colormapGlsl = colormap === 'jet' ? CM_MATLAB_JET : CM_DEFAULT
+  return `${header}
+void main() {
+  float raw_x = toNormalized(getDataValue());
+  float x = (raw_x - ${lowThreshold.toFixed(5)}) / (${highThreshold - lowThreshold}) ${ brightness > 0 ? '+' : '-' } ${Math.abs(brightness).toFixed(5)};
+
+  ${ removeBg ? 'if(x>1.0){emitTransparent();}else if(x<0.0){emitTransparent();}else{' : '' }
+    ${colormapGlsl}
+
+    emitRGB(vec3(r, g, b)*exp(${contrast.toFixed(5)}));
+  ${ removeBg ? '}' : '' }
+}
+`
+}
+
+export const PMAP_DEFAULT_CONFIG = {
+  colormap: 'jet',
+  lowThreshold: 0.05,
+  removeBg: true
+}