Skip to content

Commit c5bc612

Browse files
committed
add z slice limit where applicable, new source
1 parent b5f790e commit c5bc612

3 files changed

Lines changed: 58 additions & 13 deletions

File tree

apps/dicom-web/table.js

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ const sources = [{
99
}, {
1010
'name': 'google',
1111
'url': 'https://dicomwebproxy.app/dicomWeb',
12+
},{
13+
'name':'BMD',
14+
'url': 'https://dicom-wg26.bmd-software.com/ext/dicom-web'
1215
}];
1316
// const j4careStudiesUrl = 'https://development.j4care.com:11443/dcm4chee-arc/aets/DCM4CHEE/rs'
1417
// const dicomWebStudiesUrl = 'https://dicomwebproxy-bqmq3usc3a-uc.a.run.app/dicomWeb'
@@ -36,6 +39,9 @@ const pageStates = {
3639
}, {
3740
'name': 'google',
3841
'url': 'https://dicomwebproxy-bqmq3usc3a-uc.a.run.app/dicomWeb',
42+
},{
43+
'name':'BMD',
44+
'url': 'https://dicom-wg26.bmd-software.com/ext/dicom-web'
3945
}],
4046
},
4147
studies: {
@@ -147,13 +153,30 @@ function initialize() {
147153
}
148154
datatable = $('#datatable').DataTable({
149155
...datatableConfig,
150-
'data': pageStates[pageStates.status].data,
151-
'columns': [
152-
{data: '0020000D.Value.0', title: 'Study Id', render: generateLink},
153-
{data: '00100020.Value.0', title: 'Name'},
154-
{data: 'source', title: 'Source'},
155-
],
156+
data: pageStates[pageStates.status].data,
157+
columns: [
158+
{
159+
data: null,
160+
title: 'Study Id',
161+
render: function (data, type, row) {
162+
const value = row?.['0020000D']?.Value?.[0] ?? '';
163+
return generateLink(value, type, row);
164+
}
165+
},
166+
{
167+
data: null,
168+
title: 'Name',
169+
render: function (data, type, row) {
170+
return row?.['00100020']?.Value?.[0] ?? '';
171+
}
172+
},
173+
{
174+
data: 'source',
175+
title: 'Source'
176+
}
177+
]
156178
});
179+
157180
});
158181

159182
break;

