From 0272b2a7634c3e697facf8c0af3a8bd71d6a7e0d Mon Sep 17 00:00:00 2001
From: Xiao Gui <xgui3783@gmail.com>
Date: Mon, 29 Mar 2021 18:26:42 +0200
Subject: [PATCH] bugfix: swc size

---
 src/messaging/nmvSwc/index.spec.ts | 66 ++++++++++++++++++++++++++++++
 src/messaging/nmvSwc/index.ts      | 61 ++++++++++++++++++++++++---
 2 files changed, 121 insertions(+), 6 deletions(-)
 create mode 100644 src/messaging/nmvSwc/index.spec.ts

diff --git a/src/messaging/nmvSwc/index.spec.ts b/src/messaging/nmvSwc/index.spec.ts
new file mode 100644
index 000000000..86862ed2a
--- /dev/null
+++ b/src/messaging/nmvSwc/index.spec.ts
@@ -0,0 +1,66 @@
+import { IAV_IDS, IAV_VOXEL_SIZES_NM } from './index'
+
+const waxholmTemplates = require('!json-loader!src/res/ext/waxholmRatV2_0.json')
+const allenTemplates = require('!json-loader!src/res/ext/allenMouse.json')
+const colinTemplates = require('!json-loader!src/res/ext/colin.json')
+const mniTemplates = require('!json-loader!src/res/ext/MNI152.json')
+const bbTemplates = require('!json-loader!src/res/ext/bigbrain.json')
+
+
+const ratNehubaConfig = require('!json-loader!src/res/ext/waxholmRatV2_0NehubaConfig.json')
+const mouseNehubaConfig = require('!json-loader!src/res/ext/allenMouseNehubaConfig.json')
+const colinNehubaConfig = require('!json-loader!src/res/ext/colinNehubaConfig.json')
+const icbmNehubaConfig = require('!json-loader!src/res/ext/MNI152NehubaConfig.json')
+const bbNehubaConfig = require('!json-loader!src/res/ext/bigbrainNehubaConfig.json')
+
+const tmplArr = [
+  waxholmTemplates,
+  allenTemplates,
+  colinTemplates,
+  mniTemplates,
+  bbTemplates,
+]
+
+const configArr = [
+  ratNehubaConfig,
+  mouseNehubaConfig,
+  colinNehubaConfig,
+  icbmNehubaConfig,
+  bbNehubaConfig,
+].map(cfg => {
+
+  return {
+    layerNames: Object.keys(
+      cfg['dataset']['initialNgState']['layers']
+    ),
+    voxelSize: cfg['dataset']['initialNgState']['navigation']['pose']['position']['voxelSize']
+  }
+})
+
+describe('> messaging/nmvSwc', () => {
+  for (const tmplKey in IAV_IDS) {
+    describe(`> ${tmplKey}`, () => {
+      let tmpl, config
+      beforeAll(() => {
+        tmpl = tmplArr.find(t => t['@id'] === IAV_IDS[tmplKey])
+        config = tmpl && configArr.find(cfg => 
+          cfg.layerNames.includes(tmpl['ngId'])
+        )
+      })
+
+      it('> should be able to find tmpl by id', () => {
+        expect(tmpl).toBeTruthy()
+      })
+
+      it('> should be able to find the config', () => {
+        expect(config).toBeTruthy()
+      })
+
+      it('> voxelSize should match the hardcoded value', () => {
+        expect(
+          config.voxelSize
+        ).toEqual(IAV_VOXEL_SIZES_NM[tmplKey])
+      })
+    })
+  }
+})
diff --git a/src/messaging/nmvSwc/index.ts b/src/messaging/nmvSwc/index.ts
index 414288141..08b0ce699 100644
--- a/src/messaging/nmvSwc/index.ts
+++ b/src/messaging/nmvSwc/index.ts
@@ -22,7 +22,7 @@ const NM_IDS = {
   MNI152_2009C_ASYM: 'hbp:ICBM_Asym_r2009c(um)',
 }
 
-const IAV_IDS = {
+export const IAV_IDS = {
   AMBA_V3: 'minds/core/referencespace/v1.0.0/265d32a0-3d84-40a5-926f-bf89f68212b9',
   WAXHOLM_V1_01: 'minds/core/referencespace/v1.0.0/d5717c4a-0fa1-46e6-918c-b8003069ade8',
   BIG_BRAIN: 'minds/core/referencespace/v1.0.0/a1655b99-82f1-420f-a3c2-fe80fd4c8588',
@@ -30,6 +30,38 @@ const IAV_IDS = {
   MNI152_2009C_ASYM: 'minds/core/referencespace/v1.0.0/dafcffc5-4826-4bf1-8ff6-46b8a31ff8e2',
 }
 
+/**
+ * TODO, should unify navigation voxelSize
+ * the emitted voxelCoord should be calculated on the fly
+ */
+export const IAV_VOXEL_SIZES_NM = {
+  AMBA_V3: [
+    25000,
+    25000,
+    25000
+  ],
+  WAXHOLM_V1_01: [
+    39062.5,
+    39062.5,
+    39062.5
+  ],
+  BIG_BRAIN: [
+    21166.666015625,
+    20000,
+    21166.666015625
+  ],
+  COLIN: [
+    1000000,
+    1000000,
+    1000000,
+  ],
+  MNI152_2009C_ASYM: [
+    1000000,
+    1000000,
+    1000000
+  ]
+}
+
 const translateSpace = (spaceId: string) => {
   for (const key in NM_IDS){
     if (NM_IDS[key] === spaceId) return IAV_IDS[key]
@@ -37,6 +69,13 @@ const translateSpace = (spaceId: string) => {
   return null
 }
 
+const getVoxelFromSpace = (spaceId: string) => {
+  for (const key in NM_IDS){
+    if (NM_IDS[key] === spaceId) return IAV_VOXEL_SIZES_NM[key]
+  }
+  return null
+}
+
 export const processJsonLd = (json: { [key: string]: any }): Observable<IMessagingActions<keyof IMessagingActionTmpl>> => {
   const subject = new Subject<IMessagingActions<keyof IMessagingActionTmpl>>()
   const main = (async () => {
@@ -93,15 +132,25 @@ export const processJsonLd = (json: { [key: string]: any }): Observable<IMessagi
     )
     const uuid = getUuid()
 
-    // NG internal treats skeleton as mm 
-    const scaleUmToMm = 1e-3
+    // NG internal treats skeleton as mm
+    const voxelSize = getVoxelFromSpace(toSpace)
+    /**
+     * swc seem to scale with voxelSize... strangely enough
+     * voxelSize nm / voxel -> goal is 1 voxel/um
+     * 1e3 / voxelSize
+     */
+    const scaleUmToVoxelFixed = [
+      1e3 / voxelSize[0],
+      1e3 / voxelSize[1],
+      1e3 / voxelSize[2],
+    ]
     // NG translation works on nm scale
     const scaleUmToNm = 1e3
     const { mat3, vec3 } = (window as any).export_nehuba
     const modA = mat3.fromValues(
-      scaleUmToMm, 0, 0,
-      0, scaleUmToMm, 0,
-      0, 0, scaleUmToMm
+      scaleUmToVoxelFixed[0], 0, 0,
+      0, scaleUmToVoxelFixed[1], 0,
+      0, 0, scaleUmToVoxelFixed[2]
     )
     mat3.mul(modA, modA, [...A[0], ...A[1], ...A[2]])
     const modb = vec3.scale(vec3.create(), b, scaleUmToNm)
-- 
GitLab