diff --git a/package.json b/package.json index 5c35fe2e5aa2479354f7132fd953002e02436a8b..aa5a9d92d5c9578622a44e5e9e81cb46f7fdb146 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,7 @@ "@ngrx/store": "^9.1.1", "@types/node": "12.12.39", "export-nehuba": "0.0.4", - "hbp-connectivity-component": "^0.3.14", + "hbp-connectivity-component": "^0.3.18", "zone.js": "^0.10.2" } } diff --git a/src/atlasViewer/atlasViewer.component.ts b/src/atlasViewer/atlasViewer.component.ts index 66a9b72648ecf3a751de5c2014e0d402173f5795..8f1410127afa88217bd84cb22b2708121a4c795f 100644 --- a/src/atlasViewer/atlasViewer.component.ts +++ b/src/atlasViewer/atlasViewer.component.ts @@ -44,6 +44,7 @@ import { ngViewerSelectorClearViewEntries } from "src/services/state/ngViewerSta import { ngViewerActionClearView } from "src/services/state/ngViewerState/actions"; import { uiStateMouseOverSegmentsSelector } from "src/services/state/uiState/selectors"; import { ClickInterceptorService } from "src/glue"; +import {SET_OVERWRITTEN_COLOR_MAP} from "src/services/state/viewerState.store"; /** * TODO diff --git a/src/services/state/viewerState.store.ts b/src/services/state/viewerState.store.ts index 36435f358d7f101f7881b97170d0b38fc8260432..25adedb5c6eb7fecba4215550f1376b9379c4d72 100644 --- a/src/services/state/viewerState.store.ts +++ b/src/services/state/viewerState.store.ts @@ -42,7 +42,7 @@ export interface StateInterface { loadedNgLayers: INgLayerInterface[] connectivityRegion: string | null - overwrittenColorMap: boolean + overwrittenColorMap: string | null standaloneVolumes: any[] } @@ -81,7 +81,7 @@ export const defaultState: StateInterface = { parcellationSelected: null, templateSelected: null, connectivityRegion: '', - overwrittenColorMap: false, + overwrittenColorMap: null, standaloneVolumes: [] } @@ -219,7 +219,7 @@ export const getStateStore = ({ state = defaultState } = {}) => (prevState: Part ...prevState, connectivityRegion: '', } - case SET_CONNECTIVITY_VISIBLE: + case SET_OVERWRITTEN_COLOR_MAP: return { ...prevState, overwrittenColorMap: action.payload || '', @@ -264,7 +264,7 @@ export const ADD_TO_REGIONS_SELECTION_WITH_IDS = `ADD_TO_REGIONS_SELECTION_WITH_ export const NEHUBA_LAYER_CHANGED = `NEHUBA_LAYER_CHANGED` export const SET_CONNECTIVITY_REGION = `SET_CONNECTIVITY_REGION` export const CLEAR_CONNECTIVITY_REGION = `CLEAR_CONNECTIVITY_REGION` -export const SET_CONNECTIVITY_VISIBLE = `SET_CONNECTIVITY_VISIBLE` +export const SET_OVERWRITTEN_COLOR_MAP = `SET_OVERWRITTEN_COLOR_MAP` export const CLEAR_STANDALONE_VOLUMES = `CLEAR_STANDALONE_VOLUMES` @Injectable({ diff --git a/src/services/state/viewerState/selectors.ts b/src/services/state/viewerState/selectors.ts index bb2bd592e782891df9f03398a7bf3171314270bc..7d71b308359e9b59fac9a84d6359017471a44146 100644 --- a/src/services/state/viewerState/selectors.ts +++ b/src/services/state/viewerState/selectors.ts @@ -71,6 +71,11 @@ export const viewerStateAllRegionsFlattenedRegionSelector = createSelector( } ) +export const viewerStateOverwrittenColorMapSelector = createSelector( + state => state['viewerState'], + viewerState => viewerState['overwrittenColorMap'] +) + export const viewerStateStandAloneVolumes = createSelector( state => state['viewerState'], viewerState => viewerState['standaloneVolumes'] diff --git a/src/ui/connectivityBrowser/connectivityBrowser.component.ts b/src/ui/connectivityBrowser/connectivityBrowser.component.ts index 6941007f1550fc8dff9ab57f6b7f8b54efdd202d..0525e2c8eec0ab9c26963dec8e800b35fa8d12f2 100644 --- a/src/ui/connectivityBrowser/connectivityBrowser.component.ts +++ b/src/ui/connectivityBrowser/connectivityBrowser.component.ts @@ -2,7 +2,7 @@ import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, - EventEmitter, + EventEmitter, OnDestroy, Output, ViewChild, @@ -11,14 +11,21 @@ import { } from "@angular/core"; import {select, Store} from "@ngrx/store"; import {fromEvent, Observable, Subscription, Subject, combineLatest} from "rxjs"; -import {distinctUntilChanged, map } from "rxjs/operators"; -import {CLEAR_CONNECTIVITY_REGION, SELECT_REGIONS, SET_CONNECTIVITY_VISIBLE} from "src/services/state/viewerState.store"; -import { safeFilter} from "src/services/stateStore.service"; -import { viewerStateNavigateToRegion } from "src/services/state/viewerState.store.helper"; -import { ngViewerActionClearView } from "src/services/state/ngViewerState/actions"; -import { ngViewerSelectorClearViewEntries } from "src/services/state/ngViewerState/selectors"; -import { viewerStateAllRegionsFlattenedRegionSelector } from "src/services/state/viewerState/selectors"; -import { HttpClient } from "@angular/common/http"; +import {distinctUntilChanged, filter, map} from "rxjs/operators"; +import { + CLEAR_CONNECTIVITY_REGION, + SELECT_REGIONS, + SET_OVERWRITTEN_COLOR_MAP +} from "src/services/state/viewerState.store"; +import {safeFilter} from "src/services/stateStore.service"; +import {viewerStateNavigateToRegion} from "src/services/state/viewerState.store.helper"; +import {ngViewerActionClearView} from "src/services/state/ngViewerState/actions"; +import {ngViewerSelectorClearViewEntries} from "src/services/state/ngViewerState/selectors"; +import { + viewerStateAllRegionsFlattenedRegionSelector, + viewerStateOverwrittenColorMapSelector +} from "src/services/state/viewerState/selectors"; +import {HttpClient} from "@angular/common/http"; const CONNECTIVITY_NAME_PLATE = 'Connectivity' @@ -26,7 +33,7 @@ const CONNECTIVITY_NAME_PLATE = 'Connectivity' selector: 'connectivity-browser', templateUrl: './connectivityBrowser.template.html', }) -export class ConnectivityBrowserComponent implements OnInit, AfterViewInit, OnDestroy{ +export class ConnectivityBrowserComponent implements OnInit, AfterViewInit, OnDestroy { private setColorMap$: Subject<boolean> = new Subject() @@ -39,20 +46,29 @@ export class ConnectivityBrowserComponent implements OnInit, AfterViewInit, OnDe public connectivityUrl = 'https://connectivity-query-v1-1-connectivity.apps-dev.hbp.eu/v1.1/studies' + private accordionIsExpanded = false + @Input() - set accordionExpanded(flag: boolean){ + set accordionExpanded(flag: boolean) { /** - * ignore first update - */ + * ignore first update + */ if (this._isFirstUpdate) { this._isFirstUpdate = false return } + this.accordionIsExpanded = flag this.store$.dispatch( - ngViewerActionClearView({ payload: { - [CONNECTIVITY_NAME_PLATE]: flag - }}) + ngViewerActionClearView({ + payload: { + [CONNECTIVITY_NAME_PLATE]: flag && !this.noDataReceived + } + }) ) + this.store$.dispatch({ + type: SET_OVERWRITTEN_COLOR_MAP, + payload: flag? CONNECTIVITY_NAME_PLATE : false, + }) } @Output() @@ -60,16 +76,16 @@ export class ConnectivityBrowserComponent implements OnInit, AfterViewInit, OnDe @Output() connectivityLoadUrl: EventEmitter<string> = new EventEmitter() - + @Output() connectivityNumberReceived: EventEmitter<string> = new EventEmitter() @Input() - set region(val){ + set region(val) { const newRegionName = val && val.name if (!val) { this.store$.dispatch({ - type: SET_CONNECTIVITY_VISIBLE, + type: SET_OVERWRITTEN_COLOR_MAP, payload: false, }) return @@ -77,19 +93,19 @@ export class ConnectivityBrowserComponent implements OnInit, AfterViewInit, OnDe if (newRegionName !== this.regionName && this.defaultColorMap) { this.restoreDefaultColormap() - } + } this.regionName = newRegionName // TODO may not be necessary this.changeDetectionRef.detectChanges() } - + public regionName: string public datasetList: any[] = [] public selectedDataset: any public selectedDatasetDescription: string = '' public connectedAreas = [] - + private selectedParcellationFlatRegions$ = this.store$.pipe( select(viewerStateAllRegionsFlattenedRegionSelector) ) @@ -98,7 +114,9 @@ export class ConnectivityBrowserComponent implements OnInit, AfterViewInit, OnDe private subscriptions: Subscription[] = [] public expandMenuIndex = -1 public allRegions = [] - public defaultColorMap: Map<string, Map<number, {red: number, green: number, blue: number}>> + public defaultColorMap: Map<string, Map<number, { red: number, green: number, blue: number }>> + + public noDataReceived = false @ViewChild('connectivityComponent', {read: ElementRef}) public connectivityComponentElement: ElementRef<HTMLHbpConnectivityMatrixRowElement> @ViewChild('fullConnectivityGrid') public fullConnectivityGridElement: ElementRef<HTMLFullConnectivityGridElement> @@ -131,22 +149,42 @@ export class ConnectivityBrowserComponent implements OnInit, AfterViewInit, OnDe } public ngAfterViewInit(): void { - this.subscriptions.push( this.store$.pipe( - select(ngViewerSelectorClearViewEntries), - ).subscribe(keys => { - this.setColorMap$.next(keys.includes(CONNECTIVITY_NAME_PLATE)) + select(viewerStateOverwrittenColorMapSelector), + ).subscribe(value => { + if (this.accordionIsExpanded) { + this.setColorMap$.next(!!value) + } }) ) - + + /** + * Listen to of clear view entries + * can come from within the component (when connectivity is not available for the dataset) + * --> do not collapse + * or outside (user clicks x in chip) + * --> collapse + */ this.subscriptions.push( this.store$.pipe( select(ngViewerSelectorClearViewEntries), - ).subscribe(keys => { - this.setOpenState.emit(keys.includes(CONNECTIVITY_NAME_PLATE)) + map(arr => arr.filter(v => v === CONNECTIVITY_NAME_PLATE)), + filter(arr => arr.length ===0), + distinctUntilChanged() + ).subscribe(() => { + if (!this.noDataReceived) { + this.setOpenState.emit(false) + } }) ) + + + this.subscriptions.push(this.overwrittenColorMap$.subscribe(ocm => { + if (this.accordionIsExpanded && !ocm) { + this.setOpenState.emit(false) + } + })) this.subscriptions.push( this.selectedParcellationFlatRegions$.subscribe(flattenedRegions => { @@ -156,8 +194,8 @@ export class ConnectivityBrowserComponent implements OnInit, AfterViewInit, OnDe ) /** - * setting/restoring colormap - */ + * setting/restoring colormap + */ this.subscriptions.push( combineLatest( this.setColorMap$.pipe( @@ -167,34 +205,49 @@ export class ConnectivityBrowserComponent implements OnInit, AfterViewInit, OnDe map((e: CustomEvent) => e.detail) ) ).subscribe(([flag, connectedAreas]) => { - this.connectivityNumberReceived.emit(connectedAreas.length) - this.connectedAreas = connectedAreas - - if (flag) { - this.addNewColorMap() - this.store$.dispatch({ - type: SET_CONNECTIVITY_VISIBLE, - payload: 'connectivity', - }) + if (connectedAreas === 'No data') { + this.noDataReceived = true + return this.clearViewer() } else { - this.restoreDefaultColormap() - - /** - * TODO - * may no longer be necessary - */ - this.store$.dispatch({type: CLEAR_CONNECTIVITY_REGION}) - this.store$.dispatch({type: SET_CONNECTIVITY_VISIBLE, payload: null}) + this.store$.dispatch( + ngViewerActionClearView({ + payload: { + [CONNECTIVITY_NAME_PLATE]: true + } + }) + ) + this.noDataReceived = false + + this.connectivityNumberReceived.emit(connectedAreas.length) + this.connectedAreas = connectedAreas + + if (flag) { + this.addNewColorMap() + this.store$.dispatch({ + type: SET_OVERWRITTEN_COLOR_MAP, + payload: 'connectivity', + }) + } else { + this.restoreDefaultColormap() + + this.store$.dispatch({type: SET_OVERWRITTEN_COLOR_MAP, payload: null}) + + /** + * TODO + * may no longer be necessary + */ + this.store$.dispatch({type: CLEAR_CONNECTIVITY_REGION}) + } } }) ) this.subscriptions.push( - fromEvent(this.connectivityComponentElement?.nativeElement, 'collapsedMenuChanged', { capture: true }) + fromEvent(this.connectivityComponentElement?.nativeElement, 'collapsedMenuChanged', {capture: true}) .subscribe((e: CustomEvent) => { this.expandMenuIndex = e.detail }), - fromEvent(this.connectivityComponentElement?.nativeElement, 'customToolEvent', { capture: true }) + fromEvent(this.connectivityComponentElement?.nativeElement, 'customToolEvent', {capture: true}) .subscribe((e: CustomEvent) => { if (e.detail.name === 'export csv') { // ToDo Fix in future to use component @@ -210,6 +263,20 @@ export class ConnectivityBrowserComponent implements OnInit, AfterViewInit, OnDe this.subscriptions.forEach(s => s.unsubscribe()) } + clearViewer() { + this.store$.dispatch( + ngViewerActionClearView({ + payload: { + [CONNECTIVITY_NAME_PLATE]: false + } + }) + ) + this.connectedAreas = [] + this.connectivityNumberReceived.emit('0') + + return this.restoreDefaultColormap() + } + // ToDo Affect on component changeDataset(event = null) { if (event) { @@ -218,22 +285,22 @@ export class ConnectivityBrowserComponent implements OnInit, AfterViewInit, OnDe } if (this.datasetList.length && this.selectedDataset) { const selectedDatasetId = this.datasetList.find(d => d.name === this.selectedDataset).id - const url = selectedDatasetId? `${this.connectivityUrl}/${selectedDatasetId}` : null + const url = selectedDatasetId ? `${this.connectivityUrl}/${selectedDatasetId}` : null this.connectivityLoadUrl.emit(url) this.loadUrl = url - this.fullConnectivityLoadUrl = selectedDatasetId? `${this.connectivityUrl}/${selectedDatasetId}/full_matrix` : null + this.fullConnectivityLoadUrl = selectedDatasetId ? `${this.connectivityUrl}/${selectedDatasetId}/full_matrix` : null } } navigateToRegion(region) { this.store$.dispatch( viewerStateNavigateToRegion({ - payload: { region: this.getRegionWithName(region) } + payload: {region: this.getRegionWithName(region)} }) ) } - + selectRegion(region) { this.store$.dispatch({ type: SELECT_REGIONS, @@ -255,7 +322,7 @@ export class ConnectivityBrowserComponent implements OnInit, AfterViewInit, OnDe this.defaultColorMap = new Map(getWindow().interactiveViewer.viewerHandle.getLayersSegmentColourMap()) } - const existingMap: Map<string, Map<number, {red: number, green: number, blue: number}>> = (getWindow().interactiveViewer.viewerHandle.getLayersSegmentColourMap()) + const existingMap: Map<string, Map<number, { red: number, green: number, blue: number }>> = (getWindow().interactiveViewer.viewerHandle.getLayersSegmentColourMap()) const colorMap = new Map(existingMap) this.allRegions.forEach(r => { @@ -270,7 +337,11 @@ export class ConnectivityBrowserComponent implements OnInit, AfterViewInit, OnDe .map(r => r) if (areaAsRegion && areaAsRegion.length && areaAsRegion[0].ngId) { - colorMap.get(areaAsRegion[0].ngId).set(areaAsRegion[0].labelIndex, {red: area.color.r, green: area.color.g, blue: area.color.b}) + colorMap.get(areaAsRegion[0].ngId).set(areaAsRegion[0].labelIndex, { + red: area.color.r, + green: area.color.g, + blue: area.color.b + }) } }) getWindow().interactiveViewer.viewerHandle.applyLayersColourMap(colorMap) @@ -280,6 +351,7 @@ export class ConnectivityBrowserComponent implements OnInit, AfterViewInit, OnDe const a = document.querySelector('hbp-connectivity-matrix-row') a.downloadCSV() } + public exportFullConnectivity() { this.fullConnectivityGridElement.nativeElement['downloadCSV']() } diff --git a/src/ui/connectivityBrowser/connectivityBrowser.template.html b/src/ui/connectivityBrowser/connectivityBrowser.template.html index 0c829e754cc9908a739d81cd7531d6b5131653c7..05dd7a044ee75a57965e2795998cb463a2385578 100644 --- a/src/ui/connectivityBrowser/connectivityBrowser.template.html +++ b/src/ui/connectivityBrowser/connectivityBrowser.template.html @@ -76,6 +76,7 @@ </div> <div slot="exportslot"> <button mat-icon-button + [disabled]="noDataReceived" (click)="exportConnectivityProfile()" matTooltip="Export connectivity profile"> <i class="fas fa-download mb-2"></i> @@ -88,4 +89,4 @@ [description]="selectedDatasetDescription" onlyExport="true"> </full-connectivity-grid> -</div> \ No newline at end of file +</div> diff --git a/src/ui/nehubaContainer/nehubaContainer.component.ts b/src/ui/nehubaContainer/nehubaContainer.component.ts index ae031bd0dfcc0a55b7d09dd7d021f2f2b144e15c..ec11619054d67697cac8fdec3fbd566a74f1749b 100644 --- a/src/ui/nehubaContainer/nehubaContainer.component.ts +++ b/src/ui/nehubaContainer/nehubaContainer.component.ts @@ -306,7 +306,6 @@ export class NehubaContainer implements OnInit, OnChanges, OnDestroy { public hoveredPanelIndices$: Observable<number> - @ViewChild('connectivityComponent') public connectivityComponent: ConnectivityBrowserComponent public connectivityNumber: string constructor( diff --git a/src/ui/nehubaContainer/nehubaContainer.template.html b/src/ui/nehubaContainer/nehubaContainer.template.html index bcf5604f5366d8bd56df8e584618055bc5d14028..002a4eedfaacf90a69c3cebc23bbf975addec937 100644 --- a/src/ui/nehubaContainer/nehubaContainer.template.html +++ b/src/ui/nehubaContainer/nehubaContainer.template.html @@ -571,8 +571,7 @@ [region]="region" (setOpenState)="expansionPanel.expanded = $event" (connectivityNumberReceived)="connectivityNumber = $event" - [accordionExpanded]="expansionPanel.expanded" - #connectivityComponent> + [accordionExpanded]="expansionPanel.expanded"> </connectivity-browser> </ng-container> </mat-card-content> @@ -592,7 +591,7 @@ iav-counter #connectedCounterDir="iavCounter"> - <hbp-connectivity-matrix-row [region]="region.name" + <hbp-connectivity-matrix-row *ngIf="region && region.name" [region]="region.name" (connectivityDataReceived)="connectedCounterDir.value = $event.detail.length" class="invisible d-block h-0 w-0" loadurl="https://connectivity-query-v1-1-connectivity.apps-dev.hbp.eu/v1.1/studies/1345998a08539dc24bda8817c7d5804558d83b1c">