Skip to content

Commit

Permalink
Merge pull request #1364 from FZJ-INM1-BDA/staging
Browse files Browse the repository at this point in the history
releasing v2.12.0
  • Loading branch information
xgui3783 authored Jun 29, 2023
2 parents 0ce7197 + e2b679e commit 66bad52
Show file tree
Hide file tree
Showing 46 changed files with 765 additions and 651 deletions.
27 changes: 25 additions & 2 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,13 @@
"styles": [
"src/theme.scss",
"src/overwrite.scss",
"src/extra_styles.css"
"src/extra_styles.css",

{
"input": "export-nehuba/dist/min/main.css",
"inject": false,
"bundleName": "vanillaMain"
}
],
"scripts": [{
"input": "worker/worker.js",
Expand Down Expand Up @@ -65,15 +71,32 @@
"input": "third_party/vanilla_nehuba.js",
"inject": false,
"bundleName": "vanilla_nehuba"
},{
},

{
"input": "export-nehuba/dist/min/main.bundle.js",
"inject": false,
"bundleName": "main.bundle"
},{
"input": "export-nehuba/dist/min/chunk_worker.bundle.js",
"inject": false,
"bundleName": "chunk_worker.bundle"
},
{
"input": "export-nehuba/dist/min/draco.bundle.js",
"inject": false,
"bundleName": "draco.bundle"
},{
"input": "export-nehuba/dist/min/async_computation.bundle.js",
"inject": false,
"bundleName": "async_computation.bundle"
},{
"input": "export-nehuba/dist/min/blosc.bundle.js",
"inject": false,
"bundleName": "blosc.bundle"
},

{
"inject": false,
"input": "third_party/leap-0.6.4.js",
"bundleName": "leap-0.6.4"
Expand Down
3 changes: 3 additions & 0 deletions common/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ If you do not accept the Terms & Conditions you are not permitted to access or u
REMOVE_FRONTAL_OCTANT_HELPER_TEXT: `Hide the octant facing the user, and overlaying the slice views.`,

AUXMESH_DESC: `Some templates contain auxiliary meshes, which compliment the appearance of the template in the perspective view.`,

OVERWRITE_SAPI_ENDPOINT_ATTR: `x-sapi-base-url`,
DATA_ERROR_ATTR: `data-error`
}

exports.QUICKTOUR_DESC ={
Expand Down
73 changes: 30 additions & 43 deletions deploy/app.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
const fs = require('fs')
const path = require('path')
const express = require('express')
const app = express.Router()
const session = require('express-session')
const crypto = require('crypto')
const cookieParser = require('cookie-parser')
const bkwdMdl = require('./bkwdCompat')()

const LOCAL_CDN_FLAG = !!process.env.LOCAL_CDN
const { CONST } = require("../common/constants")

if (process.env.NODE_ENV !== 'production') {
app.use(require('cors')())
Expand Down Expand Up @@ -123,36 +121,6 @@ const PUBLIC_PATH = process.env.NODE_ENV === 'production'
*/
app.use('/.well-known', express.static(path.join(__dirname, 'well-known')))

if (LOCAL_CDN_FLAG) {
/*
* TODO setup local cdn for supported libraries map
*/
const LOCAL_CDN = process.env.LOCAL_CDN
const CDN_ARRAY = [
'https://stackpath.bootstrapcdn.com',
'https://use.fontawesome.com',
'https://unpkg.com'
]

let indexFile
fs.readFile(path.join(PUBLIC_PATH, 'index.html'), 'utf-8', (err, data) => {
if (err) throw err
if (!LOCAL_CDN) {
indexFile = data
return
}
const regexString = CDN_ARRAY.join('|').replace(/\/|\./g, s => `\\${s}`)
const regex = new RegExp(regexString, 'gm')
indexFile = data.replace(regex, LOCAL_CDN)
})

app.get('/', bkwdMdl, (_req, res) => {
if (!indexFile) return res.status(404).end()
res.setHeader('Content-Type', 'text/html; charset=utf-8')
return res.status(200).send(indexFile)
})
}

app.use((_req, res, next) => {
res.setHeader('Referrer-Policy', 'origin-when-cross-origin')
next()
Expand Down Expand Up @@ -182,23 +150,42 @@ app.get('/', (req, res, next) => {
middelware(req, res, next)
}

}, bkwdMdl, cookieParser(), (req, res) => {
}, bkwdMdl, cookieParser(), async (req, res) => {
res.setHeader('Content-Type', 'text/html')

let returnIndex = indexTemplate

if (!!process.env.LOCAL_CDN) {
const CDN_ARRAY = [
'https://stackpath.bootstrapcdn.com',
'https://use.fontawesome.com',
'https://unpkg.com'
]

const regexString = CDN_ARRAY.join('|').replace(/\/|\./g, s => `\\${s}`)
const regex = new RegExp(regexString, 'gm')
returnIndex = returnIndex.replace(regex, process.env.LOCAL_CDN)
}
const iavError = req.cookies && req.cookies['iav-error']

res.setHeader('Content-Type', 'text/html')
const attributeToAppend = {}

if (iavError) {
res.clearCookie('iav-error', { httpOnly: true, sameSite: 'strict' })
attributeToAppend[CONST.DATA_ERROR_ATTR] = iavError
}

const returnTemplate = indexTemplate
.replace(/\$\$NONCE\$\$/g, res.locals.nonce)
.replace('<atlas-viewer>', `<atlas-viewer data-error="${iavError.replace(/"/g, '&quot;')}">`)
res.status(200).send(returnTemplate)
} else {
const returnTemplate = indexTemplate
.replace(/\$\$NONCE\$\$/g, res.locals.nonce)
res.status(200).send(returnTemplate)
if (!!process.env.OVERWRITE_API_ENDPOING) {
attributeToAppend[CONST.OVERWRITE_SAPI_ENDPOINT_ATTR] = process.env.OVERWRITE_API_ENDPOING
}

const attr = Object.entries(attributeToAppend).map(([key, value]) => `${key}="${value.replace(/"/g, '&quot;')}"`).join(" ")

const returnTemplate = returnIndex
.replace(/\$\$NONCE\$\$/g, res.locals.nonce)
.replace('<atlas-viewer>', `<atlas-viewer ${attr}>`)

res.status(200).send(returnTemplate)
})

app.get('/ready', async (req, res) => {
Expand Down
2 changes: 1 addition & 1 deletion deploy/csp/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ module.exports = {
'https://unpkg.com/[email protected]/', // required for preview component
'https://unpkg.com/[email protected]/', // math jax
'https://unpkg.com/[email protected]/dist/bundle.js', // for threeSurfer (freesurfer support in browser)
'https://unpkg.com/[email protected].13/dist/ng-layer-tune/', // needed for ng layer control
'https://unpkg.com/[email protected].14/dist/ng-layer-tune/', // needed for ng layer control
'https://unpkg.com/[email protected]/', // needed for connectivity component
(req, res) => res.locals.nonce ? `'nonce-${res.locals.nonce}'` : null,
...SCRIPT_SRC,
Expand Down
17 changes: 17 additions & 0 deletions docs/releases/v2.12.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# v2.12.0

## Feature

- added opacity slider for external volumes, even if the more detail is collapsed.
- enable rat connectivity
- added visual indicators for selected subject and dataset in connectivity browser

## Bugfix

- fixed fsaverage viewer "rubber banding"

## Behind the scene

- update spotlight mechanics from in-house to angular CDK
- updated neuroglancer/nehuba dependency. This allows volumes with non-rigid affine to be displayed properly.
- allow siibra-api endpoint to be configured at runtime
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ nav:
- Fetching datasets: 'advanced/datasets.md'
- Display non-atlas volumes: 'advanced/otherVolumes.md'
- Release notes:
- v2.12.0: 'releases/v2.12.0.md'
- v2.11.4: 'releases/v2.11.4.md'
- v2.11.3: 'releases/v2.11.3.md'
- v2.11.2: 'releases/v2.11.2.md'
Expand Down
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "siibra-explorer",
"version": "2.11.4",
"version": "2.12.0",
"description": "siibra-explorer - explore brain atlases. Based on humanbrainproject/nehuba & google/neuroglancer. Built with angular",
"scripts": {
"lint": "eslint src --ext .ts",
Expand Down Expand Up @@ -66,7 +66,7 @@
"@ngrx/effects": "^14.3.2",
"@ngrx/store": "^14.3.2",
"acorn": "^8.4.1",
"export-nehuba": "0.0.12",
"export-nehuba": "^0.1.0",
"file-loader": "^6.2.0",
"jszip": "^3.6.0",
"postcss": "^8.3.6",
Expand Down
37 changes: 17 additions & 20 deletions src/atlasComponents/annotations/annotation.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { BehaviorSubject, Observable } from "rxjs";
import { distinctUntilChanged } from "rxjs/operators";
import { getUuid } from "src/util/fn";
import { PeriodicSvc } from "src/util/periodic.service";

export type TNgAnnotationEv = {
pickedAnnotationId: string
Expand Down Expand Up @@ -38,6 +39,7 @@ type _AnnotationSpec = Omit<AnnotationSpec, 'type'> & { type: number }
type AnnotationRef = Record<string, unknown>

interface NgAnnotationLayer {
isReady: () => boolean
layer: {
localAnnotations: {
references: {
Expand Down Expand Up @@ -124,16 +126,23 @@ export class AnnotationLayer {
}
}

addAnnotation(spec: AnnotationSpec){
async addAnnotation(spec: AnnotationSpec){
if (!this.nglayer) {
throw new Error(`layer has already been disposed`)
}
const localAnnotations = this.nglayer.layer.localAnnotations
this.idset.add(spec.id)
const annSpec = this.parseNgSpecType(spec)
localAnnotations.add(
annSpec
)

PeriodicSvc.AddToQueue(() => {
if (this.nglayer.isReady()) {
const localAnnotations = this.nglayer.layer.localAnnotations
this.idset.add(spec.id)
const annSpec = this.parseNgSpecType(spec)
localAnnotations.add(
annSpec
)
return true
}
return false
})
}
removeAnnotation(spec: { id: string }) {
if (!this.nglayer) return
Expand All @@ -145,7 +154,7 @@ export class AnnotationLayer {
localAnnotations.references.delete(spec.id)
}
}
updateAnnotation(spec: AnnotationSpec) {
async updateAnnotation(spec: AnnotationSpec) {
const localAnnotations = this.nglayer?.layer?.localAnnotations
if (!localAnnotations) return
const ref = localAnnotations.references.get(spec.id)
Expand All @@ -167,9 +176,6 @@ export class AnnotationLayer {
}

private parseNgSpecType(spec: AnnotationSpec): _AnnotationSpec{
const voxelSize = this.viewer.navigationState.voxelSize.toJSON()
const sanitizePoint = (p: [number, number, number]) => p.map((v, idx) => v / voxelSize[idx]) as [number, number, number]
const needSanitizePosition = voxelSize[0] !== 1 || voxelSize[1] !== 1 || voxelSize[2] !== 1
const overwrite: Partial<_AnnotationSpec> = {}
switch (spec.type) {
case "point": {
Expand All @@ -187,15 +193,6 @@ export class AnnotationLayer {
default: throw new Error(`overwrite type lookup failed for ${(spec as any).type}`)
}

/**
* The unit of annotation(s) depends on voxel size. If it is 1,1,1 then it would be in um, but often it is not.
* If not sanitized, the annotation can be miles off.
*/
if (needSanitizePosition) {
for (const key of ['point', 'pointA', 'pointB'] ) {
if (!!spec[key]) overwrite[key] = sanitizePoint(spec[key])
}
}
return {
...spec,
...overwrite,
Expand Down
12 changes: 9 additions & 3 deletions src/atlasComponents/sapi/sapi.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import { FeatureType, PathReturn, RouteParam, SapiRoute } from "./typeV3";
import { BoundingBox, SxplrAtlas, SxplrParcellation, SxplrRegion, SxplrTemplate, VoiFeature, Feature } from "./sxplrTypes";
import { parcBanList, speciesOrder } from "src/util/constants";
import { CONST } from "common/constants"

export const useViewer = {
THREESURFER: "THREESURFER",
Expand All @@ -21,7 +22,7 @@ export const useViewer = {
} as const

export const SIIBRA_API_VERSION_HEADER_KEY='x-siibra-api-version'
export const EXPECTED_SIIBRA_API_VERSION = '0.3.8'
export const EXPECTED_SIIBRA_API_VERSION = '0.3.9'

let BS_ENDPOINT_CACHED_VALUE: Observable<string> = null

Expand Down Expand Up @@ -94,7 +95,12 @@ export class SAPI{
*/
static get BsEndpoint$(): Observable<string> {
if (!!BS_ENDPOINT_CACHED_VALUE) return BS_ENDPOINT_CACHED_VALUE
const endpoints = environment.SIIBRA_API_ENDPOINTS.split(',')
const rootEl = document.querySelector('atlas-viewer')
const overwriteSapiUrl = rootEl?.getAttribute(CONST.OVERWRITE_SAPI_ENDPOINT_ATTR)

const endpoints = overwriteSapiUrl
? [ overwriteSapiUrl ]
: environment.SIIBRA_API_ENDPOINTS.split(',')
if (endpoints.length === 0) {
SAPI.ErrorMessage = `No siibra-api endpoint defined!`
return NEVER
Expand Down Expand Up @@ -296,7 +302,7 @@ export class SAPI{
switchMap(atlases => forkJoin(
atlases.items.map(atlas => translateV3Entities.translateAtlas(atlas))
)),
map(atlases => atlases.sort((a, b) => speciesOrder.indexOf(a.species) - speciesOrder.indexOf(b.species))),
map(atlases => atlases.sort((a, b) => (speciesOrder as string[]).indexOf(a.species) - (speciesOrder as string[]).indexOf(b.species))),
tap(() => {
const respVersion = SAPI.API_VERSION
if (respVersion !== EXPECTED_SIIBRA_API_VERSION) {
Expand Down
4 changes: 2 additions & 2 deletions src/atlasViewer/atlasViewer.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit {
@Inject(DARKTHEME) private darktheme$: Observable<boolean>
) {

const error = this.el.nativeElement.getAttribute('data-error')
const error = this.el.nativeElement.getAttribute(CONST.DATA_ERROR_ATTR)

if (error) {
this.snackbar.open(error, 'Dismiss', { duration: 5000 })
this.el.nativeElement.removeAttribute('data-error')
this.el.nativeElement.removeAttribute(CONST.DATA_ERROR_ATTR)
}
}

Expand Down
Loading

0 comments on commit 66bad52

Please sign in to comment.