Skip to content
9 changes: 7 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,10 @@ node_modules/

# VS Code
*.code-workspace
*~
*.swp

# Root commands
*.cmd

# vim files
**/*~
**/*.swp
46 changes: 23 additions & 23 deletions packages/static-wado-creator/lib/StaticWado.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ async function cs3dThumbnail(
dataset,
metadata,
transferSyntaxUid,
doneCallback
doneCallback,
) {
if (!originalImageFrame) {
throw new Error(`No originalImageFrame data available`);
}
if (!dataset && !metadata) {
throw new Error(
`Neither dataset ${!!dataset} nor metadata ${!!metadata} available.`
`Neither dataset ${!!dataset} nor metadata ${!!metadata} available.`,
);
}
if (isVideo(transferSyntaxUid)) {
Expand All @@ -74,7 +74,7 @@ async function cs3dThumbnail(
originalImageFrame,
dataset,
metadata,
transferSyntaxUid
transferSyntaxUid,
);
} catch (error) {
console.log("Error while decoding image:", error);
Expand All @@ -90,13 +90,13 @@ async function cs3dThumbnail(
const pixelData = dicomCodec.getPixelData(
imageFrame,
imageInfo,
transferSyntaxUid
transferSyntaxUid,
);
return staticCS.getRenderedBuffer(
transferSyntaxUid,
pixelData,
metadata,
doneCallback
doneCallback,
);
}

Expand Down Expand Up @@ -146,7 +146,7 @@ class StaticWado {
setStudyData,
rawDicomWriter: RawDicomWriter(this.options),
notificationService: new NotificationService(
this.options.notificationDir
this.options.notificationDir,
),
internalGenerateImage: cs3dThumbnail,
};
Expand Down Expand Up @@ -184,13 +184,13 @@ class StaticWado {
if (!this.showProgress) return;
this.processedFiles++;
const percentage = Math.round(
(this.processedFiles / this.totalFiles) * 100
(this.processedFiles / this.totalFiles) * 100,
);
const progressBar =
"=".repeat(Math.floor(percentage / 4)) +
"-".repeat(25 - Math.floor(percentage / 4));
process.stdout.write(
`\r[${progressBar}] ${percentage}% | ${this.processedFiles}/${this.totalFiles} files`
`\r[${progressBar}] ${percentage}% | ${this.processedFiles}/${this.totalFiles} files`,
);
}

Expand All @@ -202,7 +202,7 @@ class StaticWado {
if (fs.statSync(file).isDirectory()) {
const dirFiles = fs.readdirSync(file, { recursive: true });
this.totalFiles += dirFiles.filter(
(f) => !fs.statSync(path.join(file, f)).isDirectory()
(f) => !fs.statSync(path.join(file, f)).isDirectory(),
).length;
} else {
this.totalFiles++;
Expand All @@ -215,7 +215,7 @@ class StaticWado {
{ FailureReason: 0xd000, TextValue: "File not DICOM" },
],
},
file
file,
);
}
}
Expand Down Expand Up @@ -297,13 +297,13 @@ class StaticWado {
sopInstanceUid: dataSet.string("x00080018"),
transferSyntaxUid: dataSet.string("x00020010"),
},
params.file
params.file,
);

const targetId = transcodeId(
id,
this.options,
dataSet.uint16(Tags.RawSamplesPerPixel)
dataSet.uint16(Tags.RawSamplesPerPixel),
);

let bulkDataIndex = 0;
Expand All @@ -323,7 +323,7 @@ class StaticWado {
{
gzip: false,
mkdir: true,
}
},
);
await writeStream.write(bulkData);
await writeStream.close();
Expand All @@ -332,7 +332,7 @@ class StaticWado {
targetId,
_bulkDataIndex,
bulkData,
options
options,
);
},
imageFrame: async (originalImageFrame) => {
Expand All @@ -345,7 +345,7 @@ class StaticWado {
targetId,
originalImageFrame,
dataSet,
this.options
this.options,
);

const lossyImage = await generateLossyImage(id, decoded, this.options);
Expand All @@ -357,7 +357,7 @@ class StaticWado {
await this.callback.imageFrame(
lossyImage.id,
currentImageFrameIndex,
lossyImage.imageFrame
lossyImage.imageFrame,
);
}

Expand All @@ -369,13 +369,13 @@ class StaticWado {
id,
frameIndex: currentImageFrameIndex,
},
this.options
this.options,
);

