Skip to content
Snippets Groups Projects
Unverified Commit 01d29400 authored by xgui3783's avatar xgui3783 Committed by GitHub
Browse files

Merge pull request #1464 from FZJ-INM1-BDA/feat_annotSupport

feat: add support for .annot label file
parents 4c32255c 1f9d7e5c
No related branches found
No related tags found
No related merge requests found
...@@ -10,7 +10,8 @@ ...@@ -10,7 +10,8 @@
- Added legend to region hierarchy - Added legend to region hierarchy
- Allow latest queried concept in feature view - Allow latest queried concept in feature view
- Allow experimental flag to be set to be on at runtime (this also shows the button, allow toggling of experimental features) - Allow experimental flag to be set to be on at runtime (this also shows the button, allow toggling of experimental features)
- Added code snippet to limited panels - Feature: added supported for .annot fsaverage label
- (experimental) Added code snippet to limited panels
- (experimental) allow addition of custom linear coordinate space - (experimental) allow addition of custom linear coordinate space
- (experimental) show BigBrain slice number - (experimental) show BigBrain slice number
......
...@@ -398,13 +398,19 @@ class TranslateV3 { ...@@ -398,13 +398,19 @@ class TranslateV3 {
} }
async translateLabelledMapToThreeLabel(map:PathReturn<"/map">) { async translateLabelledMapToThreeLabel(map:PathReturn<"/map">) {
const threeLabelMap: Record<string, { laterality: 'left' | 'right', url: string, region: LabelledMap[] }> = {} const threeLabelMap: Record<string, {
const registerLayer = (url: string, laterality: 'left' | 'right', region: string, label: number) => { laterality: 'left' | 'right'
url: string
region: LabelledMap[]
clType: 'baselayer/threesurfer-label/gii-label' | 'baselayer/threesurfer-label/annot'
}> = {}
const registerLayer = (url: string, clType: 'baselayer/threesurfer-label/gii-label' | 'baselayer/threesurfer-label/annot', laterality: 'left' | 'right', region: string, label: number) => {
if (!threeLabelMap[url]) { if (!threeLabelMap[url]) {
threeLabelMap[url] = { threeLabelMap[url] = {
laterality, laterality,
region: [], region: [],
url, url,
clType
} }
} }
...@@ -416,18 +422,26 @@ class TranslateV3 { ...@@ -416,18 +422,26 @@ class TranslateV3 {
for (const regionname in map.indices) { for (const regionname in map.indices) {
for (const { volume: volIdx, fragment, label } of map.indices[regionname]) { for (const { volume: volIdx, fragment, label } of map.indices[regionname]) {
const volume = map.volumes[volIdx || 0] const volume = map.volumes[volIdx || 0]
if (!volume.formats.includes("gii-label")) { let clType: 'baselayer/threesurfer-label/gii-label' | 'baselayer/threesurfer-label/annot' | null = null
// Does not support gii-label... skipping! let providedVolume: typeof volume['providedVolumes'][string] | null = null
continue if (volume.formats.includes("gii-label")) {
clType = 'baselayer/threesurfer-label/gii-label'
providedVolume = volume.providedVolumes["gii-label"]
}
if (volume.formats.includes("freesurfer-annot")) {
clType = 'baselayer/threesurfer-label/annot'
providedVolume = volume.providedVolumes["freesurfer-annot"]
} }
const { ["gii-label"]: giiLabel } = volume.providedVolumes
if (!providedVolume || !clType) {
// does not support baselayer threesurfer label, skipping
continue
}
if (!fragment || !["left hemisphere", "right hemisphere"].includes(fragment)) { if (!fragment || !["left hemisphere", "right hemisphere"].includes(fragment)) {
console.warn(`either fragment not defined, or fragment is not '{left|right} hemisphere'. Skipping!`) console.warn(`either fragment not defined, or fragment is not '{left|right} hemisphere'. Skipping!`)
continue continue
} }
if (!giiLabel[fragment]) { if (!providedVolume[fragment]) {
// Does not support gii-label... skipping! // Does not support gii-label... skipping!
continue continue
} }
...@@ -438,7 +452,7 @@ class TranslateV3 { ...@@ -438,7 +452,7 @@ class TranslateV3 {
console.warn(`cannot determine the laterality! skipping`) console.warn(`cannot determine the laterality! skipping`)
continue continue
} }
registerLayer(giiLabel[fragment], laterality, regionname, label) registerLayer(providedVolume[fragment], clType, laterality, regionname, label)
} }
} }
return threeLabelMap return threeLabelMap
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
<link rel="stylesheet" href="version.css"> <link rel="stylesheet" href="version.css">
<link rel="icon" type="image/png" href="assets/favicons/favicon-128-light.png"/> <link rel="icon" type="image/png" href="assets/favicons/favicon-128-light.png"/>
<script src="extra_js.js"></script> <script src="extra_js.js"></script>
<script src="https://unpkg.com/three-surfer@0.0.13/dist/bundle.js" defer></script> <script src="https://unpkg.com/three-surfer@0.0.15/dist/bundle.js" defer></script>
<script type="module" src="https://unpkg.com/ng-layer-tune@0.0.26/dist/ng-layer-tune/ng-layer-tune.esm.js"></script> <script type="module" src="https://unpkg.com/ng-layer-tune@0.0.26/dist/ng-layer-tune/ng-layer-tune.esm.js"></script>
<script src="https://cdn.plot.ly/plotly-2.24.1.min.js" charset="utf-8"></script> <script src="https://cdn.plot.ly/plotly-2.24.1.min.js" charset="utf-8"></script>
<title>Siibra Explorer</title> <title>Siibra Explorer</title>
......
...@@ -22,7 +22,7 @@ export type ThreeSurferCustomLayer = { ...@@ -22,7 +22,7 @@ export type ThreeSurferCustomLayer = {
} & CustomLayerBase } & CustomLayerBase
export type ThreeSurferCustomLabelLayer = { export type ThreeSurferCustomLabelLayer = {
clType: 'baselayer/threesurfer-label' clType: 'baselayer/threesurfer-label/gii-label' | 'baselayer/threesurfer-label/annot'
source: string source: string
laterality: 'left' | 'right' laterality: 'left' | 'right'
} & CustomLayerBase } & CustomLayerBase
......
...@@ -43,7 +43,8 @@ export class ThreeSurferEffects { ...@@ -43,7 +43,8 @@ export class ThreeSurferEffects {
map( map(
cl => cl.filter(layer => cl => cl.filter(layer =>
layer.clType === "baselayer/threesurfer" || layer.clType === "baselayer/threesurfer" ||
layer.clType === "baselayer/threesurfer-label" layer.clType === "baselayer/threesurfer-label/annot" ||
layer.clType === "baselayer/threesurfer-label/gii-label"
) as ThreeSurferCustomLayer[] ) as ThreeSurferCustomLayer[]
) )
) )
...@@ -121,9 +122,9 @@ export class ThreeSurferEffects { ...@@ -121,9 +122,9 @@ export class ThreeSurferEffects {
switchMap(({ labels }) => { switchMap(({ labels }) => {
const labelMaps: ThreeSurferCustomLabelLayer[] = [] const labelMaps: ThreeSurferCustomLabelLayer[] = []
for (const key in labels) { for (const key in labels) {
const { laterality, url } = labels[key] const { laterality, url, clType } = labels[key]
labelMaps.push({ labelMaps.push({
clType: 'baselayer/threesurfer-label', clType,
id: `${url}-${laterality}`, id: `${url}-${laterality}`,
laterality, laterality,
source: url source: url
......
import { Component, Output, EventEmitter, ElementRef, OnDestroy, AfterViewInit, Optional, ChangeDetectionStrategy } from "@angular/core"; import { Component, Output, EventEmitter, ElementRef, OnDestroy, AfterViewInit, Optional, ChangeDetectionStrategy } from "@angular/core";
import { EnumViewerEvt, IViewer, TViewerEvent } from "src/viewerModule/viewer.interface"; import { EnumViewerEvt, IViewer, TViewerEvent } from "src/viewerModule/viewer.interface";
import { BehaviorSubject, combineLatest, concat, forkJoin, from, merge, NEVER, Observable, of, Subject } from "rxjs"; import { BehaviorSubject, combineLatest, concat, forkJoin, from, merge, NEVER, Observable, of, Subject, throwError } from "rxjs";
import { catchError, debounceTime, distinctUntilChanged, filter, map, scan, shareReplay, startWith, switchMap, tap, withLatestFrom } from "rxjs/operators"; import { catchError, debounceTime, distinctUntilChanged, filter, map, scan, shareReplay, startWith, switchMap, tap, withLatestFrom } from "rxjs/operators";
import { ComponentStore, LockError } from "src/viewerModule/componentStore"; import { ComponentStore, LockError } from "src/viewerModule/componentStore";
import { select, Store } from "@ngrx/store"; import { select, Store } from "@ngrx/store";
...@@ -95,6 +95,17 @@ type TThreeSurfer = { ...@@ -95,6 +95,17 @@ type TThreeSurfer = {
loadColormap: (url: string) => Promise<GiiInstance> loadColormap: (url: string) => Promise<GiiInstance>
setupAnimation: () => void setupAnimation: () => void
dispose: () => void dispose: () => void
loadVertexData: (url: string) => Promise<{
vertex: number[]
labels: {
index: number
name: string
color: number[]
vertices: number[]
}[]
readonly vertexLabels: Uint16Array
readonly colormap: Map<number, number[]>
}>
control: any control: any
camera: any camera: any
customColormap: WeakMap<TThreeGeometry, any> customColormap: WeakMap<TThreeGeometry, any>
...@@ -252,7 +263,9 @@ export class ThreeSurferGlueCmp implements IViewer<'threeSurfer'>, AfterViewInit ...@@ -252,7 +263,9 @@ export class ThreeSurferGlueCmp implements IViewer<'threeSurfer'>, AfterViewInit
) )
private vertexIndexLayers$: Observable<ThreeSurferCustomLabelLayer[]> = this.customLayers$.pipe( private vertexIndexLayers$: Observable<ThreeSurferCustomLabelLayer[]> = this.customLayers$.pipe(
map(layers => layers.filter(l => l.clType === "baselayer/threesurfer-label") as ThreeSurferCustomLabelLayer[]), map(layers => layers.filter(l =>
l.clType === "baselayer/threesurfer-label/gii-label" || l.clType === "baselayer/threesurfer-label/annot"
) as ThreeSurferCustomLabelLayer[]),
distinctUntilChanged(arrayEqual((o, n) => o.id === n.id)), distinctUntilChanged(arrayEqual((o, n) => o.id === n.id)),
) )
...@@ -265,22 +278,37 @@ export class ThreeSurferGlueCmp implements IViewer<'threeSurfer'>, AfterViewInit ...@@ -265,22 +278,37 @@ export class ThreeSurferGlueCmp implements IViewer<'threeSurfer'>, AfterViewInit
), ),
switchMap(layers => switchMap(layers =>
forkJoin( forkJoin(
layers.map(layer => layers.map(layer => {
from( if (layer.clType === "baselayer/threesurfer-label/gii-label") {
this.tsRef.loadColormap(layer.source) return from(
).pipe( this.tsRef.loadColormap(layer.source)
map(giiInstance => { ).pipe(
let vertexIndices: number[] = giiInstance[0].getData() map(giiInstance => {
if (giiInstance[0].attributes.DataType === 'NIFTI_TYPE_INT16') { let vertexIndices: number[] = giiInstance[0].getData()
vertexIndices = (window as any).ThreeSurfer.GiftiBase.castF32UInt16(vertexIndices) if (giiInstance[0].attributes.DataType === 'NIFTI_TYPE_INT16') {
} vertexIndices = (window as any).ThreeSurfer.GiftiBase.castF32UInt16(vertexIndices)
return { }
indexLayer: layer, return {
vertexIndices indexLayer: layer,
} vertexIndices
}) }
) })
) )
}
if (layer.clType === "baselayer/threesurfer-label/annot") {
return from(
this.tsRef.loadVertexData(layer.source)
).pipe(
map(v => {
return {
indexLayer: layer,
vertexIndices: v.vertexLabels
}
})
)
}
return throwError(() => new Error(`layer is neither annot nor gii-label`))
})
) )
), ),
map(layers => { map(layers => {
...@@ -317,8 +345,13 @@ export class ThreeSurferGlueCmp implements IViewer<'threeSurfer'>, AfterViewInit ...@@ -317,8 +345,13 @@ export class ThreeSurferGlueCmp implements IViewer<'threeSurfer'>, AfterViewInit
const { label, region } = curr const { label, region } = curr
let key : 'left' | 'right' let key : 'left' | 'right'
if ( /left/i.test(region.name) ) key = 'left' if (
if ( /right/i.test(region.name) ) key = 'right' /left/i.test(region.name) || /^lh/i.test(region.name)
) key = 'left'
if (
/right/i.test(region.name) || /^rh/i.test(region.name)
) key = 'right'
if (!key) { if (!key) {
/** /**
* TODO * TODO
......
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