From 2147ab78f55943549409f0091bde02ffa727421e Mon Sep 17 00:00:00 2001 From: Xiao Gui <xgui3783@gmail.com> Date: Tue, 26 Apr 2022 16:40:58 +0200 Subject: [PATCH] fix ng cusotm color map --- .../sapiViews/core/rich/module.ts | 2 + .../regionListSearch.template.html | 2 +- .../layerCtrl.service/layerCtrl.service.ts | 115 ++++++++++++------ 3 files changed, 80 insertions(+), 39 deletions(-) diff --git a/src/atlasComponents/sapiViews/core/rich/module.ts b/src/atlasComponents/sapiViews/core/rich/module.ts index 90ce115ed..8f946335e 100644 --- a/src/atlasComponents/sapiViews/core/rich/module.ts +++ b/src/atlasComponents/sapiViews/core/rich/module.ts @@ -3,6 +3,7 @@ import { NgModule } from "@angular/core"; import { ReactiveFormsModule } from "@angular/forms"; import { SxplrFlatHierarchyModule } from "src/components/flatHierarchy"; import { AngularMaterialModule } from "src/sharedModules"; +import { UtilModule } from "src/util"; import { SapiViewsUtilModule } from "../../util"; import { SapiViewsCoreRegionModule } from "../region"; import { HighlightPipe } from "./regionsHierarchy/highlight.pipe"; @@ -17,6 +18,7 @@ import { SapiViewsCoreRichRegionListSearch } from "./regionsListSearch/regionLis SapiViewsCoreRegionModule, SxplrFlatHierarchyModule, SapiViewsUtilModule, + UtilModule, ], declarations: [ SapiViewsCoreRichRegionListSearch, diff --git a/src/atlasComponents/sapiViews/core/rich/regionsListSearch/regionListSearch.template.html b/src/atlasComponents/sapiViews/core/rich/regionsListSearch/regionListSearch.template.html index 9cdee5d47..379454ff5 100644 --- a/src/atlasComponents/sapiViews/core/rich/regionsListSearch/regionListSearch.template.html +++ b/src/atlasComponents/sapiViews/core/rich/regionsListSearch/regionListSearch.template.html @@ -14,7 +14,7 @@ [matAutocomplete]="auto"> <!-- search input suffix --> - <div matSuffix> + <div matSuffix iav-stop="click"> <ng-content select="[search-input-suffix]"></ng-content> </div> diff --git a/src/viewerModule/nehuba/layerCtrl.service/layerCtrl.service.ts b/src/viewerModule/nehuba/layerCtrl.service/layerCtrl.service.ts index d6f2e4017..1fda36377 100644 --- a/src/viewerModule/nehuba/layerCtrl.service/layerCtrl.service.ts +++ b/src/viewerModule/nehuba/layerCtrl.service/layerCtrl.service.ts @@ -1,6 +1,6 @@ import { Injectable, OnDestroy } from "@angular/core"; import { select, Store } from "@ngrx/store"; -import { BehaviorSubject, combineLatest, merge, Observable, Subject, Subscription } from "rxjs"; +import { combineLatest, merge, Observable, Subject, Subscription } from "rxjs"; import { debounceTime, distinctUntilChanged, filter, map, shareReplay, startWith, switchMap, withLatestFrom } from "rxjs/operators"; import { IColorMap, INgLayerCtrl, TNgLayerCtrl } from "./layerCtrl.util"; import { SAPIRegion } from "src/atlasComponents/sapi/core"; @@ -10,6 +10,8 @@ import { annotation, atlasAppearance, atlasSelection } from "src/state"; import { serializeSegment } from "../util"; import { LayerCtrlEffects } from "./layerCtrl.effects"; import { arrayEqual } from "src/util/array"; +import { ColorMapCustomLayer } from "src/state/atlasAppearance"; +import { SapiRegionModel } from "src/atlasComponents/sapi"; export const BACKUP_COLOR = { red: 255, @@ -49,21 +51,53 @@ export class NehubaLayerControlService implements OnDestroy{ ) ) + private customLayers$ = this.store$.pipe( + select(atlasAppearance.selectors.customLayers), + distinctUntilChanged(arrayEqual((o, n) => o.id === n.id)), + shareReplay(1) + ) private activeColorMap$ = combineLatest([ - this.selectedATPR$.pipe( - map(({ atlas, parcellation, regions, template }) => { - + combineLatest([ + this.selectedATPR$, + this.customLayers$, + ]).pipe( + map(([{ atlas, parcellation, regions, template }, layers]) => { const returnVal: IColorMap = {} + + const cmCustomLayers = layers.filter(l => l.clType === "customlayer/colormap") as ColorMapCustomLayer[] + const cmBaseLayers = layers.filter(l => l.clType === "baselayer/colormap") as ColorMapCustomLayer[] + + const useCm = (() => { + /** + * if custom layer exist, use the last custom layer + */ + if (cmCustomLayers.length > 0) return cmCustomLayers[cmCustomLayers.length - 1].colormap + /** + * otherwise, use last baselayer + */ + if (cmBaseLayers.length > 0) return cmBaseLayers[cmBaseLayers.length - 1].colormap + /** + * fallback color map + */ + return { + set: () => { + throw new Error(`cannot set`) + }, + get: (r: SapiRegionModel) => SAPIRegion.GetDisplayColor(r) + } + })() + for (const r of regions) { if (!r.hasAnnotation) continue if (!r.hasAnnotation.visualizedIn) continue const ngId = getParcNgId(atlas, template, parcellation, r) - const [ red, green, blue ] = SAPIRegion.GetDisplayColor(r) const labelIndex = getRegionLabelIndex(atlas, template, parcellation, r) if (!labelIndex) continue + const [ red, green, blue ] = useCm.get(r) + if (!returnVal[ngId]) { returnVal[ngId] = {} } @@ -162,21 +196,8 @@ export class NehubaLayerControlService implements OnDestroy{ ) } - public activeColorMap: IColorMap - - public overwriteColorMap$ = new BehaviorSubject<IColorMap>(null) - - public setColorMap$: Observable<IColorMap> = merge( - this.activeColorMap$.pipe( - // TODO this is a dirty fix - // it seems, sometimes, overwritecolormap and activecolormap can emit at the same time - // (e.g. when reg selection changes) - // this ensures that the activecolormap emits later, and thus take effect over overwrite colormap - debounceTime(16), - ), - this.overwriteColorMap$.pipe( - filter(v => !!v), - ) + public setColorMap$: Observable<IColorMap> = this.activeColorMap$.pipe( + debounceTime(16), ).pipe( shareReplay(1) ) @@ -206,30 +227,42 @@ export class NehubaLayerControlService implements OnDestroy{ * selectedRegions */ this.selectedRegion$, + this.customLayers$.pipe( + map(layers => layers.filter(l => l.clType === "customlayer/colormap").length > 0), + ), /** * if layer contains non mixable layer */ - this.store$.pipe( - select(atlasAppearance.selectors.customLayers), + this.customLayers$.pipe( map(layers => layers.filter(l => l.clType === "customlayer/nglayer").length > 0), ), ]).pipe( - withLatestFrom(this.selectedATP$), - map(([[ regions, nonmixableLayerExists ], { atlas, parcellation, template }]) => { - if (nonmixableLayerExists) { + withLatestFrom(this.selectedATPR$), + map(([[ selectedRegions, customMapExists, nonmixableLayerExists ], { atlas, parcellation, template, regions }]) => { + /** + * if non mixable layer exist (e.g. pmap) + * and no custom color map exist + * hide all segmentations + */ + if (!customMapExists && nonmixableLayerExists) { return null } - /* selectedregionindexset needs to be updated regardless of forceshowsegment */ - const selectedRegionIndexSet = new Set<string>( - regions.map(r => { + /** + * if custom map exists, roi is all regions + * otherwise, roi is only selectedRegions + */ + const roi = customMapExists ? regions : selectedRegions + + const roiIndexSet = new Set<string>( + roi.map(r => { const ngId = getParcNgId(atlas, template, parcellation, r) const label = getRegionLabelIndex(atlas, template, parcellation, r) - return serializeSegment(ngId, label) - }) + return ngId && label && serializeSegment(ngId, label) + }).filter(v => !!v) ) - if (selectedRegionIndexSet.size > 0) { - return [...selectedRegionIndexSet] + if (roiIndexSet.size > 0) { + return [...roiIndexSet] } else { return [] } @@ -242,8 +275,7 @@ export class NehubaLayerControlService implements OnDestroy{ private ngLayersRegister: atlasAppearance.NgLayerCustomLayer[] = [] - private ngLayers$ = this.store$.pipe( - select(atlasAppearance.selectors.customLayers), + private ngLayers$ = this.customLayers$.pipe( map(customLayers => customLayers.filter(l => l.clType === "customlayer/nglayer") as atlasAppearance.NgLayerCustomLayer[]), distinctUntilChanged( arrayEqual((o, n) => o.id === n.id) @@ -304,10 +336,17 @@ export class NehubaLayerControlService implements OnDestroy{ ), this.ngLayers$.pipe( map(({ customLayers }) => customLayers), - startWith([] as atlasAppearance.NgLayerCustomLayer[]) + startWith([] as atlasAppearance.NgLayerCustomLayer[]), + map(customLayers => { + /** + * pmap control has its own visibility controller + */ + return customLayers + .map(l => l.id) + .filter(name => name !== NehubaLayerControlService.PMAP_LAYER_NAME) + }) ), - this.store$.pipe( - select(atlasAppearance.selectors.customLayers), + this.customLayers$.pipe( map(cl => { const otherColormapExist = cl.filter(l => l.clType === "customlayer/colormap").length > 0 const pmapExist = cl.filter(l => l.clType === "customlayer/nglayer").length > 0 @@ -320,6 +359,6 @@ export class NehubaLayerControlService implements OnDestroy{ ) ) ]).pipe( - map(([ expectedLayerNames, customLayers, pmapLayer ]) => [...expectedLayerNames, ...customLayers.map(l => l.id), ...pmapLayer]) + map(([ expectedLayerNames, customLayerNames, pmapName ]) => [...expectedLayerNames, ...customLayerNames, ...pmapName]) ) } -- GitLab