common/DicomWebMods.js

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
// special: for 'sparse' tiles, show a debug overlay on render.
44
showDebugTiles = false;
5+
// special: for z index multi-plane/focal images, pick only one z.
6+
whichZ = 1; // -1 means all no matter what.
57
function DicomWebMods() {
68
async function openSeries(baseUrl, studyId, seriesId) {
79
try {
@@ -66,6 +68,7 @@ function DicomWebMods() {
6668
// instanceWidth = tileSize*Math.ceil(instanceWidth/tileSize)
6769
instanceHeight = tileSize*Math.ceil(instanceHeight/tileSize);
6870
let tileMap = {};
71+
let uniquePhysZ = [];
6972
if (x['52009230']?.Value &&
7073
Array.isArray(x['52009230'].Value) &&
7174
x['52009230'].Value.length > 0) {
@@ -78,14 +81,16 @@ function DicomWebMods() {
7881
const row = item?.['0048021F']?.Value?.[0];
7982
const physRow = item?.['0040072A']?.Value?.[0];
8083
const physCol = item?.['0040073A']?.Value?.[0];
84+
const physZ = item?.['0040074A']?.Value?.[0];
8185
if (col !== undefined && row !== undefined && tileSize) {
8286
const tileX = Math.floor((col-1) / tileSize);
8387
const tileY = Math.floor((row-1) / tileSize);
84-
tileMap[`${tileX}_${tileY}`] = {'idx': i + 1, 'col': col-1, 'row': row-1, 'physRow': physRow, 'physCol': physCol};
88+
tileMap[`${tileX}_${tileY}`] = {'idx': i + 1, 'col': col-1, 'row': row-1, 'physRow': physRow, 'physCol': physCol, 'physZ': physZ};
8589
// console.log(row, col, tileX, tileY, i+1)
8690
}
8791
}
8892
console.log(tileMap);
93+
uniquePhysZ = [...new Set(Object.values(tileMap).map(tile => tile.physZ))].sort((a, b) => a - b);
8994
}
9095

9196
return {
@@ -95,20 +100,21 @@ function DicomWebMods() {
95100
url: x['url']?.split('/metadata')[0] ?? '',
96101
type: x['00080008']?.['Value'] ?? [],
97102
tileMap: tileMap,
103+
uniquePhysZ: uniquePhysZ,
98104
};
99105
} catch (error) {
100106
console.error('Error processing instance metadata:', error);
101107
return null;
102108
}
103109
}).filter((x)=>{
104-
if (x == null || x.height == null || x.width == null || x.height < x.tileSize || x.width < x.tileSize) {
110+
if (x == null || x.height == null || x.width == null) {
105111
return false;
106112
}
107113
let types = x['type'];
108114
for (let i=0; i< types.length; i++) {
109115
let v = types[i].toUpperCase();
110116
if (v.indexOf('LABEL') !== -1 ||
111-
v.indexOf('THUMBNAIL') !== -1 ||
117+
v.indexOf('THUMBNAIL') !==-1 ||
112118
v.indexOf('MACRO') !==-1 ||
113119
v.indexOf('OVERVIEW') !== -1) {
114120
return false;
@@ -129,6 +135,18 @@ function DicomWebMods() {
129135
instanceResults.forEach((item, index) => {
130136
item.order = index;
131137
});
138+
// get a true list of possible z values
139+
const globalUniquePhysZ = [
140+
...new Set(instanceResults.flatMap(inst => inst.uniquePhysZ))
141+
].sort((a, b) => a - b);
142+
143+
// picking a z slice
144+
if (whichZ == -1 || globalUniquePhysZ.length == 0){
145+
whichZ = false; // sinal no slices to filter between
146+
} else {
147+
whichZ = Math.min(Math.max(whichZ, 0), globalUniquePhysZ.length)
148+
instanceResults = instanceResults.filter(inst => inst.uniquePhysZ.includes(globalUniquePhysZ[whichZ]))
149+
}
132150

133151
if (showDebugTiles) {
134152
let newInstanceResults = [];
@@ -187,7 +205,9 @@ function DicomWebMods() {
187205
let tileCol = x['tileMap'][`${xPos}_${yPos}`]['col'];
188206
let physRow = x['tileMap'][`${xPos}_${yPos}`]['physRow'];
189207
let physCol = x['tileMap'][`${xPos}_${yPos}`]['physCol'];
190-
if (tileIdx !== undefined) {
208+
let physZ = x['tileMap'][`${xPos}_${yPos}`]['physZ'];
209+
210+
if (tileIdx !== undefined && (whichZ === false || physZ == globalUniquePhysZ[whichZ])) {
191211
let tileUrl = `${x['url']}/frames/${tileIdx}/rendered`;
192212
let lgFont = 50 * (x['tileSize']/1024);
193213
let smFont = 30 * (x['tileSize']/1024);
@@ -200,9 +220,10 @@ function DicomWebMods() {
200220
<text x="50%" y="35%" font-size="${smFont}" text-anchor="middle" fill="#000">dcm C: ${tileCol}</text>
201221
<text x="50%" y="40%" font-size="${smFont}" text-anchor="middle" fill="#000">phys R: ${physRow}</text>
202222
<text x="50%" y="45%" font-size="${smFont}" text-anchor="middle" fill="#000">phys C: ${physCol}</text>
203-
<text x="50%" y="60%" font-size="${smFont}" text-anchor="middle" fill="#000">L: ${level}</text>
204-
<text x="50%" y="65%" font-size="${smFont}" text-anchor="middle" fill="#000">X: ${xPos}</text>
205-
<text x="50%" y="70%" font-size="${smFont}" text-anchor="middle" fill="#000">Y: ${yPos}</text>
223+
<text x="50%" y="55%" font-size="${smFont}" text-anchor="middle" fill="#000">phys Z: ${physZ}</text>
224+
<text x="50%" y="65%" font-size="${smFont}" text-anchor="middle" fill="#000">L: ${level}</text>
225+
<text x="50%" y="70%" font-size="${smFont}" text-anchor="middle" fill="#000">X: ${xPos}</text>
226+
<text x="50%" y="75%" font-size="${smFont}" text-anchor="middle" fill="#000">Y: ${yPos}</text>
206227
</svg>
207228
`;
208229
const encoded = encodeURIComponent(svg)

core/CaMic.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class CaMic {
4444
hasMeasurementTool: true,
4545
hasPatchManager: true,
4646
hasHeatmap: false,
47+
crossOriginPolicy: 'Anonymous',
4748
};
4849
extend(this.setting, options);
4950

0 commit comments

Comments
 (0)