Compare commits
116
Commits
e618f0d917
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f323dfd559 | ||
|
|
0c4da6e022 | ||
|
|
d0f3431ef4 | ||
|
|
b961a806d9 | ||
|
|
1ddc9a810a | ||
|
|
b2bd2791a5 | ||
|
|
b527eb1139 | ||
|
|
6a0552c843 | ||
|
|
a5c530a907 | ||
|
|
41f13ade5e | ||
|
|
b0d8c72636 | ||
|
|
4dd63668b0 | ||
|
|
77bbbd548e | ||
|
|
7c17a27ec3 | ||
|
|
68248737ec | ||
|
|
13361a30a5 | ||
|
|
627cd740f1 | ||
|
|
af6e22fd91 | ||
|
|
7b786fcf9f | ||
|
|
c9902a2e15 | ||
|
|
99df1cd1c1 | ||
|
|
f169238057 | ||
|
|
f0e0fe0ef6 | ||
|
|
19702b6052 | ||
|
|
1674254a3c | ||
|
|
aeb04bcf2f | ||
|
|
e29bce42e2 | ||
|
|
d34772a3fa | ||
|
|
add45567d8 | ||
|
|
3294151a92 | ||
|
|
776b5faffe | ||
|
|
c5a58da6a3 | ||
|
|
be16e3554f | ||
|
|
6cd9e33e65 | ||
|
|
e161377245 | ||
|
|
1efd81bb0b | ||
|
|
c0c5cd6195 | ||
|
|
0c4db1904c | ||
|
|
52f4be1a96 | ||
|
|
8faa7e9be4 | ||
|
|
adff7caffd | ||
|
|
8dc4bb0aaa | ||
|
|
ef62ffac9f | ||
|
|
72462b49ef | ||
|
|
181f471806 | ||
|
|
8a0a08000e | ||
|
|
6ee9489a5f | ||
|
|
6e70a32ffe | ||
|
|
5b3e47edea | ||
|
|
8d67078a90 | ||
|
|
9c3c3573bc | ||
|
|
f695fcccd0 | ||
|
|
2f14631ad0 | ||
|
|
0ba752c28e | ||
|
|
82d4c94255 | ||
|
|
f4497ef59d | ||
|
|
e685b8b11d | ||
|
|
67329d0468 | ||
|
|
6ab976a82b | ||
|
|
4bff9b39f3 | ||
|
|
e6a6128aca | ||
|
|
654abaaaf4 | ||
|
|
1a8fb26a29 | ||
|
|
b66352f9b9 | ||
|
|
2c9b0345c4 | ||
|
|
9080370bd1 | ||
|
|
044057675e | ||
|
|
8de4efc3e2 | ||
|
|
c3ea2b4478 | ||
|
|
e2f1afe225 | ||
|
|
efc91f8b19 | ||
|
|
de9cf60adc | ||
|
|
c6f8b271a9 | ||
|
|
b917ca72c9 | ||
|
|
e6f64a6a97 | ||
|
|
3a92f5afba | ||
|
|
86a7bd143f | ||
|
|
865bc956c7 | ||
|
|
c063a3a6f3 | ||
|
|
d5046659fd | ||
|
|
28884670e4 | ||
|
|
98c71e73e2 | ||
|
|
c27a52243f | ||
|
|
ce13f9cad2 | ||
|
|
11d1dc4339 | ||
|
|
21dca7d4b5 | ||
|
|
f596dc83c9 | ||
|
|
a9e3c215ed | ||
|
|
28569a1c94 | ||
|
|
7d8caebf8c | ||
|
|
adbbf48a28 | ||
|
|
b1db098a49 | ||
|
|
cdbe31df6b | ||
|
|
c21fe2cbd7 | ||
|
|
8c218d42f4 | ||
|
|
2518da4413 | ||
|
|
43c3f75889 | ||
|
|
3f6c68523e | ||
|
|
38620d969b | ||
|
|
b408ba96b3 | ||
|
|
1fd3020f0c | ||
|
|
313c7a9e9a | ||
|
|
40be13b51a | ||
|
|
4875b95ab2 | ||
|
|
c7728bf1a2 | ||
|
|
c90c280255 | ||
|
|
be0d71d19d | ||
|
|
92e07717da | ||
|
|
52776fa71b | ||
|
|
a245c55216 | ||
|
|
ffb478af59 | ||
|
|
81edcea5ea | ||
|
|
a803e351c3 | ||
|
|
8d673fe28d | ||
|
|
1eba20c27a | ||
|
|
e7d584cd87 |
+193
-1
@@ -5,9 +5,201 @@
|
|||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Vite + React + TS</title>
|
<title>Vite + React + TS</title>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
height: auto;
|
||||||
|
min-height: 100%;
|
||||||
|
overflow: unset!important;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
/* Make viewer roots flow normally on the page */
|
||||||
|
.dicom-viewer-root {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<!-- <div id="root" class="dicom-viewer-test-root" style="max-height:500px; height:500px; overflow:auto;"></div> -->
|
||||||
|
<div id="root" class="dicom-viewer-root" style="max-height:500px; height:500px; overflow:auto;"
|
||||||
|
data-images="["http://localhost:8000/media/atlas/dicom/0fb1283bab62d691bdaf7c7e47b8c674b600cddb.dcm", "http://localhost:8000/media/atlas/dicom/c98950f460ed153c14bd1d0d32e712397ace4564.dcm", "http://localhost:8000/media/atlas/dicom/512bfc7f9d07d54ae8f92af1ab98be390174d618.dcm", "http://localhost:8000/media/atlas/dicom/5f0a6b97da797b7639361732599bfcf607c17dfc.dcm", "http://localhost:8000/media/atlas/dicom/c5f854a8c2ac36da60c8a5a2bc215639d5302d20.dcm", "http://localhost:8000/media/atlas/dicom/0cec8d98bd80818c38c657b9c5934b30316920a2.dcm", "http://localhost:8000/media/atlas/dicom/613166d33e9e35898238f0bd334969c500822bbf.dcm", "http://localhost:8000/media/atlas/dicom/48801a3aa1fea5d943cc934b74e9bc7273c1e944.dcm", "http://localhost:8000/media/atlas/dicom/db8ddb477387a41b023efae98e7e40be890886ef.dcm", "http://localhost:8000/media/atlas/dicom/8720dc9b0b3b2c596f1d87acc951818307b7ad6a.dcm", "http://localhost:8000/media/atlas/dicom/24d1e5397fa97dd0c904568a20e4649fea13d1cf.dcm", "http://localhost:8000/media/atlas/dicom/bb586d17474988a07b1c90afce456abd7f69a753.dcm", "http://localhost:8000/media/atlas/dicom/24fa49c0e482bb885c92b71f74451f558940cb4b.dcm", "http://localhost:8000/media/atlas/dicom/6d9b09614f74b21a0b2778a5129d22b3cbafd3da.dcm", "http://localhost:8000/media/atlas/dicom/39963ce191beafe943a9cf980f7320adad74c1d5.dcm", "http://localhost:8000/media/atlas/dicom/09adc694456f1e51a5ab9c1cf7eaf9d748c938db.dcm", "http://localhost:8000/media/atlas/dicom/d4f6521a9e9a26975e1218ba3b7f48a78ac46d8f.dcm", "http://localhost:8000/media/atlas/dicom/0e1490ed17cdf2ceb1bcf069400f8f47a4437561.dcm", "http://localhost:8000/media/atlas/dicom/2cb43b50760d9335df9a5f2d6bd645daf2a0c917.dcm", "http://localhost:8000/media/atlas/dicom/9b02fae29bf6e775c5ba94b0b7158e10d4697ff6.dcm", "http://localhost:8000/media/atlas/dicom/9628d1d2fb457bc6f03efa8c980ef3165092230f.dcm", "http://localhost:8000/media/atlas/dicom/b879d6488a79d38ba374366f5543aab49fa8cb86.dcm"]"
|
||||||
|
|
||||||
|
data-auto-cache-stack="true"
|
||||||
|
data-viewerstate='{"grid":{"rows":1,"cols":3},"modes":["stack","volume","volume"],"stacks":[{"i":["wadouri:http://localhost:8000/media/atlas/dicom/b879d6488a79d38ba374366f5543aab49fa8cb86.dcm","wadouri:http://localhost:8000/media/atlas/dicom/9628d1d2fb457bc6f03efa8c980ef3165092230f.dcm","wadouri:http://localhost:8000/media/atlas/dicom/9b02fae29bf6e775c5ba94b0b7158e10d4697ff6.dcm","wadouri:http://localhost:8000/media/atlas/dicom/2cb43b50760d9335df9a5f2d6bd645daf2a0c917.dcm","wadouri:http://localhost:8000/media/atlas/dicom/0e1490ed17cdf2ceb1bcf069400f8f47a4437561.dcm","wadouri:http://localhost:8000/media/atlas/dicom/d4f6521a9e9a26975e1218ba3b7f48a78ac46d8f.dcm","wadouri:http://localhost:8000/media/atlas/dicom/09adc694456f1e51a5ab9c1cf7eaf9d748c938db.dcm","wadouri:http://localhost:8000/media/atlas/dicom/39963ce191beafe943a9cf980f7320adad74c1d5.dcm","wadouri:http://localhost:8000/media/atlas/dicom/6d9b09614f74b21a0b2778a5129d22b3cbafd3da.dcm","wadouri:http://localhost:8000/media/atlas/dicom/24fa49c0e482bb885c92b71f74451f558940cb4b.dcm","wadouri:http://localhost:8000/media/atlas/dicom/bb586d17474988a07b1c90afce456abd7f69a753.dcm","wadouri:http://localhost:8000/media/atlas/dicom/24d1e5397fa97dd0c904568a20e4649fea13d1cf.dcm","wadouri:http://localhost:8000/media/atlas/dicom/8720dc9b0b3b2c596f1d87acc951818307b7ad6a.dcm","wadouri:http://localhost:8000/media/atlas/dicom/db8ddb477387a41b023efae98e7e40be890886ef.dcm","wadouri:http://localhost:8000/media/atlas/dicom/48801a3aa1fea5d943cc934b74e9bc7273c1e944.dcm","wadouri:http://localhost:8000/media/atlas/dicom/613166d33e9e35898238f0bd334969c500822bbf.dcm","wadouri:http://localhost:8000/media/atlas/dicom/0cec8d98bd80818c38c657b9c5934b30316920a2.dcm","wadouri:http://localhost:8000/media/atlas/dicom/c5f854a8c2ac36da60c8a5a2bc215639d5302d20.dcm","wadouri:http://localhost:8000/media/atlas/dicom/5f0a6b97da797b7639361732599bfcf607c17dfc.dcm","wadouri:http://localhost:8000/media/atlas/dicom/512bfc7f9d07d54ae8f92af1ab98be390174d618.dcm","wadouri:http://localhost:8000/media/atlas/dicom/c98950f460ed153c14bd1d0d32e712397ace4564.dcm","wadouri:http://localhost:8000/media/atlas/dicom/0fb1283bab62d691bdaf7c7e47b8c674b600cddb.dcm"],"u":"2.1163931708166249655895918785713305273005"}],"stackIdx":[0,0,0],"stackPos":[0,173,10],"props":[{"voiRange":{"lower":-958.5,"upper":705.5},"invert":false,"interpolationType":1,"VOILUTFunction":"LINEAR"},{"voiRange":{"lower":-1798,"upper":1641},"invert":false,"colormap":{"name":"Grayscale","opacity":1,"threshold":null}},{"voiRange":{"lower":302,"upper":2069},"invert":false,"colormap":{"name":"Grayscale","opacity":1,"threshold":null}}],"cam":[{"viewUp":[-0.015545368194580078,-0.12045262008905411,0.9925973415374756],"viewPlaneNormal":[0.9998766662057034,-0.00409140293321022,0.015162875697125405],"position":[276.090926593084,-63.25300826357402,25.12347315106698],"focalPoint":[59.93107667300279,-62.36850213007119,21.845463926704127],"parallelProjection":true,"parallelScale":170.33890849893743,"viewAngle":90,"flipHorizontal":false,"flipVertical":false,"rotation":0},{"viewUp":[0,0,1],"viewPlaneNormal":[0,-1,0],"position":[-6.060784295600456,-273.9517816053456,20.844714115543866],"focalPoint":[-6.060784295600456,-46.51629576550185,20.844714115543866],"parallelProjection":true,"parallelScale":150.85189284207627,"viewAngle":90,"flipHorizontal":false,"flipVertical":false,"rotation":0},{"viewUp":[0,0,1],"viewPlaneNormal":[1,0,0],"position":[218.5103649207617,-62.09846953239139,20.844714115543866],"focalPoint":[-8.925120919082055,-62.09846953239139,20.844714115543866],"parallelProjection":true,"parallelScale":157.88941096127814,"viewAngle":90,"flipHorizontal":false,"flipVertical":false,"rotation":0}],"orientations":[null,"coronal","sagittal"],"volumeSliceIndices":[null,173,10]}'
|
||||||
|
|
||||||
|
></div>
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<div
|
||||||
|
class="dicom-viewer-root"
|
||||||
|
id="viewer_named_simple"
|
||||||
|
data-named-stacks='[
|
||||||
|
{
|
||||||
|
"name": "CT Head (Study A)",
|
||||||
|
"imageIds": [
|
||||||
|
"http://localhost:8000/media/atlas/dicom/head_0001.dcm",
|
||||||
|
"http://localhost:8000/media/atlas/dicom/head_0002.dcm",
|
||||||
|
"http://localhost:8000/media/atlas/dicom/head_0003.dcm"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "CT Chest (Study B)",
|
||||||
|
"imageIds": [
|
||||||
|
"wadouri:http://localhost:8000/media/atlas/dicom/chest_0001.dcm",
|
||||||
|
"wadouri:http://localhost:8000/media/atlas/dicom/chest_0002.dcm"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]'
|
||||||
|
style="width:600px;height:400px;"
|
||||||
|
></div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="dicom-viewer-root"
|
||||||
|
id="viewer_named_cases"
|
||||||
|
data-named-stacks='[
|
||||||
|
{
|
||||||
|
"caseId": "CASE-001",
|
||||||
|
"studyId": "STUDY-001",
|
||||||
|
"stacks": [
|
||||||
|
{
|
||||||
|
"name": "Abdomen - Portal Venous",
|
||||||
|
"imageIds": [
|
||||||
|
"http://localhost:8000/media/atlas/dicom/abdomen_pv_0001.dcm",
|
||||||
|
"http://localhost:8000/media/atlas/dicom/abdomen_pv_0002.dcm"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Abdomen - Non-contrast",
|
||||||
|
"imageIds": [
|
||||||
|
"http://localhost:8000/media/atlas/dicom/abdomen_nc_0001.dcm"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"caseId": "CASE-002",
|
||||||
|
"studyId": "STUDY-002",
|
||||||
|
"stacks": [
|
||||||
|
{
|
||||||
|
"name": "Chest - CTA",
|
||||||
|
"imageIds": [
|
||||||
|
"http://localhost:8000/media/atlas/dicom/cta_0001.dcm",
|
||||||
|
"http://localhost:8000/media/atlas/dicom/cta_0002.dcm"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]'
|
||||||
|
style="width:600px;height:400px;margin-top:12px;"
|
||||||
|
></div> -->
|
||||||
|
<!-- <div id="root2" class="dicom-viewer-root" style="max-height:500px; height:500px; overflow:auto;"
|
||||||
|
data-images="["http://localhost:8000/media/atlas/dicom/4596ea7654b7a5074d2c3f40039c556b11fb01ae.dcm", "http://localhost:8000/media/atlas/dicom/b2fa301bc731d15be3e000402c9a79c114d17aa5.dcm", "http://localhost:8000/media/atlas/dicom/66310ef801fbecb37c5ced160c450dfd5ecc6d2d.dcm", "http://localhost:8000/media/atlas/dicom/63d2d117bf256a76a61190066f91eda6c4d67c8f.dcm", "http://localhost:8000/media/atlas/dicom/181a3575ea7fb8bf8f6449ff61e6e369a3247454.dcm", "http://localhost:8000/media/atlas/dicom/7c5c0538339266ac8897fa21c481b2f61172068e.dcm", "http://localhost:8000/media/atlas/dicom/1681410681308af7111af6644fed598fde304b96.dcm", "http://localhost:8000/media/atlas/dicom/4adcd3d7a64a9c59b530f730ce0d991bf7f27813.dcm", "http://localhost:8000/media/atlas/dicom/671e6004c7fb402a627a2282bbf304d7b4dcc12b.dcm", "http://localhost:8000/media/atlas/dicom/8d18ac56914b9de72b8aecced09654ec4b2c9bb7.dcm", "http://localhost:8000/media/atlas/dicom/74ce708a90dff0636fc4bc914fe47e8b6d9320bd.dcm", "http://localhost:8000/media/atlas/dicom/a96b6c9900570e076edf849a0ae3b52734ed2650.dcm", "http://localhost:8000/media/atlas/dicom/0183718d9336458478ec42130395d78e01492bd6.dcm", "http://localhost:8000/media/atlas/dicom/52eee968bbce5590274346eed43f1837f9daba11.dcm", "http://localhost:8000/media/atlas/dicom/961449f88197566c4643fcfd20f48ea4e810490b.dcm", "http://localhost:8000/media/atlas/dicom/1a16ad5b25e11739eadbcb8ea461072b100113a0.dcm", "http://localhost:8000/media/atlas/dicom/b89ddcc3f499059d2dedb0028a2bb1ce4abf5574.dcm", "http://localhost:8000/media/atlas/dicom/c1379c03a4e449c2fa88784d601cb766af907739.dcm", "http://localhost:8000/media/atlas/dicom/4fb532d5003c59a73f7e4248f365b1a8660ea710.dcm", "http://localhost:8000/media/atlas/dicom/e861b0de042a1f213cbccc995679aacd29c7ef53.dcm", "http://localhost:8000/media/atlas/dicom/1a854282afe264c3afff6a6e287cd646b2193a0c.dcm", "http://localhost:8000/media/atlas/dicom/f59d6d9bc33160abad3af8e2b246179b3574d884.dcm", "http://localhost:8000/media/atlas/dicom/04fadab0ed8b3f1925e601c4f9cfb792c95626c2.dcm", "http://localhost:8000/media/atlas/dicom/d45d0b12fb650e65daeeee4e5fa3b21c988597f6.dcm", "http://localhost:8000/media/atlas/dicom/e19c47b7787ac45dbc225319dfa143dc2c1fdf1f.dcm", "http://localhost:8000/media/atlas/dicom/dccabf3103a5be254a45457ce2d8d9ce9cb19a6a.dcm"]"
|
||||||
|
data-auto-cache-stack="true"
|
||||||
|
></div> -->
|
||||||
<script type="module" src="/src/main.tsx"></script>
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
|
||||||
|
<input type="file" id="dicomInput" multiple />
|
||||||
|
<button onclick="sendToViewer()">Send to Viewer</button>
|
||||||
|
<button onclick="testLoadWadouriStack()">Test Load wadouri Stack</button>
|
||||||
|
<button onclick="testLoadWadouriStack2()">Test Load wadouri Stack 2</button>
|
||||||
|
<script>
|
||||||
|
function sendToViewer() {
|
||||||
|
const files = document.getElementById('dicomInput').files;
|
||||||
|
if (window.loadDicomStackFromFiles) {
|
||||||
|
window.loadDicomStackFromFiles(files);
|
||||||
|
} else {
|
||||||
|
alert("Viewer API not ready");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function testLoadWadouriStack() {
|
||||||
|
const urls = [
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_757_XQQyovo.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_766_8fWI0Qc.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_774_c8IpxUu.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_758_6WKI7ws.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_767_TduVOb8.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_775_7zWneQ0.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_759_BtKzgS5.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_768_RdvtM8K.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_776_LhVY3Ty.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_760_a8CiR4J.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_769_YHyJ1l6.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_777_8IFYJmL.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_761_vyvO1EN.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_770_vQwi4LW.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_778_BwGAMOR.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_762_DhSgQsm.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_771_xifitCl.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_779_LyA1zYn.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_763_aVjff3H.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_772_cDQZtxQ.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_780_qaZqsqg.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_764_dDoeldL.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_773_93Hvedg.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_781_bEx9Owg.dcm",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/dicom/IMG_765_qmd5mYJ.dcm"
|
||||||
|
];
|
||||||
|
const wadouriList = urls.map(url => "wadouri:" + url);
|
||||||
|
if (window.loadDicomStackFromWadouriList) {
|
||||||
|
window.loadDicomStackFromWadouriList(wadouriList);
|
||||||
|
} else {
|
||||||
|
alert("Viewer API not ready");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function testLoadWadouriStack2() {
|
||||||
|
const urls = [
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/37b89ead539fdbbc719845333ed89498fc1e2feb",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/6eefab8694dbdcb38e8732319f38eabd14068d0d",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/27faaddb0167f359bae951020cabd15b9158c15f",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/8097cd95acca6c1a97f050ec5c96c1661290058d",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/5dd6147fa3362ab52b87903aa670c1ee6e489b78",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/c8a794e75a3a28177c71792044518a4a294dc6c6",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/6102f3d482e8242cd4ca9e3477c3e8ede5cd6b49",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/2f3407a8fafd283a219cec01c45190907b5214f6",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/ae61b2c4a09c810a7711aa473b4c5553816a2c47",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/c1ac31aebba99645c11e11ac4e96bef8a544ffe1",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/c357353b07d4366802b68a9c7ba90104b64f0b06",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/ac80a92442a68ca58a0b5c793c9ff39678cf1267",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/2856b3a5503540f2d5257d1b1793a3a2ee31024f",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/f097bd9d1d9ae33fd20ee57bd4de8187cf338913",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/76a764bdc860182374a0701f1c338bdf7d8e05a0",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/1c09f607ca2485b2681197e6e8555393879e5a04",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/616498815182e1d093c0011b90c3fb309caadb8f",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/9d04d2370d3f8e3b0220ff0f460ba12625ef3857",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/fb94a8645a0159b0e9725c0718dd723f86008008",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/43cb8280cb9dd96ddfde8028cfb20e60dfe5d756",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/65a8cbbc9b837e66e1f07ed6ecbc1dd22ea28b65",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/147a29e905fcc3c0bd2d38848beb80328c007436",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/2b8fde7b6736bd5eba3f64bd26b291634ff9a719",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/9904072307db5935bc07c1eda762aebb972950e8",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/3b4b4f1ab6c5b944c267209bb298281e0f669a2d",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/6530f91afa0021dd5ca6f4f067112ef647c42314",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/2a071c131e484213b7198c6320e8a63a176b34b0",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/efb13b2d01651b542880ef8d1d09487bc128a459",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/272800e852655f6c9ec107bd31c620e8f774afea",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/3434977ed6d75f858b02e86c9e616cd774c5c9bf",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/1b1fa4cfd2a177db0f449e4a37634250e69ec7e1",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/72ea7d1b931f246e340665cbe067c3cb4a22176d",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/f8c1d6dd25617f0c710e2f01b05d1cba3d72367f",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/333b535df6f5e501a5a8a70c2156fcb3f94c23f8",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/2ccb2a892d1d2d7022ddf7e59ccb3a184fb2676a",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/a9bef320ed90508f5466010a6af8eee86b6324c2",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/ba714cdffe76cfa95f8f7d9dee940d1ed8b8be77",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/1f2a1b7a371f72a2696c003f551caa92ebee2cc7",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/387d0fb40b96d5c532d66329f964811ca54d9c46",
|
||||||
|
"https://www.penracourses.org.uk/media/atlas/picture/71e0c4b40bd12bb7fa5d8aa30e60c58dd936ccc0"
|
||||||
|
];
|
||||||
|
const wadouriList = urls.map(url => "wadouri:" + url);
|
||||||
|
if (window.loadDicomStackFromWadouriList) {
|
||||||
|
window.loadDicomStackFromWadouriList(wadouriList);
|
||||||
|
} else {
|
||||||
|
alert("Viewer API not ready");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Generated
+3259
-1584
File diff suppressed because it is too large
Load Diff
@@ -5,16 +5,19 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "tsc && vite build",
|
"build": "tsc && vite build && cp dist/index.js /home/ross/penracourses/rad/rad/static/dv3d/index.js",
|
||||||
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cornerstonejs/calculate-suv": "1.1.0",
|
"@cornerstonejs/calculate-suv": "^1.1.0",
|
||||||
"@cornerstonejs/core": "^2.1.16",
|
"@cornerstonejs/core": "^3.19.5",
|
||||||
"@cornerstonejs/dicom-image-loader": "^2.1.16",
|
"@cornerstonejs/dicom-image-loader": "^3.19.5",
|
||||||
"@cornerstonejs/nifti-volume-loader": "^2.1.16",
|
"@cornerstonejs/nifti-volume-loader": "^3.19.5",
|
||||||
"@cornerstonejs/tools": "^2.1.16",
|
"@cornerstonejs/tools": "^3.19.5",
|
||||||
|
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||||
|
"@cornerstonejs/codec-charls": "^1.2.3",
|
||||||
|
"@cornerstonejs/codec-openjpeg": "^1.2.4",
|
||||||
"dcmjs": "0.33.0",
|
"dcmjs": "0.33.0",
|
||||||
"dicom-parser": "1.8.21",
|
"dicom-parser": "1.8.21",
|
||||||
"dicomweb-client": "0.10.4",
|
"dicomweb-client": "0.10.4",
|
||||||
@@ -43,9 +46,8 @@
|
|||||||
"rollup-plugin-dts": "^6.1.1",
|
"rollup-plugin-dts": "^6.1.1",
|
||||||
"rollup-plugin-peer-deps-external": "^2.2.4",
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
||||||
"rollup-plugin-postcss": "^4.0.2",
|
"rollup-plugin-postcss": "^4.0.2",
|
||||||
"rollup-plugin-terser": "^7.0.2",
|
|
||||||
"typescript": "^5.6.3",
|
"typescript": "^5.6.3",
|
||||||
"vite": "^5.2.0",
|
"vite": "^5.2.0",
|
||||||
"vite-plugin-static-copy": "^1.0.5"
|
"vite-plugin-static-copy": "^1.0.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Embedded Viewer — Test Page</title>
|
||||||
|
<style>
|
||||||
|
html,body{height:100%;margin:0;font-family:system-ui,Segoe UI,Roboto,Helvetica,Arial}
|
||||||
|
header{background:#111;color:#fff;padding:12px 20px}
|
||||||
|
header h1{margin:0;font-size:18px}
|
||||||
|
.page{display:flex;gap:20px;padding:20px}
|
||||||
|
.main{flex:1}
|
||||||
|
.sidebar{width:260px;background:#f6f6f6;padding:12px;border-radius:6px}
|
||||||
|
.dicom-viewer-root{width:100%;height:72vh;background:#222;color:#fff;border-radius:6px;overflow:hidden}
|
||||||
|
.controls{margin:12px 0}
|
||||||
|
.note{background:#eef;padding:10px;border-radius:4px}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1>Embedded Viewer Test</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="page">
|
||||||
|
<main class="main">
|
||||||
|
<p class="note">This page demonstrates the DICOM viewer embedded alongside other content.</p>
|
||||||
|
|
||||||
|
<div class="controls">
|
||||||
|
<button onclick="document.getElementById('main_viewer').scrollIntoView({behavior:'smooth'})">Scroll to viewer</button>
|
||||||
|
<button onclick="console.log('Example action')">Example action</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="main_viewer" class="dicom-viewer-root" data-auto-cache-stack="false"></div>
|
||||||
|
|
||||||
|
<section style="margin-top:16px">
|
||||||
|
<h2>Related information</h2>
|
||||||
|
<p>Here you can place text, controls, or other UI components while the viewer stays mounted within the page layout.</p>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<aside class="sidebar">
|
||||||
|
<h3>Sidebar</h3>
|
||||||
|
<p>Extra controls, metadata, or notes can live here.</p>
|
||||||
|
<ul>
|
||||||
|
<li>Patient: Anonymous</li>
|
||||||
|
<li>Study: Demo stack</li>
|
||||||
|
<li>Notes: Test page</li>
|
||||||
|
</ul>
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Provide noop React Refresh preamble to avoid plugin-react runtime errors -->
|
||||||
|
<script>
|
||||||
|
window.$RefreshReg$ = window.$RefreshReg$ || function() {};
|
||||||
|
window.$RefreshSig$ = window.$RefreshSig$ || function() { return function(type) { return type; }; };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Reuse the same viewer state as the penra test for convenience
|
||||||
|
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"]},{"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"]},{"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"]}],"stackIdx":[0,2,1],"stackPos":[0,0,2],"props":[{"voiRange":{"lower":39.15,"upper":559.17},"invert":false,"interpolationType":1,"VOILUTFunction":"LINEAR","colormap":{"name":"Grayscale","opacity":[]}}],"cam":[null,null,null],"orientations":[null,null,null],"volumeSliceIndices":[null,null,null]};
|
||||||
|
|
||||||
|
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', () => {
|
||||||
|
(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) {
|
||||||
|
window[fnName](s.i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log('Requested viewer to load', state.stacks.length, 'stacks');
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('loadAdditionalStack call failed', e);
|
||||||
|
}
|
||||||
|
setTimeout(() => { callWhenReady('importViewerState_main_viewer', state); }, 2000);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const started = pushStacks();
|
||||||
|
if (!started) {
|
||||||
|
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>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Empty Viewer Test</title>
|
||||||
|
<style>
|
||||||
|
html,body{height:100%;margin:0}
|
||||||
|
.dicom-viewer-root{width:100%;height:100vh;background:#222;color:#fff}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root" class="dicom-viewer-root" style="width:100%;height:100vh;"
|
||||||
|
data-auto-cache-stack="false"
|
||||||
|
data-empty="true"
|
||||||
|
></div>
|
||||||
|
|
||||||
|
<!-- Provide a small noop React Refresh preamble to avoid plugin-react preamble errors -->
|
||||||
|
<script>
|
||||||
|
// If plugin-react's preamble wasn't injected for some reason, provide no-op
|
||||||
|
// implementations so the runtime does not throw. This disables fast-refresh
|
||||||
|
// semantics for this page but keeps HMR from crashing.
|
||||||
|
window.$RefreshReg$ = window.$RefreshReg$ || function() {};
|
||||||
|
window.$RefreshSig$ = window.$RefreshSig$ || function() { return function(type) { return type; }; };
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Fluoro Multiframe Test</title>
|
||||||
|
<style>
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.dicom-viewer-root {
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
background: #222;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div
|
||||||
|
id="main_viewer"
|
||||||
|
class="dicom-viewer-root"
|
||||||
|
data-auto-cache-stack="false"
|
||||||
|
></div>
|
||||||
|
|
||||||
|
<!-- Provide noop React Refresh preamble to avoid plugin-react runtime errors -->
|
||||||
|
<script>
|
||||||
|
window.$RefreshReg$ = window.$RefreshReg$ || function () {};
|
||||||
|
window.$RefreshSig$ =
|
||||||
|
window.$RefreshSig$ ||
|
||||||
|
function () {
|
||||||
|
return function (type) {
|
||||||
|
return type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Viewer state for fluoro multiframe images (using relative paths from public/test_images/)
|
||||||
|
const state = {
|
||||||
|
grid: { rows: 1, cols: 2 },
|
||||||
|
modes: ["stack", "stack"],
|
||||||
|
stacks: [
|
||||||
|
{
|
||||||
|
i: [
|
||||||
|
"wadouri:https://www.penracourses.org.uk/media/atlas/dicom/1.3.12.2.1107.5.4.5.180506.30000026031914043350300000126.4.dcm",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
stackIdx: [0, 1],
|
||||||
|
stackPos: [0, 1],
|
||||||
|
props: [
|
||||||
|
{
|
||||||
|
voiRange: { lower: 0, upper: 500 },
|
||||||
|
invert: false,
|
||||||
|
interpolationType: 1,
|
||||||
|
VOILUTFunction: "LINEAR",
|
||||||
|
colormap: { name: "Grayscale", opacity: [] },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
voiRange: { lower: 0, upper: 500 },
|
||||||
|
invert: false,
|
||||||
|
interpolationType: 1,
|
||||||
|
VOILUTFunction: "LINEAR",
|
||||||
|
colormap: { name: "Grayscale", opacity: [] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
cam: [
|
||||||
|
{
|
||||||
|
viewUp: [0, 0, 1],
|
||||||
|
viewPlaneNormal: [1, 0, 0],
|
||||||
|
position: [150, 0, 0],
|
||||||
|
focalPoint: [0, 0, 0],
|
||||||
|
parallelProjection: true,
|
||||||
|
parallelScale: 100,
|
||||||
|
viewAngle: 90,
|
||||||
|
flipHorizontal: false,
|
||||||
|
flipVertical: false,
|
||||||
|
rotation: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
viewUp: [0, 0, 1],
|
||||||
|
viewPlaneNormal: [1, 0, 0],
|
||||||
|
position: [150, 0, 0],
|
||||||
|
focalPoint: [0, 0, 0],
|
||||||
|
parallelProjection: true,
|
||||||
|
parallelScale: 100,
|
||||||
|
viewAngle: 90,
|
||||||
|
flipHorizontal: false,
|
||||||
|
flipVertical: false,
|
||||||
|
rotation: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
orientations: [null, null],
|
||||||
|
volumeSliceIndices: [null, null],
|
||||||
|
};
|
||||||
|
|
||||||
|
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", () => {
|
||||||
|
callWhenReady("importViewerState", state);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,196 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
|
<title>Load Directory Test</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: system-ui, Arial; padding: 18px; background: #f6f6f8; color: #111 }
|
||||||
|
.controls { margin: 12px 0 }
|
||||||
|
.file-row { display:flex; gap:8px; align-items:center; padding:6px 8px; border-bottom:1px solid #eee }
|
||||||
|
.path { font-family: monospace; color:#444; flex:1 }
|
||||||
|
button { padding:6px 10px }
|
||||||
|
#fileList { border:1px solid #ddd; background:#fff; border-radius:6px; max-height:60vh; overflow:auto }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2>Directory Loader (recursive)</h2>
|
||||||
|
<p>Select a folder (uses `webkitdirectory`) — files will be read recursively.
|
||||||
|
This page will call <code>window.loadDicomStackFromFiles(files)</code> if available in the viewer.</p>
|
||||||
|
|
||||||
|
<div class="controls">
|
||||||
|
<input id="dirInput" type="file" webkitdirectory directory multiple />
|
||||||
|
<label style="margin-left:12px"><input id="onlyDcm" type="checkbox" checked /> Show only <code>.dcm</code></label>
|
||||||
|
<button id="loadSelected">Load Selected</button>
|
||||||
|
<button id="loadAll">Load All</button>
|
||||||
|
<button id="openViewerAndSend">Open Viewer & Send</button>
|
||||||
|
<button id="clear">Clear</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="fileList"></div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function(){
|
||||||
|
const input = document.getElementById('dirInput');
|
||||||
|
const fileListDiv = document.getElementById('fileList');
|
||||||
|
const onlyDcmChk = document.getElementById('onlyDcm');
|
||||||
|
|
||||||
|
function asArray(fileList){ return Array.prototype.slice.call(fileList || []); }
|
||||||
|
|
||||||
|
function renderFiles(files){
|
||||||
|
fileListDiv.innerHTML = '';
|
||||||
|
if (!files || files.length === 0) {
|
||||||
|
fileListDiv.innerHTML = '<div style="padding:12px;color:#666">No files selected</div>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const frag = document.createDocumentFragment();
|
||||||
|
files.forEach((f, idx) => {
|
||||||
|
const row = document.createElement('div');
|
||||||
|
row.className = 'file-row';
|
||||||
|
const cb = document.createElement('input');
|
||||||
|
cb.type = 'checkbox';
|
||||||
|
cb.checked = true;
|
||||||
|
cb.dataset.idx = idx;
|
||||||
|
|
||||||
|
const pathEl = document.createElement('div');
|
||||||
|
pathEl.className = 'path';
|
||||||
|
// webkitRelativePath shows the folder structure when directory input used
|
||||||
|
pathEl.textContent = f.webkitRelativePath || f.name;
|
||||||
|
|
||||||
|
const sizeEl = document.createElement('div');
|
||||||
|
sizeEl.style.width = '90px';
|
||||||
|
sizeEl.style.textAlign = 'right';
|
||||||
|
sizeEl.style.color = '#666';
|
||||||
|
sizeEl.textContent = (f.size/1024).toFixed(1)+' kB';
|
||||||
|
|
||||||
|
row.appendChild(cb);
|
||||||
|
row.appendChild(pathEl);
|
||||||
|
row.appendChild(sizeEl);
|
||||||
|
|
||||||
|
frag.appendChild(row);
|
||||||
|
});
|
||||||
|
fileListDiv.appendChild(frag);
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterFiles(files){
|
||||||
|
const onlyDcm = onlyDcmChk.checked;
|
||||||
|
if (!onlyDcm) return files;
|
||||||
|
return files.filter(f => f.name.toLowerCase().endsWith('.dcm'));
|
||||||
|
}
|
||||||
|
|
||||||
|
input.addEventListener('change', ()=>{
|
||||||
|
const all = asArray(input.files);
|
||||||
|
const filtered = filterFiles(all);
|
||||||
|
// Save filtered list on the element for retrieval
|
||||||
|
input._currentFiles = filtered;
|
||||||
|
renderFiles(filtered);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('loadSelected').addEventListener('click', ()=>{
|
||||||
|
const current = input._currentFiles || [];
|
||||||
|
if (!current.length) return alert('No files selected. Choose a folder first.');
|
||||||
|
// collect checked indices
|
||||||
|
const checked = Array.from(fileListDiv.querySelectorAll('input[type=checkbox]'))
|
||||||
|
.filter(cb=>cb.checked)
|
||||||
|
.map(cb=>parseInt(cb.dataset.idx,10))
|
||||||
|
.filter(n=>!Number.isNaN(n));
|
||||||
|
const chosen = checked.map(i=>current[i]).filter(Boolean);
|
||||||
|
if (!chosen.length) return alert('No files checked.');
|
||||||
|
sendToViewer(chosen);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('loadAll').addEventListener('click', ()=>{
|
||||||
|
const current = input._currentFiles || [];
|
||||||
|
if (!current.length) return alert('No files selected. Choose a folder first.');
|
||||||
|
sendToViewer(current);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('openViewerAndSend').addEventListener('click', async ()=>{
|
||||||
|
const current = input._currentFiles || [];
|
||||||
|
if (!current.length) return alert('No files selected. Choose a folder first.');
|
||||||
|
// Open the viewer root in a new tab/window
|
||||||
|
const viewerWin = window.open('/', '_blank');
|
||||||
|
if (!viewerWin) return alert('Failed to open viewer window (popup blocked).');
|
||||||
|
|
||||||
|
// Wait for the viewer window to expose loadDicomStackFromFiles
|
||||||
|
const timeoutMs = 15000;
|
||||||
|
const start = Date.now();
|
||||||
|
const poll = () => new Promise((resolve, reject) => {
|
||||||
|
const iv = setInterval(() => {
|
||||||
|
try {
|
||||||
|
if (viewerWin && (viewerWin.loadDicomStackFromFiles || viewerWin.loadDicomStackFromWadouriList)) {
|
||||||
|
clearInterval(iv);
|
||||||
|
resolve(true);
|
||||||
|
}
|
||||||
|
if (Date.now() - start > timeoutMs) {
|
||||||
|
clearInterval(iv);
|
||||||
|
reject(new Error('Timed out waiting for viewer API'));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// cross-origin or not ready
|
||||||
|
}
|
||||||
|
}, 250);
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await poll();
|
||||||
|
// call the function on the opened viewer window
|
||||||
|
if (viewerWin.loadDicomStackFromFiles) {
|
||||||
|
viewerWin.loadDicomStackFromFiles(current);
|
||||||
|
alert('Sent '+current.length+' file(s) to the newly opened viewer.');
|
||||||
|
} else if (viewerWin.loadDicomStackFromWadouriList) {
|
||||||
|
// fallback for remote URLs
|
||||||
|
const wadouriList = current.map(f => 'wadouri:' + URL.createObjectURL(f));
|
||||||
|
viewerWin.loadDicomStackFromWadouriList(wadouriList);
|
||||||
|
alert('Sent '+current.length+' wadouri image(s) to the newly opened viewer.');
|
||||||
|
} else {
|
||||||
|
alert('Viewer opened but API not available.');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('openViewerAndSend failed', e);
|
||||||
|
alert('Timed out waiting for viewer to be ready. Check the viewer tab.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('clear').addEventListener('click', ()=>{
|
||||||
|
input.value = null;
|
||||||
|
input._currentFiles = [];
|
||||||
|
renderFiles([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
function sendToViewer(files){
|
||||||
|
// Prefer calling the viewer global if present
|
||||||
|
if (window.loadDicomStackFromFiles && typeof window.loadDicomStackFromFiles === 'function') {
|
||||||
|
try {
|
||||||
|
// The viewer accepts FileList or File[] per typing; pass array
|
||||||
|
window.loadDicomStackFromFiles(files);
|
||||||
|
alert('Sent '+files.length+' file(s) to viewer (window.loadDicomStackFromFiles).');
|
||||||
|
return;
|
||||||
|
} catch (e) {
|
||||||
|
console.error('loadDicomStackFromFiles failed', e);
|
||||||
|
alert('Viewer call failed (see console).');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: try posting to parent (if embedded)
|
||||||
|
if (window.parent && window.parent !== window) {
|
||||||
|
try {
|
||||||
|
window.parent.postMessage({ type: 'loadFiles', filesCount: files.length }, '*');
|
||||||
|
alert('Posted message to parent with '+files.length+' files.');
|
||||||
|
return;
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
alert('Viewer integration function `window.loadDicomStackFromFiles` not found on this page.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial empty render
|
||||||
|
renderFiles([]);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>DV3D — Non-DICOM Test</title>
|
||||||
|
<style>
|
||||||
|
html,body { height:100%; margin:0; background:#111 }
|
||||||
|
#non-dicom-root { width: 100vw; height: 100vh; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="non-dicom-root" class="dicom-viewer-root"></div>
|
||||||
|
<!-- Provide a small noop React Refresh preamble to avoid plugin-react preamble errors -->
|
||||||
|
<script>
|
||||||
|
// If plugin-react's preamble wasn't injected for some reason, provide no-op
|
||||||
|
// implementations so the runtime does not throw. This disables fast-refresh
|
||||||
|
// semantics for this page but keeps HMR from crashing.
|
||||||
|
window.$RefreshReg$ = window.$RefreshReg$ || function() {};
|
||||||
|
window.$RefreshSig$ = window.$RefreshSig$ || function() { return function(type) { return type; }; };
|
||||||
|
</script>
|
||||||
|
<!-- Vite can load TSX modules directly in dev mode -->
|
||||||
|
<script type="module" src="/src/nonDicomTest.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,353 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Penra Courses — Viewer Test</title>
|
||||||
|
<style>
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.dicom-viewer-root {
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
background: #222;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div
|
||||||
|
id="main_viewer"
|
||||||
|
class="dicom-viewer-root"
|
||||||
|
data-auto-cache-stack="false"
|
||||||
|
></div>
|
||||||
|
|
||||||
|
<!-- Provide noop React Refresh preamble to avoid plugin-react runtime errors -->
|
||||||
|
<script>
|
||||||
|
window.$RefreshReg$ = window.$RefreshReg$ || function () {};
|
||||||
|
window.$RefreshSig$ =
|
||||||
|
window.$RefreshSig$ ||
|
||||||
|
function () {
|
||||||
|
return function (type) {
|
||||||
|
return type;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<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",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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",
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
}
|
||||||
|
],
|
||||||
|
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 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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>
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Test Pages — Links</title>
|
||||||
|
<style>
|
||||||
|
body{font-family:system-ui,Segoe UI,Roboto,Helvetica,Arial;margin:24px;color:#111}
|
||||||
|
h1{margin-top:0}
|
||||||
|
ul{line-height:1.6}
|
||||||
|
a{color:#0366d6}
|
||||||
|
.note{background:#f6f8fa;padding:10px;border-radius:6px;margin-bottom:12px}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Available Test Pages</h1>
|
||||||
|
<p class="note">Open any of these pages directly in the dev server to view the corresponding test.</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="/penra-test.html">penra-test.html</a> — original Penra viewer test</li>
|
||||||
|
<li><a href="/embedded-viewer-test.html">embedded-viewer-test.html</a> — viewer embedded with surrounding content</li>
|
||||||
|
<li><a href="/empty-viewer.html">empty-viewer.html</a> — empty viewer placeholder</li>
|
||||||
|
<li><a href="/load-dir-test.html">load-dir-test.html</a> — directory loading test</li>
|
||||||
|
<li><a href="/non-dicom-test.html">non-dicom-test.html</a> — non-DICOM handling test</li>
|
||||||
|
<li><a href="/index.html">index.html</a> — project index</li>
|
||||||
|
<li><a href="/fluoro-test.html">fluoro-test.html</a> — fluoro multiframe test</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>If you want these links added to the README, tell me and I will update it.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user