feat(b-values): implement parsing for multiple b-value formats and update default setting
This commit is contained in:
+302
-244
@@ -40,256 +40,314 @@
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
|
||||
<script>
|
||||
// Viewer state to import
|
||||
const state = {
|
||||
grid: { rows: 1, cols: 3 },
|
||||
modes: ["stack", "stack", "stack"],
|
||||
stacks: [
|
||||
{
|
||||
i: [
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_573_PN7j4gd.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_580_kBgyDxS.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_572_DYQisSg.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_579_ya291yy.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_571_nThHs31.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_578_1eEKjB2.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_570_qT5wuZX.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_577_v2bo1kn.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_569_oV2dHz8.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_576_kgF1iXK.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_568_iY1z50L.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_575_BipYnZH.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_567_HawAeuC.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_574_FrcCKA7.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_566_AUDtXEf.dcm",
|
||||
],
|
||||
},
|
||||
{
|
||||
i: [
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_588_tGfMjqb.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_592_Js4efiI.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_584_U8WCsNY.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_595_vFPcByt.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_587_jnB3wGF.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_591_1XZY7Le.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_583_C9KGrQ9.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_594_SqzeIRU.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_586_Hupum4d.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_590_pbyuWr4.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_582_6u9iQt1.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_593_rOYWenQ.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_585_4z2K1tj.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_589_F5fn0Wp.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_581_jmCHi0D.dcm",
|
||||
],
|
||||
},
|
||||
{
|
||||
i: [
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_631_NxRBhMn.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_619_2cVhUyC.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_607_VvL52Af.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_627_RVhaiKA.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_615_nQtPQHJ.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_603_bAAqdKn.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_623_wy2tc7i.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_611_zZY7rSC.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_599_PUL3TkF.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_630_wIQBYJQ.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_618_oi80wJN.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_606_47SpfNJ.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_626_UNSOCYt.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_614_vcVgojF.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_602_VoRYz3y.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_622_Rj39VCd.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_610_AhQNlyr.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_598_pnjpR3G.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_629_hKAK6Ph.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_617_smztH5n.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_605_EfNQSic.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_625_asIOR8i.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_613_Qaa63p7.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_601_E8lUIGL.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_621_X45Edxw.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_609_P3mWXkz.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_597_alsdinT.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_628_51IriRz.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_616_sc6CY4V.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_604_HG8um6d.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_624_qr7EmUd.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_612_NUr6yLq.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_600_ngZGDnx.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_620_FfONZ99.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_608_j131qxy.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_596_stFfHXn.dcm",
|
||||
],
|
||||
},
|
||||
],
|
||||
stackIdx: [0, 2, 1],
|
||||
stackPos: [0, 0, 2],
|
||||
props: [
|
||||
{
|
||||
voiRange: { lower: 39.150000000000034, upper: 559.1700000000001 },
|
||||
invert: false,
|
||||
interpolationType: 1,
|
||||
VOILUTFunction: "LINEAR",
|
||||
colormap: { name: "Grayscale", opacity: [] },
|
||||
},
|
||||
{
|
||||
voiRange: { lower: 23.330000000000013, upper: 333.23 },
|
||||
invert: false,
|
||||
interpolationType: 1,
|
||||
VOILUTFunction: "LINEAR",
|
||||
colormap: { name: "Grayscale", opacity: [] },
|
||||
},
|
||||
{
|
||||
voiRange: { lower: 35.47000000000003, upper: 504.35 },
|
||||
invert: false,
|
||||
interpolationType: 1,
|
||||
VOILUTFunction: "LINEAR",
|
||||
colormap: { name: "Grayscale", opacity: [] },
|
||||
},
|
||||
],
|
||||
cam: [
|
||||
{
|
||||
viewUp: [
|
||||
-0.00001587091537658125, -0.015633516013622284,
|
||||
0.9998778104782104,
|
||||
],
|
||||
viewPlaneNormal: [
|
||||
0.9999420159200826, 0.010767119415860999, 0.00018422042758444397,
|
||||
],
|
||||
position: [
|
||||
229.83617495377155, 41.64140067850747, 119.19293043555355,
|
||||
],
|
||||
focalPoint: [
|
||||
-54.36633106082782, 38.581180913933935, 119.14057149238982,
|
||||
],
|
||||
parallelProjection: true,
|
||||
parallelScale: 204.18618383081306,
|
||||
viewAngle: 90,
|
||||
flipHorizontal: false,
|
||||
flipVertical: false,
|
||||
rotation: 0,
|
||||
},
|
||||
{
|
||||
viewUp: [
|
||||
0.0010457660537213087, -0.9813110828399658, 0.1924252212047577,
|
||||
],
|
||||
viewPlaneNormal: [
|
||||
0.04514460865590469, -0.19218279979693106, -0.9803202210357175,
|
||||
],
|
||||
position: [
|
||||
-21.89042091369629, 36.68157196044922, 65.77458190917969,
|
||||
],
|
||||
focalPoint: [
|
||||
-27.218482971191406, 59.3633918762207, 181.4740447998047,
|
||||
],
|
||||
parallelProjection: true,
|
||||
parallelScale: 81.6656748487095,
|
||||
viewAngle: 90,
|
||||
flipHorizontal: false,
|
||||
flipVertical: false,
|
||||
rotation: 0,
|
||||
},
|
||||
{
|
||||
viewUp: [
|
||||
-0.00001587091537658125, -0.015633516013622284,
|
||||
0.9998778104782104,
|
||||
],
|
||||
viewPlaneNormal: [
|
||||
0.9999420159493561, 0.010767116601264741, 0.00018422603640028001,
|
||||
],
|
||||
position: [238.6157989501953, 43.7907600402832, 106.84664916992188],
|
||||
focalPoint: [
|
||||
-45.586692810058594, 40.73054122924805, 106.7942886352539,
|
||||
],
|
||||
parallelProjection: true,
|
||||
parallelScale: 178.65974529053696,
|
||||
viewAngle: 90,
|
||||
flipHorizontal: false,
|
||||
flipVertical: false,
|
||||
rotation: 0,
|
||||
},
|
||||
],
|
||||
orientations: [null, null, null],
|
||||
volumeSliceIndices: [null, null, null],
|
||||
};
|
||||
// Viewer state to import
|
||||
const state = {
|
||||
grid: { rows: 1, cols: 3 },
|
||||
modes: ["stack", "stack", "stack"],
|
||||
stacks: [
|
||||
{
|
||||
i: [
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_573_PN7j4gd.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_580_kBgyDxS.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_572_DYQisSg.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_579_ya291yy.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_571_nThHs31.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_578_1eEKjB2.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_570_qT5wuZX.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_577_v2bo1kn.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_569_oV2dHz8.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_576_kgF1iXK.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_568_iY1z50L.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_575_BipYnZH.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_567_HawAeuC.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_574_FrcCKA7.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_566_AUDtXEf.dcm",
|
||||
],
|
||||
},
|
||||
{
|
||||
i: [
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_588_tGfMjqb.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_592_Js4efiI.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_584_U8WCsNY.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_595_vFPcByt.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_587_jnB3wGF.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_591_1XZY7Le.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_583_C9KGrQ9.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_594_SqzeIRU.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_586_Hupum4d.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_590_pbyuWr4.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_582_6u9iQt1.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_593_rOYWenQ.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_585_4z2K1tj.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_589_F5fn0Wp.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_581_jmCHi0D.dcm",
|
||||
],
|
||||
},
|
||||
{
|
||||
i: [
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_631_NxRBhMn.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_619_2cVhUyC.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_607_VvL52Af.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_627_RVhaiKA.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_615_nQtPQHJ.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_603_bAAqdKn.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_623_wy2tc7i.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_611_zZY7rSC.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_599_PUL3TkF.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_630_wIQBYJQ.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_618_oi80wJN.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_606_47SpfNJ.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_626_UNSOCYt.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_614_vcVgojF.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_602_VoRYz3y.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_622_Rj39VCd.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_610_AhQNlyr.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_598_pnjpR3G.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_629_hKAK6Ph.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_617_smztH5n.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_605_EfNQSic.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_625_asIOR8i.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_613_Qaa63p7.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_601_E8lUIGL.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_621_X45Edxw.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_609_P3mWXkz.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_597_alsdinT.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_628_51IriRz.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_616_sc6CY4V.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_604_HG8um6d.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_624_qr7EmUd.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_612_NUr6yLq.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_600_ngZGDnx.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_620_FfONZ99.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_608_j131qxy.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_596_stFfHXn.dcm",
|
||||
],
|
||||
},
|
||||
{
|
||||
i: [
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_792_og2P5S6.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_793_3tKkg87.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_794_s8FB3dq.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_795_8HeRpXV.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_796_tllvzjH.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_797_AXieNgu.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_798_L8YapjK.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_799_kvuLUsW.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_800_i2eSNzF.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_801_dR3KPL5.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_802_cDgm138.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_803_Bj3PZyX.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_804_CEqcWo2.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_805_5R2LmiA.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_806_RgmKU6b.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_807_BKTkmJv.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_808_OQOf2MC.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_809_lxnU3mr.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_810_8vG5Ett.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_811_poX6D2s.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_812_k46Ws88.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_813_7Ft4JOE.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_814_V5lJKxR.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_815_1hFehRl.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_816_34UqY7Z.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_817_YG28gpL.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_818_wonhIz5.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_819_bv3zaOx.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_820_xEjnfcI.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_821_cH9fPxl.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_822_lWmBHxs.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_823_ybix6Gz.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_824_q430lCK.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_825_28trFVc.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_826_7BF6HBF.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_827_ipmO3HH.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_828_Zuppb9h.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_829_TMuror5.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_830_Mnaj7oR.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_831_2U6zI7M.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_832_V9fvVdM.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_833_AAFaoOW.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_834_vxBJLIn.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_835_ZppFa6u.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_836_adRHoD3.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_837_jjfHCn3.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_838_N21h3ne.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_839_n6FWmeX.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_840_dErur0M.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_841_PcoTakk.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_842_UmTu7Fg.dcm",
|
||||
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/IMG_843_USByQXH.dcm",
|
||||
|
||||
function callWhenReady(fnName, payload) {
|
||||
const maxWait = 5000;
|
||||
const start = Date.now();
|
||||
(function check() {
|
||||
if (window[fnName] && typeof window[fnName] === "function") {
|
||||
try {
|
||||
window[fnName](payload);
|
||||
console.log("imported viewer state via", fnName);
|
||||
} catch (e) {
|
||||
console.error("importViewerState call failed", e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (Date.now() - start > maxWait) {
|
||||
console.warn("Timed out waiting for", fnName);
|
||||
return;
|
||||
}
|
||||
setTimeout(check, 2000);
|
||||
})();
|
||||
}
|
||||
],
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
// Ask the viewer to load the stacks first (via exposed API), then wait 2s and import the viewer state.
|
||||
(function loadStacksThenImport() {
|
||||
if (!state.stacks || !Array.isArray(state.stacks)) {
|
||||
callWhenReady("importViewerState_main_viewer", state);
|
||||
return;
|
||||
}
|
||||
}
|
||||
],
|
||||
stackIdx: [0, 2, 1],
|
||||
stackPos: [0, 0, 2],
|
||||
props: [
|
||||
{
|
||||
voiRange: { lower: 39.150000000000034, upper: 559.1700000000001 },
|
||||
invert: false,
|
||||
interpolationType: 1,
|
||||
VOILUTFunction: "LINEAR",
|
||||
colormap: { name: "Grayscale", opacity: [] },
|
||||
},
|
||||
{
|
||||
voiRange: { lower: 23.330000000000013, upper: 333.23 },
|
||||
invert: false,
|
||||
interpolationType: 1,
|
||||
VOILUTFunction: "LINEAR",
|
||||
colormap: { name: "Grayscale", opacity: [] },
|
||||
},
|
||||
{
|
||||
voiRange: { lower: 35.47000000000003, upper: 504.35 },
|
||||
invert: false,
|
||||
interpolationType: 1,
|
||||
VOILUTFunction: "LINEAR",
|
||||
colormap: { name: "Grayscale", opacity: [] },
|
||||
},
|
||||
],
|
||||
cam: [
|
||||
{
|
||||
viewUp: [
|
||||
-0.00001587091537658125, -0.015633516013622284,
|
||||
0.9998778104782104,
|
||||
],
|
||||
viewPlaneNormal: [
|
||||
0.9999420159200826, 0.010767119415860999, 0.00018422042758444397,
|
||||
],
|
||||
position: [
|
||||
229.83617495377155, 41.64140067850747, 119.19293043555355,
|
||||
],
|
||||
focalPoint: [
|
||||
-54.36633106082782, 38.581180913933935, 119.14057149238982,
|
||||
],
|
||||
parallelProjection: true,
|
||||
parallelScale: 204.18618383081306,
|
||||
viewAngle: 90,
|
||||
flipHorizontal: false,
|
||||
flipVertical: false,
|
||||
rotation: 0,
|
||||
},
|
||||
{
|
||||
viewUp: [
|
||||
0.0010457660537213087, -0.9813110828399658, 0.1924252212047577,
|
||||
],
|
||||
viewPlaneNormal: [
|
||||
0.04514460865590469, -0.19218279979693106, -0.9803202210357175,
|
||||
],
|
||||
position: [
|
||||
-21.89042091369629, 36.68157196044922, 65.77458190917969,
|
||||
],
|
||||
focalPoint: [
|
||||
-27.218482971191406, 59.3633918762207, 181.4740447998047,
|
||||
],
|
||||
parallelProjection: true,
|
||||
parallelScale: 81.6656748487095,
|
||||
viewAngle: 90,
|
||||
flipHorizontal: false,
|
||||
flipVertical: false,
|
||||
rotation: 0,
|
||||
},
|
||||
{
|
||||
viewUp: [
|
||||
-0.00001587091537658125, -0.015633516013622284,
|
||||
0.9998778104782104,
|
||||
],
|
||||
viewPlaneNormal: [
|
||||
0.9999420159493561, 0.010767116601264741, 0.00018422603640028001,
|
||||
],
|
||||
position: [238.6157989501953, 43.7907600402832, 106.84664916992188],
|
||||
focalPoint: [
|
||||
-45.586692810058594, 40.73054122924805, 106.7942886352539,
|
||||
],
|
||||
parallelProjection: true,
|
||||
parallelScale: 178.65974529053696,
|
||||
viewAngle: 90,
|
||||
flipHorizontal: false,
|
||||
flipVertical: false,
|
||||
rotation: 0,
|
||||
},
|
||||
],
|
||||
orientations: [null, null, null],
|
||||
volumeSliceIndices: [null, null, null],
|
||||
};
|
||||
|
||||
function pushStacks() {
|
||||
const fnName = "loadAdditionalStack_main_viewer";
|
||||
if (window[fnName] && typeof window[fnName] === "function") {
|
||||
try {
|
||||
state.stacks.forEach((s) => {
|
||||
if (s && Array.isArray(s.i) && s.i.length) {
|
||||
// call the viewer API to load this stack into available stacks
|
||||
window[fnName](s.i);
|
||||
function callWhenReady(fnName, payload) {
|
||||
const maxWait = 5000;
|
||||
const start = Date.now();
|
||||
(function check() {
|
||||
if (window[fnName] && typeof window[fnName] === "function") {
|
||||
try {
|
||||
window[fnName](payload);
|
||||
console.log("imported viewer state via", fnName);
|
||||
} catch (e) {
|
||||
console.error("importViewerState call failed", e);
|
||||
}
|
||||
});
|
||||
console.log(
|
||||
"Requested viewer to load",
|
||||
state.stacks.length,
|
||||
"stacks",
|
||||
);
|
||||
} catch (e) {
|
||||
console.warn("loadAdditionalStack call failed", e);
|
||||
}
|
||||
// Give the viewer 2 seconds to fetch/cache and mount imageIds, then import state
|
||||
setTimeout(() => {
|
||||
callWhenReady("importViewerState_main_viewer", state);
|
||||
}, 2000);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if (Date.now() - start > maxWait) {
|
||||
console.warn("Timed out waiting for", fnName);
|
||||
return;
|
||||
}
|
||||
setTimeout(check, 2000);
|
||||
})();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const started = pushStacks();
|
||||
if (!started) {
|
||||
// wait for the viewer API then retry
|
||||
const maxWait = 5000;
|
||||
const start = Date.now();
|
||||
(function waitForApi() {
|
||||
if (pushStacks()) return;
|
||||
if (Date.now() - start > maxWait) {
|
||||
console.warn(
|
||||
"Timed out waiting for loadAdditionalStack API; importing state directly",
|
||||
);
|
||||
callWhenReady("importViewerState_main_viewer", state);
|
||||
return;
|
||||
}
|
||||
setTimeout(waitForApi, 2000);
|
||||
})();
|
||||
}
|
||||
})();
|
||||
});
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
// Ask the viewer to load the stacks first (via exposed API), then wait 2s and import the viewer state.
|
||||
(function loadStacksThenImport() {
|
||||
if (!state.stacks || !Array.isArray(state.stacks)) {
|
||||
callWhenReady("importViewerState_main_viewer", state);
|
||||
return;
|
||||
}
|
||||
|
||||
function pushStacks() {
|
||||
const fnName = "loadAdditionalStack_main_viewer";
|
||||
if (window[fnName] && typeof window[fnName] === "function") {
|
||||
try {
|
||||
state.stacks.forEach((s) => {
|
||||
if (s && Array.isArray(s.i) && s.i.length) {
|
||||
// call the viewer API to load this stack into available stacks
|
||||
window[fnName](s.i);
|
||||
}
|
||||
});
|
||||
console.log(
|
||||
"Requested viewer to load",
|
||||
state.stacks.length,
|
||||
"stacks",
|
||||
);
|
||||
} catch (e) {
|
||||
console.warn("loadAdditionalStack call failed", e);
|
||||
}
|
||||
// Give the viewer 2 seconds to fetch/cache and mount imageIds, then import state
|
||||
setTimeout(() => {
|
||||
callWhenReady("importViewerState_main_viewer", state);
|
||||
}, 2000);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const started = pushStacks();
|
||||
if (!started) {
|
||||
// wait for the viewer API then retry
|
||||
const maxWait = 5000;
|
||||
const start = Date.now();
|
||||
(function waitForApi() {
|
||||
if (pushStacks()) return;
|
||||
if (Date.now() - start > maxWait) {
|
||||
console.warn(
|
||||
"Timed out waiting for loadAdditionalStack API; importing state directly",
|
||||
);
|
||||
callWhenReady("importViewerState_main_viewer", state);
|
||||
return;
|
||||
}
|
||||
setTimeout(waitForApi, 2000);
|
||||
})();
|
||||
}
|
||||
})();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+104
-21
@@ -232,7 +232,7 @@ const GROUPING_RULE_DEFINITIONS: GroupingRuleDefinition[] = [
|
||||
id: "contentTime",
|
||||
label: "Content/Acquisition time",
|
||||
description: "Content Time (0008,0033) / Acquisition Time (0008,0032)",
|
||||
defaultEnabled: true,
|
||||
defaultEnabled: false,
|
||||
},
|
||||
{
|
||||
id: "echoTime",
|
||||
@@ -296,6 +296,66 @@ function parseNumericValueList(raw?: string | null): number[] {
|
||||
.filter((value) => Number.isFinite(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract b-value(s) from a dicomParser DataSet. Handles multiple VR encodings:
|
||||
* - (0018,9087) DiffusionBValue — VR FD (double) in Enhanced MR, DS (string) in some classic MR
|
||||
* - (0019,100C) GE private — VR DS
|
||||
* - (0043,1039) GE legacy — VR IS/DS
|
||||
* - (2001,1003) Philips private — VR FL (32-bit float)
|
||||
*/
|
||||
function parseBValuesFromDataSet(dataSet: any): number[] {
|
||||
if (!dataSet || typeof dataSet !== "object") return [];
|
||||
|
||||
const tryNumeric = (tagId: string): number | null => {
|
||||
// DS/IS string form
|
||||
if (typeof dataSet.string === "function") {
|
||||
const raw = dataSet.string(tagId);
|
||||
if (raw != null && raw !== "") {
|
||||
const vals = parseNumericValueList(raw);
|
||||
if (vals.length > 0 && Number.isFinite(vals[0]) && vals[0] >= 0) return vals[0];
|
||||
}
|
||||
}
|
||||
// FD — 64-bit double (standard DiffusionBValue in Enhanced MR)
|
||||
if (typeof dataSet.double === "function") {
|
||||
try {
|
||||
const v = dataSet.double(tagId);
|
||||
if (Number.isFinite(v) && v >= 0) return v;
|
||||
} catch (_) {}
|
||||
}
|
||||
// FL — 32-bit float (Philips private (2001,1003))
|
||||
if (typeof dataSet.float === "function") {
|
||||
try {
|
||||
const v = dataSet.float(tagId);
|
||||
if (Number.isFinite(v) && v >= 0) return v;
|
||||
} catch (_) {}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// Standard (0018,9087) DiffusionBValue
|
||||
const v1 = tryNumeric("x00189087");
|
||||
if (v1 !== null) return [v1];
|
||||
|
||||
// GE private (0019,100C)
|
||||
const v2 = tryNumeric("x0019100c");
|
||||
if (v2 !== null) return [v2];
|
||||
|
||||
// GE legacy (0043,1039) — IS format, first value is b-value
|
||||
if (typeof dataSet.string === "function") {
|
||||
const raw = dataSet.string("x00431039");
|
||||
if (raw) {
|
||||
const parts = parseNumericValueList(raw);
|
||||
if (parts.length > 0 && Number.isFinite(parts[0]) && parts[0] >= 0) return [parts[0]];
|
||||
}
|
||||
}
|
||||
|
||||
// Philips private (2001,1003) — VR FL
|
||||
const v3 = tryNumeric("x20011003");
|
||||
if (v3 !== null) return [v3];
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
function normalizeToWadouriOrExternal(imageId: string): string {
|
||||
if (imageId.startsWith("wadouri:") || imageId.startsWith("external:")) {
|
||||
return imageId;
|
||||
@@ -1439,19 +1499,6 @@ export default function App({ container_id, imageStacks, autoCacheStack, annotat
|
||||
const cached = bValuesByBaseImageRef.current[baseUrl];
|
||||
if (cached) return cached;
|
||||
|
||||
const parseBValuesFromDataSet = (dataSet: any): number[] => {
|
||||
if (!dataSet || typeof dataSet.string !== "function") return [];
|
||||
const standard = parseNumericValueList(dataSet.string("x00189087")); // DiffusionBValue
|
||||
if (standard.length > 0) return standard;
|
||||
const gePrivate = parseNumericValueList(dataSet.string("x0019100c"));
|
||||
if (gePrivate.length > 0) return gePrivate;
|
||||
const geLegacyPrivate = parseNumericValueList(dataSet.string("x00431039"));
|
||||
if (geLegacyPrivate.length > 0) return geLegacyPrivate;
|
||||
const privatePhilips = parseNumericValueList(dataSet.string("x20011003"));
|
||||
if (privatePhilips.length > 0) return privatePhilips;
|
||||
return [];
|
||||
};
|
||||
|
||||
try {
|
||||
const cacheManager = cornerstoneDICOMImageLoader?.wadouri?.dataSetCacheManager;
|
||||
if (cacheManager?.get) {
|
||||
@@ -1466,13 +1513,42 @@ export default function App({ container_id, imageStacks, autoCacheStack, annotat
|
||||
// Continue with fetch fallback.
|
||||
}
|
||||
|
||||
// Helper: parse bytes tolerating truncation (header-only range requests)
|
||||
const tryParseBytes = (bytes: Uint8Array): number[] => {
|
||||
try {
|
||||
return parseBValuesFromDataSet(dicomParser.parseDicom(bytes));
|
||||
} catch (e: any) {
|
||||
// dicomParser throws on truncation but attaches partial dataSet
|
||||
if (e?.dataSet) {
|
||||
const partial = parseBValuesFromDataSet(e.dataSet);
|
||||
if (partial.length > 0) return partial;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
// Range request — first 64 KB is enough to find b-value tags in the header
|
||||
try {
|
||||
const rangeResponse = await fetch(baseUrl, { headers: { Range: "bytes=0-65535" } });
|
||||
if (rangeResponse.ok || rangeResponse.status === 206) {
|
||||
const buf = await rangeResponse.arrayBuffer();
|
||||
const result = tryParseBytes(new Uint8Array(buf));
|
||||
if (result.length > 0 || rangeResponse.status === 200) {
|
||||
bValuesByBaseImageRef.current[baseUrl] = result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Fall through to full fetch.
|
||||
}
|
||||
|
||||
// Full fetch fallback (only if range request failed or server doesn't support Range)
|
||||
try {
|
||||
const response = await fetch(baseUrl);
|
||||
const arrayBuffer = await response.arrayBuffer();
|
||||
const dataSet = dicomParser.parseDicom(new Uint8Array(arrayBuffer));
|
||||
const fromFetch = parseBValuesFromDataSet(dataSet);
|
||||
bValuesByBaseImageRef.current[baseUrl] = fromFetch;
|
||||
return fromFetch;
|
||||
const buf = await response.arrayBuffer();
|
||||
const result = tryParseBytes(new Uint8Array(buf));
|
||||
bValuesByBaseImageRef.current[baseUrl] = result;
|
||||
return result;
|
||||
} catch (e) {
|
||||
bValuesByBaseImageRef.current[baseUrl] = [];
|
||||
return [];
|
||||
@@ -1656,8 +1732,15 @@ export default function App({ container_id, imageStacks, autoCacheStack, annotat
|
||||
.map((candidate) => candidate.ruleValues[ruleId])
|
||||
.filter((value): value is string => !!value);
|
||||
const distinct = new Set(values);
|
||||
// Ignore rules that are constant (or effectively unique per image) to avoid over-fragmentation.
|
||||
return distinct.size > 1 && distinct.size < Math.max(2, candidates.length);
|
||||
// Only activate when:
|
||||
// 1. Multiple distinct values (not constant across the series)
|
||||
// 2. Not effectively unique per-image (would produce a group of 1 per image)
|
||||
// 3. At least 70% of images have a value for this rule — avoids fragmenting when
|
||||
// only a handful of images returned metadata (e.g., b-value fetch failed for most)
|
||||
const coverage = values.length / candidates.length;
|
||||
return distinct.size > 1
|
||||
&& distinct.size < Math.max(2, candidates.length)
|
||||
&& coverage >= 0.7;
|
||||
})
|
||||
: [];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user