Skip to content
Snippets Groups Projects
Commit dd7475b2 authored by Xiao Gui's avatar Xiao Gui
Browse files

feat: freesurfer metadata from siibra-api

parent 63227621
No related branches found
No related tags found
No related merge requests found
...@@ -199,7 +199,7 @@ export class PureContantService implements OnDestroy{ ...@@ -199,7 +199,7 @@ export class PureContantService implements OnDestroy{
) )
} }
private getSpacesAndParc(atlasId: string) { private getSpacesAndParc(atlasId: string): Observable<{ templateSpaces: TSpaceFull[], parcellations: TParc[] }> {
const cacheKey = `getSpacesAndParc::${atlasId}` const cacheKey = `getSpacesAndParc::${atlasId}`
if (this.httpCallCache.has(cacheKey)) return this.httpCallCache.get(cacheKey) if (this.httpCallCache.has(cacheKey)) return this.httpCallCache.get(cacheKey)
...@@ -451,8 +451,54 @@ export class PureContantService implements OnDestroy{ ...@@ -451,8 +451,54 @@ export class PureContantService implements OnDestroy{
mapTo({ templateSpaces, parcellations, ngLayerObj }) mapTo({ templateSpaces, parcellations, ngLayerObj })
) )
}), }),
map(({ templateSpaces, ngLayerObj }) => { map(({ templateSpaces, parcellations, ngLayerObj }) => {
return templateSpaces.map(tmpl => { return templateSpaces.map(tmpl => {
// configuring three-surfer
let threeSurferConfig = {}
const threeSurferVolSrc = tmpl.volume_src.find(v => v.volume_type === 'threesurfer/gii')
if (threeSurferVolSrc) {
const foundP = parcellations.find(p => {
return !!p.volumeSrc[tmpl.id]
})
const url = threeSurferVolSrc.url
const { surfaces } = threeSurferVolSrc.detail['threesurfer/gii'] as { surfaces: {mode: string, hemisphere: 'left' | 'right', url: string}[] }
const modObj = {}
for (const surface of surfaces) {
const modeToConcat = {
mesh: surface.url,
hemisphere: surface.hemisphere,
colormap: (() => {
const hemisphereKey = surface.hemisphere === 'left'
? 'left hemisphere'
: 'right hemisphere'
const lbl = foundP.volumeSrc[tmpl.id][hemisphereKey].find(v => v.volume_type === 'threesurfer/gii-label')
return lbl?.url
})()
}
if (!modObj[surface.mode]) {
modObj[surface.mode] = []
}
modObj[surface.mode].push(modeToConcat)
}
foundP[tmpl.id]
threeSurferConfig = {
"three-surfer": {
'@context': {
root: url
},
modes: Object.keys(modObj).map(name => {
return {
name,
meshes: modObj[name]
}
})
},
nehubaConfig: null,
nehubaConfigURL: null,
useTheme: 'dark'
}
}
const darkTheme = tmpl.src_volume_type === 'mri' const darkTheme = tmpl.src_volume_type === 'mri'
const nehubaConfig = getNehubaConfig(darkTheme) const nehubaConfig = getNehubaConfig(darkTheme)
const initialLayers = nehubaConfig.dataset.initialNgState.layers const initialLayers = nehubaConfig.dataset.initialNgState.layers
...@@ -513,7 +559,8 @@ export class PureContantService implements OnDestroy{ ...@@ -513,7 +559,8 @@ export class PureContantService implements OnDestroy{
name: parc.name, name: parc.name,
regions regions
} }
}) }),
...threeSurferConfig
} }
}) })
}) })
......
...@@ -6,7 +6,7 @@ type TSpaceType = 'mri' | 'histology' ...@@ -6,7 +6,7 @@ type TSpaceType = 'mri' | 'histology'
type TNgTransform = number[][] type TNgTransform = number[][]
type TVolumeType = 'nii' | 'neuroglancer/precomputed' | 'neuroglancer/precompmesh' | 'detailed maps' type TVolumeType = 'nii' | 'neuroglancer/precomputed' | 'neuroglancer/precompmesh' | 'detailed maps' | 'threesurfer/gii' | 'threesurfer/gii-label'
type TParcModality = 'cytoarchitecture' | 'functional modes' | 'fibre architecture' type TParcModality = 'cytoarchitecture' | 'functional modes' | 'fibre architecture'
type TAuxMesh = { type TAuxMesh = {
......
...@@ -2,7 +2,7 @@ import { Component, Input, Output, EventEmitter, ElementRef, OnChanges, OnDestro ...@@ -2,7 +2,7 @@ import { Component, Input, Output, EventEmitter, ElementRef, OnChanges, OnDestro
import { IViewer, TViewerEvent } from "src/viewerModule/viewer.interface"; import { IViewer, TViewerEvent } from "src/viewerModule/viewer.interface";
import { TThreeSurferConfig, TThreeSurferMode } from "../types"; import { TThreeSurferConfig, TThreeSurferMode } from "../types";
import { parseContext } from "../util"; import { parseContext } from "../util";
import { retry } from 'common/util' import { retry, flattenRegions } from 'common/util'
@Component({ @Component({
selector: 'three-surfer-glue-cmp', selector: 'three-surfer-glue-cmp',
...@@ -27,8 +27,8 @@ export class ThreeSurferGlueCmp implements IViewer, OnChanges, AfterViewInit, On ...@@ -27,8 +27,8 @@ export class ThreeSurferGlueCmp implements IViewer, OnChanges, AfterViewInit, On
private config: TThreeSurferConfig private config: TThreeSurferConfig
public modes: TThreeSurferMode[] = [] public modes: TThreeSurferMode[] = []
public selectedMode: string public selectedMode: string
private colormap: Map<string, Map<number, [number, number, number]>> = new Map()
private regionMap: Map<string, Map<number, any>> = new Map()
constructor( constructor(
private el: ElementRef, private el: ElementRef,
){ ){
...@@ -63,7 +63,12 @@ export class ThreeSurferGlueCmp implements IViewer, OnChanges, AfterViewInit, On ...@@ -63,7 +63,12 @@ export class ThreeSurferGlueCmp implements IViewer, OnChanges, AfterViewInit, On
const tsM = await this.tsRef.loadMesh( const tsM = await this.tsRef.loadMesh(
parseContext(mesh, [this.config['@context']]) parseContext(mesh, [this.config['@context']])
) )
const applyCM = this.colormap.get(hemisphere)
const rMap = this.regionMap.get(hemisphere)
const applyCM = new Map()
for (const [ lblIdx, region ] of rMap.entries()) {
applyCM.set(lblIdx, (region.rgb || [200, 200, 200]).map(v => v/255))
}
const tsC = await this.tsRef.loadColormap( const tsC = await this.tsRef.loadColormap(
parseContext(colormap, [this.config['@context']]) parseContext(colormap, [this.config['@context']])
...@@ -90,7 +95,10 @@ export class ThreeSurferGlueCmp implements IViewer, OnChanges, AfterViewInit, On ...@@ -90,7 +95,10 @@ export class ThreeSurferGlueCmp implements IViewer, OnChanges, AfterViewInit, On
} }
async ngOnChanges(){ async ngOnChanges(){
if (this.tsRef) this.ngOnDestroy() if (this.tsRef) {
this.ngOnDestroy()
this.ngAfterViewInit()
}
if (this.selectedTemplate) { if (this.selectedTemplate) {
/** /**
...@@ -116,13 +124,21 @@ export class ThreeSurferGlueCmp implements IViewer, OnChanges, AfterViewInit, On ...@@ -116,13 +124,21 @@ export class ThreeSurferGlueCmp implements IViewer, OnChanges, AfterViewInit, On
) )
} }
for (const region of this.selectedParcellation.regions) { const flattenedRegions = flattenRegions(this.selectedParcellation.regions)
const map = new Map<number, [number, number, number]>() for (const region of flattenedRegions) {
for (const child of region.children) { if (region.labelIndex) {
const color = (child.iav?.rgb as [number, number, number] ) || [200, 200, 200] const hemisphere = /left/.test(region.name)
map.set(Number(child.grayvalue), color.map(v => v/255) as [number, number, number]) ? 'left'
: /right/.test(region.name)
? 'right'
: null
if (!hemisphere) throw new Error(`region ${region.name} does not have hemisphere defined`)
if (!this.regionMap.has(hemisphere)) {
this.regionMap.set(hemisphere, new Map())
}
const rMap = this.regionMap.get(hemisphere)
rMap.set(region.labelIndex, region)
} }
this.colormap.set(region.name, map)
} }
// load mode0 by default // load mode0 by default
...@@ -165,9 +181,9 @@ export class ThreeSurferGlueCmp implements IViewer, OnChanges, AfterViewInit, On ...@@ -165,9 +181,9 @@ export class ThreeSurferGlueCmp implements IViewer, OnChanges, AfterViewInit, On
return this.handleMouseoverEvent([]) return this.handleMouseoverEvent([])
} }
const foundRegion = this.selectedParcellation.regions.find(({ name }) => name === key) const hemisphereMap = this.regionMap.get(key)
if (!foundRegion) { if (!hemisphereMap) {
return this.handleMouseoverEvent( return this.handleMouseoverEvent(
Array.from(labelIdxSet).map(v => { Array.from(labelIdxSet).map(v => {
return `unknown#${v}` return `unknown#${v}`
...@@ -178,7 +194,7 @@ export class ThreeSurferGlueCmp implements IViewer, OnChanges, AfterViewInit, On ...@@ -178,7 +194,7 @@ export class ThreeSurferGlueCmp implements IViewer, OnChanges, AfterViewInit, On
return this.handleMouseoverEvent( return this.handleMouseoverEvent(
Array.from(labelIdxSet) Array.from(labelIdxSet)
.map(lblIdx => { .map(lblIdx => {
const ontoR = foundRegion.children.find(ontR => Number(ontR.grayvalue) === lblIdx) const ontoR = hemisphereMap.get(Number(lblIdx))
if (ontoR) { if (ontoR) {
return ontoR.name return ontoR.name
} else { } else {
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment