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

Merge pull request #85 from FZJ-INM1-BDA/dev

merge dev
parents 5f0b8315 9b0c6b45
No related branches found
No related tags found
No related merge requests found
const {AtlasPage} = require('../util')
const TEST_DATA = [
{
url: "/?templateSelected=MNI+152+ICBM+2009c+Nonlinear+Asymmetric&parcellationSelected=JuBrain+Cytoarchitectonic+Atlas",
templateName: 'MNI 152 ICBM 2009c Nonlinear Asymmetric',
position: [450, 200],
expectedRegion: 'Area hOc1 (V1, 17, CalcS) - left hemisphere',
expectedTemplateLabels: [
{
name: 'Big Brain (Histology)',
expectedPosition: [3187941, -50436480, 3430986]
},
{
name: 'MNI Colin 27',
expectedPosition: [
-8533787,
-84646549,
1855106
]
},
],
},
{
url: "/?templateSelected=Big+Brain+%28Histology%29&parcellationSelected=Cytoarchitectonic+Maps&cNavigation=0.0.0.-W000.._eCwg.2-FUe3._-s_W.2_evlu..7LIx..1n5q~.1FYC.2Is-..1B9C",
templateName: 'Big Brain (Histology)',
position: [691,678], // [370, 150],
expectedRegion: 'Area STS1 (STS)',
expectedTemplateLabels: [
{
name: 'MNI Colin 27',
hemisphere: 'Left',
expectedPosition: [-54514755, -16753913, -5260713]
},
{
name: 'MNI Colin 27',
hemisphere: 'Right',
expectedPosition: [54536567, -17992636, -5712544]
},
{
name: 'MNI 152 ICBM 2009c Nonlinear Asymmetric',
hemisphere: 'Left',
expectedPosition: [-55442669, -18314601, -6381831]
},
{
name: 'MNI 152 ICBM 2009c Nonlinear Asymmetric',
hemisphere: 'Right',
expectedPosition: [52602966, -18339402, -5666868]
},
],
},
]
describe('explore same region in different templates', () => {
let iavPage
beforeAll(async () => {
iavPage = new AtlasPage()
await iavPage.init()
})
TEST_DATA.forEach(template => {
template.expectedTemplateLabels.forEach(expectedTemplate => {
it (`testing ${template.expectedRegion} exploring at: ${template.name}`, async () => {
if (template.url) {
await iavPage.goto(template.url)
} else {
await iavPage.goto()
await iavPage.selectTitleTemplateParcellation(template.name)
}
const {position} = template
const tag = await iavPage.getSideNavTag()
await tag.click()
await iavPage.wait(1000)
await iavPage.waitUntilAllChunksLoaded()
await iavPage.cursorMoveToAndClick({ position })
await iavPage.showOtherTemplateMenu()
await iavPage.wait(500)
const otherTemplates = await iavPage.getAllOtherTemplates()
const { name, hemisphere, expectedPosition } = expectedTemplate
const idx = otherTemplates.findIndex(template => {
if (hemisphere) {
if (template.indexOf(hemisphere) < 0) return false
}
return template.indexOf(name) >= 0
})
expect(idx).toBeGreaterThanOrEqual(0)
await iavPage.clickNthItemAllOtherTemplates(idx)
await iavPage.wait(500)
await iavPage.waitUntilAllChunksLoaded()
const navState = await iavPage.getNavigationState()
// somehow there are slight deviations (1nm in most cases)
// giving a tolerance of 0.1um
for (const idx in navState.position) {
expect(
Math.abs(navState.position[idx] - expectedPosition[idx])
).toBeLessThanOrEqual(100)
}
})
})
})
})
......@@ -23,6 +23,20 @@ async function _getIndexFromArrayOfWebElements(search, webElements) {
const regionSearchAriaLabelText = 'Search for any region of interest in the atlas selected'
const vertifyPos = position => {
if (!position) throw new Error(`cursorGoto: position must be defined!`)
const x = Array.isArray(position) ? position[0] : position.x
const y = Array.isArray(position) ? position[1] : position.y
if (!x) throw new Error(`cursorGoto: position.x or position[0] must be defined`)
if (!y) throw new Error(`cursorGoto: position.y or position[1] must be defined`)
return {
x,
y
}
}
class WdBase{
constructor() {
browser.waitForAngularEnabled(false)
......@@ -79,12 +93,19 @@ class WdBase{
}
async cursorMoveTo({ position }) {
if (!position) throw new Error(`cursorGoto: position must be defined!`)
const x = Array.isArray(position) ? position[0] : position.x
const y = Array.isArray(position)? position[1] : position.y
if (!x) throw new Error(`cursorGoto: position.x or position[0] must be defined`)
if (!y) throw new Error(`cursorGoto: position.y or position[1] must be defined`)
const { x, y } = vertifyPos(position)
return this._driver.actions()
.move()
.move({
x,
y,
duration: 1000
})
.perform()
}
async cursorMoveToAndClick({ position }) {
const { x, y } = vertifyPos(position)
return this._driver.actions()
.move()
.move({
......@@ -92,6 +113,7 @@ class WdBase{
y,
duration: 1000
})
.click()
.perform()
}
......@@ -461,6 +483,37 @@ class WdLayoutPage extends WdBase{
else await menuItems[index].click()
}
// other templates
async showOtherTemplateMenu(){
await this._driver
.findElement( By.css('[aria-label="Show availability in other reference spaces"]') )
.click()
}
_getOtherTemplateMenu(){
return this._driver
.findElement( By.css('[aria-label="Availability in other reference spaces"]') )
}
_getAllOtherTemplates(){
return this._getOtherTemplateMenu().findElements( By.css('[mat-menu-item]') )
}
async getAllOtherTemplates(){
const els = await this._getAllOtherTemplates()
const returnArr = []
for (const el of els) {
returnArr.push(await _getTextFromWebElement(el))
}
return returnArr
}
async clickNthItemAllOtherTemplates(index){
const arr = await this._getAllOtherTemplates()
if (!arr[index]) throw new Error(`index out of bound: trying to access ${index} from arr with length ${arr.length}`)
await arr[index].click()
}
_getFavDatasetIcon(){
return this._driver
.findElement( By.css('[aria-label="Show pinned datasets"]') )
......@@ -745,4 +798,4 @@ class PptrIAVPage{
exports.waitMultiple = process.env.WAIT_ULTIPLE || 1
exports.AtlasPage = WdIavPage
exports.LayoutPage = WdLayoutPage
\ No newline at end of file
exports.LayoutPage = WdLayoutPage
......@@ -106,7 +106,7 @@ export const getStateStore = ({ state = defaultState } = {}) => (prevState: Part
// taken care of by effect.ts
// landmarksSelected : [],
// navigation : {},
navigation : action.navigation,
dedicatedView : null,
}
}
......
import {EventEmitter, Input, Output} from "@angular/core";
import { Store } from "@ngrx/store";
import {SET_CONNECTIVITY_REGION} from "src/services/state/viewerState.store";
import {select, Store} from "@ngrx/store";
import {NEWVIEWER, SET_CONNECTIVITY_REGION} from "src/services/state/viewerState.store";
import {
EXPAND_SIDE_PANEL_CURRENT_VIEW,
IavRootStoreInterface, OPEN_SIDE_PANEL,
SHOW_SIDE_PANEL_CONNECTIVITY,
} from "src/services/stateStore.service";
import { VIEWERSTATE_CONTROLLER_ACTION_TYPES } from "../viewerStateController/viewerState.base";
import {distinctUntilChanged, shareReplay} from "rxjs/operators";
import {Observable} from "rxjs";
export class RegionBase {
......@@ -20,10 +22,40 @@ export class RegionBase {
@Output() public closeRegionMenu: EventEmitter<boolean> = new EventEmitter()
public loadedTemplate$: Observable<any[]>
public templateSelected$: Observable<any[]>
public parcellationSelected$: Observable<any[]>
protected loadedTemplates: any[]
protected selectedTemplate: any
protected selectedParcellation: any
public sameRegionTemplate: any[] = []
private parcellationRegions: any[] = []
constructor(
private store$: Store<IavRootStoreInterface>,
) {
const viewerState$ = this.store$.pipe(
select('viewerState'),
shareReplay(1),
)
this.loadedTemplate$ = viewerState$.pipe(
select('fetchedTemplates'),
distinctUntilChanged()
)
this.templateSelected$ = viewerState$.pipe(
select('templateSelected'),
distinctUntilChanged(),
)
this.parcellationSelected$ = viewerState$.pipe(
select('parcellationSelected'),
distinctUntilChanged(),
)
}
public navigateToRegion() {
......@@ -56,4 +88,65 @@ export class RegionBase {
connectivityRegion: regionName,
})
}
getDifferentTemplatesSameRegion() {
this.sameRegionTemplate = []
this.loadedTemplates.forEach(template => {
if (this.selectedTemplate.name !== template.name) {
template.parcellations.forEach(parcellation => {
this.parcellationRegions = []
this.getAllRegionsFromParcellation(parcellation.regions)
this.parcellationRegions.forEach(pr => {
if (JSON.stringify(pr.fullId) === JSON.stringify(this.region.fullId)) {
const baseAreaHemisphere =
this.region.name.includes(' - right hemisphere')? 'Right' :
this.region.name.includes(' - left hemisphere')? 'Left'
: null
const areaHemisphere =
pr.name.includes(' - right hemisphere')? 'Right'
: pr.name.includes(' - left hemisphere')? 'Left'
: null
const sameRegionSpace = {template: template, parcellation: parcellation, region: pr}
if (!baseAreaHemisphere && areaHemisphere) {
this.sameRegionTemplate.push({
...sameRegionSpace,
hemisphere: areaHemisphere
})
} else
if (!this.sameRegionTemplate.map(sr => sr.template).includes(template)) {
if (!(baseAreaHemisphere && areaHemisphere && baseAreaHemisphere !== areaHemisphere)) {
this.sameRegionTemplate.push(sameRegionSpace)
}
}
}
})
})
}
})
}
changeView(index) {
this.closeRegionMenu.emit()
this.store$.dispatch({
type : NEWVIEWER,
selectTemplate : this.sameRegionTemplate[index].template,
selectParcellation : this.sameRegionTemplate[index].parcellation,
navigation: {position: this.sameRegionTemplate[index].region.position},
})
}
public getAllRegionsFromParcellation = (regions) => {
for (const region of regions) {
if (region.children && region.children.length) {
this.getAllRegionsFromParcellation(region.children)
} else {
this.parcellationRegions.push(region)
}
}
}
}
import { Component } from "@angular/core";
import {Component, ElementRef, OnDestroy, OnInit, ViewChild} from "@angular/core";
import { Store } from "@ngrx/store";
import {MatMenuTrigger} from "@angular/material/menu";
import {Subscription} from "rxjs";
import { IavRootStoreInterface } from "src/services/stateStore.service";
import { RegionBase } from '../region.base'
......@@ -9,11 +10,37 @@ import { RegionBase } from '../region.base'
templateUrl: './regionMenu.template.html',
styleUrls: ['./regionMenu.style.css'],
})
export class RegionMenuComponent extends RegionBase {
export class RegionMenuComponent extends RegionBase implements OnInit, OnDestroy {
@ViewChild('additionalActionsPanel', {read: ElementRef}) additionalActionsPanelElement: ElementRef
private subscriptions: Subscription[] = []
constructor(
store$: Store<IavRootStoreInterface>,
) {
super(store$)
}
ngOnInit(): void {
this.subscriptions.push(
this.templateSelected$.subscribe(template => {
this.selectedTemplate = template
}),
this.parcellationSelected$.subscribe(parcellation => {
this.selectedParcellation = parcellation
}),
this.loadedTemplate$.subscribe(templates => {
this.loadedTemplates = templates
this.getDifferentTemplatesSameRegion()
// this.bigBrainJubrainSwitch()
// this.getSameParcellationTemplates()
}),
)
}
ngOnDestroy(): void {
this.subscriptions.forEach(s => s.unsubscribe())
}
}
......@@ -11,7 +11,7 @@
<mat-card-content>
{{ region.description }}
</mat-card-content>
<mat-card-actions class="d-flex flex-row flex-wrap">
<div class="d-flex flex-row flex-wrap">
<button mat-button
(click)="toggleRegionSelected()"
[color]="isSelected ? 'primary': 'basic'">
......@@ -46,5 +46,34 @@
</button>
</div>
</mat-menu>
</mat-card-actions>
</mat-card>
\ No newline at end of file
<!-- Menu to navigate between template spaces to explore same region -->
<div>
<button mat-button
aria-label="Show availability in other reference spaces"
*ngIf="sameRegionTemplate.length"
[matMenuTriggerFor]="additionalActions">
<i class="fas fa-brain"></i>
<span>
Change template
</span>
<i class="fas fa-angle-right"></i>
</button>
</div>
<mat-menu
[aria-label]="'Availability in other reference spaces'"
#additionalActions="matMenu"
xPosition="before"
hasBackdrop="false">
<div>
<button mat-menu-item *ngFor="let sameRegion of sameRegionTemplate; let i = index" (click)="changeView(i)" class="d-flex">
<span class="overflow-x-hidden text-truncate"> {{sameRegion.template.name}} </span>
<span *ngIf="sameRegion.hemisphere"> - {{sameRegion.hemisphere}}</span>
</button>
</div>
</mat-menu>
</div>
</mat-card>
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