From ba4aad9dd4623b752f1d0a2dbc4d39cb0c07335c Mon Sep 17 00:00:00 2001 From: Xiao Gui <xgui3783@gmail.com> Date: Mon, 4 Jan 2021 17:39:20 +0100 Subject: [PATCH] WIP nehuba --- src/ui/nehubaContainer/nehuba.module.ts | 22 --- .../nehubaContainer.component.spec.ts | 21 ++- .../nehubaContainer.component.ts | 10 +- .../nehubaContainer.template.html | 21 +-- src/viewerModule/index.ts | 1 + src/viewerModule/module.ts | 14 ++ src/viewerModule/nehuba/actions.ts | 10 ++ src/viewerModule/nehuba/constants.ts | 69 +++++++++ src/viewerModule/nehuba/index.ts | 4 + src/viewerModule/nehuba/module.ts | 39 +++++ .../nehubaViewer.component.spec.ts | 0 .../nehubaViewer/nehubaViewer.component.ts | 11 +- .../nehubaViewer/nehubaViewer.style.css | 0 .../nehubaViewer/nehubaViewer.template.html | 0 .../nehubaViewerGlue.component.ts | 138 ++++++++++++++++++ .../nehubaViewerGlue.style.css | 0 .../nehubaViewerGlue.template.html | 5 + .../nehubaViewerInterface.directive.spec.ts | 0 .../nehubaViewerInterface.directive.ts | 2 +- .../nehubaViewerTouch.directive.ts | 0 src/viewerModule/nehuba/store.ts | 36 +++++ .../nehuba}/util.ts | 0 src/viewerModule/viewer.interface.ts | 48 ++++++ .../viewerCmp/viewerCmp.component.ts | 12 ++ .../viewerCmp/viewerCmp.style.css | 0 .../viewerCmp/viewerCmp.template.html | 0 26 files changed, 409 insertions(+), 54 deletions(-) delete mode 100644 src/ui/nehubaContainer/nehuba.module.ts create mode 100644 src/viewerModule/index.ts create mode 100644 src/viewerModule/module.ts create mode 100644 src/viewerModule/nehuba/actions.ts create mode 100644 src/viewerModule/nehuba/constants.ts create mode 100644 src/viewerModule/nehuba/index.ts create mode 100644 src/viewerModule/nehuba/module.ts rename src/{ui/nehubaContainer => viewerModule/nehuba}/nehubaViewer/nehubaViewer.component.spec.ts (100%) rename src/{ui/nehubaContainer => viewerModule/nehuba}/nehubaViewer/nehubaViewer.component.ts (99%) rename src/{ui/nehubaContainer => viewerModule/nehuba}/nehubaViewer/nehubaViewer.style.css (100%) rename src/{ui/nehubaContainer => viewerModule/nehuba}/nehubaViewer/nehubaViewer.template.html (100%) create mode 100644 src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.component.ts create mode 100644 src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.style.css create mode 100644 src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.template.html rename src/{ui/nehubaContainer => viewerModule/nehuba}/nehubaViewerInterface/nehubaViewerInterface.directive.spec.ts (100%) rename src/{ui/nehubaContainer => viewerModule/nehuba}/nehubaViewerInterface/nehubaViewerInterface.directive.ts (99%) rename src/{ui/nehubaContainer => viewerModule/nehuba}/nehubaViewerInterface/nehubaViewerTouch.directive.ts (100%) create mode 100644 src/viewerModule/nehuba/store.ts rename src/{ui/nehubaContainer => viewerModule/nehuba}/util.ts (100%) create mode 100644 src/viewerModule/viewer.interface.ts create mode 100644 src/viewerModule/viewerCmp/viewerCmp.component.ts create mode 100644 src/viewerModule/viewerCmp/viewerCmp.style.css create mode 100644 src/viewerModule/viewerCmp/viewerCmp.template.html diff --git a/src/ui/nehubaContainer/nehuba.module.ts b/src/ui/nehubaContainer/nehuba.module.ts deleted file mode 100644 index 0104d0c01..000000000 --- a/src/ui/nehubaContainer/nehuba.module.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { NgModule } from "@angular/core"; -import { NehubaViewerContainerDirective } from './nehubaViewerInterface/nehubaViewerInterface.directive' -import { NehubaViewerUnit } from "./nehubaViewer/nehubaViewer.component"; -import { CommonModule } from "@angular/common"; -@NgModule({ - imports: [ - CommonModule - ], - declarations: [ - NehubaViewerContainerDirective, - NehubaViewerUnit - ], - exports: [ - NehubaViewerContainerDirective, - NehubaViewerUnit - ], - entryComponents: [ - NehubaViewerUnit - ] -}) - -export class NehubaModule{} diff --git a/src/ui/nehubaContainer/nehubaContainer.component.spec.ts b/src/ui/nehubaContainer/nehubaContainer.component.spec.ts index 796c6ce28..3a839f318 100644 --- a/src/ui/nehubaContainer/nehubaContainer.component.spec.ts +++ b/src/ui/nehubaContainer/nehubaContainer.component.spec.ts @@ -8,16 +8,14 @@ import { TouchSideClass } from "./touchSideClass.directive" import { MaximmisePanelButton } from "./maximisePanelButton/maximisePanelButton.component" import { LayoutModule } from 'src/layouts/layout.module' import { PureContantService, UtilModule } from "src/util" -import { AtlasLayerSelector } from "../atlasLayerSelector/atlasLayerSelector.component" +import { AtlasLayerSelector } from "../../atlasComponents/uiSelectors/atlasLayerSelector/atlasLayerSelector.component" import { StatusCardComponent } from './statusCard/statusCard.component' import { NehubaViewerTouchDirective } from './nehubaViewerInterface/nehubaViewerTouch.directive' import { MobileOverlay } from "./mobileOverlay/mobileOverlay.component" -import { RegionMenuComponent } from "../parcellationRegion/regionMenu/regionMenu.component" -import { DatabrowserModule } from "../databrowserModule" + +import { DatabrowserModule } from "../../atlasComponents/databrowserModule" import { SplashScreen } from "./splashScreen/splashScreen.component" import { CurrentLayout } from 'src/ui/config/currentLayout/currentLayout.component' -import { RegionDirective } from 'src/ui/parcellationRegion/region.directive' -import { RegionTextSearchAutocomplete } from "../viewerStateController/regionSearch/regionSearch.component" import { MobileControlNubStylePipe } from './pipes/mobileControlNubStyle.pipe' import { ReorderPanelIndexPipe } from './reorderPanelIndex.pipe' import { AuthModule } from 'src/auth' @@ -29,7 +27,6 @@ import { NehubaModule } from './nehuba.module' import { CommonModule } from '@angular/common' import { IMPORT_NEHUBA_INJECT_TOKEN } from './nehubaViewer/nehubaViewer.component' import { viewerStateCustomLandmarkSelector, viewerStateHelperStoreName } from 'src/services/state/viewerState.store.helper' -import { RenderViewOriginDatasetLabelPipe } from '../parcellationRegion/region.base' import { By } from '@angular/platform-browser' import { ARIA_LABELS } from 'common/constants' import { NoopAnimationsModule } from '@angular/platform-browser/animations' @@ -38,8 +35,10 @@ import { hot } from 'jasmine-marbles' import { HttpClientTestingModule } from '@angular/common/http/testing' import { ngViewerSelectorOctantRemoval, ngViewerSelectorPanelMode, ngViewerSelectorPanelOrder } from 'src/services/state/ngViewerState/selectors' import { PANELS } from 'src/services/state/ngViewerState/constants' -import { RegionalFeaturesModule } from '../regionalFeatures' +import { RegionalFeaturesModule } from '../../atlasComponents/regionalFeatures' import { Landmark2DModule } from './2dLandmarks/module' +import { ParcellationRegionModule } from 'src/atlasComponents/parcellationRegion' +import { AtlasCmpParcellationModule } from 'src/atlasComponents/parcellation' const { TOGGLE_SIDE_PANEL, @@ -81,6 +80,8 @@ describe('> nehubaContainer.component.ts', () => { HttpClientModule, CommonModule, RegionalFeaturesModule, + ParcellationRegionModule, + AtlasCmpParcellationModule, /** * because the change done to pureconstant service, need to intercept http call to avoid crypto error message @@ -97,16 +98,14 @@ describe('> nehubaContainer.component.ts', () => { StatusCardComponent, NehubaViewerTouchDirective, MobileOverlay, - RegionMenuComponent, + SplashScreen, CurrentLayout, - RegionDirective, - RegionTextSearchAutocomplete, // pipes MobileControlNubStylePipe, ReorderPanelIndexPipe, - RenderViewOriginDatasetLabelPipe, + RegionAccordionTooltipTextPipe, ], providers: [ diff --git a/src/ui/nehubaContainer/nehubaContainer.component.ts b/src/ui/nehubaContainer/nehubaContainer.component.ts index 31baa1076..63123a69b 100644 --- a/src/ui/nehubaContainer/nehubaContainer.component.ts +++ b/src/ui/nehubaContainer/nehubaContainer.component.ts @@ -8,7 +8,6 @@ import { MatDrawer } from "@angular/material/sidenav"; import { LoggingService } from "src/logging"; import { CHANGE_NAVIGATION, - generateLabelIndexId, getMultiNgIdsRegionsLabelIndexMap, getNgIds, ILandmark, @@ -26,6 +25,7 @@ import { NehubaViewerUnit } from "./nehubaViewer/nehubaViewer.component"; import { compareLandmarksChanged } from "src/util/constants"; import { PureContantService } from "src/util"; import { ARIA_LABELS, IDS, CONST } from 'common/constants' +import { serialiseParcellationRegion } from "common/util" import { ngViewerActionSetPerspOctantRemoval, PANELS, ngViewerActionToggleMax, ngViewerActionAddNgLayer, ngViewerActionRemoveNgLayer } from "src/services/state/ngViewerState.store.helper"; import { viewerStateSelectRegionWithIdDeprecated, viewerStateAddUserLandmarks, viewreStateRemoveUserLandmarks, viewerStateCustomLandmarkSelector, viewerStateSelectedParcellationSelector, viewerStateSelectedTemplateSelector, viewerStateSelectedRegionsSelector } from 'src/services/state/viewerState.store.helper' import { SwitchDirective } from "src/util/directives/switch.directive"; @@ -36,7 +36,6 @@ import { import { getFourPanel, getHorizontalOneThree, getSinglePanel, getVerticalOneThree, calculateSliceZoomFactor, scanSliceViewRenderFn as scanFn, takeOnePipe } from "./util"; import { NehubaViewerContainerDirective } from "./nehubaViewerInterface/nehubaViewerInterface.directive"; import { ITunableProp } from "./mobileOverlay/mobileOverlay.component"; -import {ConnectivityBrowserComponent} from "src/ui/connectivityBrowser/connectivityBrowser.component"; import { viewerStateMouseOverCustomLandmark } from "src/services/state/viewerState/actions"; import { ngViewerSelectorNehubaReady, ngViewerSelectorOctantRemoval, ngViewerSelectorPanelMode, ngViewerSelectorPanelOrder } from "src/services/state/ngViewerState/selectors"; import { REGION_OF_INTEREST } from "src/util/interfaces"; @@ -307,7 +306,6 @@ export class NehubaContainer implements OnInit, OnChanges, OnDestroy { public hoveredPanelIndices$: Observable<number> public connectivityNumber: string - public connectivityLoadUrl: string constructor( private pureConstantService: PureContantService, @@ -757,7 +755,7 @@ export class NehubaContainer implements OnInit, OnChanges, OnDestroy { /* selectedregionindexset needs to be updated regardless of forceshowsegment */ this.selectedRegionIndexSet = !prevParcellation || prevParcellation === selectedParcellation? - new Set(regions.map(({ngId = defaultNgId, labelIndex}) => generateLabelIndexId({ ngId, labelIndex }))) : new Set() + new Set(regions.map(({ngId = defaultNgId, labelIndex}) => serialiseParcellationRegion({ ngId, labelIndex }))) : new Set() if ( forceShowSegment === false || (forceShowSegment === null && hideSegmentFlag) ) { this.nehubaViewer.hideAllSeg() @@ -818,7 +816,7 @@ export class NehubaContainer implements OnInit, OnChanges, OnDestroy { this.selectedRegions$.pipe( filter(() => !!this.nehubaViewer), ).subscribe(regions => { - this.nehubaViewer.initRegions = regions.map(({ ngId, labelIndex }) => generateLabelIndexId({ ngId, labelIndex })) + this.nehubaViewer.initRegions = regions.map(({ ngId, labelIndex }) => serialiseParcellationRegion({ ngId, labelIndex })) }) ) @@ -1080,7 +1078,7 @@ export class NehubaContainer implements OnInit, OnChanges, OnDestroy { const selectRegionIds = [] this.multiNgIdsRegionsLabelIndexMap.forEach((map, ngId) => { Array.from(map.keys()).forEach(labelIndex => { - selectRegionIds.push(generateLabelIndexId({ ngId, labelIndex })) + selectRegionIds.push(serialiseParcellationRegion({ ngId, labelIndex })) }) }) this.store.dispatch(viewerStateSelectRegionWithIdDeprecated({ diff --git a/src/ui/nehubaContainer/nehubaContainer.template.html b/src/ui/nehubaContainer/nehubaContainer.template.html index b08904a09..921151abb 100644 --- a/src/ui/nehubaContainer/nehubaContainer.template.html +++ b/src/ui/nehubaContainer/nehubaContainer.template.html @@ -393,7 +393,6 @@ <!-- regional features--> <ng-template #regionalFeaturesTmpl> <data-browser - [parcellation]="selectedParcellation" [disableVirtualScroll]="true" [regions]="regions"> </data-browser> @@ -572,7 +571,6 @@ [parcellationId]="selectedParcellation['@id']" (setOpenState)="expansionPanel.expanded = $event" (connectivityNumberReceived)="connectivityNumber = $event" - (connectivityLoadUrl)="connectivityLoadUrl = $event" [accordionExpanded]="expansionPanel.expanded"> </connectivity-browser> </ng-container> @@ -592,13 +590,16 @@ <div class="w-0 h-0" iav-counter #connectedCounterDir="iavCounter"> - - <hbp-connectivity-matrix-row *ngIf="region && region.name" - [region]="region.name + (region.status? ' - ' + region.status : '')" - (connectivityDataReceived)="connectedCounterDir.value = $event.detail.length" - class="invisible d-block h-0 w-0" - [loadurl]="connectivityLoadUrl"> - </hbp-connectivity-matrix-row> + <!-- TODO figure out why conn browser does not work here --> + <!-- @fsdavid, can you take a look why this component is not emitting connectivityNumberReceived event? --> + <connectivity-browser *ngIf="region && region.name" + class="d-block h-0 w-0 overflow-hidden" + [region]="region" + [parcellationId]="selectedParcellation['@id']" + [accordionExpanded]="true" + (connectivityNumberReceived)="connectedCounterDir.value = $event"> + + </connectivity-browser> </div> </mat-accordion> </ng-template> @@ -667,7 +668,7 @@ <landmark-2d-flat-cmp *ngFor="let spatialData of (selectedPtLandmarks$ | async)" (mouseenter)="handleMouseEnterLandmark(spatialData)" (mouseleave)="handleMouseLeaveLandmark(spatialData)" - [highlight]="spatialData.highlight ? spatialData.highlight : false" + [color]="spatialData.highlight ? [255, 0, 0] : [255, 255, 255]" [positionX]="getPositionX(panelIndex, spatialData)" [positionY]="getPositionY(panelIndex, spatialData)" [positionZ]="getPositionZ(panelIndex, spatialData)"> diff --git a/src/viewerModule/index.ts b/src/viewerModule/index.ts new file mode 100644 index 000000000..6e5c74fbe --- /dev/null +++ b/src/viewerModule/index.ts @@ -0,0 +1 @@ +export { ViewerModule } from "./module" \ No newline at end of file diff --git a/src/viewerModule/module.ts b/src/viewerModule/module.ts new file mode 100644 index 000000000..95ea23da8 --- /dev/null +++ b/src/viewerModule/module.ts @@ -0,0 +1,14 @@ +import { CommonModule } from "@angular/common"; +import { NgModule } from "@angular/core"; +import { NehubaModule } from "./nehuba"; + +@NgModule({ + imports: [ + CommonModule, + NehubaModule, + ], + declarations: [], + exports: [] +}) + +export class ViewerModule{} \ No newline at end of file diff --git a/src/viewerModule/nehuba/actions.ts b/src/viewerModule/nehuba/actions.ts new file mode 100644 index 000000000..979a485f1 --- /dev/null +++ b/src/viewerModule/nehuba/actions.ts @@ -0,0 +1,10 @@ +import { createAction, props } from "@ngrx/store"; +import { INgLayerInterface } from "src/services/state/ngViewerState.store"; +import { NEHUBA_VIEWER_FEATURE_KEY } from "./constants"; + +export const actionAddNgLayer = createAction( + `[${NEHUBA_VIEWER_FEATURE_KEY}] [addNgLayer]`, + props<{ + layers: INgLayerInterface[] + }>() +) \ No newline at end of file diff --git a/src/viewerModule/nehuba/constants.ts b/src/viewerModule/nehuba/constants.ts new file mode 100644 index 000000000..31cdb1d29 --- /dev/null +++ b/src/viewerModule/nehuba/constants.ts @@ -0,0 +1,69 @@ + +export const NEHUBA_VIEWER_FEATURE_KEY = 'ngViewerFeature' + +export interface INgLayerInterface { + name: string // displayName + source: string + mixability: string // base | mixable | nonmixable + annotation?: string // + id?: string // unique identifier + visible?: boolean + shader?: string + transform?: any +} + + +export function 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 function getMultiNgIdsRegionsLabelIndexMap(parcellation: any = {}, inheritAttrsOpt: any = { ngId: 'root' }): Map<string, Map<number, any>> { + const map: Map<string, Map<number, any>> = new Map() + + const inheritAttrs = Object.keys(inheritAttrsOpt) + if (inheritAttrs.indexOf('children') >=0 ) throw new Error(`children attr cannot be inherited`) + + const processRegion = (region: any) => { + const { ngId: rNgId } = region + const existingMap = map.get(rNgId) + const labelIndex = Number(region.labelIndex) + if (labelIndex) { + if (!existingMap) { + const newMap = new Map() + newMap.set(labelIndex, region) + map.set(rNgId, newMap) + } else { + existingMap.set(labelIndex, region) + } + } + + if (region.children && Array.isArray(region.children)) { + for (const r of region.children) { + const copiedRegion = { ...r } + for (const attr of inheritAttrs){ + copiedRegion[attr] = copiedRegion[attr] || region[attr] || parcellation[attr] + } + processRegion(copiedRegion) + } + } + } + + if (!parcellation) throw new Error(`parcellation needs to be defined`) + if (!parcellation.regions) throw new Error(`parcellation.regions needs to be defined`) + if (!Array.isArray(parcellation.regions)) throw new Error(`parcellation.regions needs to be an array`) + + for (const region of parcellation.regions){ + const copiedregion = { ...region } + for (const attr of inheritAttrs){ + copiedregion[attr] = copiedregion[attr] || parcellation[attr] + } + processRegion(copiedregion) + } + + return map +} diff --git a/src/viewerModule/nehuba/index.ts b/src/viewerModule/nehuba/index.ts new file mode 100644 index 000000000..240412426 --- /dev/null +++ b/src/viewerModule/nehuba/index.ts @@ -0,0 +1,4 @@ +export { NehubaViewerTouchDirective } from "./nehubaViewerInterface/nehubaViewerTouch.directive" +export { NehubaModule } from "./module" +export { NehubaViewerContainerDirective } from "./nehubaViewerInterface/nehubaViewerInterface.directive" +export { NehubaViewerUnit } from "./nehubaViewer/nehubaViewer.component" diff --git a/src/viewerModule/nehuba/module.ts b/src/viewerModule/nehuba/module.ts new file mode 100644 index 000000000..88e9c4ecd --- /dev/null +++ b/src/viewerModule/nehuba/module.ts @@ -0,0 +1,39 @@ +import { NgModule } from "@angular/core"; +import { NehubaViewerContainerDirective } from './nehubaViewerInterface/nehubaViewerInterface.directive' +import { IMPORT_NEHUBA_INJECT_TOKEN, NehubaViewerUnit } from "./nehubaViewer/nehubaViewer.component"; +import { CommonModule } from "@angular/common"; +import { APPEND_SCRIPT_TOKEN } from "src/util/constants"; +import { importNehubaFactory } from "./util"; +import { NehubaViewerTouchDirective } from "./nehubaViewerInterface/nehubaViewerTouch.directive"; +import { StoreModule } from "@ngrx/store"; +import { NEHUBA_VIEWER_FEATURE_KEY } from "./constants"; +import { reducer } from "./store"; + +@NgModule({ + imports: [ + CommonModule, + StoreModule.forFeature( + NEHUBA_VIEWER_FEATURE_KEY, + reducer + ) + ], + declarations: [ + NehubaViewerContainerDirective, + NehubaViewerUnit, + NehubaViewerTouchDirective, + ], + exports: [ + NehubaViewerContainerDirective, + NehubaViewerUnit, + NehubaViewerTouchDirective, + ], + providers: [ + { + provide: IMPORT_NEHUBA_INJECT_TOKEN, + useFactory: importNehubaFactory, + deps: [ APPEND_SCRIPT_TOKEN ] + } + ] +}) + +export class NehubaModule{} diff --git a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.spec.ts b/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.spec.ts similarity index 100% rename from src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.spec.ts rename to src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.spec.ts diff --git a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts b/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.ts similarity index 99% rename from src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts rename to src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.ts index d1edab5e0..5626c2803 100644 --- a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts +++ b/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.ts @@ -3,7 +3,6 @@ import { fromEvent, Subscription, ReplaySubject, BehaviorSubject, Observable, ra import { debounceTime, filter, map, scan, startWith, mapTo, switchMap, take, skip } from "rxjs/operators"; import { AtlasWorkerService } from "src/atlasViewer/atlasViewer.workerService.service"; import { StateInterface as ViewerConfiguration } from "src/services/state/viewerConfig.store"; -import { getNgIdLabelIndexFromId } from "src/services/stateStore.service"; import { LoggingService } from "src/logging"; import { getExportNehuba, getViewer, setNehubaViewer } from "src/util/fn"; @@ -11,7 +10,7 @@ import { getExportNehuba, getViewer, setNehubaViewer } from "src/util/fn"; import '!!file-loader?context=third_party&name=main.bundle.js!export-nehuba/dist/min/main.bundle.js' import '!!file-loader?context=third_party&name=chunk_worker.bundle.js!export-nehuba/dist/min/chunk_worker.bundle.js' import { scanSliceViewRenderFn } from "../util"; -import { intToRgb as intToColour } from 'common/util' +import { intToRgb as intToColour, deserialiseParcRegionId } from 'common/util' const NG_LANDMARK_LAYER_NAME = 'spatial landmark layer' const NG_USER_LANDMARK_LAYER_NAME = 'user landmark layer' @@ -681,9 +680,13 @@ export class NehubaViewerUnit implements OnInit, OnDestroy { const reduceFn: (acc: Map<string, number[]>, curr: string) => Map<string, number[]> = (acc, curr) => { const newMap = new Map(acc) - const { ngId, labelIndex } = getNgIdLabelIndexFromId({ labelIndexId: curr }) + const { ngId, labelIndex } = deserialiseParcRegionId(curr) const exist = newMap.get(ngId) - if (!exist) { newMap.set(ngId, [Number(labelIndex)]) } else { newMap.set(ngId, [...exist, Number(labelIndex)]) } + if (!exist) { + newMap.set(ngId, [Number(labelIndex)]) + } else { + newMap.set(ngId, [...exist, Number(labelIndex)]) + } return newMap } diff --git a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.style.css b/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.style.css similarity index 100% rename from src/ui/nehubaContainer/nehubaViewer/nehubaViewer.style.css rename to src/viewerModule/nehuba/nehubaViewer/nehubaViewer.style.css diff --git a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.template.html b/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.template.html similarity index 100% rename from src/ui/nehubaContainer/nehubaViewer/nehubaViewer.template.html rename to src/viewerModule/nehuba/nehubaViewer/nehubaViewer.template.html diff --git a/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.component.ts b/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.component.ts new file mode 100644 index 000000000..84fb0edc8 --- /dev/null +++ b/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.component.ts @@ -0,0 +1,138 @@ +import { Component, Input, OnChanges, SimpleChanges, ViewChild } from "@angular/core"; +import { Store } from "@ngrx/store"; +import { Subject } from "rxjs"; +import { ngViewerActionAddNgLayer } from "src/services/state/ngViewerState/actions"; +import { getNgIds, getMultiNgIdsRegionsLabelIndexMap } from "../constants"; +import { IViewer, TViewerEvent } from "../../viewer.interface"; +import { NehubaViewerUnit } from "../nehubaViewer/nehubaViewer.component"; +import { NehubaViewerContainerDirective } from "../nehubaViewerInterface/nehubaViewerInterface.directive"; + +interface INgLayerInterface { + name: string // displayName + source: string + mixability: string // base | mixable | nonmixable + annotation?: string // + id?: string // unique identifier + visible?: boolean + shader?: string + transform?: any +} + + +@Component({ + selector: 'iav-cmp-viewer-nehuba-glue', + templateUrl: './nehubaViewerGlue.template.html', + styleUrls: [ + './nehubaViewerGlue.style.css' + ] +}) + +export class NehubaGlueCmp implements IViewer, OnChanges{ + + @ViewChild(NehubaViewerContainerDirective, { static: true }) + public nehubaContainerDirective: NehubaViewerContainerDirective + + public viewerEvents$ = new Subject<TViewerEvent>() + + private viewerUnit: NehubaViewerUnit + private ngLayersRegister: {layers: INgLayerInterface[]} = { + layers: [] + } + private multiNgIdsRegionsLabelIndexMap: Map<string, Map<number, any>> + + @Input() + public selectedParcellation: any + + @Input() + public selectedTemplate: any + + ngOnChanges(sc: SimpleChanges){ + const { + selectedParcellation, + selectedTemplate + } = sc + if (selectedTemplate.currentValue !== selectedTemplate.previousValue) { + this.loadTmpl(selectedTemplate.currentValue, selectedParcellation.currentValue) + } else if (selectedParcellation.currentValue !== selectedParcellation.previousValue) { + + } + } + + private loadParc(parcellation: any) { + /** + * parcellaiton may be undefined + */ + if ( !(parcellation && parcellation.regions)) { + return + } + + /** + * first, get all all the ngIds, including parent id from parcellation (if defined) + */ + const ngIds = getNgIds(parcellation.regions).concat( parcellation.ngId ? parcellation.ngId : []) + + this.multiNgIdsRegionsLabelIndexMap = getMultiNgIdsRegionsLabelIndexMap(parcellation) + + this.viewerUnit.multiNgIdsLabelIndexMap = this.multiNgIdsRegionsLabelIndexMap + this.viewerUnit.auxilaryMeshIndices = parcellation.auxillaryMeshIndices || [] + + /* TODO replace with proper KG id */ + /** + * need to set unique array of ngIds, or else workers will be overworked + */ + this.viewerUnit.ngIds = Array.from(new Set(ngIds)) + } + + private async loadTmpl(template: any, parcellation: any) { + this.nehubaContainerDirective.createNehubaInstance(template) + this.viewerUnit = this.nehubaContainerDirective.nehubaViewerInstance + + const foundParcellation = parcellation + && template?.parcellations?.find(p => parcellation.name === p.name) + this.loadParc(foundParcellation || template.parcellations[0]) + + + const nehubaConfig = template.nehubaConfig + const initialSpec = nehubaConfig.dataset.initialNgState + const {layers} = initialSpec + + const dispatchLayers = Object.keys(layers).map(key => { + const layer = { + name : key, + source : layers[key].source, + mixability : layers[key].type === 'image' + ? 'base' + : 'mixable', + visible : typeof layers[key].visible === 'undefined' + ? true + : layers[key].visible, + transform : typeof layers[key].transform === 'undefined' + ? null + : layers[key].transform, + } + this.ngLayersRegister.layers.push(layer) + return layer + }) + + this.store.dispatch(ngViewerActionAddNgLayer({ + layer: dispatchLayers + })) + } + + constructor( + private store: Store<any> + ){ + this.viewerEvents$.next({ + type: 'MOUSEOVER_ANNOTATION', + data: {} + }) + } + + handleViewerLoadedEvent(flag: boolean) { + this.viewerEvents$.next({ + type: 'VIEWERLOADED', + data: flag + }) + } + +} \ No newline at end of file diff --git a/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.style.css b/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.style.css new file mode 100644 index 000000000..e69de29bb diff --git a/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.template.html b/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.template.html new file mode 100644 index 000000000..2077c35c5 --- /dev/null +++ b/src/viewerModule/nehuba/nehubaViewerGlue/nehubaViewerGlue.template.html @@ -0,0 +1,5 @@ +<div + iav-nehuba-viewer-container + (iavNehubaViewerContainerViewerLoading)="handleViewerLoadedEvent($event)"> + +</div> \ No newline at end of file diff --git a/src/ui/nehubaContainer/nehubaViewerInterface/nehubaViewerInterface.directive.spec.ts b/src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerInterface.directive.spec.ts similarity index 100% rename from src/ui/nehubaContainer/nehubaViewerInterface/nehubaViewerInterface.directive.spec.ts rename to src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerInterface.directive.spec.ts diff --git a/src/ui/nehubaContainer/nehubaViewerInterface/nehubaViewerInterface.directive.ts b/src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerInterface.directive.ts similarity index 99% rename from src/ui/nehubaContainer/nehubaViewerInterface/nehubaViewerInterface.directive.ts rename to src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerInterface.directive.ts index f4a1973ae..77d0da2c0 100644 --- a/src/ui/nehubaContainer/nehubaViewerInterface/nehubaViewerInterface.directive.ts +++ b/src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerInterface.directive.ts @@ -3,7 +3,7 @@ import { NehubaViewerUnit, INehubaLifecycleHook } from "../nehubaViewer/nehubaVi import { Store, select } from "@ngrx/store"; import { IavRootStoreInterface } from "src/services/stateStore.service"; import { Subscription, Observable, fromEvent } from "rxjs"; -import { distinctUntilChanged, filter, debounceTime, shareReplay, scan, map, throttleTime, switchMapTo } from "rxjs/operators"; +import { distinctUntilChanged, filter, debounceTime, scan, map, throttleTime, switchMapTo } from "rxjs/operators"; import { StateInterface as ViewerConfigStateInterface } from "src/services/state/viewerConfig.store"; import { getNavigationStateFromConfig, takeOnePipe } from "../util"; import { NEHUBA_LAYER_CHANGED, CHANGE_NAVIGATION } from "src/services/state/viewerState.store"; diff --git a/src/ui/nehubaContainer/nehubaViewerInterface/nehubaViewerTouch.directive.ts b/src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerTouch.directive.ts similarity index 100% rename from src/ui/nehubaContainer/nehubaViewerInterface/nehubaViewerTouch.directive.ts rename to src/viewerModule/nehuba/nehubaViewerInterface/nehubaViewerTouch.directive.ts diff --git a/src/viewerModule/nehuba/store.ts b/src/viewerModule/nehuba/store.ts new file mode 100644 index 000000000..f00a21703 --- /dev/null +++ b/src/viewerModule/nehuba/store.ts @@ -0,0 +1,36 @@ +import { createReducer } from "@ngrx/store"; +import { INgLayerInterface } from "src/services/state/ngViewerState.store"; + + +/** + * TODO port from global store to feature store + */ + +enum EnumPanelMode { + FOUR_PANEL = 'FOUR_PANEL', + V_ONE_THREE = 'V_ONE_THREE', + H_ONE_THREE = 'H_ONE_THREE', + SINGLE_PANEL = 'SINGLE_PANEL', +} + +interface INehubaFeature { + layers: INgLayerInterface[] + panelMode: string + panelOrder: string + octantRemoval: boolean + clearViewQueue: { + [key: string]: boolean + } +} + +const defaultState: INehubaFeature = { + layers: [], + panelMode: EnumPanelMode.FOUR_PANEL, + panelOrder: '0123', + octantRemoval: true, + clearViewQueue: {} +} + +export const reducer = createReducer( + defaultState +) \ No newline at end of file diff --git a/src/ui/nehubaContainer/util.ts b/src/viewerModule/nehuba/util.ts similarity index 100% rename from src/ui/nehubaContainer/util.ts rename to src/viewerModule/nehuba/util.ts diff --git a/src/viewerModule/viewer.interface.ts b/src/viewerModule/viewer.interface.ts new file mode 100644 index 000000000..536a5eec6 --- /dev/null +++ b/src/viewerModule/viewer.interface.ts @@ -0,0 +1,48 @@ +import { Observable } from "rxjs"; + +type TLayersColorMap = Map<string, Map<number, { red: number, green: number, blue: number }>> + +interface IViewerCtrl { + + // navigation control + setNavigationLoc(coord: number[], realSpace?: boolean): void + moveToNavigationLoc(coord: number[], realSpace?: boolean): void + setNavigationOri(quat: number[]): void + moveToNavigationOri(quat: number[]): void + + // segment control + showSegment(segment: any): void + hideSegment(segment: any): void + showAllSegments(): void + hideAllSegments(): void + + // landmark control + addLandmarks(landmarks: any[]): void + removeLandmarks(landmarks: any[]): void + + // layer control + addLayer(layerSpec: any): void + removeLayer(layerId: string): void + applyLayersColourMap(map: TLayersColorMap): void + getLayersColourMap(): TLayersColorMap +} + +type TViewerEventMOAnno = { + type: "MOUSEOVER_ANNOTATION" + data: any +} + +type TViewerEventViewerLoaded = { + type: "VIEWERLOADED", + data: boolean +} + +export type TViewerEvent = TViewerEventMOAnno | TViewerEventViewerLoaded + +export interface IViewer{ + + selectedTemplate: any + selectedParcellation: any + viewerCtrlHandler?: IViewerCtrl + viewerEvents$: Observable<TViewerEvent> +} \ No newline at end of file diff --git a/src/viewerModule/viewerCmp/viewerCmp.component.ts b/src/viewerModule/viewerCmp/viewerCmp.component.ts new file mode 100644 index 000000000..ba31dac3d --- /dev/null +++ b/src/viewerModule/viewerCmp/viewerCmp.component.ts @@ -0,0 +1,12 @@ +import { Component } from "@angular/core"; + +@Component({ + selector: 'iav-cmp-viewer-container', + templateUrl: './viewerCmp.template.html', + styleUrls: [ + './viewerCmp.style.css' + ] +}) + +export class ViewerCmp{ +} \ No newline at end of file diff --git a/src/viewerModule/viewerCmp/viewerCmp.style.css b/src/viewerModule/viewerCmp/viewerCmp.style.css new file mode 100644 index 000000000..e69de29bb diff --git a/src/viewerModule/viewerCmp/viewerCmp.template.html b/src/viewerModule/viewerCmp/viewerCmp.template.html new file mode 100644 index 000000000..e69de29bb -- GitLab