Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Private Dictionary support with Private Creator. #9

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,41 @@
}
},
"additionalProperties": false
},
"dicom.privateDictionary": {
"description": "The list of private creator and private tags information. Key is private creator. value is object of DICOM tags. but style is ODDS00XX",
"type": "object",
"patternProperties": {
".*": {
"description": "The list of private DICOM tags that will be used along with private tags. Each key must be an 8-digit uppercase hex string representing the DICOM group/element. but style is ODDS00XX",
"type": "object",
"patternProperties": {
"^[0-9A-F]{8}$": {
"type": "object",
"properties": {
"vr": {
"description": "Value representation name, such as 'SL'.",
"type": "string",
"pattern": "^[A-Z]{2}$"
},
"name": {
"description": "Element name (camelCase recommended).",
"type": "string"
},
"forceVr": {
"description": "Force this VR type for this element. Use with care.",
"type": "boolean"
}
},
"required": [
"vr",
"name"
]
}
}
}
},
"additionalProperties": false
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/contentProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as parser from 'dicom-parser';
import { standardDataElements, DicomDataElements } from 'dicom-data-dictionary';
import { EncConverter, createEncConverter } from './encConverter';
import { buildTreeFromDataSet, ParsedElement } from './extractor';
import { PrivateTagDict } from "./privateTagDict";

/**
* Transforms the parsed elements into indented text.
Expand Down Expand Up @@ -62,6 +63,7 @@ export default class DicomContentProvider
const config = vscode.workspace.getConfiguration('dicom');
const additionalDict: DicomDataElements = config.get('dictionary') || {};
const dictionary = Object.assign({}, standardDataElements, additionalDict);
const privateDictionary: PrivateTagDict = config.get('privateDictionary') || {};
const showPrivateTags = !!config.get('showPrivateTags');

if (!(uri instanceof vscode.Uri)) return '';
Expand Down Expand Up @@ -92,6 +94,7 @@ export default class DicomContentProvider
rootDataSet,
showPrivateTags,
dictionary,
privateDictionary,
encConverter
});

Expand Down
50 changes: 47 additions & 3 deletions src/extractor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { DataSet } from 'dicom-parser';
import { DataSet, Element } from 'dicom-parser';
import { DicomDataElements, TagInfo } from 'dicom-data-dictionary';
import { EncConverter } from './encConverter';
import { PrivateTagDict } from './privateTagDict';

export interface ParsedElement {
tag: string; // like '(0008,0060)'
Expand Down Expand Up @@ -160,6 +161,44 @@ function findTagInfo(
return undefined;
}

function findTagInfoPrivate(
dictionary: PrivateTagDict,
privateCreatorTable: any,
dataSet: DataSet,
element: Element,
encConverter: EncConverter
): (TagInfo & { forceVr?: string }) | undefined {

const tag = element.tag;
const privateCreatorLow = tag.substring(5, 7);

if (privateCreatorLow === '00') {
const bin = Buffer.from(
dataSet.byteArray.buffer,
element.dataOffset,
element.length
);
const privateCreator = encConverter(bin, 'LO');
privateCreatorTable[tag] = privateCreator.trim();
return { name: 'PrivateCreator', vr: 'LO' };
}

const privateCreatorKey = 'x' + tag.substring(1, 5) + '00' + privateCreatorLow;
if (privateCreatorKey in privateCreatorTable) {
const privateCreator = privateCreatorTable[privateCreatorKey];

if (privateCreator in dictionary) {
const privateKey = tag.substring(1, 5) + '00' + tag.substring(7, 9);
const privateDictionary = dictionary[privateCreator];

if (privateDictionary !== undefined && privateKey in privateDictionary) {
return privateDictionary[privateKey];
}
}
}
return { name: privateCreatorKey, vr: 'LO' };
}

/**
* Iterates of DICOM dataSet from dicom-parser and creates a
* human-readable tree, which then can be transformed into a text document.
Expand All @@ -172,10 +211,12 @@ export function buildTreeFromDataSet(
rootDataSet: DataSet;
showPrivateTags: boolean;
dictionary: DicomDataElements;
privateDictionary: PrivateTagDict;
encConverter: EncConverter;
}
): ParsedElement[] {
const { rootDataSet, showPrivateTags, dictionary, encConverter } = deps;
const { rootDataSet, showPrivateTags, dictionary, privateDictionary, encConverter } = deps;
const privateCreatorTable = {};
const entries: ParsedElement[] = [];
const keys = Object.keys(dataSet.elements).sort();
for (const key of keys) {
Expand All @@ -188,7 +229,10 @@ export function buildTreeFromDataSet(
// "Item delimitation" tag in a sequence
if (key === 'xfffee00d') continue;

const tagInfo = findTagInfo(dictionary, element.tag);
const tagInfo = isPrivateTag
? findTagInfoPrivate(privateDictionary, privateCreatorTable, dataSet, element, encConverter)
: findTagInfo(dictionary, element.tag);

const vr: string =
(tagInfo && tagInfo.forceVr && tagInfo.vr) ||
element.vr ||
Expand Down
6 changes: 6 additions & 0 deletions src/privateTagDict.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { DicomDataElements } from 'dicom-data-dictionary';

export interface PrivateTagDict {

[privateCreator: string]: DicomDataElements | undefined;
}