init
This commit is contained in:
191
nv/html/dwv/tests/dicom/anonymiser.html
Normal file
191
nv/html/dwv/tests/dicom/anonymiser.html
Normal file
@@ -0,0 +1,191 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>DICOM Anonymiser</title>
|
||||
<meta charset="UTF-8">
|
||||
<script type="text/javascript" src="../../src/dicom/dicomParser.js"></script>
|
||||
<script type="text/javascript" src="../../src/dicom/dicomWriter.js"></script>
|
||||
<script type="text/javascript" src="../../src/dicom/dictionary.js"></script>
|
||||
<script type="text/javascript">
|
||||
// rules file
|
||||
var _rulesFile = null;
|
||||
// dicom file
|
||||
var _dicomFile = null;
|
||||
// DICOM elements
|
||||
var _dicomElements = null;
|
||||
// handle DICOM file load
|
||||
function onLoadDICOMFile(event)
|
||||
{
|
||||
// parse DICOM
|
||||
var parser = new dwv.dicom.DicomParser();
|
||||
parser.parse(event.target.result);
|
||||
// store elements
|
||||
_dicomElements = parser.getRawDicomElements();
|
||||
// activate generate button
|
||||
var element = document.getElementById("generate");
|
||||
element.className = "button button-active";
|
||||
}
|
||||
// generate DICOM data
|
||||
function generate()
|
||||
{
|
||||
// check validity
|
||||
if (!isValidRules()) {
|
||||
return;
|
||||
}
|
||||
// create writer with textarea rules
|
||||
var writer = new dwv.dicom.DicomWriter();
|
||||
writer.rules = JSON.parse(document.getElementById('rules').value);
|
||||
var dicomBuffer = null;
|
||||
try {
|
||||
dicomBuffer = writer.getBuffer(_dicomElements);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
alert(error.message);
|
||||
}
|
||||
// view as Blob to allow download
|
||||
var blob = new Blob([dicomBuffer], {type: 'application/dicom'});
|
||||
// update generate button
|
||||
var element = document.getElementById("generate");
|
||||
element.href = URL.createObjectURL(blob);
|
||||
element.download = "anonym-" + _dicomFile.name;
|
||||
}
|
||||
// save the rules as a JSON file
|
||||
function saveRules()
|
||||
{
|
||||
// check validity
|
||||
if (!isValidRules()) {
|
||||
return;
|
||||
}
|
||||
// get text from the textarea
|
||||
var text = document.getElementById('rules').value;
|
||||
// view as Blob to allow download
|
||||
var blob = new Blob([text], {type:"text/plain"});
|
||||
// update save button
|
||||
var element = document.getElementById("save");
|
||||
element.download = (_rulesFile === null ? "rules.json" : _rulesFile.name);
|
||||
element.href = URL.createObjectURL(blob);
|
||||
}
|
||||
// is the JSON valid?
|
||||
function isValidRules()
|
||||
{
|
||||
try {
|
||||
JSON.parse(document.getElementById('rules').value);
|
||||
}
|
||||
catch (error) {
|
||||
alert("The JSON is not valid, please check it with JSONLint.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// open JSONLint to check the rules
|
||||
function launchJSONLint()
|
||||
{
|
||||
var text = document.getElementById('rules').value;
|
||||
var link = "http://jsonlint.com/?json=" + encodeURIComponent(text);
|
||||
window.open(link);
|
||||
}
|
||||
// handle input DICOM file
|
||||
function onInputDICOMFile(event)
|
||||
{
|
||||
if (event.target.files.length === 0) {
|
||||
return;
|
||||
}
|
||||
_dicomFile = event.target.files[0];
|
||||
var reader = new FileReader();
|
||||
reader.onload = onLoadDICOMFile;
|
||||
reader.readAsArrayBuffer(_dicomFile);
|
||||
}
|
||||
// handle input rules file
|
||||
function onInputRulesFile(event)
|
||||
{
|
||||
if (event.target.files.length === 0) {
|
||||
return;
|
||||
}
|
||||
_rulesFile = event.target.files[0];
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (event) {
|
||||
document.getElementById('rules').value = event.target.result;
|
||||
};
|
||||
reader.readAsText(_rulesFile);
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
body { font-family: Arial, Helvetica, sans-serif; }
|
||||
textarea { width: 99%; margin: 2px; }
|
||||
fieldset { background: whitesmoke; border: 1px solid grey; }
|
||||
.button {
|
||||
padding: 3px 7px 3px 7px;
|
||||
text-align: center;
|
||||
border-radius: 3px;
|
||||
border: 1px solid grey;
|
||||
text-decoration: none;
|
||||
font: 80% sans-serif;
|
||||
color: black;
|
||||
background: #E3E3E3;
|
||||
}
|
||||
.button-active {
|
||||
color: black;
|
||||
background: #E3E3E3;
|
||||
}
|
||||
.button-disabled {
|
||||
color: grey;
|
||||
background: #F3F3F3;
|
||||
}
|
||||
.button:hover {
|
||||
border: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>DWV DICOM Anonymiser</h1>
|
||||
|
||||
<p>Simple DICOM "anonymisation" tool. Available rules: <code>copy</code>,
|
||||
<code>remove</code>, <code>clear</code>, <code>replace(value)</code>.</p>
|
||||
|
||||
<form name="genform">
|
||||
|
||||
<fieldset>
|
||||
<label for="infile">DICOM file: </label>
|
||||
<input id="infile" type="file" name="file" onchange="onInputDICOMFile(event);">
|
||||
<br>
|
||||
<br><label for="inrulesfile">JSON rules file: </label>
|
||||
<input id="inrulesfile" type="file" name="file" onchange="onInputRulesFile(event);">
|
||||
</fieldset>
|
||||
|
||||
<textarea id="rules" rows="25">
|
||||
{
|
||||
"default": {
|
||||
"action": "remove", "value": null
|
||||
},
|
||||
"PatientName": {
|
||||
"action": "replace", "value": "Anonymised"
|
||||
},
|
||||
"Meta Element": {
|
||||
"action": "copy", "value": null
|
||||
},
|
||||
"Acquisition": {
|
||||
"action": "copy", "value": null
|
||||
},
|
||||
"Image Presentation": {
|
||||
"action": "copy", "value": null
|
||||
},
|
||||
"Procedure": {
|
||||
"action": "copy", "value": null
|
||||
},
|
||||
"Pixel Data": {
|
||||
"action": "copy", "value": null
|
||||
}
|
||||
}
|
||||
</textarea>
|
||||
|
||||
<fieldset>
|
||||
<a href="#" id="jsonlint" class="button" onclick="launchJSONLint();">JSONLint</a>
|
||||
<a href="#" id="save" class="button" onclick="saveRules();">Save Rules</a>
|
||||
<a href="#" id="generate" class="button button-disabled" onclick="generate();">Generate</a>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
216
nv/html/dwv/tests/dicom/dicomParser.test.js
Normal file
216
nv/html/dwv/tests/dicom/dicomParser.test.js
Normal file
@@ -0,0 +1,216 @@
|
||||
/**
|
||||
* Tests for the 'dicom/dicomParser.js' file.
|
||||
*/
|
||||
/** @module tests/dicom */
|
||||
// Do not warn if these variables were not defined before.
|
||||
/* global QUnit */
|
||||
QUnit.module("dicomParser");
|
||||
|
||||
// WARNING about PhantomJS 1.9
|
||||
// ---------------------------
|
||||
// TypedArray implementation seems incomplete, at least different than observed
|
||||
// behavior in browsers...
|
||||
// For a DICOM dataset, it was giving an:
|
||||
// 'RangeError: ArrayBuffer length minus the byteOffset is not a multiple of the element size.'
|
||||
// Which seem to originate from reading the data of first tag
|
||||
// (FileMetaInformationGroupLength, Uint32 -> size=4)
|
||||
// at offset 140 of a file of size 3070. 3070-140=2930; 2930/4=732.5...
|
||||
//
|
||||
// Error which, according to specs, should be thrown when the size of the data
|
||||
// to read is not specified (see
|
||||
// https://www.khronos.org/registry/typedarray/specs/latest/#7). But it is specified...
|
||||
//
|
||||
// So I updated the data to be of the correct size (in this case 3072)...
|
||||
|
||||
/**
|
||||
* Tests for {@link dwv.dicom.DicomParser} using simple DICOM data.
|
||||
* Using remote file for CI integration.
|
||||
* @function module:tests/dicom~dicomParser
|
||||
*/
|
||||
QUnit.test("Test simple DICOM parsing.", function (assert) {
|
||||
var done = assert.async();
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
var urlRoot = "https://raw.githubusercontent.com/ivmartel/dwv/master";
|
||||
var url = urlRoot + "/tests/data/dwv-test-simple.dcm";
|
||||
request.open('GET', url, true);
|
||||
request.responseType = "arraybuffer";
|
||||
request.onerror = function (event) {
|
||||
console.log(event);
|
||||
};
|
||||
request.onload = function (/*event*/) {
|
||||
assert.ok((this.response.byteLength!==0), "Got a response.");
|
||||
|
||||
// parse DICOM
|
||||
var dicomParser = new dwv.dicom.DicomParser();
|
||||
dicomParser.parse(this.response);
|
||||
|
||||
var numRows = 32;
|
||||
var numCols = 32;
|
||||
|
||||
// raw tags
|
||||
var rawTags = dicomParser.getRawDicomElements();
|
||||
// check values
|
||||
assert.equal(rawTags.x00280010.value[0], numRows, "Number of rows (raw)");
|
||||
assert.equal(rawTags.x00280011.value[0], numCols, "Number of columns (raw)");
|
||||
// ReferencedImageSequence - ReferencedSOPInstanceUID
|
||||
assert.equal(rawTags.x00081140.value[0].x00081155.value[0],
|
||||
"1.3.12.2.1107.5.2.32.35162.2012021515511672669154094",
|
||||
"ReferencedImageSequence SQ (raw)");
|
||||
|
||||
// wrapped tags
|
||||
var tags = dicomParser.getDicomElements();
|
||||
// wrong key
|
||||
assert.equal(tags.getFromKey("x12345678"), null, "Wrong key");
|
||||
assert.notOk(tags.getFromKey("x12345678"), "Wrong key fails if test" );
|
||||
// empty key
|
||||
assert.equal(tags.getFromKey("x00081050"), "", "Empty key");
|
||||
assert.notOk(tags.getFromKey("x00081050"), "Empty key fails if test" );
|
||||
// good key
|
||||
assert.equal(tags.getFromKey("x00280010"), numRows, "Good key");
|
||||
assert.ok(tags.getFromKey("x00280010"), "Good key passes if test" );
|
||||
// zero value (passes test since it is a string)
|
||||
assert.equal(tags.getFromKey("x00181318"), 0, "Good key, zero value");
|
||||
assert.ok(tags.getFromKey("x00181318"), "Good key, zero value passes if test" );
|
||||
|
||||
// check values
|
||||
assert.equal(tags.getFromName("Rows"), numRows, "Number of rows");
|
||||
assert.equal(tags.getFromName("Columns"), numCols, "Number of columns");
|
||||
// ReferencedImageSequence - ReferencedSOPInstanceUID
|
||||
// only one item value -> returns the object directly
|
||||
// (no need for tags.getFromName("ReferencedImageSequence")[0])
|
||||
assert.equal(tags.getFromName("ReferencedImageSequence").x00081155.value[0],
|
||||
"1.3.12.2.1107.5.2.32.35162.2012021515511672669154094",
|
||||
"ReferencedImageSequence SQ");
|
||||
|
||||
// finish async test
|
||||
done();
|
||||
};
|
||||
request.send(null);
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests for {@link dwv.dicom.DicomParser} using sequence test DICOM data.
|
||||
* Using remote file for CI integration.
|
||||
* @function module:tests/dicom~dicomParser
|
||||
*/
|
||||
QUnit.test("Test sequence DICOM parsing.", function (assert) {
|
||||
var done = assert.async();
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
var urlRoot = "https://raw.githubusercontent.com/ivmartel/dwv/master";
|
||||
var url = urlRoot + "/tests/data/dwv-test-sequence.dcm";
|
||||
request.open('GET', url, true);
|
||||
request.responseType = "arraybuffer";
|
||||
request.onload = function (/*event*/) {
|
||||
assert.ok((this.response.byteLength!==0), "Got a response.");
|
||||
|
||||
// parse DICOM
|
||||
var dicomParser = new dwv.dicom.DicomParser();
|
||||
dicomParser.parse(this.response);
|
||||
// raw tags
|
||||
var rawTags = dicomParser.getRawDicomElements();
|
||||
assert.ok((Object.keys(rawTags).length!==0), "Got raw tags.");
|
||||
// wrapped tags
|
||||
var tags = dicomParser.getDicomElements();
|
||||
assert.ok((tags.dumpToTable().length!==0), "Got wrapped tags.");
|
||||
|
||||
// ReferencedImageSequence: explicit sequence
|
||||
var seq00 = tags.getFromName("ReferencedImageSequence");
|
||||
assert.equal(seq00.length, 3, "ReferencedImageSequence length");
|
||||
assert.equal(seq00[0].x00081155.value[0],
|
||||
"1.3.12.2.1107.5.2.32.35162.2012021515511672669154094",
|
||||
"ReferencedImageSequence - item0 - ReferencedSOPInstanceUID");
|
||||
assert.equal(seq00[1].x00081155.value[0],
|
||||
"1.3.12.2.1107.5.2.32.35162.2012021515511286933854090",
|
||||
"ReferencedImageSequence - item1 - ReferencedSOPInstanceUID");
|
||||
|
||||
// SourceImageSequence: implicit sequence
|
||||
var seq01 = tags.getFromName("SourceImageSequence");
|
||||
assert.equal(seq01.length, 3, "SourceImageSequence length");
|
||||
assert.equal(seq01[0].x00081155.value[0],
|
||||
"1.3.12.2.1107.5.2.32.35162.2012021515511672669154094",
|
||||
"SourceImageSequence - item0 - ReferencedSOPInstanceUID");
|
||||
assert.equal(seq01[1].x00081155.value[0],
|
||||
"1.3.12.2.1107.5.2.32.35162.2012021515511286933854090",
|
||||
"SourceImageSequence - item1 - ReferencedSOPInstanceUID");
|
||||
|
||||
// ReferencedPatientSequence: explicit empty sequence
|
||||
var seq10 = tags.getFromName("ReferencedPatientSequence");
|
||||
assert.equal(seq10.length, 0, "ReferencedPatientSequence length");
|
||||
|
||||
// ReferencedOverlaySequence: implicit empty sequence
|
||||
var seq11 = tags.getFromName("ReferencedOverlaySequence");
|
||||
assert.equal(seq11.length, 0, "ReferencedOverlaySequence length");
|
||||
|
||||
// ReferringPhysicianIdentificationSequence: explicit empty item
|
||||
var seq12 = tags.getFromName("ReferringPhysicianIdentificationSequence");
|
||||
assert.equal(seq12.xFFFEE000.value.length, 0,
|
||||
"ReferringPhysicianIdentificationSequence item length");
|
||||
|
||||
// ConsultingPhysicianIdentificationSequence: implicit empty item
|
||||
var seq13 = tags.getFromName("ConsultingPhysicianIdentificationSequence");
|
||||
assert.equal(seq13.xFFFEE000.value.length, 0,
|
||||
"ConsultingPhysicianIdentificationSequence item length");
|
||||
|
||||
// ReferencedStudySequence: explicit sequence of sequence
|
||||
var seq20 = tags.getFromName("ReferencedStudySequence");
|
||||
// just one element
|
||||
//assert.equal(seq20.length, 2, "ReferencedStudySequence length");
|
||||
assert.equal(seq20.x0040A170.value[0].x00080100.value[0],
|
||||
"123456",
|
||||
"ReferencedStudySequence - seq - item0 - CodeValue");
|
||||
|
||||
// ReferencedSeriesSequence: implicit sequence of sequence
|
||||
var seq21 = tags.getFromName("ReferencedSeriesSequence");
|
||||
// just one element
|
||||
//assert.equal(seq21.length, 2, "ReferencedSeriesSequence length");
|
||||
assert.equal(seq21.x0040A170.value[0].x00080100.value[0],
|
||||
"789101",
|
||||
"ReferencedSeriesSequence - seq - item0 - CodeValue");
|
||||
|
||||
// ReferencedInstanceSequence: explicit empty sequence of sequence
|
||||
var seq30 = tags.getFromName("ReferencedInstanceSequence");
|
||||
assert.equal(seq30.x0040A170.value.length, 0,
|
||||
"ReferencedInstanceSequence - seq - length");
|
||||
|
||||
// ReferencedVisitSequence: implicit empty sequence of sequence
|
||||
var seq31 = tags.getFromName("ReferencedVisitSequence");
|
||||
assert.equal(seq31.x0040A170.value.length, 0,
|
||||
"ReferencedVisitSequence - seq - length");
|
||||
|
||||
// finish async test
|
||||
done();
|
||||
};
|
||||
request.send(null);
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests for {@link dwv.dicom.cleanString}.
|
||||
* @function module:tests/dicom~cleanString
|
||||
*/
|
||||
QUnit.test("Test cleanString.", function (assert) {
|
||||
// undefined
|
||||
assert.equal(dwv.dicom.cleanString(), null, "Clean undefined");
|
||||
// null
|
||||
assert.equal(dwv.dicom.cleanString(null), null, "Clean null");
|
||||
// empty
|
||||
assert.equal(dwv.dicom.cleanString(""), "", "Clean empty");
|
||||
// short
|
||||
assert.equal(dwv.dicom.cleanString("a"), "a", "Clean short");
|
||||
// special
|
||||
var special = String.fromCharCode("u200B");
|
||||
assert.equal(dwv.dicom.cleanString(special), "", "Clean just special");
|
||||
// regular
|
||||
var str = " El cielo azul ";
|
||||
var refStr = "El cielo azul";
|
||||
assert.equal(dwv.dicom.cleanString(str), refStr, "Clean regular");
|
||||
// regular with special
|
||||
str = " El cielo azul" + special;
|
||||
refStr = "El cielo azul";
|
||||
assert.equal(dwv.dicom.cleanString(str), refStr, "Clean regular with special");
|
||||
// regular with special and ending space (not trimmed)
|
||||
str = " El cielo azul " + special;
|
||||
refStr = "El cielo azul ";
|
||||
assert.equal(dwv.dicom.cleanString(str), refStr, "Clean regular with special 2");
|
||||
});
|
||||
283
nv/html/dwv/tests/dicom/dicomWriter.test.js
Normal file
283
nv/html/dwv/tests/dicom/dicomWriter.test.js
Normal file
@@ -0,0 +1,283 @@
|
||||
/**
|
||||
* Tests for the 'dicom/dicomWriter.js' file.
|
||||
*/
|
||||
/** @module tests/dicom */
|
||||
// Do not warn if these variables were not defined before.
|
||||
/* global QUnit */
|
||||
QUnit.module("dicomWriter");
|
||||
|
||||
var dwv = dwv || {};
|
||||
dwv.utils = dwv.utils || {};
|
||||
dwv.utils.test = dwv.utils.test || {};
|
||||
|
||||
/**
|
||||
* Tests for {@link dwv.dicom.DicomWriter} using simple DICOM data.
|
||||
* Using remote file for CI integration.
|
||||
* @function module:tests/dicom~dicomWriter
|
||||
*/
|
||||
QUnit.test("Test multiframe writer support.", function (assert) {
|
||||
var done = assert.async();
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
var urlRoot = "https://raw.githubusercontent.com/ivmartel/dwv/master";
|
||||
var url = urlRoot + "/tests/data/multiframe-test1.dcm";
|
||||
request.open('GET', url, true);
|
||||
request.responseType = "arraybuffer";
|
||||
request.onerror = function (event) {
|
||||
console.log(event);
|
||||
};
|
||||
request.onload = function (/*event*/) {
|
||||
assert.ok((this.response.byteLength!==0), "Got a response.");
|
||||
|
||||
// parse DICOM
|
||||
var dicomParser = new dwv.dicom.DicomParser();
|
||||
dicomParser.parse(this.response);
|
||||
|
||||
var numFrames = 16;
|
||||
|
||||
// raw tags
|
||||
var rawTags = dicomParser.getRawDicomElements();
|
||||
// check values
|
||||
assert.equal(rawTags.x00280008.value[0], numFrames, "Number of frames");
|
||||
// length of value array for pixel data
|
||||
assert.equal(rawTags.x7FE00010.value.length, numFrames, "Length of value array for pixel data");
|
||||
|
||||
var dicomWriter = new dwv.dicom.DicomWriter();
|
||||
var buffer = dicomWriter.getBuffer(rawTags);
|
||||
|
||||
dicomParser = new dwv.dicom.DicomParser();
|
||||
dicomParser.parse(buffer);
|
||||
|
||||
rawTags = dicomParser.getRawDicomElements();
|
||||
|
||||
// check values
|
||||
assert.equal(rawTags.x00280008.value[0], numFrames, "Number of frames");
|
||||
// length of value array for pixel data
|
||||
assert.equal(rawTags.x7FE00010.value.length, numFrames, "Length of value array for pixel data");
|
||||
|
||||
// finish async test
|
||||
done();
|
||||
};
|
||||
request.send(null);
|
||||
});
|
||||
|
||||
QUnit.test("Test patient anonymisation", function (assert) {
|
||||
var done = assert.async();
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
var urlRoot = "https://raw.githubusercontent.com/ivmartel/dwv/master";
|
||||
var url = urlRoot + "/tests/data/dwv-test-anonymise.dcm";
|
||||
request.open('GET', url, true);
|
||||
request.responseType = "arraybuffer";
|
||||
request.onerror = function (event) {
|
||||
console.log(event);
|
||||
};
|
||||
request.onload = function (/*event*/) {
|
||||
assert.ok((this.response.byteLength!==0), "Got a response.");
|
||||
|
||||
// parse DICOM
|
||||
var dicomParser = new dwv.dicom.DicomParser();
|
||||
dicomParser.parse(this.response);
|
||||
|
||||
var patientsNameAnonymised = 'anonymise-name';
|
||||
var patientsIdAnonymised = 'anonymise-id';
|
||||
var rules = {
|
||||
'default': {action: 'copy', value: null },
|
||||
'x00100010' : {action: 'replace', value: patientsNameAnonymised }, // tag
|
||||
'PatientID': {action: 'replace', value: patientsIdAnonymised}, // tag name 'x00100020'
|
||||
'Patient' : {action: 'remove', value: null }, // group name 'x0010'
|
||||
};
|
||||
|
||||
var patientsName = 'dwv-patient-test';
|
||||
var patientID = 'dwv-patient-id123';
|
||||
var patientsBirthDate = '19830101';
|
||||
var patientsSex = 'M';
|
||||
|
||||
// raw tags
|
||||
var rawTags = dicomParser.getRawDicomElements();
|
||||
// check values
|
||||
assert.equal(rawTags.x00100010.value[0], patientsName, "patientsName");
|
||||
assert.equal(rawTags.x00100020.value[0], patientID, "patientID");
|
||||
assert.equal(rawTags.x00100030.value[0], patientsBirthDate, "patientsBirthDate");
|
||||
assert.equal(rawTags.x00100040.value[0], patientsSex, "patientsSex");
|
||||
|
||||
var dicomWriter = new dwv.dicom.DicomWriter();
|
||||
dicomWriter.rules = rules;
|
||||
var buffer = dicomWriter.getBuffer(rawTags);
|
||||
|
||||
dicomParser = new dwv.dicom.DicomParser();
|
||||
|
||||
dicomParser.parse(buffer);
|
||||
|
||||
rawTags = dicomParser.getRawDicomElements();
|
||||
|
||||
// check values
|
||||
assert.equal(rawTags.x00100010.value[0], patientsNameAnonymised, "patientName");
|
||||
assert.equal(rawTags.x00100020.value[0], patientsIdAnonymised, "patientID");
|
||||
assert.notOk(rawTags.x00100030, "patientsBirthDate");
|
||||
assert.notOk(rawTags.x00100040, "patientsSex");
|
||||
|
||||
// finish async test
|
||||
done();
|
||||
};
|
||||
request.send(null);
|
||||
});
|
||||
|
||||
/**
|
||||
* Get a string representation of an object.
|
||||
* TypedArray.toString can return '[object Uint8Array]' on old browsers
|
||||
* (such as in PhantomJs).
|
||||
* @param {Object} obj The input object
|
||||
* @return {String} The string.
|
||||
*/
|
||||
dwv.utils.test.toString = function ( obj ) {
|
||||
var res = obj.toString();
|
||||
if ( res.substr(0,7) === "[object" &&
|
||||
res.substr((res.length - 6),6) === "Array]") {
|
||||
res = "";
|
||||
for ( var i = 0; i < obj.length; ++i ) {
|
||||
res += obj[i];
|
||||
if ( i !== obj.length - 1 ) {
|
||||
res += ",";
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compare JSON tags and DICOM elements
|
||||
* @param {Object} jsonTags The JSON tags.
|
||||
* @param {Object} dicomElements The DICOM elements
|
||||
* @param {String} name The name of the test.
|
||||
* @param {Object} comaprator An object with an equal function (such as Qunit assert).
|
||||
*/
|
||||
dwv.utils.test.compare = function ( jsonTags, dicomElements, name, comparator ) {
|
||||
// check content
|
||||
if (jsonTags === null || jsonTags === 0) {
|
||||
return;
|
||||
}
|
||||
var keys = Object.keys(jsonTags);
|
||||
for ( var k = 0; k < keys.length; ++k ) {
|
||||
var tag = keys[k];
|
||||
var tagGE = dwv.dicom.getGroupElementFromName(tag);
|
||||
var tagKey = dwv.dicom.getGroupElementKey(tagGE.group, tagGE.element);
|
||||
var element = dicomElements.getDEFromKey(tagKey);
|
||||
var value = dicomElements.getFromKey(tagKey, true);
|
||||
if ( element.vr !== "SQ" ) {
|
||||
comparator.equal(dwv.utils.test.toString(value), jsonTags[tag], name + " - " + tag);
|
||||
} else {
|
||||
// check content
|
||||
if (jsonTags[tag] === null || jsonTags[tag] === 0) {
|
||||
continue;
|
||||
}
|
||||
// supposing same order of subkeys and indices...
|
||||
var subKeys = Object.keys(jsonTags[tag]);
|
||||
var index = 0;
|
||||
for ( var sk = 0; sk < subKeys.length; ++sk ) {
|
||||
if ( subKeys[sk] !== "explicitLength" ) {
|
||||
var wrap = new dwv.dicom.DicomElementsWrapper(value[index]);
|
||||
dwv.utils.test.compare(jsonTags[tag][subKeys[sk]], wrap, name, comparator);
|
||||
++index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test a JSON config.
|
||||
* @param {Object} config A JSON config representing DICOM tags.
|
||||
* @param {Object} assert A Qunit assert.
|
||||
*/
|
||||
dwv.utils.test.testConfig = function (config, assert) {
|
||||
// convert JSON to DICOM element object
|
||||
var res = dwv.dicom.getElementsFromJSONTags(config.tags);
|
||||
var dicomElements = res.elements;
|
||||
// pixels: small gradient square
|
||||
dicomElements.x7FE00010 = dwv.dicom.generatePixelDataFromJSONTags(config.tags, res.offset);
|
||||
|
||||
// create DICOM buffer
|
||||
var writer = new dwv.dicom.DicomWriter();
|
||||
var dicomBuffer = null;
|
||||
try {
|
||||
dicomBuffer = writer.getBuffer(dicomElements);
|
||||
} catch (error) {
|
||||
assert.ok(false, "Caught error: "+error);
|
||||
return;
|
||||
}
|
||||
|
||||
// parse the buffer
|
||||
var dicomParser = new dwv.dicom.DicomParser();
|
||||
dicomParser.parse(dicomBuffer);
|
||||
var elements = dicomParser.getDicomElements();
|
||||
|
||||
// compare contents
|
||||
dwv.utils.test.compare(config.tags, elements, config.name, assert);
|
||||
};
|
||||
|
||||
QUnit.test("Test synthetic dicom explicit", function (assert) {
|
||||
var done = assert.async();
|
||||
|
||||
// get the list of configs
|
||||
var request = new XMLHttpRequest();
|
||||
var urlRoot = "https://raw.githubusercontent.com/ivmartel/dwv/master";
|
||||
var url = urlRoot + "/tests/dicom/synthetic-data_explicit.json";
|
||||
request.open('GET', url, true);
|
||||
request.onerror = function (event) {
|
||||
console.error(event);
|
||||
};
|
||||
request.onload = function (/*event*/) {
|
||||
var configs = JSON.parse(this.responseText);
|
||||
for (var i = 0; i < configs.length; ++i ) {
|
||||
dwv.utils.test.testConfig(configs[i], assert);
|
||||
}
|
||||
// finish async test
|
||||
done();
|
||||
};
|
||||
request.send(null);
|
||||
});
|
||||
|
||||
QUnit.test("Test synthetic dicom implicit", function (assert) {
|
||||
var done = assert.async();
|
||||
|
||||
// get the list of configs
|
||||
var request = new XMLHttpRequest();
|
||||
var urlRoot = "https://raw.githubusercontent.com/ivmartel/dwv/master";
|
||||
var url = urlRoot + "/tests/dicom/synthetic-data_implicit.json";
|
||||
request.open('GET', url, true);
|
||||
request.onerror = function (event) {
|
||||
console.error(event);
|
||||
};
|
||||
request.onload = function (/*event*/) {
|
||||
var configs = JSON.parse(this.responseText);
|
||||
for (var i = 0; i < configs.length; ++i ) {
|
||||
dwv.utils.test.testConfig(configs[i], assert);
|
||||
}
|
||||
// finish async test
|
||||
done();
|
||||
};
|
||||
request.send(null);
|
||||
});
|
||||
|
||||
QUnit.test("Test synthetic dicom explicit big endian", function (assert) {
|
||||
var done = assert.async();
|
||||
|
||||
// get the list of configs
|
||||
var request = new XMLHttpRequest();
|
||||
var urlRoot = "https://raw.githubusercontent.com/ivmartel/dwv/master";
|
||||
var url = urlRoot + "/tests/dicom/synthetic-data_explicit_big-endian.json";
|
||||
request.open('GET', url, true);
|
||||
request.onerror = function (event) {
|
||||
console.error(event);
|
||||
};
|
||||
request.onload = function (/*event*/) {
|
||||
var configs = JSON.parse(this.responseText);
|
||||
for (var i = 0; i < configs.length; ++i ) {
|
||||
dwv.utils.test.testConfig(configs[i], assert);
|
||||
}
|
||||
// finish async test
|
||||
done();
|
||||
};
|
||||
request.send(null);
|
||||
});
|
||||
192
nv/html/dwv/tests/dicom/generator.html
Normal file
192
nv/html/dwv/tests/dicom/generator.html
Normal file
@@ -0,0 +1,192 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>DICOM Generator</title>
|
||||
<meta charset="UTF-8">
|
||||
<script type="text/javascript" src="../../src/dicom/dicomParser.js"></script>
|
||||
<script type="text/javascript" src="../../src/dicom/dicomWriter.js"></script>
|
||||
<script type="text/javascript" src="../../src/dicom/dictionary.js"></script>
|
||||
<script type="text/javascript">
|
||||
// tags file
|
||||
var _tagsFile = null;
|
||||
// generate DICOM data
|
||||
function generate()
|
||||
{
|
||||
// check validity
|
||||
if (!isValidTags()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get tags from the textarea
|
||||
var tags = JSON.parse(document.getElementById('tags').value);
|
||||
// optional pixel generator (cannot be propagated)
|
||||
var pixelGenerator = "gradSquare";
|
||||
if ( typeof tags.PixelData !== "undefined" ) {
|
||||
pixelGenerator = tags.PixelData;
|
||||
delete tags.PixelData;
|
||||
}
|
||||
// convert JSON to DICOM element object
|
||||
var res = dwv.dicom.getElementsFromJSONTags(tags);
|
||||
var dicomElements = res.elements;
|
||||
// pixels: small gradient square
|
||||
dicomElements.x7FE00010 = null;
|
||||
try {
|
||||
dicomElements.x7FE00010 = dwv.dicom.generatePixelDataFromJSONTags(
|
||||
tags, res.offset, pixelGenerator);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
alert(error.message);
|
||||
}
|
||||
|
||||
// create writer
|
||||
var writer = new dwv.dicom.DicomWriter();
|
||||
var dicomBuffer = null;
|
||||
try {
|
||||
dicomBuffer = writer.getBuffer(dicomElements);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
alert(error.message);
|
||||
}
|
||||
// view as Blob to allow download
|
||||
var blob = new Blob([dicomBuffer], {type: 'application/dicom'});
|
||||
// update generate button
|
||||
var element = document.getElementById("generate");
|
||||
element.download = "dwv-generated.dcm";
|
||||
element.href = URL.createObjectURL(blob);
|
||||
}
|
||||
// save the tags as a JSON file
|
||||
function saveTags()
|
||||
{
|
||||
// check validity
|
||||
if (!isValidTags()) {
|
||||
return;
|
||||
}
|
||||
// get text from the textarea
|
||||
var text = document.getElementById('tags').value;
|
||||
// view as Blob to allow download
|
||||
var blob = new Blob([text], {type:"text/plain"});
|
||||
// update save button
|
||||
var element = document.getElementById("save");
|
||||
console.log(_tagsFile);
|
||||
element.download = (_tagsFile === null ? "tags.json" : _tagsFile.name);
|
||||
element.href = URL.createObjectURL(blob);
|
||||
}
|
||||
// is the JSON valid?
|
||||
function isValidTags()
|
||||
{
|
||||
try {
|
||||
JSON.parse(document.getElementById('tags').value);
|
||||
}
|
||||
catch (error) {
|
||||
alert("The JSON is not valid, please check it with JSONLint.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// open JSONLint to check the tags
|
||||
function launchJSONlint()
|
||||
{
|
||||
var text = document.getElementById('tags').value;
|
||||
var link = "http://jsonlint.com/?json=" + encodeURIComponent(text);
|
||||
window.open(link);
|
||||
}
|
||||
// handle input tags file
|
||||
function onInputTagsFile(event)
|
||||
{
|
||||
if (event.target.files.length === 0) {
|
||||
return;
|
||||
}
|
||||
_tagsFile = event.target.files[0];
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (event) {
|
||||
document.getElementById('tags').value = event.target.result;
|
||||
};
|
||||
reader.readAsText(_tagsFile);
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
body { font-family: Arial, Helvetica, sans-serif; }
|
||||
textarea { width: 99%; margin: 2px; }
|
||||
fieldset { background: whitesmoke; border: 1px solid grey; }
|
||||
.button {
|
||||
padding: 3px 7px 3px 7px;
|
||||
text-align: center;
|
||||
border-radius: 3px;
|
||||
border: 1px solid grey;
|
||||
text-decoration: none;
|
||||
font: 80% sans-serif;
|
||||
color: black;
|
||||
background: #E3E3E3;
|
||||
}
|
||||
.button-active {
|
||||
color: black;
|
||||
background: #E3E3E3;
|
||||
}
|
||||
.button-disabled {
|
||||
color: grey;
|
||||
background: #F3F3F3;
|
||||
}
|
||||
.button:hover {
|
||||
border: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>DWV DICOM Generator</h1>
|
||||
|
||||
<p>Simple DICOM data generator from json tags.
|
||||
Mainly used for generating test data, <b>use at your own risks!</b>
|
||||
<br>No need for a 'FileMetaInformationGroupLength', it is calculated automatically.
|
||||
Values should not be <code>null</code>...
|
||||
<br>Sequences have an optional <code>explicitLength</code> boolean parameter to write them
|
||||
and all their elements with implicit or explicit length. Its default value is <code>true</code>.
|
||||
Set as <code>{}</code>, a sequence will
|
||||
be written with explicit zero length, a <code>0</code> value will mean implicit length.
|
||||
</p>
|
||||
|
||||
<form name="genform">
|
||||
|
||||
<fieldset>
|
||||
<label for="intagsfile">JSON DICOM tags file: </label>
|
||||
<input id="intagsfile" type="file" name="file" onchange="onInputTagsFile(event);">
|
||||
</fieldset>
|
||||
|
||||
<textarea id="tags" rows="25">
|
||||
{
|
||||
"TransferSyntaxUID": "1.2.840.10008.1.2.1",
|
||||
"Modality": "MR",
|
||||
"PatientName": "dwv-patient-name",
|
||||
"PhotometricInterpretation": "MONOCHROME2",
|
||||
"SamplesPerPixel": 1,
|
||||
"PlanarConfiguration": 0,
|
||||
"PixelRepresentation": 0,
|
||||
"Rows": 32,
|
||||
"Columns": 32,
|
||||
"BitsAllocated": 16,
|
||||
"BitsStored": 12,
|
||||
"HighBit": 11,
|
||||
"ReferencedImageSequence": {
|
||||
"explicitLength": true,
|
||||
"item0": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511672669154094"
|
||||
},
|
||||
"item1": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511286933854090"
|
||||
}
|
||||
}
|
||||
}
|
||||
</textarea>
|
||||
|
||||
<fieldset>
|
||||
<a href="#" id="jsonlint" class="button" onclick="launchJSONlint();">JSONLint</a>
|
||||
<a href="#" id="save" class="button" onclick="saveTags();">Save Tags</a>
|
||||
<a href="#" id="generate" class="button" onclick="generate();">Generate</a>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
93
nv/html/dwv/tests/dicom/synthetic-data.html
Normal file
93
nv/html/dwv/tests/dicom/synthetic-data.html
Normal file
@@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>DICOM synthetic data</title>
|
||||
<meta charset="UTF-8">
|
||||
<style>
|
||||
body { font-family: Arial, Helvetica, sans-serif; }
|
||||
</style>
|
||||
<script type="text/javascript" src="../../src/dicom/dicomParser.js"></script>
|
||||
<script type="text/javascript" src="../../src/dicom/dicomWriter.js"></script>
|
||||
<script type="text/javascript" src="../../src/dicom/dictionary.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
// Create an object url from (JSON) tags.
|
||||
function getObjectUrlFromTags(tags) {
|
||||
// convert JSON to DICOM element object
|
||||
var res = dwv.dicom.getElementsFromJSONTags(tags);
|
||||
var dicomElements = res.elements;
|
||||
// pixels: small gradient square
|
||||
dicomElements.x7FE00010 = dwv.dicom.generatePixelDataFromJSONTags(tags, res.offset);
|
||||
|
||||
// create DICOM buffer
|
||||
var writer = new dwv.dicom.DicomWriter();
|
||||
var dicomBuffer = null;
|
||||
try {
|
||||
dicomBuffer = writer.getBuffer(dicomElements);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return;
|
||||
}
|
||||
|
||||
// blob and then url
|
||||
var blob = new Blob([dicomBuffer], {type: 'application/dicom'});
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
|
||||
// create list from configs
|
||||
var getConfigsHtmlList = function (configs) {
|
||||
var ul = document.createElement("ul");
|
||||
for (var i = 0; i < configs.length; ++i ) {
|
||||
// download link
|
||||
var link = document.createElement("a");
|
||||
link.href = getObjectUrlFromTags(configs[i].tags);
|
||||
var fileName = "dwv-generated-" + configs[i].name + ".dcm";
|
||||
link.download = fileName
|
||||
link.appendChild( document.createTextNode( fileName ) );
|
||||
// list element
|
||||
var li = document.createElement("li");
|
||||
li.append(link)
|
||||
li.appendChild( document.createTextNode( ": " + configs[i].description ) );
|
||||
// append to list
|
||||
ul.append(li);
|
||||
}
|
||||
return ul;
|
||||
}
|
||||
|
||||
// get the list of configs and display them with a download link
|
||||
var getFileConfigsHtmlList = function (fileName) {
|
||||
var urlRoot = "https://raw.githubusercontent.com/ivmartel/dwv/master";
|
||||
var url = urlRoot + "/tests/dicom/" + fileName + ".json";
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('GET', url, true);
|
||||
request.onerror = function (event) {
|
||||
console.error(event);
|
||||
};
|
||||
request.onload = function (/*event*/) {
|
||||
var content = document.getElementById("content");
|
||||
var title = document.createElement("h2");
|
||||
title.appendChild( document.createTextNode( fileName ) );
|
||||
content.append(title);
|
||||
var configs = JSON.parse(this.responseText);
|
||||
content.append(getConfigsHtmlList(configs));
|
||||
};
|
||||
request.send(null);
|
||||
}
|
||||
|
||||
// create lists
|
||||
getFileConfigsHtmlList("synthetic-data_explicit");
|
||||
getFileConfigsHtmlList("synthetic-data_implicit");
|
||||
getFileConfigsHtmlList("synthetic-data_explicit_big-endian");
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>DWV DICOM synthetic data</h1>
|
||||
|
||||
<div id="content"></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
193
nv/html/dwv/tests/dicom/synthetic-data_explicit.json
Normal file
193
nv/html/dwv/tests/dicom/synthetic-data_explicit.json
Normal file
@@ -0,0 +1,193 @@
|
||||
[
|
||||
{
|
||||
"name": "test00",
|
||||
"description": "Little Endian Explicit test data.",
|
||||
"tags": {
|
||||
"TransferSyntaxUID": "1.2.840.10008.1.2.1",
|
||||
"Modality": "MR",
|
||||
"PatientName": "dwv-patient-name-00",
|
||||
"PhotometricInterpretation": "MONOCHROME2",
|
||||
"SamplesPerPixel": 1,
|
||||
"PixelRepresentation": 0,
|
||||
"Rows": 32,
|
||||
"Columns": 32,
|
||||
"BitsAllocated": 16,
|
||||
"BitsStored": 12,
|
||||
"HighBit": 11
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "test01",
|
||||
"description": "Little Endian Explicit test data with PixelRepresentation=1.",
|
||||
"tags": {
|
||||
"TransferSyntaxUID": "1.2.840.10008.1.2.1",
|
||||
"Modality": "MR",
|
||||
"PatientName": "dwv-patient-name-01",
|
||||
"PhotometricInterpretation": "MONOCHROME2",
|
||||
"SamplesPerPixel": 1,
|
||||
"PixelRepresentation": 1,
|
||||
"Rows": 32,
|
||||
"Columns": 32,
|
||||
"BitsAllocated": 16,
|
||||
"BitsStored": 12,
|
||||
"HighBit": 11
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "test02",
|
||||
"description": "Little Endian Explicit 8bits RGB test data.",
|
||||
"tags": {
|
||||
"TransferSyntaxUID": "1.2.840.10008.1.2.1",
|
||||
"Modality": "MR",
|
||||
"PatientName": "dwv-patient-name-02",
|
||||
"PhotometricInterpretation": "RGB",
|
||||
"SamplesPerPixel": 3,
|
||||
"PlanarConfiguration": 1,
|
||||
"PixelRepresentation": 0,
|
||||
"Rows": 32,
|
||||
"Columns": 32,
|
||||
"BitsAllocated": 8,
|
||||
"BitsStored": 8,
|
||||
"HighBit": 7
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "test03",
|
||||
"description": "Little Endian Explicit test data with explicit length sequence.",
|
||||
"tags": {
|
||||
"TransferSyntaxUID": "1.2.840.10008.1.2.1",
|
||||
"Modality": "MR",
|
||||
"PatientName": "dwv-patient-name-03",
|
||||
"PhotometricInterpretation": "MONOCHROME2",
|
||||
"SamplesPerPixel": 1,
|
||||
"PixelRepresentation": 0,
|
||||
"Rows": 32,
|
||||
"Columns": 32,
|
||||
"BitsAllocated": 16,
|
||||
"BitsStored": 12,
|
||||
"HighBit": 11,
|
||||
"ReferencedImageSequence": {
|
||||
"explicitLength": true,
|
||||
"item0": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511672669154094"
|
||||
},
|
||||
"item1": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511286933854090"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "test04",
|
||||
"description": "Little Endian Explicit test data with implicit length sequence.",
|
||||
"tags": {
|
||||
"TransferSyntaxUID": "1.2.840.10008.1.2.1",
|
||||
"Modality": "MR",
|
||||
"PatientName": "dwv-patient-name-04",
|
||||
"PhotometricInterpretation": "MONOCHROME2",
|
||||
"SamplesPerPixel": 1,
|
||||
"PixelRepresentation": 0,
|
||||
"Rows": 32,
|
||||
"Columns": 32,
|
||||
"BitsAllocated": 16,
|
||||
"BitsStored": 12,
|
||||
"HighBit": 11,
|
||||
"ReferencedImageSequence": {
|
||||
"explicitLength": false,
|
||||
"item0": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511672669154094"
|
||||
},
|
||||
"item1": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511286933854090"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "test05",
|
||||
"description": "Little Endian Explicit test data with massive sequence.",
|
||||
"tags": {
|
||||
"TransferSyntaxUID": "1.2.840.10008.1.2.1",
|
||||
"Modality": "MR",
|
||||
"PatientName": "dwv-patient-name-05",
|
||||
"PhotometricInterpretation": "MONOCHROME2",
|
||||
"SamplesPerPixel": 1,
|
||||
"PixelRepresentation": 0,
|
||||
"Rows": 32,
|
||||
"Columns": 32,
|
||||
"BitsAllocated": 16,
|
||||
"BitsStored": 12,
|
||||
"HighBit": 11,
|
||||
"ReferencedImageSequence": {
|
||||
"explicitLength": true,
|
||||
"item0": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511672669154094"
|
||||
},
|
||||
"item1": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511286933854090"
|
||||
},
|
||||
"item2": {}
|
||||
},
|
||||
"SourceImageSequence": {
|
||||
"explicitLength": false,
|
||||
"item0": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511672669154094"
|
||||
},
|
||||
"item1": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511286933854090"
|
||||
},
|
||||
"item2": 0
|
||||
},
|
||||
"ReferencedPatientSequence": {},
|
||||
"ReferencedOverlaySequence": 0,
|
||||
"ReferringPhysicianIdentificationSequence": {
|
||||
"explicitLength": true,
|
||||
"item0": {}
|
||||
},
|
||||
"ConsultingPhysicianIdentificationSequence": {
|
||||
"explicitLength": false,
|
||||
"item0": 0
|
||||
},
|
||||
"ReferencedStudySequence": {
|
||||
"explicitLength": true,
|
||||
"item0": {
|
||||
"PurposeOfReferenceCodeSequence": {
|
||||
"item0": {
|
||||
"CodeValue": "123456"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ReferencedSeriesSequence": {
|
||||
"explicitLength": false,
|
||||
"item0": {
|
||||
"PurposeOfReferenceCodeSequence": {
|
||||
"item0": {
|
||||
"CodeValue": "789101"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ReferencedInstanceSequence": {
|
||||
"explicitLength": true,
|
||||
"item0": {
|
||||
"PurposeOfReferenceCodeSequence": {}
|
||||
}
|
||||
},
|
||||
"ReferencedVisitSequence": {
|
||||
"explicitLength": false,
|
||||
"item0": {
|
||||
"PurposeOfReferenceCodeSequence": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
193
nv/html/dwv/tests/dicom/synthetic-data_explicit_big-endian.json
Normal file
193
nv/html/dwv/tests/dicom/synthetic-data_explicit_big-endian.json
Normal file
@@ -0,0 +1,193 @@
|
||||
[
|
||||
{
|
||||
"name": "test20",
|
||||
"description": "Big Endian Explicit test data.",
|
||||
"tags": {
|
||||
"TransferSyntaxUID": "1.2.840.10008.1.2.2",
|
||||
"Modality": "MR",
|
||||
"PatientName": "dwv-patient-name-20",
|
||||
"PhotometricInterpretation": "MONOCHROME2",
|
||||
"SamplesPerPixel": 1,
|
||||
"PixelRepresentation": 0,
|
||||
"Rows": 32,
|
||||
"Columns": 32,
|
||||
"BitsAllocated": 16,
|
||||
"BitsStored": 12,
|
||||
"HighBit": 11
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "test21",
|
||||
"description": "Big Endian Explicit test data with PixelRepresentation=1.",
|
||||
"tags": {
|
||||
"TransferSyntaxUID": "1.2.840.10008.1.2.2",
|
||||
"Modality": "MR",
|
||||
"PatientName": "dwv-patient-name-21",
|
||||
"PhotometricInterpretation": "MONOCHROME2",
|
||||
"SamplesPerPixel": 1,
|
||||
"PixelRepresentation": 1,
|
||||
"Rows": 32,
|
||||
"Columns": 32,
|
||||
"BitsAllocated": 16,
|
||||
"BitsStored": 12,
|
||||
"HighBit": 11
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "test22",
|
||||
"description": "Big Endian Explicit 8bits RGB test data.",
|
||||
"tags": {
|
||||
"TransferSyntaxUID": "1.2.840.10008.1.2.2",
|
||||
"Modality": "MR",
|
||||
"PatientName": "dwv-patient-name-22",
|
||||
"PhotometricInterpretation": "RGB",
|
||||
"SamplesPerPixel": 3,
|
||||
"PlanarConfiguration": 1,
|
||||
"PixelRepresentation": 0,
|
||||
"Rows": 32,
|
||||
"Columns": 32,
|
||||
"BitsAllocated": 8,
|
||||
"BitsStored": 8,
|
||||
"HighBit": 7
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "test23",
|
||||
"description": "Big Endian Explicit test data with explicit length sequence.",
|
||||
"tags": {
|
||||
"TransferSyntaxUID": "1.2.840.10008.1.2.2",
|
||||
"Modality": "MR",
|
||||
"PatientName": "dwv-patient-name-23",
|
||||
"PhotometricInterpretation": "MONOCHROME2",
|
||||
"SamplesPerPixel": 1,
|
||||
"PixelRepresentation": 0,
|
||||
"Rows": 32,
|
||||
"Columns": 32,
|
||||
"BitsAllocated": 16,
|
||||
"BitsStored": 12,
|
||||
"HighBit": 11,
|
||||
"ReferencedImageSequence": {
|
||||
"explicitLength": true,
|
||||
"item0": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511672669154094"
|
||||
},
|
||||
"item1": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511286933854090"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "test24",
|
||||
"description": "Big Endian Explicit test data with implicit length sequence.",
|
||||
"tags": {
|
||||
"TransferSyntaxUID": "1.2.840.10008.1.2.2",
|
||||
"Modality": "MR",
|
||||
"PatientName": "dwv-patient-name-24",
|
||||
"PhotometricInterpretation": "MONOCHROME2",
|
||||
"SamplesPerPixel": 1,
|
||||
"PixelRepresentation": 0,
|
||||
"Rows": 32,
|
||||
"Columns": 32,
|
||||
"BitsAllocated": 16,
|
||||
"BitsStored": 12,
|
||||
"HighBit": 11,
|
||||
"ReferencedImageSequence": {
|
||||
"explicitLength": false,
|
||||
"item0": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511672669154094"
|
||||
},
|
||||
"item1": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511286933854090"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "test25",
|
||||
"description": "Big Endian Explicit test data with massive sequence.",
|
||||
"tags": {
|
||||
"TransferSyntaxUID": "1.2.840.10008.1.2.2",
|
||||
"Modality": "MR",
|
||||
"PatientName": "dwv-patient-name-25",
|
||||
"PhotometricInterpretation": "MONOCHROME2",
|
||||
"SamplesPerPixel": 1,
|
||||
"PixelRepresentation": 0,
|
||||
"Rows": 32,
|
||||
"Columns": 32,
|
||||
"BitsAllocated": 16,
|
||||
"BitsStored": 12,
|
||||
"HighBit": 11,
|
||||
"ReferencedImageSequence": {
|
||||
"explicitLength": true,
|
||||
"item0": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511672669154094"
|
||||
},
|
||||
"item1": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511286933854090"
|
||||
},
|
||||
"item2": {}
|
||||
},
|
||||
"SourceImageSequence": {
|
||||
"explicitLength": false,
|
||||
"item0": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511672669154094"
|
||||
},
|
||||
"item1": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511286933854090"
|
||||
},
|
||||
"item2": 0
|
||||
},
|
||||
"ReferencedPatientSequence": {},
|
||||
"ReferencedOverlaySequence": 0,
|
||||
"ReferringPhysicianIdentificationSequence": {
|
||||
"explicitLength": true,
|
||||
"item0": {}
|
||||
},
|
||||
"ConsultingPhysicianIdentificationSequence": {
|
||||
"explicitLength": false,
|
||||
"item0": 0
|
||||
},
|
||||
"ReferencedStudySequence": {
|
||||
"explicitLength": true,
|
||||
"item0": {
|
||||
"PurposeOfReferenceCodeSequence": {
|
||||
"item0": {
|
||||
"CodeValue": "123456"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ReferencedSeriesSequence": {
|
||||
"explicitLength": false,
|
||||
"item0": {
|
||||
"PurposeOfReferenceCodeSequence": {
|
||||
"item0": {
|
||||
"CodeValue": "789101"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ReferencedInstanceSequence": {
|
||||
"explicitLength": true,
|
||||
"item0": {
|
||||
"PurposeOfReferenceCodeSequence": {}
|
||||
}
|
||||
},
|
||||
"ReferencedVisitSequence": {
|
||||
"explicitLength": false,
|
||||
"item0": {
|
||||
"PurposeOfReferenceCodeSequence": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
193
nv/html/dwv/tests/dicom/synthetic-data_implicit.json
Normal file
193
nv/html/dwv/tests/dicom/synthetic-data_implicit.json
Normal file
@@ -0,0 +1,193 @@
|
||||
[
|
||||
{
|
||||
"name": "test10",
|
||||
"description": "Little Endian Implicit test data.",
|
||||
"tags": {
|
||||
"TransferSyntaxUID": "1.2.840.10008.1.2",
|
||||
"Modality": "MR",
|
||||
"PatientName": "dwv-patient-name-10",
|
||||
"PhotometricInterpretation": "MONOCHROME2",
|
||||
"SamplesPerPixel": 1,
|
||||
"PixelRepresentation": 0,
|
||||
"Rows": 32,
|
||||
"Columns": 32,
|
||||
"BitsAllocated": 16,
|
||||
"BitsStored": 12,
|
||||
"HighBit": 11
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "test11",
|
||||
"description": "Little Endian Implicit test data with PixelRepresentation=1.",
|
||||
"tags": {
|
||||
"TransferSyntaxUID": "1.2.840.10008.1.2",
|
||||
"Modality": "MR",
|
||||
"PatientName": "dwv-patient-name-11",
|
||||
"PhotometricInterpretation": "MONOCHROME2",
|
||||
"SamplesPerPixel": 1,
|
||||
"PixelRepresentation": 1,
|
||||
"Rows": 32,
|
||||
"Columns": 32,
|
||||
"BitsAllocated": 16,
|
||||
"BitsStored": 12,
|
||||
"HighBit": 11
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "test12",
|
||||
"description": "Little Endian Implicit 8bits RGB test data.",
|
||||
"tags": {
|
||||
"TransferSyntaxUID": "1.2.840.10008.1.2",
|
||||
"Modality": "MR",
|
||||
"PatientName": "dwv-patient-name-12",
|
||||
"PhotometricInterpretation": "RGB",
|
||||
"SamplesPerPixel": 3,
|
||||
"PlanarConfiguration": 1,
|
||||
"PixelRepresentation": 0,
|
||||
"Rows": 32,
|
||||
"Columns": 32,
|
||||
"BitsAllocated": 8,
|
||||
"BitsStored": 8,
|
||||
"HighBit": 7
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "test13",
|
||||
"description": "Little Endian Implicit test data with explicit length sequence.",
|
||||
"tags": {
|
||||
"TransferSyntaxUID": "1.2.840.10008.1.2",
|
||||
"Modality": "MR",
|
||||
"PatientName": "dwv-patient-name-13",
|
||||
"PhotometricInterpretation": "MONOCHROME2",
|
||||
"SamplesPerPixel": 1,
|
||||
"PixelRepresentation": 0,
|
||||
"Rows": 32,
|
||||
"Columns": 32,
|
||||
"BitsAllocated": 16,
|
||||
"BitsStored": 12,
|
||||
"HighBit": 11,
|
||||
"ReferencedImageSequence": {
|
||||
"explicitLength": true,
|
||||
"item0": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511672669154094"
|
||||
},
|
||||
"item1": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511286933854090"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "test14",
|
||||
"description": "Little Endian Implicit test data with implicit length sequence.",
|
||||
"tags": {
|
||||
"TransferSyntaxUID": "1.2.840.10008.1.2.1",
|
||||
"Modality": "MR",
|
||||
"PatientName": "dwv-patient-name-14",
|
||||
"PhotometricInterpretation": "MONOCHROME2",
|
||||
"SamplesPerPixel": 1,
|
||||
"PixelRepresentation": 0,
|
||||
"Rows": 32,
|
||||
"Columns": 32,
|
||||
"BitsAllocated": 16,
|
||||
"BitsStored": 12,
|
||||
"HighBit": 11,
|
||||
"ReferencedImageSequence": {
|
||||
"explicitLength": false,
|
||||
"item0": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511672669154094"
|
||||
},
|
||||
"item1": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511286933854090"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "test15",
|
||||
"description": "Little Endian Explicit test data with massive sequence.",
|
||||
"tags": {
|
||||
"TransferSyntaxUID": "1.2.840.10008.1.2.1",
|
||||
"Modality": "MR",
|
||||
"PatientName": "dwv-patient-name-15",
|
||||
"PhotometricInterpretation": "MONOCHROME2",
|
||||
"SamplesPerPixel": 1,
|
||||
"PixelRepresentation": 0,
|
||||
"Rows": 32,
|
||||
"Columns": 32,
|
||||
"BitsAllocated": 16,
|
||||
"BitsStored": 12,
|
||||
"HighBit": 11,
|
||||
"ReferencedImageSequence": {
|
||||
"explicitLength": true,
|
||||
"item0": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511672669154094"
|
||||
},
|
||||
"item1": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511286933854090"
|
||||
},
|
||||
"item2": {}
|
||||
},
|
||||
"SourceImageSequence": {
|
||||
"explicitLength": false,
|
||||
"item0": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511672669154094"
|
||||
},
|
||||
"item1": {
|
||||
"ReferencedSOPClassUID": "1.2.840.10008.5.1.4.1.1.4",
|
||||
"ReferencedSOPInstanceUID": "1.3.12.2.1107.5.2.32.35162.2012021515511286933854090"
|
||||
},
|
||||
"item2": 0
|
||||
},
|
||||
"ReferencedPatientSequence": {},
|
||||
"ReferencedOverlaySequence": 0,
|
||||
"ReferringPhysicianIdentificationSequence": {
|
||||
"explicitLength": true,
|
||||
"item0": {}
|
||||
},
|
||||
"ConsultingPhysicianIdentificationSequence": {
|
||||
"explicitLength": false,
|
||||
"item0": 0
|
||||
},
|
||||
"ReferencedStudySequence": {
|
||||
"explicitLength": true,
|
||||
"item0": {
|
||||
"PurposeOfReferenceCodeSequence": {
|
||||
"item0": {
|
||||
"CodeValue": "123456"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ReferencedSeriesSequence": {
|
||||
"explicitLength": false,
|
||||
"item0": {
|
||||
"PurposeOfReferenceCodeSequence": {
|
||||
"item0": {
|
||||
"CodeValue": "789101"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ReferencedInstanceSequence": {
|
||||
"explicitLength": true,
|
||||
"item0": {
|
||||
"PurposeOfReferenceCodeSequence": {}
|
||||
}
|
||||
},
|
||||
"ReferencedVisitSequence": {
|
||||
"explicitLength": false,
|
||||
"item0": {
|
||||
"PurposeOfReferenceCodeSequence": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user