return this.callback.imageFrame(
transcodedId,
currentImageFrameIndex,
transcodedImageFrame
transcodedImageFrame,
);
},
videoWriter: async (_dataSet) => this.callback.videoWriter(id, _dataSet),
Expand All @@ -394,14 +394,14 @@ class StaticWado {
dataSet,
transcodedMeta,
this.callback,
this.options
this.options,
);
await thumbnailService.generateRendered(
id,
dataSet,
transcodedMeta,
this.callback,
this.options
this.options,
);
await this.callback.metadata(targetId, transcodedMeta);

Expand All @@ -418,14 +418,14 @@ class StaticWado {
dataSet,
metadata,
transferSyntaxUid,
doneCallback
doneCallback,
) {
return cs3dThumbnail(
originalImageFrame,
dataSet,
metadata,
transferSyntaxUid,
doneCallback
doneCallback,
);
}

Expand Down Expand Up @@ -464,7 +464,7 @@ class StaticWado {
const study = await JSONReader(
`${studiesDir}/${dir}`,
"index.json.gz",
null
null,
);
if (study === null) {
console.log("No study found in", dir);
Expand Down
2 changes: 1 addition & 1 deletion packages/static-wado-creator/lib/createPart10.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const createFmi = (instance) => {
UncompressedLEIExplicit;
const MediaStorageSOPClassUID = Tags.getValue(
instance,
Tags.MediaStorageSOPClassUID
Tags.MediaStorageSOPClassUID,
);
const SOPInstanceUID = Tags.getValue(instance, Tags.SOPInstanceUID);
const naturalFmi = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,83 +1,23 @@
const {
import {
Tags,
readBulkData,
handleHomeRelative,
} = require("@radicalimaging/static-wado-util");
const dcmjs = require("dcmjs");
readBulkDataValue,
readAllBulkData,
} from "@radicalimaging/static-wado-util";
import dcmjs from "dcmjs";

const StaticWado = require("./StaticWado");
const adaptProgramOpts = require("./util/adaptProgramOpts");
const WriteStream = require("./writer/WriteStream");
import StaticWado from "./StaticWado";
import adaptProgramOpts from "./util/adaptProgramOpts";
import WriteStream from "./writer/WriteStream";

const UncompressedLEIExplicit = "1.2.840.10008.1.2.1";
const { DicomDict, DicomMetaDictionary } = dcmjs.data;

const fileMetaInformationVersionArray = new Uint8Array(2);
fileMetaInformationVersionArray[1] = 1;

const readBulkDataValue = async (studyDir, instance, value, options) => {
const { BulkDataURI } = value;
value.vr = "OB";
const seriesUid = Tags.getValue(instance, Tags.SeriesInstanceUID);
const numberOfFrames = Tags.getValue(instance, Tags.NumberOfFrames) || 1;
if (BulkDataURI.indexOf("/frames") !== -1) {
const seriesDir = `${studyDir}/series/${seriesUid}`;
if (options?.frame === false) {
return;
}
// Really only support a limited number of frames based on memory size
value.Value = [];
if (typeof options?.frame === "number") {
console.noQuiet("Reading frame", options.frame);
const bulk = await readBulkData(seriesDir, BulkDataURI, options.frame);
if (!bulk) {
return;
}
value.Value[options.frame - 1] = bulk.binaryData;
value.transferSyntaxUid = bulk.transferSyntaxUid;
value.contentType = bulk.contentType;
return;
}
console.noQuiet("Reading frames", 1, "...", numberOfFrames);
for (let frame = 1; frame <= numberOfFrames; frame++) {
const bulk = await readBulkData(seriesDir, BulkDataURI, frame);
if (!bulk) break;
value.Value.push(bulk.binaryData);
value.transferSyntaxUid = bulk.transferSyntaxUid;
value.contentType = bulk.contentType;
}
} else {
const bulk = await readBulkData(studyDir, BulkDataURI);
value.Value = [new ArrayBuffer(bulk.binaryData)];
value.contentType = bulk.contentType;
}
};

const readBinaryData = async (dir, instance, options = { frame: true }) => {
for (const tag of Object.keys(instance)) {
const v = instance[tag];
if (v.BulkDataURI) {
await readBulkDataValue(dir, instance, v, options);
continue;
}
if (!v.vr) {
const value0 = v.Value?.[0];
if (typeof value0 === "string") {
v.vr = "LT";
} else {
console.log("Deleting", tag, v.Value, v);
delete instance[tag];
}
continue;
}
if (v.vr === "SQ" && v.Values?.length) {
await Promise.all(v.Values.map(readBinaryData));
continue;
}
}
};

module.exports = async function createThumbnail(options, program) {
export async function createThumbnail(options, program) {
const finalOptions = adaptProgramOpts(options, {
...this,
// Instance metadata is the instances/<sopUID>/metadata.gz files
Expand Down Expand Up @@ -141,7 +81,7 @@ module.exports = async function createThumbnail(options, program) {
continue;
}

await readBinaryData(dir, instance, codecOptions);
await readAllBulkData(dir, instance, codecOptions);

const availableTransferSyntaxUID = Tags.getValue(
instance,
Expand Down Expand Up @@ -178,4 +118,6 @@ module.exports = async function createThumbnail(options, program) {
}
}
await Promise.all(promises);
};
}

export default createThumbnail;
9 changes: 8 additions & 1 deletion packages/static-wado-creator/lib/mkdicomwebConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ const ConfigPoint = require("config-point");
const { staticWadoConfig } = require("@radicalimaging/static-wado-util");
const createMain = require("./createMain");
const createPart10 = require("./createPart10");
const createThumbnail = require("./createThumbnail");
const { createThumbnail } = require("./createThumbnail");
const { transcodeImages } = require("./transcodeImages");
const deleteMain = require("./deleteMain");
const rejectMain = require("./rejectMain");
const serverMain = require("./serverMain");
Expand Down Expand Up @@ -305,6 +306,12 @@ const { mkdicomwebConfig } = ConfigPoint.register({
},
],
},
{
command: "transcode",
main: transcodeImages,
helpDescription:
"Transcode images or create alternate representations for the specified study",
},
{
command: "instance",
arguments: ["input"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ async function deduplicateSingleInstance(id, imageFrame, { force }) {
deduplicated,
key,
this.extractors[key],
TagLists.RemoveExtract
TagLists.RemoveExtract,
);
const hashKey = getValue(extracted, Tags.DeduppedHash);
await studyData.addExtracted(this, hashKey, extracted);
Expand Down Expand Up @@ -99,7 +99,7 @@ const InstanceDeduplicate = (options) =>
const deduppedInstance = await this.deduplicateSingleInstance(
id,
imageFrame,
options
options,
);
if (deduppedInstance) {
// this refers to callee
Expand Down
4 changes: 2 additions & 2 deletions packages/static-wado-creator/lib/operation/ScanStudy.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ function ScanStudy(options) {
const deduplicatedInstancesPath = path.join(
deduplicatedInstancesRoot,
// studyInstanceUid,
studySubDir
studySubDir,
);
const deduplicatedPath = path.join(deduplicatedRoot, studySubDir);
console.verbose(
"Importing",
studyInstanceUid,
studyPath,
deduplicatedInstancesPath,
deduplicatedPath
deduplicatedPath,
);
return this.completeStudy.getCurrentStudyData(this, {
studyPath,
Expand Down
Loading