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

bugfix: fsaverage on chnage variant, showing

multiple variant meshes
bugfix: fsaverage err URL encoding selected
regions
maint: some simplification
parent e1c0808a
No related branches found
No related tags found
No related merge requests found
Showing
with 493 additions and 210 deletions
# v2.10.1 # v2.10.1
## Bugfix
- fsaverage on change variant, showing multiple meshes
- fsaverage erroneous URL encoding of selected region
## Behind the scenes ## Behind the scenes
- Housekeeping CI/CD - Housekeeping CI/CD
- Simplify some behind the scenes code
...@@ -9,6 +9,7 @@ export const IDS = { ...@@ -9,6 +9,7 @@ export const IDS = {
COLIN27: "minds/core/referencespace/v1.0.0/7f39f7be-445b-47c0-9791-e971c0b6d992", COLIN27: "minds/core/referencespace/v1.0.0/7f39f7be-445b-47c0-9791-e971c0b6d992",
WAXHOLM: "minds/core/referencespace/v1.0.0/d5717c4a-0fa1-46e6-918c-b8003069ade8", WAXHOLM: "minds/core/referencespace/v1.0.0/d5717c4a-0fa1-46e6-918c-b8003069ade8",
MEBRAINS: "minds/core/referencespace/v1.0.0/MEBRAINS", MEBRAINS: "minds/core/referencespace/v1.0.0/MEBRAINS",
FSAVERAGE: 'minds/core/referencespace/v1.0.0/tmp-fsaverage'
}, },
PARCELLATION: { PARCELLATION: {
JBA29: "minds/core/parcellationatlas/v1.0.0/94c1125b-b87e-45e4-901c-00daee7f2579-290", JBA29: "minds/core/parcellationatlas/v1.0.0/94c1125b-b87e-45e4-901c-00daee7f2579-290",
......
...@@ -22,7 +22,7 @@ export const useViewer = { ...@@ -22,7 +22,7 @@ export const useViewer = {
} as const } as const
export const SIIBRA_API_VERSION_HEADER_KEY='x-siibra-api-version' export const SIIBRA_API_VERSION_HEADER_KEY='x-siibra-api-version'
export const EXPECTED_SIIBRA_API_VERSION = '0.3.0' export const EXPECTED_SIIBRA_API_VERSION = '0.3.1'
let BS_ENDPOINT_CACHED_VALUE: Observable<string> = null let BS_ENDPOINT_CACHED_VALUE: Observable<string> = null
......
...@@ -77,7 +77,6 @@ export class RouteStateTransformSvc { ...@@ -77,7 +77,6 @@ export class RouteStateTransformSvc {
} }
const regionMap = new Map<string, SxplrRegion>(allParcellationRegions.map(region => [region.name, region])) const regionMap = new Map<string, SxplrRegion>(allParcellationRegions.map(region => [region.name, region]))
const ngIdToRegionMap: Map<string, Map<number, SxplrRegion[]>> = new Map()
const [ ngMap, threeMap ] = await Promise.all([ const [ ngMap, threeMap ] = await Promise.all([
this.sapi.getTranslatedLabelledNgMap(selectedParcellation, selectedTemplate), this.sapi.getTranslatedLabelledNgMap(selectedParcellation, selectedTemplate),
......
...@@ -12,14 +12,67 @@ import { Effect } from "./effects" ...@@ -12,14 +12,67 @@ import { Effect } from "./effects"
import * as mainActions from "../actions" import * as mainActions from "../actions"
import { atlasSelection } from ".." import { atlasSelection } from ".."
import { BrowserAnimationsModule } from "@angular/platform-browser/animations" import { BrowserAnimationsModule } from "@angular/platform-browser/animations"
import { translateV3Entities } from "src/atlasComponents/sapi/translateV3"
import { PathReturn } from "src/atlasComponents/sapi/typeV3"
describe("> effects.ts", () => { describe("> effects.ts", () => {
describe("> Effect", () => { describe("> Effect", () => {
let actions$ = new Observable<Action>() let actions$ = new Observable<Action>()
let hoc1left: SxplrRegion
let hoc1leftCentroid: SxplrRegion let simpleHoc1: SxplrRegion = {
let hoc1leftCentroidWrongSpc: SxplrRegion name: 'foo',
id: '',
type: "SxplrRegion",
parentIds: [],
}
let hoc1LeftMni152: PathReturn<"/regions/{region_id}"> = {
"@id": "",
versionIdentifier: '',
"@type": '',
hasAnnotation: {
criteriaQualityType: {},
internalIdentifier: "",
bestViewPoint: {
coordinateSpace: {
"@id": IDS.TEMPLATES.MNI152
} as any,
coordinates: [
{
value: 1,
},{
value: 2,
},{
value: 3,
}
]
}
}
}
let hoc1LeftColin27: PathReturn<"/regions/{region_id}"> = {
"@id": "",
versionIdentifier: '',
"@type": '',
hasAnnotation: {
criteriaQualityType: {},
internalIdentifier: "",
bestViewPoint: {
coordinateSpace: {
"@id": IDS.TEMPLATES.COLIN27
} as any,
coordinates: [
{
value: 1,
},{
value: 2,
},{
value: 3,
}
]
}
}
}
beforeEach(async () => { beforeEach(async () => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
...@@ -34,26 +87,6 @@ describe("> effects.ts", () => { ...@@ -34,26 +87,6 @@ describe("> effects.ts", () => {
provideMockActions(() => actions$) provideMockActions(() => actions$)
] ]
}) })
/**
* only need to populate hoc1 left once
*/
if (!hoc1left) {
const sapisvc = TestBed.inject(SAPI)
const regions = await sapisvc.getParcRegions(IDS.PARCELLATION.JBA29).toPromise()
hoc1left = regions.find(r => /hoc1/i.test(r.name) && /left/i.test(r.name))
if (!hoc1left) throw new Error(`cannot find hoc1 left`)
hoc1leftCentroid = JSON.parse(JSON.stringify(hoc1left))
hoc1leftCentroid.centroid = {
space: {
id: IDS.TEMPLATES.BIG_BRAIN
} as SxplrTemplate,
loc: [1, 2, 3]
}
hoc1leftCentroidWrongSpc = JSON.parse(JSON.stringify(hoc1leftCentroid))
hoc1leftCentroidWrongSpc.centroid.space.id = IDS.TEMPLATES.COLIN27
}
}) })
it('> can be init', () => { it('> can be init', () => {
...@@ -229,10 +262,39 @@ describe("> effects.ts", () => { ...@@ -229,10 +262,39 @@ describe("> effects.ts", () => {
}) })
describe('> onNavigateToRegion', () => { describe('> onNavigateToRegion', () => {
const translatedRegion = {
"@id": "",
versionIdentifier: '',
"@type": '',
hasAnnotation: {
criteriaQualityType: {},
internalIdentifier: "",
bestViewPoint: {
coordinateSpace: {
"@id": IDS.TEMPLATES.MNI152
} as any,
coordinates: [
{
value: 1,
},{
value: 2,
},{
value: 3,
}
]
}
}
} as PathReturn<"/regions/{region_id}">
let retrieveRegionSpy: jasmine.Spy
beforeEach(async () => { beforeEach(async () => {
retrieveRegionSpy = spyOn(translateV3Entities, 'retrieveRegion')
actions$ = hot('a', { actions$ = hot('a', {
a: actions.navigateToRegion({ a: actions.navigateToRegion({
region: hoc1left region: simpleHoc1
}) })
}) })
const mockStore = TestBed.inject(MockStore) const mockStore = TestBed.inject(MockStore)
...@@ -264,6 +326,7 @@ describe("> effects.ts", () => { ...@@ -264,6 +326,7 @@ describe("> effects.ts", () => {
beforeEach(() => { beforeEach(() => {
const mockStore = TestBed.inject(MockStore) const mockStore = TestBed.inject(MockStore)
mockStore.overrideSelector(atpSelector, null) mockStore.overrideSelector(atpSelector, null)
retrieveRegionSpy.and.
}) })
it('> returns general error', () => { it('> returns general error', () => {
...@@ -302,16 +365,7 @@ describe("> effects.ts", () => { ...@@ -302,16 +365,7 @@ describe("> effects.ts", () => {
}) })
describe('> if inputs are fine', () => { describe('> if inputs are fine', () => {
let regionGetDetailSpy: jasmine.Spy = jasmine.createSpy()
beforeEach(() => {
const sapi = TestBed.inject(SAPI)
regionGetDetailSpy.and.returnValue(
of(hoc1leftCentroid)
)
})
afterEach(() => {
if (regionGetDetailSpy) regionGetDetailSpy.calls.reset()
})
it('> getRegionDetailSpy is called, and calls navigateTo', () => { it('> getRegionDetailSpy is called, and calls navigateTo', () => {
const eff = TestBed.inject(Effect) const eff = TestBed.inject(Effect)
expect(eff.onNavigateToRegion).toBeObservable( expect(eff.onNavigateToRegion).toBeObservable(
...@@ -330,9 +384,6 @@ describe("> effects.ts", () => { ...@@ -330,9 +384,6 @@ describe("> effects.ts", () => {
describe('> returns null', () => { describe('> returns null', () => {
beforeEach(() => { beforeEach(() => {
regionGetDetailSpy.and.returnValue(
of(null)
)
}) })
it('> generalactionerror', () => { it('> generalactionerror', () => {
...@@ -348,9 +399,7 @@ describe("> effects.ts", () => { ...@@ -348,9 +399,7 @@ describe("> effects.ts", () => {
}) })
describe('> general throw', () => { describe('> general throw', () => {
beforeEach(() => { beforeEach(() => {
regionGetDetailSpy.and.returnValue(
throwError(`oh noes`)
)
}) })
it('> generalactionerror', () => { it('> generalactionerror', () => {
...@@ -358,7 +407,7 @@ describe("> effects.ts", () => { ...@@ -358,7 +407,7 @@ describe("> effects.ts", () => {
expect(eff.onNavigateToRegion).toBeObservable( expect(eff.onNavigateToRegion).toBeObservable(
hot(`a`, { hot(`a`, {
a: mainActions.generalActionError({ a: mainActions.generalActionError({
message: `Error getting region centroid` message: `getting region detail error! cannot get coordinates`
}) })
}) })
) )
...@@ -368,9 +417,7 @@ describe("> effects.ts", () => { ...@@ -368,9 +417,7 @@ describe("> effects.ts", () => {
describe('> does not contain props attr', () => { describe('> does not contain props attr', () => {
beforeEach(() => { beforeEach(() => {
regionGetDetailSpy.and.returnValue(
of(hoc1left)
)
}) })
it('> generalactionerror', () => { it('> generalactionerror', () => {
......
import { Injectable } from "@angular/core"; import { Injectable } from "@angular/core";
import { Actions, createEffect, ofType } from "@ngrx/effects"; import { Actions, createEffect, ofType } from "@ngrx/effects";
import { forkJoin, merge, NEVER, Observable, of } from "rxjs"; import { forkJoin, merge, NEVER, Observable, of } from "rxjs";
import { filter, map, mapTo, switchMap, switchMapTo, take, withLatestFrom } from "rxjs/operators"; import { catchError, filter, map, mapTo, switchMap, switchMapTo, take, withLatestFrom } from "rxjs/operators";
import { SAPI, SAPIRegion } from "src/atlasComponents/sapi"; import { SAPI, SAPIRegion } from "src/atlasComponents/sapi";
import * as mainActions from "../actions" import * as mainActions from "../actions"
import { select, Store } from "@ngrx/store"; import { select, Store } from "@ngrx/store";
...@@ -346,27 +346,35 @@ export class Effect { ...@@ -346,27 +346,35 @@ export class Effect {
select(selectors.selectedParcellation) select(selectors.selectedParcellation)
) )
), ),
map(([{ region: _region }, selectedTemplate, selectedAtlas, selectedParcellation]) => { switchMap(([{ region: _region }, selectedTemplate, selectedAtlas, selectedParcellation]) => {
if (!selectedAtlas || !selectedTemplate || !selectedParcellation || !_region) { if (!selectedAtlas || !selectedTemplate || !selectedParcellation || !_region) {
return mainActions.generalActionError({ return of(
message: `atlas, template, parcellation or region not set` mainActions.generalActionError({
}) message: `atlas, template, parcellation or region not set`
})
)
} }
return this.sapiSvc.v3Get("/regions/{region_id}", {
const region = translateV3Entities.retrieveRegion(_region) path: {
region_id: _region.name
if (region.hasAnnotation?.bestViewPoint && region.hasAnnotation.bestViewPoint.coordinateSpace['@id'] === selectedTemplate["@id"]) { },
return actions.navigateTo({ query: {
parcellation_id: selectedParcellation.id,
space_id: selectedTemplate.id
}
}).pipe(
map(reg => actions.navigateTo({
animation: true, animation: true,
navigation: { navigation: {
position: region.hasAnnotation.bestViewPoint.coordinates.map(v => v.value * 1e6) position: reg.hasAnnotation.bestViewPoint.coordinates.map(v => v.value * 1e6)
} }
}) })),
} catchError(() => of(
mainActions.generalActionError({
return mainActions.generalActionError({ message: `getting region detail error! cannot get coordinates`
message: `getting region detail error! cannot get coordinates` })
}) )),
)
}) })
)) ))
......
...@@ -174,7 +174,7 @@ export function getParcNgId(atlas: SxplrAtlas, tmpl: SxplrTemplate, parc: SxplrP ...@@ -174,7 +174,7 @@ export function getParcNgId(atlas: SxplrAtlas, tmpl: SxplrTemplate, parc: SxplrP
: null : null
} }
if (parc.id === IDS.PARCELLATION.JBA30) { if (parc.id === IDS.PARCELLATION.JBA30 && tmpl.id !== IDS.TEMPLATES.FSAVERAGE) {
return `_${MultiDimMap.GetKey(atlas.id, tmpl.id, parc.id, "whole brain")}` return `_${MultiDimMap.GetKey(atlas.id, tmpl.id, parc.id, "whole brain")}`
} }
......
...@@ -10,12 +10,17 @@ import { ...@@ -10,12 +10,17 @@ import {
import { LayerCtrlEffects } from "./layerCtrl.effects" import { LayerCtrlEffects } from "./layerCtrl.effects"
import { NEVER } from "rxjs" import { NEVER } from "rxjs"
import { RouterService } from "src/routerModule/router.service" import { RouterService } from "src/routerModule/router.service"
import { HttpClientModule } from "@angular/common/http"
import { BaseService } from "../base.service/base.service"
describe('> layerctrl.service.ts', () => { describe('> layerctrl.service.ts', () => {
describe('> NehubaLayerControlService', () => { describe('> NehubaLayerControlService', () => {
let mockStore: MockStore let mockStore: MockStore
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports:[
HttpClientModule,
],
providers: [ providers: [
{ {
provide: RouterService, provide: RouterService,
...@@ -30,6 +35,13 @@ describe('> layerctrl.service.ts', () => { ...@@ -30,6 +35,13 @@ describe('> layerctrl.service.ts', () => {
useValue: { useValue: {
onATPDebounceNgLayers$: NEVER onATPDebounceNgLayers$: NEVER
} }
},
{
provide: BaseService,
useValue: {
selectedATPR$: NEVER,
completeNgIdLabelRegionMap$: NEVER,
}
} }
] ]
}) })
......
...@@ -32,8 +32,6 @@ export class NehubaLayerControlService implements OnDestroy{ ...@@ -32,8 +32,6 @@ export class NehubaLayerControlService implements OnDestroy{
private defaultNgLayers$ = this.layerEffects.onATPDebounceNgLayers$ private defaultNgLayers$ = this.layerEffects.onATPDebounceNgLayers$
private selectedATP$ = this.baseService.selectedATP$
public selectedATPR$ = this.baseService.selectedATPR$ public selectedATPR$ = this.baseService.selectedATPR$
private customLayers$ = this.store$.pipe( private customLayers$ = this.store$.pipe(
......
...@@ -9,6 +9,8 @@ import { LayerCtrlEffects } from "../layerCtrl.service/layerCtrl.effects" ...@@ -9,6 +9,8 @@ import { LayerCtrlEffects } from "../layerCtrl.service/layerCtrl.effects"
import { NEVER, of, pipe } from "rxjs" import { NEVER, of, pipe } from "rxjs"
import { mapTo, take } from "rxjs/operators" import { mapTo, take } from "rxjs/operators"
import { selectorAuxMeshes } from "../store" import { selectorAuxMeshes } from "../store"
import { HttpClientModule } from "@angular/common/http"
import { BaseService } from "../base.service/base.service"
const fits1 = {} as SxplrRegion const fits1 = {} as SxplrRegion
...@@ -59,6 +61,9 @@ describe('> mesh.service.ts', () => { ...@@ -59,6 +61,9 @@ describe('> mesh.service.ts', () => {
describe('> NehubaMeshService', () => { describe('> NehubaMeshService', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [
HttpClientModule,
],
providers: [ providers: [
provideMockStore(), provideMockStore(),
NehubaMeshService, NehubaMeshService,
...@@ -67,6 +72,12 @@ describe('> mesh.service.ts', () => { ...@@ -67,6 +72,12 @@ describe('> mesh.service.ts', () => {
useValue: { useValue: {
onATPDebounceNgLayers$: NEVER onATPDebounceNgLayers$: NEVER
} }
},
{
provide: BaseService,
useValue: {
completeNgIdLabelRegionMap$: NEVER
}
} }
] ]
}) })
...@@ -151,11 +162,18 @@ describe('> mesh.service.ts', () => { ...@@ -151,11 +162,18 @@ describe('> mesh.service.ts', () => {
* in the case of julich brain 2.9 in colin 27, we expect selecting a region will hide meshes from all relevant ngIds (both left and right) * in the case of julich brain 2.9 in colin 27, we expect selecting a region will hide meshes from all relevant ngIds (both left and right)
*/ */
it('> expect the emitted value to be incl all ngIds', () => { it('> expect the emitted value to be incl all ngIds', () => {
const bService = TestBed.inject(BaseService)
bService.completeNgIdLabelRegionMap$ = of({
[ngId1]: {},
[ngId2]: {
[labelIndex2]: fits1
}
})
const service = TestBed.inject(NehubaMeshService) const service = TestBed.inject(NehubaMeshService)
expect( expect(
service.loadMeshes$ service.loadMeshes$
).toBeObservable( ).toBeObservable(
hot('(ab)', { hot('abc', {
a: { a: {
layer: { layer: {
name: ngId1 name: ngId1
...@@ -167,6 +185,12 @@ describe('> mesh.service.ts', () => { ...@@ -167,6 +185,12 @@ describe('> mesh.service.ts', () => {
name: ngId2 name: ngId2
}, },
labelIndicies: [ labelIndex2 ] labelIndicies: [ labelIndex2 ]
},
c: {
layer: {
name: auxMesh.ngId
},
labelIndicies: auxMesh.labelIndicies
} }
}) })
) )
......
...@@ -19,12 +19,12 @@ ...@@ -19,12 +19,12 @@
<mat-menu #fsModeSelMenu="matMenu"> <mat-menu #fsModeSelMenu="matMenu">
<div class="sxplr-custom-cmp text sxplr-pl-2 m-2"> <div class="sxplr-custom-cmp text sxplr-pl-2 m-2">
<mat-checkbox *ngFor="let item of lateralityMeshRecord | keyvalue" <mat-checkbox *ngFor="let item of meshVisible$ | async "
class="d-block" class="d-block"
iav-stop="click" iav-stop="click"
(change)="updateMeshVisibility()" (change)="toggleMeshVis(item.label)"
[(ngModel)]="item.value.visible"> [checked]="item.visible">
{{ item.key }} {{ item.label }}
</mat-checkbox> </mat-checkbox>
</div> </div>
<mat-divider></mat-divider> <mat-divider></mat-divider>
......
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