diff --git a/CT/dicominfo2.m b/CT/dicominfo2.m deleted file mode 100644 index 70b8a64..0000000 --- a/CT/dicominfo2.m +++ /dev/null @@ -1,712 +0,0 @@ -function metadata = dicominfo2(filename, varargin) -%DICOMINFO Read metadata from DICOM message. -% INFO = DICOMINFO(FILENAME) reads the metadata from the compliant -% DICOM file specified in the string FILENAME. -% -% INFO = DICOMINFO(FILENAME, 'dictionary', D) uses the data dictionary -% file given in the string D to read the DICOM message. The file in D -% must be on the MATLAB search path. The default value is dicom-dict.mat. -% -% Example: -% -% info = dicominfo('CT-MONO2-16-ankle.dcm'); -% -% See also DICOMREAD, DICOMWRITE, DICOMDISP, DICOMDICT, DICOMUID. - -% Copyright 1993-2014 The MathWorks, Inc. -% MODIFIED by Raphaël Obrist (line 54) - - -% Parse input arguments. -if (nargin < 1) - - error(message('images:dicominfo:tooFewInputs')) - -end - -% Set the dictionary. -args = parseInputs(varargin{:}); -dicomdict('set_current', args.Dictionary) -dictionary = dicomdict('get_current'); - -% Get the metadata. -try - - % Get details about the file to read. - fileDetails = getFileDetails(filename); - - % Ensure the file is actually DICOM. - if (~isdicom(fileDetails.name)) - error(message('images:dicominfo:notDICOM')) - end - - % Parse the DICOM file. - attrs = dicomparse(fileDetails.name, ... - fileDetails.bytes, ... - getMachineEndian, ... - false, ... - dictionary); - - % Process the raw attributes. - [metadata,attrNames] = processMetadata(attrs, true, dictionary); - metadata = dicom_set_imfinfo_values(metadata); - metadata = setMoreImfinfoValues(metadata, fileDetails); - %metadata = processOverlays(metadata, dictionary); - metadata = processCurveData(metadata, attrs, attrNames); - - pixelDataField = dicomlookup_actions('7fe0', '0010', dictionary); - if (isfield(metadata, pixelDataField)) - metadata = rmfield(metadata, pixelDataField); - end - -catch ME - - dicomdict('reset_current'); - rethrow(ME) - -end - -% Reset the dictionary. -dicomdict('reset_current'); - - - -function [metadata,attrNames] = processMetadata(attrs, isTopLevel, dictionary) - -if (isempty(attrs)) - metadata = []; - return -end - -% Create a structure for the output and get the names of attributes. -[metadata, attrNames] = createMetadataStruct(attrs, isTopLevel, dictionary); - -% Fill the metadata structure, converting data along the way. -for currentAttr = 1:numel(attrNames) - - this = attrs(currentAttr); - metadata.(attrNames{currentAttr}) = convertRawAttr(this, dictionary); - -end - - - -function processedAttr = convertRawAttr(rawAttr, dictionary) - -% Information about whether to swap is contained in the attribute. -swap = needToSwap(rawAttr); - -% Determine the correct output encoding. -if (isempty(rawAttr.VR)) - - % Look up VR for implicit VR files. Use 'UN' for unknown - % tags. (See PS 3.5 Sec. 6.2.2.) - vr = findVRFromTag(rawAttr.Group, rawAttr.Element, dictionary); - if (~isempty(vr)) - - % Some attributes have a conditional VR. Pick the first. - rawAttr.VR = vr; - if (numel(rawAttr.VR) > 2) - rawAttr.VR = rawAttr.VR(1:2); - end - - else - rawAttr.VR = 'UN'; - end - -end - -% Convert raw data. (See PS 3.5 Sec. 6.2 for full VR details.) -switch (rawAttr.VR) -case {'AE','AS','CS','DA','DT','LO','LT','SH','ST','TM','UI','UT'} - - processedAttr = deblankAndStripNulls(char(rawAttr.Data)); - -case {'AT'} - - % For historical reasons don't transpose AT. - processedAttr = dicom_typecast(rawAttr.Data, 'uint16', swap); - -case {'DS', 'IS'} - - processedAttr = sscanf(char(rawAttr.Data), '%f\\'); - -case {'FL', 'OF'} - - processedAttr = dicom_typecast(rawAttr.Data, 'single', swap)'; - -case 'FD' - - processedAttr = dicom_typecast(rawAttr.Data, 'double', swap)'; - -case 'OB' - - processedAttr = rawAttr.Data'; - -case {'OW', 'US'} - - processedAttr = dicom_typecast(rawAttr.Data, 'uint16', swap)'; - -case 'PN' - - processedAttr = parsePerson(deblankAndStripNulls(char(rawAttr.Data))); - -case 'SL' - - processedAttr = dicom_typecast(rawAttr.Data, 'int32', swap)'; - -case 'SQ' - - processedAttr = parseSequence(rawAttr.Data, dictionary); - -case 'SS' - - processedAttr = dicom_typecast(rawAttr.Data, 'int16', swap)'; - -case 'UL' - - processedAttr = dicom_typecast(rawAttr.Data, 'uint32', swap)'; - -case 'UN' - - % It's possible that the attribute contains a private sequence - % with implicit VR; in which case the Data field contains the - % parsed sequence. - if (isstruct(rawAttr.Data)) - processedAttr = parseSequence(rawAttr.Data, dictionary); - else - processedAttr = rawAttr.Data'; - end - -otherwise - - % PS 3.5-1999 Sec. 6.2 indicates that all unknown VRs can be - % interpretted as UN. - processedAttr = rawAttr.Data'; - -end - -% Change empty arrays to 0-by-0. -if isempty(processedAttr) - processedAttr = reshape(processedAttr, [0 0]); -end - - - -function byteOrder = getMachineEndian - -persistent endian - -if (~isempty(endian)) - byteOrder = endian; - return -end - -[~, ~, endian] = computer; -byteOrder = endian; - - - -function args = parseInputs(varargin) - -% Set default values -args.Dictionary = dicomdict('get'); - -% Parse arguments based on their number. -if (nargin > 1) - - paramStrings = {'dictionary'}; - - % For each pair - for k = 1:2:length(varargin) - param = lower(varargin{k}); - - - if (~ischar(param)) - error(message('images:dicominfo:parameterNameNotString')); - end - - idx = strmatch(param, paramStrings); - - if (isempty(idx)) - error(message('images:dicominfo:unrecognizedParameterName', param)); - elseif (length(idx) > 1) - error(message('images:dicominfo:ambiguousParameterName', param)); - end - - switch (paramStrings{idx}) - case 'dictionary' - - if (k == length(varargin)) - error(message('images:dicominfo:missingDictionary')); - else - args.Dictionary = varargin{k + 1}; - end - - end % switch - - end % for - -end - - - -function personName = parsePerson(personString) -%PARSEPERSON Get the various parts of a person name - -% A description and examples of PN values is in PS 3.5-2000 Table 6.2-1. - -pnParts = {'FamilyName' - 'GivenName' - 'MiddleName' - 'NamePrefix' - 'NameSuffix'}; - -if (isempty(personString)) - personName = makePerson(pnParts); - return -end - -people = tokenize(personString, '\\'); % Must quote '\' for calls to STRREAD. - -personName = struct([]); - -for p = 1:length(people) - - % ASCII, ideographic, and phonetic characters are separated by '='. - components = tokenize(people{p}, '='); - - if (isempty(components)) - personName = makePerson(pnParts); - return - end - - - % Only use ASCII parts. - - if (~isempty(components{1})) - - % Get the separate parts of the person's name from the component. - componentParts = tokenize(components{1}, '^'); - - % The DICOM standard requires that PN values have five or fewer - % values separated by "^". Some vendors produce files with more - % than these person name parts. - if (numel(componentParts) <= 5) - - % If there are the correct numbers, put them in separate fields. - for q = 1:length(componentParts) - - personName(p).(pnParts{q}) = componentParts{q}; - - end - - else - - % If there are more, just return the whole string. - personName(p).FamilyName = people{p}; - - end - - else - - % Use full string as value if no ASCII is present. - if (~isempty(components)) - personName(p).FamilyName = people{p}; - end - - end - -end - - - -function personStruct = makePerson(pnParts) -%MAKEPERSON Make an empty struct containing the PN fields. - -for p = 1:numel(pnParts) - personStruct.(pnParts{p}) = ''; -end - - - -function processedStruct = parseSequence(attrs, dictionary) - -numItems = countItems(attrs); -itemNames = getItemNames(numItems); - -% Initialize the structure to contain this structure. -structInitializer = cat(1, itemNames, cell(1, numItems)); -processedStruct = struct(structInitializer{:}); - -% Process each item (but not delimiters). -item = 0; -for idx = 1:numel(attrs) - - this = attrs(idx); - if (~isDelimiter(this)) - item = item + 1; - processedStruct.(itemNames{item}) = processMetadata(this.Data, false, dictionary); - end - -end - - - -function header = getImfinfoFields - -header = {'Filename', '' - 'FileModDate', '' - 'FileSize', [] - 'Format', 'DICOM' - 'FormatVersion', 3.0 - 'Width', [] - 'Height', [] - 'BitDepth', [] - 'ColorType', ''}'; - - - -function metadata = setMoreImfinfoValues(metadata, d) - -metadata.Filename = d.name; -metadata.FileModDate = d.date; -metadata.FileSize = d.bytes; - - - -function details = getFileDetails(filename) - -% Get the fully qualified path to the file. -fid = fopen(filename); -if (fid > 0) - - fullPathFilename = fopen(fid); - fclose(fid); - -else - - % Look for the file with a different extension. - file = dicom_create_file_struct; - file.Filename = filename; - file = dicom_get_msg(file); - - if (isempty(file.Filename)) - error(message('images:dicominfo:noFileOrMessagesFound', filename)); - end - - % dicom_get_msg looks up the fully qualified path. - fullPathFilename = file.Filename; - -end - -details = dir(fullPathFilename); -details.name = fullPathFilename; - - - -function [metadata, attrNames] = createMetadataStruct(attrs, isTopLevel, dictionary) - -% Get the attribute names. -totalAttrs = numel(attrs); -attrNames = cell(1, totalAttrs); - -for currentAttr = 1:totalAttrs - attrNames{currentAttr} = ... - dicomlookup_actions(attrs(currentAttr).Group, ... - attrs(currentAttr).Element, ... - dictionary); - - % Empty attributes indicate that a public/retired attribute was - % not found in the data dictionary. This used to be an error - % condition, but is easily resolved by providing a special - % attribute name. - if (isempty(attrNames{currentAttr})) - attrNames{currentAttr} = sprintf('Unknown_%04X_%04X', ... - attrs(currentAttr).Group, ... - attrs(currentAttr).Element); - end -end - -% Remove duplicate attribute names. Keep the last appearance of the attribute. -[tmp, reorderIdx] = unique(attrNames); -if (numel(tmp) ~= totalAttrs) - warning(message('images:dicominfo:attrWithSameName')) -end - -uniqueAttrNames = attrNames(sort(reorderIdx)); -uniqueTotalAttrs = numel(uniqueAttrNames); - -% Create a metadata structure to hold the parsed attributes. Use a -% cell array initializer, which has a populated section for IMFINFO -% data and an unitialized section for the attributes from the DICOM -% file. -if (isTopLevel) - structInitializer = cat(2, getImfinfoFields(), ... - cat(1, uniqueAttrNames, cell(1, uniqueTotalAttrs))); -else - structInitializer = cat(1, uniqueAttrNames, cell(1, uniqueTotalAttrs)); -end - -metadata = struct(structInitializer{:}); - - - -function str = deblankAndStripNulls(str) -%DEBLANKANDDENULL Deblank a string, treating char(0) as a blank. - -if (isempty(str)) - return -end - -while (~isempty(str) && (str(end) == 0)) - str(end) = ''; -end - -str = deblank(str); - - - -function vr = findVRFromTag(group, element, dictionary) - -% Look up the attribute. -attr = dicomlookup_helper(group, element, dictionary); - -% Get the vr. -if (~isempty(attr)) - - vr = attr.VR; - -else - - % Private creator attributes should be treated as CS. - if ((rem(group, 2) == 1) && (element == 0)) - vr = 'UL'; - elseif ((rem(group, 2) == 1) && (element < 256)) - vr = 'CS'; - else - vr = 'UN'; - end - -end - - - -function out = processOverlays(in, dictionary) - -out = in; - -% Look for overlays. -allFields = fieldnames(in); -idx = strmatch('OverlayData', allFields); - -if (isempty(idx)) - return -end - -% Convert each overlay data attribute. -for p = 1:numel(idx) - - olName = allFields{idx(p)}; - - % The overlay fields can be present but empty. - if (isempty(in.(olName))) - continue; - end - - % Which repeating group is this? - [group, element] = dicomlookup_actions(olName, dictionary); - - % Get relevant details. All overlays are in groups 6000 - 60FE. - overlay.Rows = double(in.(dicomlookup_actions(group, '0010', dictionary))); - overlay.Columns = double(in.(dicomlookup_actions(group, '0011', dictionary))); - - sppTag = dicomlookup_actions(group, '0012', dictionary); - if (isfield(in, sppTag)) - overlay.SamplesPerPixel = double(in.(sppTag)); - else - overlay.SamplesPerPixel = 1; - end - - bitsTag = dicomlookup_actions(group, '0100', dictionary); - if (isfield(in, bitsTag)) - overlay.BitsAllocated = double(in.(bitsTag)); - else - overlay.BitsAllocated = 1; - end - - numTag = dicomlookup_actions(group, '0015', dictionary); - if (isfield(in, numTag)) - overlay.NumberOfFrames = double(in.(numTag)); - else - overlay.NumberOfFrames = 1; - end - - % We could potential support more overlays later. - if ((overlay.BitsAllocated > 1) || (overlay.SamplesPerPixel > 1)) - - warning(message('images:dicominfo:unsupportedOverlay', sprintf( '(%04X,%04X)', group, element ))); - continue; - - end - - % Process the overlay. - for frame = 1:(overlay.NumberOfFrames) - - overlayData = tobits(in.(olName)); - numSamples = overlay.Columns * overlay.Rows * overlay.NumberOfFrames; - out.(olName) = permute(reshape(overlayData(1:numSamples), ... - overlay.Columns, ... - overlay.Rows, ... - overlay.NumberOfFrames), ... - [2 1 3]); - - end - -end - - - -function out = processCurveData(in, attrs, attrNames) -% Reference - PS 3.3 - 2003 C 10.2. The Curve Data's final data type -% depends on DataValueRepresentation. Process those attributes here. - -% Passing in attrs because we may need to swap the data depending on the -% endianness of the machine and the attribute. - -% default -out = in; - -% Look for Curve Data. -allFields = fieldnames(in); -idx = strmatch('CurveData', allFields); - -if (isempty(idx)) - return -end - -% All the Curve Data attributes will have the same endianness, so we just need -% to check one attribute and apply that setting to the rest. - -curveDataName = allFields{idx(1)}; -curveDataLoc = strncmp(curveDataName,attrNames, length(curveDataName)); -swap = needToSwap(attrs(curveDataLoc)); - -for p = 1 : numel(idx) - - curveDataName = allFields{idx(p)}; - - underscore = strfind(curveDataName,'_'); - % The data type of the Curve Data comes from the - % DataValueRepresentation attribute. - numOfRepeatedAttr = curveDataName(underscore+1:end); - dvrName = strcat('DataValueRepresentation','_',numOfRepeatedAttr); - - if ~isfield(in,dvrName) - % do nothing - continue; - else - - dataType = in.(dvrName); - % See PS 3.3-2003, C 10.2.1.2 - switch dataType - case 0 - expDataType = 'uint16'; - case 1 - expDataType = 'int16'; - case 2 - expDataType = 'single'; - case 3 - expDataType = 'double'; - case 4 - expDataType = 'int32'; - otherwise - warning(message('images:dicominfo:unknownDataType', dataType)); - end - - % We need to undo any previous swapping before calling typecast, and do the - % final swapping afterwards. - - if swap - out.(curveDataName) = ... - swapbytes(typecast(swapbytes(in.(curveDataName)), ... - expDataType)); - else - out.(curveDataName) = typecast(in.(curveDataName), expDataType); - end - end -end - - - -function itemNames = getItemNames(numberOfItems) - -% Create a cell array of item names, which can be quickly used. -persistent namesCell -if (isempty(namesCell)) - namesCell = generateItemNames(50); -end - -% If the number of cached names is too small, expand it and recache. -if (numberOfItems > numel(namesCell)) - namesCell = generateItemNames(numberOfItems); -end - -% Return the first n item names. -itemNames = namesCell(1:numberOfItems); - - - -function namesCell = generateItemNames(numberOfItems) - -namesCell = cell(1, numberOfItems); -for idx = 1:numberOfItems - namesCell{idx} = sprintf('Item_%d', idx); -end - - - -function tf = needToSwap(currentAttr) - -switch (getMachineEndian) -case 'L' - if (currentAttr.IsLittleEndian) - tf = false; - else - tf = true; - end - -case 'B' - if (currentAttr.IsLittleEndian) - tf = true; - else - tf = false; - end - -otherwise - error(message('images:dicominfo:unknownEndian', getMachineEndian)) - -end - - - -function tf = isDelimiter(attr) - -% True if (FFFE,E00D) or (FFFE,E0DD). -tf = (attr.Group == 65534) && ... - ((attr.Element == 57357) || (attr.Element == 57565)); - - - -function count = countItems(attrs) - -if (isempty(attrs)) - count = 0; -else - % Find the items (FFFE,E000) in the array of attributes (all of - % which are item tags or delimiters; no normal attributes - % appear in attrs here). - idx = find(([attrs(:).Group] == 65534) & ... - ([attrs(:).Element] == 57344)); - count = numel(idx); -end \ No newline at end of file diff --git a/CT/infoCT.m b/CT/infoCT.m deleted file mode 100644 index 357888f..0000000 --- a/CT/infoCT.m +++ /dev/null @@ -1,321 +0,0 @@ -%% infoCT - -% This script lists the technical and the personal informations linked to the dicoms for -% "Pathologic" and "Normal" patients and returns the excel file "InfoCT". -% -% Alex Terrier comment: This scipt only works with matlab R2015a from a Windows system. It is -% using a modified version of dicominfo.m (dicominfo2.m) and a modified -% private function directory. This script should be updated and abandoned. - -% INPUT: 'normal' or 'pathologic' - -% Author: RO-EPFL-LBO -% Date: 2016-09-05 -%% -function infoCT - -addpath(genpath('CT')); -addpath(genpath('XLS_MySQL_DB')); -addpath(genpath('muscles')); -addpath(genpath('anatomy')); -addpath(genpath('Generated_Amira_TCL_Scripts')); - -XLSShoulderDatabaseLocation = '../../../data/Excel/'; % Location of the XLS ShoulderDatabase - -list{1,1} = 'sCase.id'; -list{1,2} = 'patient.IPP'; -list{1,3} = 'patient.initials'; -list{1,4} = 'patient.gender'; -list{1,5} = 'patient.birth_date'; -%list{1,6} = 'patient.age'; -%list{1,7} = 'patient.ethnicity'; -list{1,6} = 'patient.height'; -list{1,7} = 'patient.weight'; -%list{1,10} = 'patient.BMI'; -list{1,8} = 'shoulder.side'; -list{1,9} = 'CT.date'; -list{1,10} = 'CT.kernel'; -list{1,11} = 'CT.pixel_size'; -list{1,12} = 'CT.slice_spacing'; -list{1,13} = 'CT.slice_thickness'; -list{1,14} = 'CT.tension'; -list{1,15} = 'CT.current'; -list{1,16} = 'CT.institution'; -list{1,17} = 'CT.manufacturer'; -list{1,18} = 'CT.model'; -list{1,19} = 'CT.protocol'; - -directory = '../../../data'; - - -%% Loop over all the normal and pathologic cases - - location = 'N'; - l=1; - rootDir = '../../../data/N'; - for levelDir1 = 0:9 - for levelDir2 = 0:9 - curentDir = sprintf('%s/%d/%d/N*', rootDir, levelDir1, levelDir2); - folderInfo = dir(curentDir); - for i=1:1:numel(folderInfo) - name = folderInfo(i).name; - sCases_normal{l,1} = folderInfo(i).name; - sCases_normal{l,2} = levelDir1; - sCases_normal{l,3} = levelDir2; - sCases_normal{l,4} = 'N'; - l=l+1; - end - end - end - - location = 'P'; - l=1; - rootDir = '../../../data/P'; - for levelDir1 = 0:9 - for levelDir2 = 0:9 - curentDir = sprintf('%s/%d/%d/P*', rootDir, levelDir1, levelDir2); - folderInfo = dir(curentDir); - - for i=1:1:numel(folderInfo) - name = folderInfo(i).name; - sCases_pathologic{l,1} = folderInfo(i).name; - sCases_pathologic{l,2} = levelDir1; - sCases_pathologic{l,3} = levelDir2; - sCases_pathologic{l,4} = 'P'; - l=l+1; - end - end - end - - sCases = [sCases_normal;sCases_pathologic]; - -%% Data exportation from dicom -for j=2:1:numel(sCases(:,1))+1 - - patient = char(sCases(j-1,1)) - levelDir1 = cell2mat(sCases(j-1,2)); - levelDir2 = cell2mat(sCases(j-1,3)); - location = char(sCases(j-1,4)); - finalDirectory = sprintf('%s/%s/%d/%d', directory, location, levelDir1, levelDir2); - - if exist(sprintf('%s/%s/CT-%s-1/dicom', finalDirectory,patient,patient),'dir') == 7 %if a folder "dicom" exist, the patient name is added to the "measured" column -% directoryin=list(j,1); -% directoryin=char(directoryin); - - ctdirectoryin = sprintf('%s/%s/CT-%s-1/dicom',finalDirectory, patient, patient); - images = dir(ctdirectoryin); - ct=images(10).name; - ct2=images(11).name; - inpath=[ctdirectoryin,'/',ct]; - inpath2=[ctdirectoryin,'/',ct2]; - info=dicominfo2(inpath); - info2=dicominfo2(inpath2); - - - - %Patient# - list{j,1} = strtok(patient,'-'); - - %Weight - tf = isfield(info,'PatientWeight'); % Test si le champ "PatientWeight" existe - - if tf==1 - weight=info.PatientWeight; - else - weight=' '; - end - list{j,7} = weight; - - %Height - tf = isfield(info,'PatientSize'); % Test si le champ "PatientSize" existe - - if tf==1 - Size=info.PatientSize; - Size=Size*100; - Size=round(Size,0); - else - Size=' '; - end - list{j,6} = Size; - - %Gender - tf = isfield(info,'PatientSex'); % Test si le champ "PatientSex" existe - - if tf==1 - gender=info.PatientSex; - else - gender=' '; - end - list{j,4} = gender; - - %Birth date - tf = isfield(info,'PatientBirthDate'); % Test si le champ "PatientBirthDate" existe - - if tf==1 - date=info.PatientBirthDate; - date=[date(1:4) '.' date(5:6) '.' date(7:8)]; - else - date=' '; - end - list{j,5} = date; - - %CT date - tf = isfield(info,'AcquisitionDate'); % Test si le champ "AcquisitionDate" existe - - if tf==1 - ctdate=info.AcquisitionDate; - ctdate=[ctdate(1:4) '.' ctdate(5:6) '.' ctdate(7:8)]; - else - ctdate=' '; - end - list{j,9} = ctdate; - - %IPP - tf = isfield(info,'PatientID'); % Test si le champ "PatientID" existe - - if tf==1 - - id=info.PatientID; - else - - id=' '; - end - list{j,2} = id; - - %Kernel - tf = isfield(info,'ConvolutionKernel'); % Test si le champ "ConvolutionKernel" existe - - if tf==1 - kernel=info.ConvolutionKernel; - else - kernel=' '; - end - list{j,10} = kernel; - - %Pixel Size - tf = isfield(info,'PixelSpacing'); % Test si le champ "PixelSpacing" existe - - if tf==1 - pixel1=info.PixelSpacing(1); - %pixel2=info.PixelSpacing(2); - pixel1=num2str(pixel1); - %pixel2=num2str(pixel2); - %pixel= ['[',pixel1,',',pixel2,']']; - pixel= [,pixel1,]; - else - pixel=' '; - end - list{j,11} = pixel; - - %Slice Thickness - tf = isfield(info,'SliceThickness'); % Test si le champ "SliceThickness" existe - - if tf==1 - thickness=info.SliceThickness; - else - thickness=' '; - end - list{j,13} = thickness; - - %Tension - tf = isfield(info,'KVP'); % Test si le champ "KVP" existe - - if tf==1 - tension=info.KVP; - else - tension=' '; - end - list{j,14} = tension; - - - %Current - tf = isfield(info,'XrayTubeCurrent'); % Test si le champ "XrayTubeCurrent" existe - - if tf==1 - current=info.XrayTubeCurrent; - else - current=' '; - end - list{j,15} = current; - - - %Institution Name - tf = isfield(info,'InstitutionName'); % Test si le champ "InstitutionName" existe - - if tf==1 - instname=info.InstitutionName; - else - instname=' '; - end - list{j,16} = instname; - - %Manufacturer - tf = isfield(info,'Manufacturer'); % Test si le champ "Manufacturer" existe - - if tf==1 - manufacturer=info.Manufacturer; - else - manufacturer=' '; - end - list{j,17} = manufacturer; - - %Model Name - tf = isfield(info,'ManufacturerModelName'); % Test si le champ "ManufacturerModelName" existe - - if tf==1 - manufacturermn=info.ManufacturerModelName; - else - manufacturermn=' '; - end - list{j,18} = manufacturermn; - - %Protocol Name - tf = isfield(info,'ProtocolName'); % Test si le champ "ProtocolName" existe - - if tf==1 - protocol=info.ProtocolName; - else - protocol=' '; - end - list{j,19} = protocol; - - %Spacing Between Slices - tf = isfield(info,'ImagePositionPatient'); % Test si le champ "ImagePositionPatient" existe - - if tf==1 - pos1 = info.ImagePositionPatient(3); - pos2 = info2.ImagePositionPatient(3); - %pixel1=num2str(pixel1); - %pixel2=num2str(pixel2); - %pixel= ['[',pixel1,',',pixel2,']']; - space2= abs(pos1-pos2); - else - space2=' '; - end - list{j,12} = space2; - - % %Patient Name - % tf = isfield(info,'PatientName'); % Test si le champ "PatientName" existe - % - % if tf==1 - % name = info.PatientName.FamilyName; - % - % %pixel1=num2str(pixel1); - % - % else - % name=' '; - % end - % list{j,8} = name; - else - list{j,1} = strtok(patient,'-'); - end - if strcmp(patient,'P410-95295') - end -end -delete([XLSShoulderDatabaseLocation 'xlsFromMatlab/CT.xls']); -xlswrite([XLSShoulderDatabaseLocation 'xlsFromMatlab/CT'], list) - -addpath('XLS_MySQL_DB'); -MainExcel2SQL; -end - diff --git a/CT/private/analyze75open.m b/CT/private/analyze75open.m deleted file mode 100644 index 1b6a4b9..0000000 --- a/CT/private/analyze75open.m +++ /dev/null @@ -1,38 +0,0 @@ -function fid = analyze75open(filename, ext, mode, defaultByteOrder) -% Open an Analyze 7.5 file. - -% Copyright 2006-2011 The MathWorks, Inc. - - - -% Ensure that filename has a .hdr extension -[pname, fname, passedExt] = fileparts(filename); - -if ~isempty(passedExt) - switch lower(passedExt) - case {'.hdr','.img'} - % The file has the correct extension. - - otherwise - error(message('images:analyze75info:invalidFileFormat', passedExt)); - - end % switch -end % if - -filename = fullfile(pname, [fname '.' ext]); - -if (nargin < 4) - defaultByteOrder = 'ieee-be'; -end - -% Open the file with the default ByteOrder. -fid = fopen(filename, mode, defaultByteOrder); - -if (fid == -1) - if ~isempty(dir(filename)) - error(message('images:isanalyze75:hdrFileOpen', filename)) - else - error(message('images:isanalyze75:hdrFileExist', filename)) - end % if - -end diff --git a/CT/private/bitparse.mexw64 b/CT/private/bitparse.mexw64 deleted file mode 100644 index 312a559..0000000 Binary files a/CT/private/bitparse.mexw64 and /dev/null differ diff --git a/CT/private/dicom_add_attr.m b/CT/private/dicom_add_attr.m deleted file mode 100644 index 8dc6fac..0000000 --- a/CT/private/dicom_add_attr.m +++ /dev/null @@ -1,976 +0,0 @@ -function attr_str = dicom_add_attr(attr_str, group, element, dictionary, varargin) -%DICOM_ADD_ATTR Add an attribute to a structure of attributes. -% OUT = DICOM_ADD_ATTR(IN, GROUP, ELEMENT, DICTIONARY, DATA, VR) add -% the attribute (GROUP,ELEMENT) with DATA and value representation -% VR to the structure IN. -% -% OUT = DICOM_ADD_ATTR(IN, GROUP, ELEMENT, DICTIONARY, DATA) add the -% attribute (GROUP,ELEMENT) with DATA to the structure IN. The -% value representation for this attribute is inferred from the data -% dictionary; if the VR value is not unique, an error will be -% issued. -% -% OUT = DICOM_ADD_ATTR(IN, GROUP, ELEMENT, DICTIONARY) add the empty -% attribute specified by (GROUP, ELEMENT) to IN. The VR value for -% the attribute will be picked from the data dictionary. -% -% See also DICOM_ADD_ITEM. - -% Copyright 1993-2011 The MathWorks, Inc. - - -pos = length(attr_str) + 1; - -% -% Group and Element. -% - -attr_str(pos).Group = get_group_or_element(group); -attr_str(pos).Element = get_group_or_element(element); - - -% Get attribute's properties from dictionary. -attr_dict = dicom_dict_lookup(attr_str(pos).Group, ... - attr_str(pos).Element, ... - dictionary); - -if ((isempty(attr_dict)) && (rem(group, 2) == 1)) - - % Private data needs certain values to be set. - if (nargin < 6) - attr_dict(1).VR = 'UN'; - end - - attr_dict(1).VM = [0 inf]; - -end - - -% -% VR. -% - -if (nargin == 6) - - % VR provided. - attr_str(pos).VR = varargin{2}; - -elseif ((nargin == 5) && ... - ((iscell(attr_dict.VR)) && (length(attr_dict.VR) > 1))) - - % Data provided, but multiple possible VR values. - error(message('images:dicom_add_attr:attributeRequiresVRArg', sprintf( '(%04X,%04X)', attr_str( pos ).Group, attr_str( pos ).Element ))) - -else - - % Single VR value or empty data. Use first VR value. - if (iscell(attr_dict.VR)) - - attr_str(pos).VR = attr_dict.VR{1}; - - else - - attr_str(pos).VR = attr_dict.VR; - - end - -end - - -% -% VM -% - -attr_str(pos).VM = attr_dict.VM; - - -% -% Data. -% - -% Get data from varargin or create default empty data. -if (nargin > 4) - data = varargin{1}; -else - data = []; -end - - -% -% Convert MATLAB data to DICOM's type and style. -% - -attr_str(pos).Data = validate_data(data, attr_str(pos)); - - - -function data_out = validate_data(data_in, attr_str) -%VALIDATE_DATA Validate user-provided data and massage to acceptable form. - -vr_details = get_vr_details(attr_str.VR); - -if (~isempty(data_in)) - - attr_tag = sprintf('(%04X,%04X)', attr_str.Group, attr_str.Element); - - % Check type. - if (~has_correct_data_type(class(data_in), vr_details.Types_accept)) - error(message('images:dicom_add_attr:attributeHasWrongType', attr_tag)) - end - - % Convert data. - data_out = massage_data(data_in, attr_str); - - % Check VM. - if (~has_correct_vm(data_out, attr_str.VM, vr_details)) - - warning(message('images:dicom_add_attr:wrongAttribNum', attr_tag)); - - end - - % Check lengths. - if (~has_correct_lengths(data_out, vr_details)) - - warning(message('images:dicom_add_attr:wrongAttribData', attr_tag)); - end - - % Validate data, if appropriate. - if (ischar(data_out)) - - if (~isempty(find_invalid_chars(data_out, vr_details))) - - warning(message('images:dicom_add_attr:invalidAttribChar', attr_tag)); - end - end - - % Pad data, if necessary. - switch (class(data_out)) - case {'uint8', 'int8', 'char'} - if (rem(numel(data_out), 2) == 1) - data_out = pad_data(data_out, vr_details); - end - end - -else - - data_out = data_in; - -end - - - -function val = get_group_or_element(in) - -if (isempty(in)) - - error(message('images:dicom_add_attr:groupElementNotHexOrInt')) - -elseif (ischar(in)) - - val = sscanf(in, '%x'); - -elseif (isnumeric(in)) - - val = in; - -else - - error(message('images:dicom_add_attr:groupElementNotHexOrInt')) - -end - - - -function details = get_vr_details(vr_in) -%GET_VR_DETAILS Get properties of a Value Representation. - -persistent vr_hash; -persistent vr_details; - -if (isempty(vr_hash)) - - % Build up the hash table and details structures. - [vr_hash, vr_details] = build_vr_details; - - % Get the details from the new hash. - details = get_vr_details(vr_in); - -else - - % Find the VR passed in. - idx = strmatch(vr_in, vr_hash); - - if (isempty(idx)) - - details = []; - - else - - details = vr_details(idx); - - end - -end - - - -function [vr_hash, vr_details] = build_vr_details -%BUILD_VR_DETAILS Create a hash table of VR properties. - -% Character categories. -ASCII_UPPER = 65:90; -ASCII_NUMS = 48:57; -ASCII_LF = 10; -ASCII_FF = 12; -ASCII_CR = 13; -ASCII_ESC = 27; -DICOM_CTRL = [ASCII_LF, ASCII_FF, ASCII_CR, ASCII_ESC]; -DICOM_NONCTRL = 32:126; -DICOM_DEFAULT = [DICOM_CTRL, DICOM_NONCTRL]; -DICOM_EXTENDED = 127:255; -DICOM_ALL = [DICOM_DEFAULT, DICOM_EXTENDED]; - -% Datatype categories. -TYPES_SIGNED = {'int8', 'int16', 'int32'}; -TYPES_UNSIGNED = {'uint8', 'uint16', 'uint32'}; -TYPES_FLOATING = {'double', 'single'}; -TYPES_INTEGRAL = [TYPES_SIGNED, TYPES_UNSIGNED]; -TYPES_NUMERIC = [TYPES_INTEGRAL, TYPES_FLOATING, {'logical'}]; - -% Hash of VRs. -vr_hash = {'AE' - 'AS' - 'AT' - 'CS' - 'DA' - 'DS' - 'DT' - 'FD' - 'FL' - 'IS' - 'LO' - 'LT' - 'OB' - 'OW' - 'PN' - 'SH' - 'SL' - 'SQ' - 'SS' - 'ST' - 'TM' - 'UI' - 'UL' - 'UN' - 'US' - 'UT'}; - -% Struct of VR details. - -vr_details(1).VR_name = 'AE'; -vr_details(1).Types_accept = {'char'}; -vr_details(1).Types_output = 'char'; -vr_details(1).Size_range = [0 16]; -vr_details(1).Separator = '\'; -vr_details(1).Char_repertoire = DICOM_NONCTRL; - -vr_details(2).VR_name = 'AS'; -vr_details(2).Types_accept = {'char'}; -vr_details(2).Types_output = 'char'; -vr_details(2).Size_range = [0 4]; -vr_details(2).Separator = '\'; -vr_details(2).Char_repertoire = [ASCII_NUMS, 'D', 'W', 'M', 'Y']; - -vr_details(3).VR_name = 'AT'; -vr_details(3).Types_accept = TYPES_NUMERIC; -vr_details(3).Types_output = 'uint16'; -vr_details(3).Size_range = [2 2]; -vr_details(3).Separator = []; -vr_details(3).Char_repertoire = ''; - -vr_details(4).VR_name = 'CS'; -vr_details(4).Types_accept = {'char'}; -vr_details(4).Types_output = 'char'; -vr_details(4).Size_range = [0 16]; -vr_details(4).Separator = '\'; -vr_details(4).Char_repertoire = [ASCII_UPPER, ASCII_NUMS, ' ', '_']; - -vr_details(5).VR_name = 'DA'; -vr_details(5).Types_accept = {'char', 'double'}; -vr_details(5).Types_output = 'char'; -vr_details(5).Size_range = [8 10]; % 10 ALLOWS FOR PRE 3.0. -vr_details(5).Separator = '\'; -vr_details(5).Char_repertoire = [ASCII_NUMS, '.']; - -vr_details(6).VR_name = 'DS'; -vr_details(6).Types_accept = [{'char'}, TYPES_NUMERIC]; -vr_details(6).Types_output = 'char'; -vr_details(6).Size_range = [0 16]; -vr_details(6).Separator = '\'; -vr_details(6).Char_repertoire = [ASCII_NUMS, '+', '-', 'E', 'e', '.', ' ']; - -vr_details(7).VR_name = 'DT'; -vr_details(7).Types_accept = {'char', 'double'}; -vr_details(7).Types_output = 'char'; -vr_details(7).Size_range = [0 26]; -vr_details(7).Separator = '\'; -vr_details(7).Char_repertoire = [ASCII_NUMS, '+', '-', '.']; - -vr_details(8).VR_name = 'FD'; -vr_details(8).Types_accept = TYPES_NUMERIC; -vr_details(8).Types_output = 'double'; -vr_details(8).Size_range = [1 1]; -vr_details(8).Separator = []; -vr_details(8).Char_repertoire = ''; - -vr_details(9).VR_name = 'FL'; -vr_details(9).Types_accept = TYPES_NUMERIC; -vr_details(9).Types_output = 'single'; -vr_details(9).Size_range = [1 1]; -vr_details(9).Separator = []; -vr_details(9).Char_repertoire = ''; - -vr_details(10).VR_name = 'IS'; -vr_details(10).Types_accept = TYPES_NUMERIC; -vr_details(10).Types_output = 'char'; -vr_details(10).Size_range = [0 12]; -vr_details(10).Separator = '\'; -vr_details(10).Char_repertoire = [ASCII_NUMS, '-', ' ']; - -vr_details(11).VR_name = 'LO'; -vr_details(11).Types_accept = {'char'}; -vr_details(11).Types_output = 'char'; -vr_details(11).Size_range = [0 64]; -vr_details(11).Separator = '\'; -vr_details(11).Char_repertoire = [DICOM_NONCTRL, DICOM_EXTENDED, ASCII_ESC]; - -vr_details(12).VR_name = 'LT'; -vr_details(12).Types_accept = {'char'}; -vr_details(12).Types_output = 'char'; -vr_details(12).Size_range = [0 10240]; -vr_details(12).Separator = ''; -vr_details(12).Char_repertoire = DICOM_ALL; - -vr_details(13).VR_name = 'OB'; -vr_details(13).Types_accept = {'uint8', 'int8', 'logical'}; -vr_details(13).Types_output = 'uint8'; -vr_details(13).Size_range = [0 inf]; -vr_details(13).Separator = []; -vr_details(13).Char_repertoire = ''; - -vr_details(14).VR_name = 'OW'; -vr_details(14).Types_accept = [TYPES_INTEGRAL, {'logical'}]; -vr_details(14).Types_output = 'uint16'; -vr_details(14).Size_range = [0 inf]; -vr_details(14).Separator = []; -vr_details(14).Char_repertoire = ''; - -vr_details(15).VR_name = 'PN'; -vr_details(15).Types_accept = {'char', 'struct'}; -vr_details(15).Types_output = 'char'; -vr_details(15).Size_range = [0 (64 * 3)]; % 64 chars / component group. -vr_details(15).Separator = '\'; -vr_details(15).Char_repertoire = [DICOM_NONCTRL, ASCII_ESC, DICOM_EXTENDED]; - -vr_details(16).VR_name = 'SH'; -vr_details(16).Types_accept = {'char'}; -vr_details(16).Types_output = 'char'; -vr_details(16).Size_range = [0 16]; -vr_details(16).Separator = '\'; -vr_details(16).Char_repertoire = [DICOM_NONCTRL, ASCII_ESC, DICOM_EXTENDED]; - -vr_details(17).VR_name = 'SL'; -vr_details(17).Types_accept = TYPES_NUMERIC; -vr_details(17).Types_output = 'int32'; -vr_details(17).Size_range = [1 1]; -vr_details(17).Separator = []; -vr_details(17).Char_repertoire = ''; - -vr_details(18).VR_name = 'SQ'; -vr_details(18).Types_accept = {'struct'}; -vr_details(18).Types_output = 'struct'; -vr_details(18).Size_range = [1 1]; % All SQ attributes have VM of 1. -vr_details(18).Separator = []; -vr_details(18).Char_repertoire = ''; - -vr_details(19).VR_name = 'SS'; -vr_details(19).Types_accept = TYPES_NUMERIC; -vr_details(19).Types_output = 'int16'; -vr_details(19).Size_range = [1 1]; -vr_details(19).Separator = []; -vr_details(19).Char_repertoire = ''; - -vr_details(20).VR_name = 'ST'; -vr_details(20).Types_accept = {'char'}; -vr_details(20).Types_output = 'char'; -vr_details(20).Size_range = [0 1024]; -vr_details(20).Separator = ''; -vr_details(20).Char_repertoire = DICOM_ALL; - -% ':' allowed for backward compatibility. -% See note for TM in PS-3.5 Sec. 6.2.0. -vr_details(21).VR_name = 'TM'; -vr_details(21).Types_accept = {'char', 'double'}; -vr_details(21).Types_output = 'char'; -vr_details(21).Size_range = [0 16]; -vr_details(21).Separator = '\'; -vr_details(21).Char_repertoire = [ASCII_NUMS, '.', ' ', ':']; - -vr_details(22).VR_name = 'UI'; -vr_details(22).Types_accept = {'char'}; -vr_details(22).Types_output = 'char'; -vr_details(22).Size_range = [0 64]; -vr_details(22).Separator = '\'; -vr_details(22).Char_repertoire = [ASCII_NUMS, '.', 0]; - -vr_details(23).VR_name = 'UL'; -vr_details(23).Types_accept = TYPES_NUMERIC; -vr_details(23).Types_output = 'uint32'; -vr_details(23).Size_range = [1 1]; -vr_details(23).Separator = []; -vr_details(23).Char_repertoire = ''; - -vr_details(24).VR_name = 'UN'; -vr_details(24).Types_accept = [TYPES_NUMERIC, {'char'}, {'struct'}]; -vr_details(24).Types_output = 'uint8'; % Don't convert raw data. -vr_details(24).Size_range = [0 inf]; -vr_details(24).Separator = []; -vr_details(24).Char_repertoire = 0:255; % Anything is allowed. - -vr_details(25).VR_name = 'US'; -vr_details(25).Types_accept = TYPES_NUMERIC; -vr_details(25).Types_output = 'uint16'; -vr_details(25).Size_range = [1 1]; -vr_details(25).Separator = []; -vr_details(25).Char_repertoire = ''; - -vr_details(26).VR_name = 'UT'; -vr_details(26).Types_accept = {'char'}; -vr_details(26).Types_output = 'char'; -vr_details(26).Size_range = [0 (2^32 - 2)]; -vr_details(26).Separator = ''; -vr_details(26).Char_repertoire = DICOM_ALL; - - - -function tf = has_correct_data_type(datatype, acceptable) -%HAS_CORRECT_DATA_TYPE Verify that the data is of the right type. - -switch (datatype) -case acceptable - tf = true; -otherwise - tf = false; -end - - - -function tf = has_correct_vm(data, vm, vr_details) -%HAS_CORRECT_VM Verify that data has correct number of components. - -switch (class(data)) -case 'char' - - if (isempty(vr_details.Separator)) - tf = true; - else - idx = find(data == vr_details.Separator); - - tf = ((length(idx) + 1) >= vm(1)) & ... - ((length(idx) + 1) <= vm(2)); - end - -case 'struct' - - tf = true; - -case {'uint8', 'int8', 'uint16', 'int16', 'uint32', 'int32', ... - 'double', 'single'} - - tf = (numel(data) >= vm(1) * vr_details.Size_range(1)) & ... - (numel(data) <= vm(2) * vr_details.Size_range(2)); - -otherwise - - tf = false; - -end - - - -function data_out = massage_data(data_in, attr_str) -%MASSAGE_DATA Convert data to its DICOM type. - -% We assume that this won't be called on data that can't be converted. -% The function HAS_CORRECT_DATA_TYPE permits this assumption. - -switch (attr_str.VR) -case 'AT' - - % Attribute tags must be stored as UINT16 pairs. - data_out = uint16(data_in); - - if (numel(data_out) ~= length(data_in)) - - if (size(data_out, 2) ~= 2) - error(message('images:dicom_add_attr:AttributeNeedsPairsOfUint16Data', sprintf( '(%04X,%04X)', attr_str.Group, attr_str.Element ))) - - end - - data_out = data_out'; - - end - - data_out = data_out(:); - -case 'DA' - - % Convert a MATLAB serial date to a string. - if (isa(data_in, 'double')) - - % - warning(message('images:dicom_add_attr:serialDateToString', sprintf( '(%04X,%04X)', attr_str.Group, attr_str.Element ))) - - - tmp = datestr(data_in, 30); % yyyymmddTHHMMSS - data_out = tmp(1:8); - - else - - data_out = data_in; - - end - -case 'DS' - - % Convert numeric values to strings. - if (~ischar(data_in)) - - data_out = convertNumericToString(data_in); - - else - - data_out = data_in; - - end - -case 'DT' - - % Convert a MATLAB serial date to a string. - if (isa(data_in, 'double')) - - - % - warning(message('images:dicom_add_attr:serialDateToString', sprintf( '(%04X,%04X)', attr_str.Group, attr_str.Element ))) - - - - data_out = ''; - - for p = 1:length(data_in) - - tmp_base = datestr(data_in, 30); % yyyymmddTHHMMSS - tmp_base(9) = ''; - - v = datevec(data_in); - tmp_fraction = sprintf('%0.6f', (v(end) - round(v(end)))); - tmp_fraction(1) = ''; % Remove leading 0. - - data_out = [data_out '\' tmp_base tmp_fraction(2:end)]; %#ok - - end - - else - - data_out = data_in; - - end - -case 'FD' - - data_out = double(data_in); - -case 'FL' - - data_out = single(data_in); - -case 'IS' - - % Convert numeric values to strings. - if (~ischar(data_in)) - - data_out = sprintf('%d\\', round(data_in)); - data_out(end) = ''; - - else - - data_out = data_in; - - end - -case 'OB' - - % Convert logical values to packed UINT8 arrays. - if (islogical(data_in)) - - data_out = pack_logical(data_in, 8); - - else - data_out = data_in; - end - -case 'OW' - - if (islogical(data_in)) - - % Convert logical values to packed UINT8 arrays. - data_out = pack_logical(data_in, 16); - - elseif (isa(data_in, 'uint32') || isa(data_in, 'uint32')) - - % 32-bit values need to be swapped as 16-bit short words not - % 32-bit words (e.g., "1234" byte order on LE should become - % "2143" on BE machines, and vice versa). - data_out = dicom_typecast(data_in, 'uint16'); - - else - data_out = data_in; - end - -case 'PN' - - % Convert person structures to strings. - if (isstruct(data_in)) - - data_out = struct_to_pn(data_in); - - else - - data_out = data_in; - - end - -case 'SL' - - data_out = int32(data_in); - -case 'SS' - - data_out = int16(data_in); - -case 'TM' - - % Convert a MATLAB serial date to a string. - if (isa(data_in, 'double')) - - % - warning(message('images:dicom_add_attr:serialDateToString', sprintf( '(%04X,%04X)', attr_str.Group, attr_str.Element ))) - - - tmp = datestr(data_in, 30); % yyyymmddTHHMMSS - data_out = tmp(10:end); - - else - - data_out = data_in; - end - -case 'UL' - - data_out = uint32(data_in); - -case 'UN' - - if (isnumeric(data_in)) - data_out = dicom_typecast(data_in, 'uint8'); - else - data_out = data_in; - end - -case 'US' - - data_out = uint16(data_in); - -otherwise - - data_out = data_in; - -end - - - -function pn_string = struct_to_pn(pn_struct) -%STRUCT_TO_PN Convert a person name in a struct to a character string. - -pn_string = ''; - -for p = 1:length(pn_struct) - - % Build up the PN string for this value. - tmp = ''; - - if (isfield(pn_struct, 'FamilyName')) - tmp = [tmp, pn_struct.FamilyName, '^']; %#ok - else - tmp = [tmp, '^']; %#ok - end - - if (isfield(pn_struct, 'GivenName')) - tmp = [tmp, pn_struct.GivenName, '^']; %#ok - else - tmp = [tmp, '^']; %#ok - end - - if (isfield(pn_struct, 'MiddleName')) - tmp = [tmp, pn_struct.MiddleName, '^']; %#ok - else - tmp = [tmp, '^']; %#ok - end - - if (isfield(pn_struct, 'NamePrefix')) - tmp = [tmp, pn_struct.NamePrefix, '^']; %#ok - else - tmp = [tmp, '^']; %#ok - end - - if (isfield(pn_struct, 'NameSuffix')) - tmp = [tmp, pn_struct.NameSuffix, '^']; %#ok - else - tmp = [tmp, '^']; %#ok - end - - % Remove trailing null components. - while ((~isempty(tmp)) && (isequal(tmp(end), '^'))) - tmp(end) = ''; - end - - % Add this value to the output string. - pn_string = [pn_string, tmp, '\']; %#ok - -end - -% Remove trailing delimiter ('\'). -pn_string(end) = ''; - - - -function bad_chars = find_invalid_chars(data, vr_details) -%FIND_INVALID_CHARS Look for invalid characters - -bad_chars = setdiff(data, [vr_details.Char_repertoire, vr_details.Separator]); - - - -function out = pad_data(in, vr_details) -%PAD_DATA Pad data to an even length - -switch (vr_details.VR_name) -case {'AE', 'CS', 'DS' 'DT', 'IS', 'LO', 'LT', 'PN', 'SH', 'ST', 'TM', 'UT'} - - out = in; - out(end + 1) = ' '; - -case {'OB', 'UI', 'UN'} - - out = in; - out(end + 1) = 0; - -otherwise - - % If it's numeric, it's even-byte aligned unless its 8-bit. - if ((isa(in, 'uint8')) || (isa(in, 'int8'))) - - out = in; - out(end + 1) = 0; - - else - - out = in; - - end - -end - - - -function tf = has_correct_lengths(data, vr_details) -%HAS_CORRECT_LENGTHS Determine if data components are correctly sized. - -if (isempty(vr_details.Separator)) - - % If there's no separator, then data lengths are unimportant (except - % for attributes with a VR of "AT", which have two UINT16 components.) - - if (isnumeric(data)) - - if (isequal(vr_details.VR_name, 'AT')) - - if (rem(numel(data), 2) == 1) - tf = 0; - else - tf = 1; - end - - else - - tf = 1; - - end - - elseif (isstruct(data)) - - tf = 1; - - else - - tf = ((numel(data) >= vr_details.Size_range(1)) & ... - (numel(data) <= vr_details.Size_range(2))); - - end - -else - - % Find the separators. - idx = find(data == vr_details.Separator); - component_start = 1; - - tf = 1; - - % Test lengths for all but last component. - for p = 1:length(idx) - - component_end = idx(p) - 1; - - data_length = component_end - component_start + 1; - - tf = tf * ... - ((data_length >= vr_details.Size_range(1)) & ... - (data_length <= vr_details.Size_range(2))); - - component_start = component_end + 2; - - end - - % Test length of the last (or only) component. - data_length = numel(data) - component_start + 1; - - tf = tf * ... - ((data_length >= vr_details.Size_range(1)) & ... - (data_length <= vr_details.Size_range(2))); - -end - - - -function strData = convertNumericToString(numData) -% Convert numeric data to character strings representing that -% data. DICOM number strings can be at most 16-bytes long and -% should use exponential notation where necessary. -% -% We use a complicated set of rules involving the sign of the data -% and its base-10 logarithm to pick a precision value for SPRINTF -% that maximizes the significant digits and prints at most 16 -% characters. -% -% When viewed on a number line, the state transitions for the -% precision value are listed below. (That is, where do the rules -% for determining the format specifier change?) -% -% * -1E+14 -% * -1E+0 (aka -1) -% * -1E-5 -% * 0 -% * 1E-5 -% * 1E+0 (aka 1) -% * 1E+14 - -strData = ''; -for idx = 1:numel(numData) - - if (numData(idx) == 0) - - % Avoid "log of 0" warnings and needless computations. - fmtString = '%d'; - - else - - power10 = floor(log10(abs(double(numData(idx))))); - - if (numData >= 0) - - % The precision is: - % 0 <= x < 1E-5 --> %.10G - % 1E-5 <= x < 1 --> varies - % 1 <= x < 1E14 --> %.15G - % 1E14 <= x --> %.10G - if (power10 >= 14) - fmtString = '%.10G'; - else - precision = max(10, min(15, power10 + 15)); - fmtString = sprintf('%%.%dG', precision); - end - - else - - % The precision is: - % x < -1E14 --> %.9G - % -1E14 <= x < -1 --> %.14G - % -1 <= x < -1E-5 --> varies - % -1E-5 <= x < 0 --> %.9G - if (power10 >= 14) - fmtString = '%.9G'; - else - precision = max(9, min(14, power10 + 14)); - fmtString = sprintf('%%.%dG', precision); - end - end - - end - - strData = [strData, '\', sprintf(fmtString, numData(idx))]; %#ok - -end - -% Remove the leading '\' from the first iteration. -strData(1) = ''; - - - -function data_out = pack_logical(data_in, bits) - -% Transpose the data to row-major format. -data_in = data_in'; -data_in = data_in(:); - -% The easiest way to pack the data is to perform matrix -% multiplication after reshaping the data to match the -% bit positions in the output data. (Pad if necessary.) -padded_output_length = ceil(numel(data_in) / bits); -if ((numel(data_in) / bits) ~= padded_output_length) - - data_in(padded_output_length * bits) = 0; - -end - -% MATLAB doesn't support matrix multiplication of integral types, -% so use double. (Reshape the input data to be n-by-bits and -% multiply by the bits-by-1 mask to make an n-by-1 packed array.) -data_in = reshape(double(data_in), bits, [])'; - -mask = zeros(bits, 1); -for idx = 1:bits - mask(idx) = 2^(idx - 1); -end - -% Pack the bits via matrix multiplication. -data_out = data_in * mask; - -% Convert double data back to the correct type. -switch (bits) -case 8 - data_out = uint8(data_out); -case 16 - data_out = uint16(data_out); -otherwise - error(message('images:dicom_add_attr:badPackBits')) -end diff --git a/CT/private/dicom_add_item.m b/CT/private/dicom_add_item.m deleted file mode 100644 index 0768d47..0000000 --- a/CT/private/dicom_add_item.m +++ /dev/null @@ -1,101 +0,0 @@ -function attr_str = dicom_add_item(attr_str, group, element, varargin) -%DICOM_ADD_ITEM Add an item/delimiter to a structure of attributes. -% OUT = DICOM_ADD_ITEM(IN, GROUP, ELEMENT) -% OUT = DICOM_ADD_ITEM(IN, GROUP, ELEMENT, DATA) -% -% This function is similar to DICOM_ADD_ATTR, but it doesn't allow -% specifying VR values and can only be used for attributes of group -% FFFE. -% -% See also DICOM_ADD_ATTR, DICOM_ADD_PIXEL_DATA. - -% Copyright 1993-2010 The MathWorks, Inc. - - -% See PS-3.5 Sec. 7.5 for details on sequence and item encoding. - - -% Get group and element. -tmp.Group = get_group_or_element(group); -tmp.Element = get_group_or_element(element); - -% Get data value. -if (nargin > 4) - error(message('images:dicom_add_item:tooManyInputArgs')); -elseif (nargin == 3) - tmp.Data = []; -else - tmp.Data = varargin{1}; -end - -tmp.VR = 'UN'; - -% Check the group and element values. -if (tmp.Group ~= 65534) % 0xFFFE == 65534 - error(message('images:dicom_add_item:groupNotAccepted', sprintf( '%X', tmp.Group ))) -end - -switch (tmp.Element) -case {57344} % 0xE000 == 57344 - - % Data is okay for (FFFE,E000). - -case {57357, 57565} % 0xE00D == 57357, 0XE0DD == 57565 - - if (~isempty(tmp.Data)) - error(message('images:dicom_add_item:AttributeCannotHaveData', sprintf( '(%04X,%04X)', tmp.Group, tmp.Element ))) - end - -otherwise - error(message('images:dicom_add_item:attributeNotSupported', sprintf( '(%04X,%04X)', tmp.Group, tmp.Element ))) - -end - -% Pad the data to an even byte boundary. -if (rem(getSizeInBytes(tmp.Data), 2) == 1) - tmp.Data(end + 1) = uint8(0); -end - -% Store the data. -attr_str = cat(2, attr_str, tmp); - - -function numBytes = getSizeInBytes(data) - -switch (class(data)) -case {'uint8', 'int8'} - multiplier = 1; - -case {'uint16', 'int16'} - multiplier = 2; - -case {'uint32', 'int32', 'single'} - multiplier = 4; - -case {'double'} - multiplier = 8; - -end - -numBytes = multiplier * numel(data); - - -function val = get_group_or_element(in) - -if (isempty(in)) - - error(message('images:dicom_add_item:groupElementNotHexOrInt')) - -elseif (ischar(in)) - - val = sscanf(in, '%x'); - -elseif (isnumeric(in)) - - val = in; - -else - - error(message('images:dicom_add_item:groupElementNotHexOrInt')) - -end diff --git a/CT/private/dicom_close_msg.m b/CT/private/dicom_close_msg.m deleted file mode 100644 index 2b9f43e..0000000 --- a/CT/private/dicom_close_msg.m +++ /dev/null @@ -1,22 +0,0 @@ -function file = dicom_close_msg(file) -%DICOM_CLOSE_MSG Close a DICOM message. -% FILE = DICOM_CLOSE_MSG(FILE) closes the DICOM message pointed to in -% FILE.FID. The returned value, FILE, is the updated file structure. - -% Copyright 1993-2010 The MathWorks, Inc. - -if (file.FID > 0) - - result = fclose(file.FID); - - if (result == -1) - - error(message('images:dicom_close_msg:unableToClose', file.Filename, ferror( file.FID ))) - - end - -else - - error(message('images:dicom_close_msg:invalidFID')) - -end diff --git a/CT/private/dicom_compress_pixel_cells.m b/CT/private/dicom_compress_pixel_cells.m deleted file mode 100644 index 15e7732..0000000 --- a/CT/private/dicom_compress_pixel_cells.m +++ /dev/null @@ -1,133 +0,0 @@ -function attrs = dicom_compress_pixel_cells(pixel_cells, txfr, bits_allocated, dims) -%DICOM_COMPRESS_PIXEL_CELLS Compress pixel cells into fragments. -% ATTRS = DICOM_COMPRESS_PIXEL_CELLS(CELLS, TXFR, BITS, DIMS) compress -% the pixel cells CELLS using the transfer syntax TXFR. BITS is the -% size of each pixel cell, and DIMS is the MATLAB dimensions of the -% data contained in the pixel cells. -% -% The result is a structure of attributes containing the compressed -% pixel cell fragments and item delimiters. -% -% See also DICOM_ADD_ITEM. - -% Copyright 1993-2010 The MathWorks, Inc. - - -% Encapsulated (compressed) pixel cells have the following structure: -% -% (7FE0,0010) with undefined length (handled elsewhere) -% (FFFE,0000) containing off-set table or 0 length data -% (FFFE,0000) for each fragment (a collection of UINT8 data) -% (FFFE,00DD) with 0 length data - -% Create an empty container for the "sequence." -attrs = struct([]); - -% Compress the pixel_cells. -[fragments, frames] = compress_cells(pixel_cells, txfr, bits_allocated, dims); - -% Create the Basic Offset Table. -offsets = build_offset_table(fragments, frames); -attrs = dicom_add_item(attrs, 'FFFE', 'E000', offsets); - -% Add the fragments. -for p = 1:length(fragments) - - attrs = dicom_add_item(attrs, 'FFFE', 'E000', fragments{p}); - -end - -% Add the sequence delimiter. -attrs = dicom_add_item(attrs, 'FFFE', 'E0DD'); - - - -function [fragments, frames] = compress_cells(pixel_cells, txfr, ... - bits_allocated, dims) -%COMPRESS_CELLS Return a cell array of encoded pixel cell fragments. - -switch (txfr) -case '1.2.840.10008.1.2.5' - - [fragments, frames] = dicom_encode_rle(pixel_cells, bits_allocated, dims); - fragments = padFragments(fragments); - -case '1.2.840.10008.1.2.4.50' - - [fragments, frames] = dicom_encode_jpeg_lossy(pixel_cells, bits_allocated); - fragments = padFragments(fragments); - -case '1.2.840.10008.1.2.4.70' - - [fragments, frames] = dicom_encode_jpeg_lossless(pixel_cells, bits_allocated); - fragments = padFragments(fragments); - -case '1.2.840.10008.1.2.4.90' - - [fragments, frames] = dicom_encode_jpeg2000_lossless(pixel_cells, bits_allocated); - fragments = padFragments(fragments); - -case '1.2.840.10008.1.2.4.91' - - [fragments, frames] = dicom_encode_jpeg2000_lossy(pixel_cells, bits_allocated); - fragments = padFragments(fragments); - -otherwise - error(message('images:dicom_compress_pixel_cells:cannotCompress', txfr)) - -end - - - -function offset_table = build_offset_table(fragments, frames) -%BUILD_OFFSET_TABLE Create a vector of offsets to the start of the frames. - -% Don't store an offset table for just one frame. -if (length(frames) == 1) - offset_table = uint32([]); - return -end - -% Build an offset table, a UINT32 vector with byte offsets to the -% beginning of the next frame. The offsets are relative to the end of -% the offset table item, which is always followed by the first fragment. -offset_table = repmat(uint32(0), size(frames)); - -current_offset = 0; -current_frame = 1; - -for p = 1:length(fragments) - - if (p == frames(current_frame)) - - % Beginning of frame starts at current position. - offset_table(current_frame) = current_offset; - current_frame = current_frame + 1; - - % Offset to next fragment is 8 bytes for tag and length plus size - % of fragment. - current_offset = current_offset + 8 + numel(fragments{p}); - - else - - % Not the beginning of a new frame. - current_offset = current_offset + 8 + numel(fragments{p}); - - end - -end - - - -function fragments = padFragments(fragments) -%padFragments Add null bytes to odd-length fragments. - -for p = 1:numel(fragments) - - if (rem(numel(fragments{p}), 2) == 1) - - fragments{p}(end+1) = 0; - - end - -end diff --git a/CT/private/dicom_convert_meta_to_attr.m b/CT/private/dicom_convert_meta_to_attr.m deleted file mode 100644 index 22957cf..0000000 --- a/CT/private/dicom_convert_meta_to_attr.m +++ /dev/null @@ -1,166 +0,0 @@ -function attr = dicom_convert_meta_to_attr(attr_name, metadata, dictionary, txfr) -%DICOM_CONVERT_META_TO_ATTR Convert a metadata field to an attr struct. - -% Copyright 1993-2011 The MathWorks, Inc. - -% Look up the attribute tag. -tag = dicom_tag_lookup(attr_name, dictionary); - -if (isempty(tag)) - - attr = []; - return - -end - -% Get the VR. -VR = determine_VR(tag, metadata, dictionary, txfr); - -% Process struct data - Person Names (PN) and sequences (SQ). -if (isequal(VR, 'PN') || isPersonName(metadata.(attr_name))) - - data = dicom_encode_pn(metadata.(attr_name)); - -elseif (isequal(VR, 'SQ') || isstruct(metadata.(attr_name))) - - data = encode_SQ(metadata.(attr_name), dictionary, txfr); - -else - - data = metadata.(attr_name); - -end - - -% Add the attribute. -if (isempty(VR)) - attr = dicom_add_attr([], tag(1), tag(2), dictionary, data); -else - attr = dicom_add_attr([], tag(1), tag(2), dictionary, data, VR); -end - - - -function VR = determine_VR(tag, metadata, dictionary, txfr) -%DETERMINE_VR Find an attribute's value representation (VR). - -attr_details = dicom_dict_lookup(tag(1), tag(2), dictionary); - -if (isempty(attr_details)) - - if (tag(2) == 0) - VR = 'UL'; - else - VR = []; - end - -else - - VR = attr_details.VR; - - if (iscell(VR)) - - % If it's US/SS, look at Pixel Representation (0028,0103). - % If it's OB/OW, look at whether it's compressed. - - - if (~isempty(strfind([VR{:}], 'US'))) - - PixRep = dicomlookup('0028','0103'); - if (isfield(metadata, PixRep) && (metadata.(PixRep) == 1)) - VR = 'SS'; - else - VR = 'US'; - end - - elseif (isequal(tag, uint16([sscanf('7fe0', '%x'), ... - sscanf('0010', '%x')]))) - - uidDetails = dicom_uid_decode(txfr); - bitDepth = metadata.(dicomlookup('0028', '0100')); - - if (uidDetails.Compressed) - - VR = 'OB'; - - elseif (isequal(uidDetails.VR, 'IMPLICIT')) - - VR = 'OW'; - - elseif (bitDepth > 8) - - VR = 'OW'; - - else - - VR = 'OB'; - - end - - else - VR = VR{1}; - end - - end - -end - - - -function attrs = encode_SQ(SQ_struct, dictionary, txfr) -%ENCODE_SQ Turn a structure of sequence data into attributes. - -attrs = []; - -if (isempty(SQ_struct)) - return -end - -% Don't worry about encoding rules yet. Just convert the MATLAB struct -% containing item and data fields into an array of attribute structs. - -items = fieldnames(SQ_struct); -for p = 1:numel(items) - - data = encode_item(SQ_struct.(items{p}), dictionary, txfr); - attrs = dicom_add_attr(attrs, 'fffe', 'e000', dictionary, data); - -end - - - -function attrs = encode_item(item_struct, dictionary, txfr) -%ENCODE_ITEM Turn one item of a sequence into attributes. - -attrs = []; - -if (isempty(item_struct)) - return -end - -attr_names = fieldnames(item_struct); -for p = 1:numel(attr_names) - - new_attr = dicom_convert_meta_to_attr(attr_names{p}, item_struct, dictionary, txfr); - attrs = cat(2, attrs, new_attr); - -end - - - -function tf = isPersonName(attr) - -if (isstruct(attr)) - - tf = isfield(attr, 'FamilyName') || ... - isfield(attr, 'GivenName') || ... - isfield(attr, 'MiddleName') || ... - isfield(attr, 'NamePrefix') || ... - isfield(attr, 'NameSuffix'); - -else - - tf = false; - -end - diff --git a/CT/private/dicom_copy_IOD.m b/CT/private/dicom_copy_IOD.m deleted file mode 100644 index 33ed893..0000000 --- a/CT/private/dicom_copy_IOD.m +++ /dev/null @@ -1,141 +0,0 @@ -function [all_attrs, status] = dicom_copy_IOD(X, map, metadata, options) -%DICOM_COPY_IOD Copy attributes from metadata to an arbitrary IOD. -% [ATTRS, STATUS] = DICOM_COPY_IOD(X, MAP, METADATA, OPTIONS) creates -% a structure array of DICOM attributes for an arbitrary SOP class -% corresponding to the class contained in the metadata structure. The -% value of image pixel attributes are derived from the image X and the -% colormap MAP. Non-image attributes are derived from the METADATA -% struct (typically given by DICOMINFO) and the transfer syntax UID -% (OPTIONS.txfr). -% -% NOTE: This routine does not verify that attributes in METADATA belong -% in the information object. A risk exists that invalid data passed to -% this routine will lead to formally correct DICOM files that contain -% incomplete or nonsensical data. -% -% See also: DICOMWRITE, DICOM_CREATE_IOD. - -% Copyright 1993-2014 The MathWorks, Inc. - -dictionary = dicomdict('get_current'); - -all_attrs = []; -status = []; - -% Determine what kind of object to write. -IOD_UID = getIOD(metadata, options, dictionary); - -% Update the instance-specific and required metadata. -metadata = dicom_prep_SOPCommon(metadata, IOD_UID, dictionary); -metadata = dicom_prep_FileMetadata(metadata, IOD_UID, options.txfr, dictionary); -metadata = dicom_prep_ImagePixel(metadata, X, map, options.txfr, options.usemetadatabitdepths, dictionary); - -% Get the metadata fields that need to be processed. -metadata_fields = fieldnames(metadata); -fields_to_write = remove_dicominfo_fields(metadata_fields); - -% Process all of the remaining metadata -for p = 1:numel(fields_to_write) - - attr_name = fields_to_write{p}; - - % Private tags have an odd group number. Only write them if the - % 'WritePrivate' option was true. - tag = dicom_tag_lookup(attr_name, dictionary); - if (isempty(tag)) || ((~options.writeprivate) && (rem(tag(1), 2) == 1)) - continue; - end - - new_attr = dicom_convert_meta_to_attr(attr_name, metadata, dictionary, options.txfr); - all_attrs = cat(2, all_attrs, new_attr); - -end - - - -function fields_out = remove_dicominfo_fields(metadata_fields) -%REMOVE_DICOMINFO_FIELDS Strip DICOMINFO-specific fields from metadata. - -dicominfo_fields = get_dicominfo_fields; -fields_out = setdiff(metadata_fields, dicominfo_fields); - - - -function fields = get_dicominfo_fields -%GET_DICOMINFO_FIELDS Get a cell array of field names specific to DICOMINFO. - -fields = {'Filename' - 'FileModDate' - 'FileSize' - 'Format' - 'FormatVersion' - 'Width' - 'Height' - 'BitDepth' - 'ColorType' - 'SelectedFrames' - 'FileStruct' - 'StartOfPixelData'}; - - - -function uidValue = getIOD(metadata, options, dictionary) - -% A field containing the SOP Class UID is necessary for writing. -% Look for the fields (0002,0002) and/or (0008,0016) in the metadata -% and/or options. - -% (0002,0002) is usually called "Media Storage SOP Class UID." It's the -% file metadata version of (0008,0016). -MediaStorageUID_name = dicom_name_lookup('0002', '0002', dictionary); - -if (isfield(metadata, MediaStorageUID_name)) - uidValue_0002_0002 = metadata.(MediaStorageUID_name); -else - uidValue_0002_0002 = ''; -end - -% (0008,0016) is usually known as "SOP Class UID." -SOPClassUID_name = dicom_name_lookup('0008', '0016', dictionary); -if (isfield(options, 'sopclassuid')) - - uidValue_0008_0016 = options.sopclassuid; - -else - - % Look for the SOP Class UID in the metadata under a different name. - if (isfield(metadata, SOPClassUID_name)) - uidValue_0008_0016 = metadata.(SOPClassUID_name); - else - uidValue_0008_0016 = ''; - end - -end - -% Pick the value of the UID. -if (~isempty(uidValue_0002_0002) && isempty(uidValue_0008_0016)) - - % Use the value of (0002,0002). - uidValue = uidValue_0002_0002; - -elseif (isempty(uidValue_0002_0002) && ~isempty(uidValue_0008_0016)) - - % Use the value of (0008, 0016). - uidValue = uidValue_0008_0016; - -elseif (~isempty(uidValue_0002_0002) && ~isempty(uidValue_0008_0016)) - - % If both Media Storage Class UID and SOP Class UID are present, they - % must match. - if isequal(uidValue_0002_0002, uidValue_0008_0016) - uidValue = uidValue_0002_0002; - else - error(message('images:dicom_copy_IOD:iodMismatch', SOPClassUID_name, MediaStorageUID_name)) - end - -else - - error(message('images:dicom_copy_IOD:missingSOPClassUID', SOPClassUID_name)); - -end - diff --git a/CT/private/dicom_create_IOD.m b/CT/private/dicom_create_IOD.m deleted file mode 100644 index b311c5d..0000000 --- a/CT/private/dicom_create_IOD.m +++ /dev/null @@ -1,603 +0,0 @@ -function [attrs, status] = dicom_create_IOD(IOD_UID, X, map, metadata, options) -%DICOM_CREATE_IOD Create the attributes for a given IOD. -% [ATTRS, STATUS] = DICOM_CREATE_IOD(UID, X, MAP, METADATA, TXFR) -% creates a structure array of DICOM attributes for the SOP Class -% corresponding to UID. The attributes' values are bassed on the image -% X, colormap MAP, the METADATA struct (as given by DICOMINFO, for -% example), and the transfer syntax UID (TXFR) used to encode the -% file. -% -% This is the principal function of DICOM information object creation. -% -% See also DICOMWRITE, DICOM_PREP_METADATA, DICOM_IODS, DICOM_MODULES. - -% Copyright 1993-2014 The MathWorks, Inc. - -dictionary = dicomdict('get_current'); - -% Find modules and other details. -iod_details = get_iod_details(IOD_UID); - -if (isempty(iod_details)) - error(message('images:dicom_create_IOD:unimplementedIOD', IOD_UID)); -end - -% Set necessary values for this IOD. -metadata = dicom_prep_metadata(IOD_UID, metadata, X, map, options.txfr, options.usemetadatabitdepths, dictionary); - -% Look for all of the private metadata. -if (isfield(options, 'writeprivate')) - - if (islogical(options.writeprivate) || ... - isnumeric(options.writeprivate)) - - if (options.writeprivate) - - [private_tags, private_names] = find_private_metadata(metadata, dictionary); - - end - - else - - error(message('images:dicom_create_IOD:invalidWritePrivateValue')) - - end - -end - -% A module definition function must be registered for unsupported or -% private modules. Private IODs need only use a custom definition -% function for unimplemented modules, but they must have a definition -% function listed. (Registration not yet supported.) -if (isempty(iod_details.Def_fcn)) - error(message('images:dicom_create_IOD:noModuleDefinitionFcn', iod_details.Name, IOD_UID)); -end - -attrs = []; -status = []; -for p = 1:numel(iod_details.Modules(:,1)) - - % Determine whether to encode this module. - if (test_module_condition(X, metadata, iod_details.Modules(p,:), dictionary)) - - % Find the attributes in the module. - module_details = dicom_modules(iod_details.Modules{p,1}); - - if (isempty(module_details)) - error(message('images:dicom_create_IOD:undefinedModule', iod_details.Modules{ p, 1 })); - end - - % Process attributes. - [new_attrs, new_status] = process_modules(module_details.Attrs, ... - metadata, ... - dictionary); - attrs = add_to_IOD(attrs, new_attrs); - status = add_to_status(status, new_status); - - end - -end - -% Process any private metadata. -if ((options.writeprivate) && (~isempty(private_tags))) - - new_attrs = process_private(private_tags, private_names, metadata, dictionary, options.txfr); - attrs = add_to_IOD(attrs, new_attrs); - -end - - - -function iod_details = get_iod_details(IOD_UID) -%GET_IOD_DETAILS Find the details of a given IOD. - -% Load IOD definitions. -iod_directory = dicom_iods; - -% Look for a particular UID. -idx = strmatch(IOD_UID, {iod_directory.UID}, 'exact'); - -if (isempty(idx)) - iod_details = []; -else - iod_details = iod_directory(idx); -end - - - -function attrs = add_to_IOD(attrs, new_attrs) -%ADD_TO_IOD Add attributes to an existing IOD. -attrs = cat(2, attrs, new_attrs); - - - -function status = add_to_status(status, new_status) -%ADD_TO_STATUS Add status values to an existing status struct. - -fnames = fieldnames(new_status); -for p = 1:numel(fnames) - if (isfield(status, fnames{p})) - status(1).(fnames{p}) = [status(1).(fnames{p}) ... - new_status(1).(fnames{p})]; - else - status(1).(fnames{p}) = new_status(1).(fnames{p}); - end -end - - - -function [attrs, status] = process_modules(attr_details, metadata, dictionary) -%PROCESS_MODULES Create attributes from a module definition. - -attrs = []; -status.BadAttribute = {}; -status.MissingCondition = {}; -status.MissingData = {}; -status.SuspectAttribute = {}; - -p = 0; -numAttrs = numel(attr_details(:,1)); -% For each attribute in the module... -while (p < numAttrs) - - p = p + 1; - - level = attr_details{p, 1}; - group = attr_details{p, 2}; - element = attr_details{p, 3}; - attr_type = attr_details{p, 4}; - vr_map = attr_details{p, 5}; - enum_values = attr_details{p, 6}; - condition = attr_details{p, 7}; - - % Skip all sequence attributes for now. - % - % NOTE: At this point, all sequences in supported modules are - % type 3 (optional). We can, and will, safely skip all - % attributes in a sequence (including the top level attribute). - - nextAttr = p + 1; - if ((p < numAttrs) && ... - (attr_details{nextAttr, 1} > level)) - - % The "level" determines nesting, with 0 as the - % non-sequence elements - while ((nextAttr <= numAttrs) && ... - (attr_details{nextAttr, 1} > level)) - - nextAttr = nextAttr + 1; - - end - - % Point to the next attribute after the sequence. - p = nextAttr - 1; - continue - - end - - % - % Look for the attribute from the module. - % - try - name = dicom_name_lookup(group, element, dictionary); - catch - status.BadAttribute{end + 1} = sprintf('(%s,%s)', ... - group, element); - continue; - end - - if (isempty(name)) - status.BadAttribute{end + 1} = sprintf('(%s,%s)', ... - group, element); - continue; - end - - % - % Determine how to handle the attribute. - % - switch (attr_type) - case {'1', '2', '3'} - % Must process the attribute. No special action. - - case {'1C', '2C'} - % Conditionally process the attribute. - if (isempty(condition)) - - status.MissingCondition{end + 1} = sprintf('(%s,%s)', ... - group, element); - continue; - - else - - if (~check_condition(condition, metadata, dictionary)) - continue; - end - - end - - otherwise - status.BadAttribute{end + 1} = sprintf('(%s,%s)', group, element); - continue; - - end - - % Process special VR mapping. - if ((isequal(group, '7FE0')) && (isequal(element, '0010'))) - VR = get_pixelData_VR(metadata, dictionary); - else - if (numel(vr_map) == 0) - VR = ''; - else - VR = remap_vr(group, element, vr_map, metadata, dictionary); - end - end - - % - % Add the attribute. - % - if (isfield(metadata, name)) - - % Process acceptable values. - if ((~isempty(enum_values)) && (~isempty(metadata.(name)))) - if (~check_values(metadata.(name), enum_values)) - status.SuspectAttribute{end + 1} = sprintf('(%s,%s)', ... - group, element); - end - end - - % Add the attribute. - if (isempty(VR)) - attrs = dicom_add_attr(attrs, group, element, dictionary, ... - metadata.(name)); - else - attrs = dicom_add_attr(attrs, group, element, dictionary, ... - metadata.(name), VR); - end - - else - - switch (attr_type) - case {'1', '1C'} - - % The attribute should exist. - status.MissingData{end + 1} = sprintf('(%s,%s)', ... - group, element); - continue; - - case {'2', '2C'} - - % Nonexistent attributes have empty data. - attrs = dicom_add_attr(attrs, group, element, dictionary); - - end - - % Nonexistent type 3 is ignored. - - end - -end - - - -function tf = check_condition(expr, metadata, dictionary) -%CHECK_CONDITION Determine whether a particular condition is true. -% -% Conditions are LISP-style cell arrays. The first element is a -% conditional operator, remaining cells are arguments to the operator. -% -% Conditions can be nested. Each cell array in expr indicates a new -% conditional expression. - -% -% Error checking -% -if (~iscell(expr)) - error(message('images:dicom_create_IOD:conditionalsMustBeCellArrays')) -end - -if (numel(expr) == 1) - operator = expr{1}; - operands = {}; -else - operator = expr{1}; - operands = expr(2:end); -end - - -% -% Process conditional expressions recursively. -% -switch (lower(operator)) -case 'and' - - % This AND short circuits. - for p = 1:numel(operands) - tf = check_condition(operands{p}, metadata, dictionary); - - if (~tf) - return - end - end - -case 'equal' - - if (numel(operands) ~= 2) - error(message('images:dicom_create_IOD:presentOpNeeds2Args')) - end - - % Get the group and element from the first operand. - group = operands{1}(2:5); - element = operands{1}(7:10); - - % Look up the metadata value. - name = dicom_name_lookup(group, element, dictionary); - - if (isfield(metadata, name)) - tf = isequal(metadata.(name), operands{2}); - else - tf = false; - end - -case 'false' - - tf = false; - -case 'not' - - if (numel(operands) ~= 1) - error(message('images:dicom_create_IOD:tooManyArgsToNot')) - else - tf = ~check_condition(operands{1}, metadata, dictionary); - end - -case 'or' - - % This OR short circuits. - for p = 1:numel(operands) - tf = check_condition(operands{p}, metadata, dictionary); - - if (tf) - return - end - end - -case 'present' - - if (numel(operands) ~= 1) - error(message('images:dicom_create_IOD:presentNeeds1Arg')) - end - - % Get the group and element from the first operand. - group = operands{1}(2:5); - element = operands{1}(7:10); - - % Look up the metadata value. - name = dicom_name_lookup(group, element, dictionary); - - tf = isfield(metadata, name); - -case 'true' - - tf = true; - -otherwise - error(message('images:dicom_create_IOD:badConditionalOp', operator)) -end - - - -function tf = test_module_condition(X, metadata, module, dictionary) -%TEST_MODULE_CONDITIONS Test whether a module should be created. - -moduleType = module{2}; -moduleCondition = module{3}; - -switch (moduleType) -case {'M'} - - tf = true; - -case {'U', 'C'} - - if (isempty(moduleCondition)) - tf = false; - return - end - - switch (moduleCondition{1}) - case 'HAS_FILEMETADATA' - tf = true; - - case 'HAS_BOLUS' - tf = isfield(metadata, dicom_name_lookup('0018', '0010', dictionary)); - - case 'HAS_OVERLAY' - tf = isfield(metadata, dicom_name_lookup('6000', '0010', dictionary)); - - case 'HAS_VOILUT' - tf = ((isfield(metadata, dicom_name_lookup('0028', '3010', dictionary))) || ... - (isfield(metadata, dicom_name_lookup('0028', '1050', dictionary)))); - - case 'IS_MULTIFRAME' - tf = size(X,4) > 1; - - case 'NEEDS_SC_CINE' - - framePointerAttr = dicom_name_lookup('0028', '0009', dictionary); - if (isfield(metadata, framePointerAttr)) - - framePointer = metadata.(framePointerAttr); - tf = (isequal(framePointer(:), sscanf('0018 1063', '%x')) || ... - isequal(framePointer(:), sscanf('0018 1065', '%x'))); - - else - - tf = false; - - end - - case 'TRUE' - tf = true; - - case 'FALSE' - tf = false; - - otherwise - tf = false; - - end - -otherwise - error(message('images:dicom_create_IOD:unknownModuleType', moduleType)) - -end - - - -function VR = remap_vr(group, element, vr_map, metadata, dictionary) -%REMAP_VR Translate a VR mapping into a VR value. - -% Default behavior is an empty VR. -VR = ''; - -if (numel(vr_map) > 1) - - % First item in VR map is an attribute tag. - cond_name = dicom_name_lookup(vr_map{1}(2:5), vr_map{1}(7:10), dictionary); - - % Remaining items map the conditional attribute's value to a VR. - if (isfield(metadata, cond_name)) - - for p = 2:numel(vr_map) - - if (isequal(metadata.(cond_name), vr_map{p}{1})) - - VR = vr_map{p}{2}; - return - - end - - end - - end - - % If the condition isn't met (or the attribute isn't present), - % use the first entry in the attribute's VR list. - if (isempty(VR)) - - attr = dicom_dict_lookup(group, element); - VR = attr.VR; - - end - -elseif (numel(vr_map) == 1) - - % Only item in VR map is the VR. - VR = vr_map{1}; - -end - - - -function VR = get_pixelData_VR(metadata, dictionary) -%GET_PIXELDATA_VR Get the VR for (7FE0,0010). -% -% PS 3.5 Sec. 8 contains the rules for picking the VR of (7FE0,0010). - -uid_details = dicom_uid_decode(metadata.(dicom_name_lookup('0002','0010', dictionary))); - -if (uid_details.Compressed) - - % Compressed pixels are always stored OB. - VR = 'OB'; - -elseif (isequal(uid_details.VR, 'Implicit')) - - % Implicit VR transfer syntaxes are always OW. - VR = 'OW'; - -else - - % The VR of other Explicit VR transfter syntaxes depends on the bit - % depth of the pixels. - if (metadata.(dicom_name_lookup('0028','0100', dictionary)) <= 8) - VR = 'OB'; - else - VR = 'OW'; - end - -end - - - -function tf = check_values(attr_data, enum_values) -%CHECK_VALUE Verify an attribute's data against required values. - -if (iscellstr(enum_values)) - - tf = any(strcmp(attr_data, enum_values)); - -else - - tmp = 0; - for p = 1:numel(enum_values) - tmp = tmp + isequal(attr_data, enum_values{p}); - end - - tf = (tmp > 0); - -end - - - -function [private_attrs, private_names] = find_private_metadata(metadata, dictionary) -%FIND_PRIVATE_METADATA Find user-contributed private metadata. - -% Private attributes have odd element values in their tag. -% -% By default these values come back from DICOMINFO with field names like -% "Private_0029_1004" and "Private_0029_10xx_Creator". -% -% If a custom data dictionary is provided, the names will look like -% regular DICOM attributes. - -private_attrs = {}; -private_names = {}; - -% Look through metadata for private attributes. -fields = fieldnames(metadata); - -for p = 1:numel(fields) - - tag = dicom_tag_lookup(fields{p}, dictionary); - - if ((~isempty(tag)) && (rem(tag(1), 2) ~= 0)) - private_attrs{end + 1} = tag; %#ok - private_names{end + 1} = fields{p}; %#ok - end - -end - - - -function [attrs, status] = process_private(private_tags, private_names, metadata, dictionary, txfr) -%PROCESS_PRIVATE Create attributes from the private data list. - -% Delay judgement of Private attributes. -status.BadAttribute = {}; -status.MissingCondition = {}; -status.MissingData = {}; -status.SuspectAttribute = {}; - -% Preallocate the attribute structure. -attrs(numel(private_tags)).Group = []; -attrs(end).Element = []; -attrs(end).VR = ''; -attrs(end).VM = []; -attrs(end).Data = []; - -% Convert the private data to a writable attribute. -for p = 1:numel(private_tags) - attrs(p) = dicom_convert_meta_to_attr(private_names{p}, metadata, dictionary, txfr); -end - diff --git a/CT/private/dicom_create_attr.m b/CT/private/dicom_create_attr.m deleted file mode 100644 index 4c63cae..0000000 --- a/CT/private/dicom_create_attr.m +++ /dev/null @@ -1,13 +0,0 @@ -function attr = dicom_create_attr -%DICOM_CREATE_ATTR Create a structure to contain an attribute. -% ATTR = DICOM_CREATE_ATTR create a structure ATTR to contain an -% attribute's metadata. The fields are filled with empty values. - -% Copyright 1993-2005 The MathWorks, Inc. - -attr = struct('Name', '', ... - 'Group', [], ... - 'Element', [], ... - 'VR', '', ... - 'VM', [], ... - 'Length', []); diff --git a/CT/private/dicom_create_file_struct.m b/CT/private/dicom_create_file_struct.m deleted file mode 100644 index 12c41b1..0000000 --- a/CT/private/dicom_create_file_struct.m +++ /dev/null @@ -1,16 +0,0 @@ -function file = dicom_create_file_struct -%CREATE_FILE_STRUCT Create a file structure with default values. -% FILE = DICOM_CREATE_FILE create a structure FILE to contain -% information about the DICOM message pool. On creation, the fields -% are filled with values to indicate that no files have been chosen. - -% Copyright 1993-2010 The MathWorks, Inc. - -file.Filename = ''; -file.Current_Message = 0; -file.FID = -1; -file.Current_Endian = ''; -file.Pixel_Endian = ''; -file.Current_VR = ''; -file.Warn.Current = 0; -file.Warn.Max = inf; diff --git a/CT/private/dicom_decode_jpg8.m b/CT/private/dicom_decode_jpg8.m deleted file mode 100644 index 3662a4a..0000000 --- a/CT/private/dicom_decode_jpg8.m +++ /dev/null @@ -1,49 +0,0 @@ -function pixel_cells = dicom_decode_jpg8(comp_fragment) -%DICOM_DECODE_JPG8 Decode a JPEG compressed bytestream. -% PIXEL_CELLS = DICOM_DECODE_JPG8(COMP_FRAGMENT) decompresses the 8-bit -% to 16-bit lossy or lossless JPEG compressed fragment COMP_FRAGMENT and -% returns the decompressed PIXEL_CELLS. PIXEL_CELLS is an m-by-n -% rectangular array of image data returned by IMREAD and contains a -% complete, correctly shaped and oriented image. -% -% PIXEL_CELLS is a UINT8 array is the JPEG file contains 8 or fewer bytes -% per sample. Otherwise PIXEL_CELLS is a UINT16 array. PIXEL_CELLS will -% need to be cast to a signed type if the DICOM file's Pixel Representation -% is 1. -% -% See also: IMREAD, IMFINFO. - -% Copyright 1993-2010 The MathWorks, Inc. - -% Open a temporary file for the JPEG data. -tmp_file = tempname; -fid = fopen(tmp_file, 'w'); - -if (fid < 3) - error(message('images:dicom_decode_jpg8:CouldNotOpenFile', tmp_file)) -end - -% Write the JPEG bytestream to the file. -count = fwrite(fid, comp_fragment, 'uint8'); - -if (count ~= length(comp_fragment)) - warning(message('images:dicom_decode_jpg8:dataTruncatedWhenWritingToTempFile')) -end - -% Close the temporary file. -fclose(fid); - -% Reread the file. -try - pixel_cells = imread(tmp_file, 'jpeg'); -catch ME - delete(tmp_file); - rethrow(ME) -end - -% Remove the temporary file. -try - delete(tmp_file); -catch - warning(message('images:dicom_decode_jpg8:CouldNotDeleteTempFile', tmp_file)) -end diff --git a/CT/private/dicom_decode_pixel_cells.m b/CT/private/dicom_decode_pixel_cells.m deleted file mode 100644 index d072990..0000000 --- a/CT/private/dicom_decode_pixel_cells.m +++ /dev/null @@ -1,139 +0,0 @@ -function [pixels, overlays] = dicom_decode_pixel_cells(data, info, ol_bits) -%DICOM_DECODE_PIXEL_CELLS Get pixel values and overlay bits from pixel cells. -% [PIXELS, OVERLAYS] = DICOM_DECODE_PIXEL_CELLS(DATA, INFO, BITS) -% extracts the pixel and overlay data from the pixel cells DATA. INFO -% is the metadata structure for the pixel data array DATA. OL_BITS is -% a vector of bit positions in DATA which contain overlay data, which -% are always single bits. -% -% The PIXELS returned are a vector of integer values without overlay -% data. The values in PIXELS have been shifted to start at the -% least-significant byte for each element, so that they actually -% represent the correct pixel values without further modification. -% -% The OVERLAYS array is an m-by-n-by-1-by-p logical array, where p is -% the number of overlays in the DATA. - -% Copyright 1993-2005 The MathWorks, Inc. - - -% -% Read overlays. -% - -if (isempty(ol_bits)) - - overlays = logical([]); - -else - - overlays = repmat(false, [info.Rows info.Columns info.NumberOfFrames ... - length(ol_bits)]); - -end - -level = 0; - -for p = 1:length(ol_bits) - - level = level + 1; - - plane = bitget(data, (ol_bits(p) + 1)); - plane = reshape(plane, [size(overlays,1), size(overlays,2), ... - size(overlays,3)]); - - plane = permute(plane, [2 1 3]); - overlays(:, :, :, level) = plane; - -end - -% -% Strip out overlays. -% - -% Convert signed data temporarily to unsigned. -if (info.PixelRepresentation == 1) - - switch (class(data)) - case 'int8' - data = dicom_typecast(data, 'uint8'); - case 'int16' - data = dicom_typecast(data, 'uint16'); - case 'int32' - data = dicom_typecast(data, 'uint32'); - end - -end - -% Remove higher order overlays. -mask = (2^(info.HighBit + 1) - 1); -data = bitand(data, mask); - -% Remove lower order overlays. -bit_offset = (info.HighBit + 1) - info.BitsStored; -data = bitshift(data, -bit_offset); - -% Fit the data into an appropriate sized storage unit. -container_size = ceil(info.BitsStored / 8) * 8; - -if (info.PixelRepresentation == 1) - - sign_bit = info.HighBit - bit_offset + 1; - has_negative = any(bitget(data, sign_bit)); - - % Move the size bit to the end of the data container (e.g., the 8th - % or 16th bit) and fill old sign bit with 0. - if ((sign_bit ~= container_size) && (has_negative)) - - mask = bitget(data, sign_bit); - data = bitor(data, bitshift(mask, container_size)); - data = bitset(data, sign_bit, 0); - - end - -end - -% Convert signed data back from unsigned. -if (info.PixelRepresentation == 1) - - switch (class(data)) - case 'uint8' - data = dicom_typecast(data, 'int8'); - case 'uint16' - data = dicom_typecast(data, 'int16'); - case 'uint32' - data = dicom_typecast(data, 'int32'); - end - -end - -% -% Store pixel bits. -% - -switch (container_size) -case 8 - - if (info.PixelRepresentation == 0) - pixels = uint8(data); - else - pixels = int8(data); - end - -case 16 - - if (info.PixelRepresentation == 0) - pixels = uint16(data); - else - pixels = int16(data); - end - -case 32 - - if (info.PixelRepresentation == 0) - pixels = uint32(data); - else - pixels = int32(data); - end - -end diff --git a/CT/private/dicom_decode_rle_segment.mexw64 b/CT/private/dicom_decode_rle_segment.mexw64 deleted file mode 100644 index c7fe647..0000000 Binary files a/CT/private/dicom_decode_rle_segment.mexw64 and /dev/null differ diff --git a/CT/private/dicom_dict_lookup.m b/CT/private/dicom_dict_lookup.m deleted file mode 100644 index 6f8f38c..0000000 --- a/CT/private/dicom_dict_lookup.m +++ /dev/null @@ -1,71 +0,0 @@ -function attr = dicom_dict_lookup(group, element, dictionary) -%DICOM_DICT_LOOKUP Lookup an attribute in the data dictionary. -% ATTRIBUTE = DICOM_DICT_LOOKUP(GROUP, ELEMENT, DICTIONARY) searches for -% the attribute (GROUP,ELEMENT) in the data dictionary, DICTIONARY. A -% structure containing the attribute's properties from the dictionary -% is returned. ATTRIBUTE is empty if (GROUP,ELEMENT) is not in -% DICTIONARY. -% -% Note: GROUP and ELEMENT can be either decimal values or hexadecimal -% strings. - -% Copyright 1993-2010 The MathWorks, Inc. - - -% IMPORTANT NOTE: -% -% This function must be wrapped inside of a try-catch-end block in order -% to prevent the DICOM file from being left open after an error. - - -MAX_GROUP = 65535; % 0xFFFF -MAX_ELEMENT = 65535; % 0xFFFF - -% -% Load the data dictionary. -% - -persistent tags values prev_dictionary; -mlock; - -% Load dictionary for the first time or if dictionary has changed. -if ((isempty(values)) || (~isequal(prev_dictionary, dictionary))) - - [tags, values] = dicom_load_dictionary(dictionary); - prev_dictionary = dictionary; - -end - -% -% Convert hex strings to decimals. -% - -if (ischar(group)) - group = sscanf(group, '%x'); -end - -if (ischar(element)) - element = sscanf(element, '%x'); -end - -if (group > MAX_GROUP) - error(message('images:dicom_dict_lookup:groupOutOfRange', sprintf( '%x', group ), sprintf( '(%x,%04x)', group, element ))) -end - - -if (element > MAX_ELEMENT) - error(message('images:dicom_dict_lookup:elementOutOfRange', sprintf( '%x', element ), sprintf( '(%04x,%x)', group, element ))) -end - -% -% Look up the attribute. -% - -% Group and Element values in the published data dictionary are 0-based. -index = tags((group + 1), (element + 1)); - -if (index == 0) - attr = struct([]); -else - attr = values(index); -end diff --git a/CT/private/dicom_encode_attrs.m b/CT/private/dicom_encode_attrs.m deleted file mode 100644 index 3386628..0000000 --- a/CT/private/dicom_encode_attrs.m +++ /dev/null @@ -1,320 +0,0 @@ -function data_streams = dicom_encode_attrs(attrs, txfr_syntax, uid_details) -%DICOM_ENCODE_ATTRS Encode a collection of attributes to a data stream. -% STREAMS = DICOM_ENCODE_ATTRS(ATTRS, TXFR) encode the attributes in -% the structure ATTRS according to the transfer syntax TXFR. The -% result is a cell array containing vectors of UINT8 values, which -% represent the values to be written to the output device. Each cell -% contains the encoded data stream for all of the attributes which -% share a common group number. -% -% Note: It is assumed that the attribute's data is already in the -% corresponding data type for the VR (e.g., if the VR is UL, the data -% is already UINT32). -% -% See also DICOM_ADD_ATTR, DICOM_ENCODE_PIXEL_CELLS. - -% Copyright 1993-2010 The MathWorks, Inc. - - -% -% Determine whether data will need to be byte swapped. -% - -[swap_file, swap_meta, swap_pixel] = determine_swap(txfr_syntax, uid_details); -PIXEL_GROUP = sscanf('7fe0', '%x'); -PIXEL_ELEMENT = sscanf('0010', '%x'); - -% -% Process the attributes. -% - -total_attrs = length(attrs); -current_attr = 1; -current_stream = 1; - -data_streams = {}; - -while (current_attr <= total_attrs) - - current_group = attrs(current_attr).Group; - stream = uint8([]); - - % Process each attribute of the group. - while (attrs(current_attr).Group == current_group) - - % Get the current attribute. - attr = attrs(current_attr); - - % Create the UINT8 output stream. - if (attr.Element == 0) - - % Skip group lengths. - encoded_attr = uint8([]); - - elseif (current_group == 2) - - encoded_attr = create_encoded_attr(attr, uid_details, swap_file); - - elseif ((attr.Group == PIXEL_GROUP) && ... - (attr.Element == PIXEL_ELEMENT)) - - encoded_attr = create_encoded_attr(attr, uid_details, swap_pixel); - - % GE format has different endianness within the PixelData - % attribute. Fix it. - if (isequal(txfr_syntax, '1.2.840.113619.5.2')) - encoded_attr = fix_pixel_attr(encoded_attr); - end - - else - - encoded_attr = create_encoded_attr(attr, uid_details, swap_meta); - - end - - % Add to the output stream. - stream = [stream encoded_attr]; %#ok - current_attr = current_attr + 1; - - % Don't index past the end of the attrs array. - if (current_attr > total_attrs) - break - end - - end - - % Prepend group length attribute. - if (current_group == 2) - - len_attr.Group = current_group; - len_attr.Element = 0; - len_attr.VR = 'UL'; - len_attr.Data = uint32(length(stream)); - - encoded_attr = create_encoded_attr(len_attr, uid_details, swap_file); - - stream = [encoded_attr stream]; - - end - - % Store the stream. - data_streams{current_stream} = stream; - - current_stream = current_stream + 1; - -end - - - -function segment = create_encoded_attr(attr, uid_details, swap) - -% If it's a sequence, recursively enocde the items and attributes. -if (isstruct(attr.Data)) - - fnames = fieldnames(attr.Data); - - if ((isequal(attr.VR, 'PN')) || ... - (~isempty(strfind(lower(fnames{1}), 'name')))) - - attr.Data = dicom_encode_pn(attr.Data); - - else - - attr.Data = encode_structure(attr.Data, uid_details, swap); - - end -end - -% Determine size of data. -switch (class(attr.Data)) -case {'uint8', 'int8', 'char'} - data_size = 1; - -case {'uint16', 'int16'} - data_size = 2; - -case {'uint32', 'int32', 'single'} - data_size = 4; - -case {'double'} - data_size = 8; - -end - -% Group and Element -segment = dicom_typecast(uint16(attr.Group), 'uint8', swap); -segment = [segment dicom_typecast(uint16(attr.Element), 'uint8', swap)]; - -% VR and Length -if ((isequal(uid_details.VR, 'Implicit')) && (attr.Group > 2)) - - % VR does not appear in the file. - - len = uint32(data_size * length(attr.Data)); - -else - - % VR. - segment = [segment uint8(attr.VR)]; - - % Determine length. - switch (attr.VR) - case {'OB', 'OW', 'SQ'} - - segment = [segment uint8([0 0])]; % Padding. - - len = uint32(data_size * length(attr.Data)); - - case {'UN'} - - if (attr.Group == 65534) % 0xfffe - - % Items/delimiters don't have VR or two-byte padding. - segment((end - 1):end) = []; - - else - - segment = [segment uint8([0 0])]; % Padding. - - end - - len = uint32(data_size * length(attr.Data)); - - case {'UT'} - - % Syntactically this is read the same as OB/OW/etc., but it - % cannot have undefined length. - - segment = [segment uint8([0 0])]; % Padding. - - len = uint32(data_size * length(attr.Data)); - - case {'AE','AS','AT','CS','DA','DS','DT','FD','FL','IS', ... - 'LO','LT', 'PN','SH','SL','SS','ST','TM','UI','UL','US'} - - len = uint16(data_size * length(attr.Data)); - - otherwise - - % PS 3.5-1999 Sec. 6.2 indicates that all unknown VRs can be - % interpretted as being the same as OB, OW, SQ, or UN. The - % size of data is not known but, the reading structure is. - - segment = [segment uint8([0 0])]; % Padding. - - len = uint32(data_size * length(attr.Data)); - - end - - % Special case for length of encapsulated (7FE0,0010). - if (((attr.Group == 32736) && (attr.Element == 16)) && ... - (uid_details.Compressed == 1)) - - % Undefined length. - len = dicom_undefined_length(); - - end - -end - -% If the data length is odd, then we will have to pad it. Add one to the -% length of the attribute. -if ((len ~= dicom_undefined_length()) && (rem(len, 2) ~= 0)) - len = len + 1; -end - -% Add the length and data to the segment. -segment = [segment dicom_typecast(len, 'uint8', swap)]; - -if (ischar(attr.Data)) - segment = [segment uint8(attr.Data(:)')]; -else - tmp = dicom_typecast(attr.Data, 'uint8', swap); - segment = [segment tmp(:)']; -end - -% Pad the data (if necessary) by adding a null byte. -if (rem(numel(segment), 2) ~= 0) - segment(end + 1) = 0; %#ok -end - - - -function [tf_file, tf_meta, tf_pixel] = determine_swap(txfr_syntax, uid_details) - -[a, b, endian] = computer; - -switch (endian) -case 'B' - - if (isequal(txfr_syntax, '1.2.840.113619.5.2')) - tf_file = 1; - tf_meta = 1; - tf_pixel = 0; - elseif (isequal(uid_details.Endian, 'ieee-be')) - tf_file = 1; - tf_meta = 0; - tf_pixel = 0; - else - tf_file = 1; - tf_meta = 1; - tf_pixel = 1; - end - -case 'L' - - if (isequal(txfr_syntax, '1.2.840.113619.5.2')) - tf_file = 0; - tf_meta = 0; - tf_pixel = 1; - elseif (isequal(uid_details.Endian, 'ieee-le')) - tf_file = 0; - tf_meta = 0; - tf_pixel = 0; - else - tf_file = 0; - tf_meta = 1; - tf_pixel = 1; - end - -end - - - -function data = fix_pixel_attr(data) - -% GE's special transfer syntax has different endianness within the -% attribute. Swap the bytes for the tag and length. Leave the rest -% alone. -% -% Swapping always needs to be done regardless of the endianness of the -% processor. It undoes a prior, unwanted swap of the tag and length. - -tag = data(1:4); -tag = dicom_typecast(dicom_typecast(tag, 'uint16'), 'uint8', 1); - -len = data(5:8); -len = dicom_typecast(dicom_typecast(len, 'uint32'), 'uint8', 1); - -data(1:4) = tag; -data(5:8) = len; - - - -function encoded_data = encode_structure(struct_data, uid_details, swap) -%ENCODE_STRUCTURE Turn a structure of data into a byte stream. - -% If it's a sequence, the structure will contain fields named 'Item_n'. -% To encode the sequence: -% (1) Add an item tag. -% (2) Encode the attributes within the item. - -encoded_data = uint8([]); - -for p = 1:numel(struct_data) - - tmp = dicom_encode_attrs(struct_data(p), uid_details.Value, uid_details); - encoded_data = [encoded_data ... - tmp{1}]; - -end diff --git a/CT/private/dicom_encode_jpeg2000_lossless.m b/CT/private/dicom_encode_jpeg2000_lossless.m deleted file mode 100644 index 423770d..0000000 --- a/CT/private/dicom_encode_jpeg2000_lossless.m +++ /dev/null @@ -1,38 +0,0 @@ -function [fragments, frames] = dicom_encode_jpeg2000_lossless(X, bits) -%DICOM_ENCODE_JPEG2000_LOSSLESS Encode pixel cells using lossless JPEG. -% [FRAGMENTS, LIST] = DICOM_ENCODE_JPEG2000_LOSSLESS(X) compresses and -% encodes the image X using lossless JPEG compression. FRAGMENTS is -% a cell array containing the encoded frames (as UINT 8data) from the -% compressor. LIST is a vector of indices to the first fragment of -% each compressed frame of a multiframe image. -% -% See also DICOM_ENCODE_RLE, DICOM_ENCODE_JPEG2000_LOSSY. - -% Copyright 2010 The MathWorks, Inc. - - -% Use IMWRITE to create a JPEG image. - -numFrames = size(X,4); -fragments = cell(numFrames, 1); -frames = 1:numFrames; - -for p = 1:numFrames - - tempfile = tempname; - imwrite(X(:,:,:,p), tempfile, 'j2c', 'mode', 'lossless'); - - % Read the image from the temporary file. - fid = fopen(tempfile, 'r'); - fragments{p} = fread(fid, inf, 'uint8=>uint8'); - fclose(fid); - - % Remove the temporary file. - try - delete(tempfile) - catch - warning(message('images:dicom_encode_jpeg2000_lossless:tempFileDelete', tempfile)); - end - -end - diff --git a/CT/private/dicom_encode_jpeg2000_lossy.m b/CT/private/dicom_encode_jpeg2000_lossy.m deleted file mode 100644 index df135dd..0000000 --- a/CT/private/dicom_encode_jpeg2000_lossy.m +++ /dev/null @@ -1,38 +0,0 @@ -function [fragments, frames] = dicom_encode_jpeg2000_lossy(X, bits) -%DICOM_ENCODE_JPEG2000_LOSSY Encode pixel cells using lossy JPEG. -% [FRAGMENTS, LIST] = DICOM_ENCODE_JPEG2000_LOSSY(X) compresses and -% encodes the image X using lossy JPEG2000 compression. FRAGMENTS is -% a cell array containing the encoded frames (as UINT8 data) from the -% compressor. LIST is a vector of indices to the first fragment of -% each compressed frame of a multiframe image. -% -% See also DICOM_ENCODE_RLE, DICOM_ENCODE_JPEG2000_LOSSY. - -% Copyright 2010 The MathWorks, Inc. - - -% Use IMWRITE to create a JPEG2000 image. - -numFrames = size(X,4); -fragments = cell(numFrames, 1); -frames = 1:numFrames; - -for p = 1:numFrames - - tempfile = tempname; - imwrite(X(:,:,:,p), tempfile, 'j2c', 'mode', 'lossy'); - - % Read the image from the temporary file. - fid = fopen(tempfile, 'r'); - fragments{p} = fread(fid, inf, 'uint8=>uint8'); - fclose(fid); - - % Remove the temporary file. - try - delete(tempfile) - catch - warning(message('images:dicom_encode_jpeg2000_lossy:tempFileDelete', tempfile)); - end - -end - diff --git a/CT/private/dicom_encode_jpeg_lossless.m b/CT/private/dicom_encode_jpeg_lossless.m deleted file mode 100644 index a883d69..0000000 --- a/CT/private/dicom_encode_jpeg_lossless.m +++ /dev/null @@ -1,46 +0,0 @@ -function [fragments, frames] = dicom_encode_jpeg_lossless(X, bits) -%DICOM_ENCODE_JPEG_LOSSLESS Encode pixel cells using lossless JPEG. -% [FRAGMENTS, LIST] = DICOM_ENCODE_JPEG_LOSSLES(X) compresses and -% encodes the image X using baseline lossles JPEG compression. -% FRAGMENTS is a cell array containing the encoded frames (as UINT8 -% data) from the compressor. LIST is a vector of indices to the first -% fragment of each compressed frame of a multiframe image. -% -% See also DICOM_ENCODE_RLE, DICOM_ENCODE_JPEG_LOSSY. - -% Copyright 1993-2010 The MathWorks, Inc. - - -% Use IMWRITE to create a JPEG image. - -classname = class(X); - -switch (classname) -case {'int8', 'int16'} - tmp = dicom_typecast(X(:), ['u' classname]); - X = reshape(tmp, size(X)); -end - -numFrames = size(X,4); -fragments = cell(numFrames, 1); -frames = 1:numFrames; - -for p = 1:numFrames - - tempfile = tempname; - imwrite(X(:,:,:,p), tempfile, 'jpeg', 'mode', 'lossless', 'bitdepth', bits); - - % Read the image from the temporary file. - fid = fopen(tempfile, 'r'); - fragments{p} = fread(fid, inf, 'uint8=>uint8'); - fclose(fid); - - % Remove the temporary file. - try - delete(tempfile) - catch - warning(message('images:dicom_encode_jpeg_lossless:tempFileDelete', tempfile)); - end - -end - diff --git a/CT/private/dicom_encode_jpeg_lossy.m b/CT/private/dicom_encode_jpeg_lossy.m deleted file mode 100644 index e5f1822..0000000 --- a/CT/private/dicom_encode_jpeg_lossy.m +++ /dev/null @@ -1,90 +0,0 @@ -function [fragments, frames] = dicom_encode_jpeg_lossy(X, bits) -%DICOM_ENCODE_JPEG_LOSSY Encode pixel cells using lossy JPEG compression. -% [FRAGMENTS, LIST] = DICOM_ENCODE_JPEG_LOSSY(X) compresses and encodes -% the image X using baseline lossy JPEG compression. FRAGMENTS is a -% cell array containing the encoded frames (as UINT8 data) from the -% compressor. LIST is a vector of indices to the first fragment of -% each compressed frame of a multiframe image. -% -% See also DICOM_ENCODE_RLE, DICOM_ENCODE_JPEG_LOSSLESS. - -% Copyright 1993-2011 The MathWorks, Inc. - -% Because lossy JPEG compression of signed data doesn't make sense, -% error. See PS 3.5 Sec. 8.2.1. -X = convertSigned(X); - -% Use IMWRITE to create a JPEG image, but don't warn about signed data. - -numFrames = size(X,4); -fragments = cell(numFrames, 1); -frames = 1:numFrames; - -% The maximum bit-depth for lossy JPEG is 12 bits/sample. -if (bits > 12) - bits = 12; -end - -if (max(X(:)) >= 4096) - warning(message('images:dicom_encode_jpeg_lossy:sampleTooLarge', sprintf( '%ld', max( X( : ) ) ))) -end - -% Write each frame. -for p = 1:numFrames - - tempfile = tempname; - imwrite(X(:,:,:,p), tempfile, 'jpeg', 'bitdepth', bits); - - % Read the image from the temporary file. - fid = fopen(tempfile, 'r'); - fragments{p} = fread(fid, inf, 'uint8=>uint8'); - fclose(fid); - - % Remove the temporary file. - try - delete(tempfile) - catch %#ok - warning(message('images:dicom_encode_jpeg_lossy:tempFileDelete', tempfile)); - end - -end - - -function X = convertSigned(X) -% Image has signed data. - -if (~isConvertible(X)) - - error(message('images:dicom_encode_jpeg_lossy:signedData')) - -end - -switch (class(X)) -case 'int8' - - X = uint8(X); - -case 'int16' - - X = uint16(X); - -case 'int32' - - X = uint32(X); - -case 'int64' - - X = uint8(X); - -otherwise - - % No op. - -end - - - -function tf = isConvertible(X) - -%We can silently convert any type where all of the values are nonnegative. -tf = ~(any(X(:) < 0)); \ No newline at end of file diff --git a/CT/private/dicom_encode_pixel_cells.m b/CT/private/dicom_encode_pixel_cells.m deleted file mode 100644 index a00ebe9..0000000 --- a/CT/private/dicom_encode_pixel_cells.m +++ /dev/null @@ -1,125 +0,0 @@ -function pixelCells = dicom_encode_pixel_cells(X, map, ba, bs, hb) -%DICOM_ENCODE_PIXEL_CELLS Convert an image to pixel cells. -% PIXCELLS = DICOM_ENCODE_PIXEL_CELLS(X, MAP) convert the image X with -% colormap MAP to a sequence of DICOM pixel cells. - -% Copyright 1993-2014 The MathWorks, Inc. - -% Images are stored across then down. If there are multiple samples, -% keep all samples for each pixel contiguously stored. -X = permute(X, [3 2 1 4]); - -pixelCells = basicEncoding(X, map, ba); - -% For floating point pixels, basicEncoding() is sufficient. -switch (class(X)) -case {'single', 'double', 'logical'} - return -case {'uint8', 'int8'} - maxBitsAlloc = 8; -case {'uint16', 'int16'} - maxBitsAlloc = 16; -case {'uint32', 'int32'} - maxBitsAlloc = 32; -case {'uint64', 'int64'} - maxBitsAlloc = 64; -otherwise - assert(false, 'Internal error: Unsupported data type') -end - -% Find out whether to shift the pixels within the cell. Pixels that fully -% span have a "high bit" value one less than "bits stored" (0-based). -if (hb ~= (bs - 1)) - pixelCells = shiftPixels(pixelCells, bs, hb); -end - -% "Squeeze" the extra bits out of the pixel stream if BitsAllocated is less -% than the number of bits used by the MATLAB datatype. -if (ba ~= maxBitsAlloc) - pixelCells = advancedEncoding(pixelCells, ba); -end - -%-------------------------------------------------------------------------- -function pixelCells = basicEncoding(X, map, ba) - -% Convert to correct output type. -switch (class(X)) -case 'logical' - - warning(message('images:dicom_encode_pixel_cells:scalingLogicalData')); - - tmp = uint8(X); - tmp(X) = 255; - - X = tmp; - -case {'single', 'double'} - - maxValue = 2^ba - 1; - - if (isempty(map)) - - % RGB or Grayscale. - X = uint16(maxValue * X); - - else - - if (size(X, 1) == 1) - - % Indexed. - X = uint16(X - 1); - - elseif (size(X, 1) == 4) - - % RGBA - X(1:3, :, :) = X(1:3, :, :) * maxValue; - X(4, :, :) = X(4, :, :) - 1; - X = uint16(X); - - end - end -end - -pixelCells = X(:); - -%-------------------------------------------------------------------------- -function pixelCells = advancedEncoding(pixelCells, ba) -%advancedEncoding Encode pixel cells while writing to a temporary file and -%then reading the encoded pixels back to the buffer. This truncates "short" -%pixel cells that don't span the full datatype. - -pixelCellClass = class(pixelCells); - -% Write the data to the temporary file, squeezing out extra bits. The last -% pixel cell will be padded to end on a byte boundary. -filename = tempname(); -fid = fopen(filename, 'wb'); -if (fid < 0) - error(message('images:dicomwrite:tempFileNotCreated')) -end - -fileCleaner = onCleanup(@() delete(filename)); - -switch (pixelCellClass) - case {'int8', 'int16', 'int32', 'int64'} - precision = sprintf('bit%d', ba); - case {'uint8', 'uint16', 'uint32', 'uint64'} - precision = sprintf('ubit%d', ba); -end -fwrite(fid, pixelCells, precision); -fclose(fid); - -% Read all of the data back into the original encoded class type. Each -% "pixel cell" read will incorporate more than one pixel, but this is done -% to ensure that any potential byte-swapping happens correctly. -precision = sprintf('%s=>%s', pixelCellClass, pixelCellClass); - -fid = fopen(filename, 'rb'); -pixelCells = fread(fid, inf, precision); -fclose(fid); - -%-------------------------------------------------------------------------- -function pixelCells = shiftPixels(pixelCells, bs, hb) - -bitsToShift = hb - bs + 1; -pixelCells = bitshift(pixelCells, bitsToShift); diff --git a/CT/private/dicom_encode_pn.m b/CT/private/dicom_encode_pn.m deleted file mode 100644 index e5b4bd0..0000000 --- a/CT/private/dicom_encode_pn.m +++ /dev/null @@ -1,59 +0,0 @@ -function PN_chars = dicom_encode_pn(PN_struct) -%DICOM_ENCODE_PN Turn a structure of name info into a formatted string. - -% Copyright 1993-2006 The MathWorks, Inc. - -% Empty values and undecorated PN strings should fall through. -if ((~isstruct(PN_struct)) || (isempty(PN_struct))) - PN_chars = PN_struct; - return -else - PN_chars = ''; -end - -% Encode a decorated PN struct. -for p = 1:numel(PN_struct) - - % Add each of the components to the output string. - if (isfield(PN_struct, 'FamilyName')) - PN_chars = [PN_chars PN_struct.FamilyName '^']; - else - PN_chars = [PN_chars '^']; - end - - if (isfield(PN_struct, 'GivenName')) - PN_chars = [PN_chars PN_struct.GivenName '^']; - else - PN_chars = [PN_chars '^']; - end - - if (isfield(PN_struct, 'MiddleName')) - PN_chars = [PN_chars PN_struct.MiddleName '^']; - else - PN_chars = [PN_chars '^']; - end - - if (isfield(PN_struct, 'NamePrefix')) - PN_chars = [PN_chars PN_struct.NamePrefix '^']; - else - PN_chars = [PN_chars '^']; - end - - if (isfield(PN_struct, 'NameSuffix')) - PN_chars = [PN_chars PN_struct.NameSuffix '^']; - else - PN_chars = [PN_chars '^']; - end - - % Remove extraneous '^' separators. - while ((~isempty(PN_chars)) && (PN_chars(end) == '^')) - PN_chars(end) = ''; - end - - % Separate multiple values. - PN_chars = [PN_chars '\']; - -end - -% Remove extra value delimiter '\'. -PN_chars(end) = ''; diff --git a/CT/private/dicom_encode_rle.m b/CT/private/dicom_encode_rle.m deleted file mode 100644 index 286401e..0000000 --- a/CT/private/dicom_encode_rle.m +++ /dev/null @@ -1,271 +0,0 @@ -function [fragments, frames] = dicom_encode_rle(pixel_cells, bits_allocated, dims) -%DICOM_ENCODE_RLE Run-length encode pixel cells. -% [FRAGMENTS, LIST] = DICOM_ENCODE_RLE(PIXCELLS, BITS, DIMS) compresses -% the pixel cells PIXCELLS using run-length encoding. BITS is the -% number of bits allocated for each pixel cell, and DIMS is the -% original dimensions of the image stored in PIXCELLS, which is now a -% vector. FRAGMENTS is a cell array containing the encoded frames (as -% UINT8 data) from the compressor. LIST is a vector of indices to the -% first fragment of each compressed frame of a multiframe image. -% -% See also DICOM_ENCODE_JPEG_LOSSY. - -% Copyright 1993-2011 The MathWorks, Inc. - - -% Run-length encoded pixel cells have the following form: -% -% RLE Header (16 UINT32 components) -% - The first component is number of RLE segments (0 - 15) -% - The remaining 15 components are offsets to the beginning of each -% segment (or 0 if there are no more segments). -% RLE Segment 1 -% RLE Segment 2 -% etc. -% -% The segments are generated by stripping off successive bytes from the -% composite pixel code, starting with the most significant byte [1]. -% The stripped bytes are passed through the RLE coder to create the -% compressed segment. -% -% Individual image rows must be sent through the coder separately even if -% they are part of the same segment. This prevents a run from spanning -% multiple rows. The compressed rows are concatenated within each -% segment. -% -% If a composite pixel cell does not end on byte boundaries, 0 bits are -% appended to the least significant byte. This will happen if the number -% of bits allocated for pixels and overlays (0028,0100) is not divisible -% by 8. -% -% Sequences of bytes can be compressed into an arbitrary number of -% fragments. This allows for encoding the image into a set of "strips". -% The only restriction is that each fragment must contain the same number -% of pixel cell elements in each segment (e.g., the same number of red, -% green, and blue samples, etc.). -% -% [1] - A composite pixel code is one pixel cell in the sequence of pixel -% cells. The unstated conclusion of using composite pixel codes is -% that planar configuration (0028,0006) must be 0 if more than one -% sample is present and RLE coding is used. -% -% See Annex G in part 5 of the DICOM spec for more details. - -% DICOM_ENCODE_PIXEL_CELLS explicitly creates pixel cells that are byte -% aligned. -if (rem(bits_allocated, 8) ~= 0) - error(message('images:dicom_encode_rle:badBitsAllocated')) -end - -% Reshape data to make segment creation easy. -if (length(dims) >= 3) - num_segments = (bits_allocated / 8) * dims(3); -else - num_segments = (bits_allocated / 8); -end - -if (num_segments > 15) - error(message('images:dicom_encode_rle:tooManySegments')) -end - -if (numel(dims) == 4) - numFrames = dims(4); -else - numFrames = 1; -end - -swap = determine_swap; - -pixel_cells = dicom_typecast(pixel_cells, 'uint8', swap); -pixel_cells = reshape(pixel_cells, [num_segments, ... - (numel(pixel_cells) / num_segments)]); - -offset = 0; - -fragments = cell(1, numFrames); -for f = 1:numFrames - - encoded_data = []; - - % Encode each segment. - segment_lengths = zeros(1, num_segments); - for p = 1:num_segments - - segment = []; - - % Encode each row. - for q = 1:dims(1) - - start_idx = offset + (q - 1) * dims(2) + 1; - end_idx = offset + q * dims(2); - - encoded_row = dicom_encode_rle_segment(pixel_cells(p, start_idx:end_idx)); - - segment = [segment; encoded_row]; %#ok - - end - - % Store segment. - encoded_data = [encoded_data; segment]; %#ok - segment_lengths(p) = numel(segment); - - end - - offset = end_idx; - - % Create RLE header. - header = repmat(uint32(0), [16 1]); - header(1) = uint32(num_segments); - header(2) = uint32(64); - - for p = 2:(num_segments) - - header(p + 1) = uint32(64 + sum(segment_lengths(1:(p - 1)))); - - end - - encoded_data = [dicom_typecast(header, 'uint8', swap); encoded_data]; %#ok - - % Create output from fragments. - fragments{f} = encoded_data; - -end - -frames = 1:numFrames; - - - -% This is essentially how dicom_rle_encode_segment() works. -% function coded_bytes = rle_coder(X) -% -% X = double(X(:)); -% -% current_pos = 1; -% max_pos = numel(X); -% -% % Find runs. Where the diff is 0, there is a repeated value. The first run -% % is not included. -% X_diff = diff(X); -% X_reps = find(X_diff == 0); -% rep_pix = [X_reps(1); X_reps(find(diff(X_reps) > 1) + 1); (max_pos + 1)]; -% -% all_runs = find(X_diff ~= 0) + 1; -% -% rep_number = 1; -% next_rep = rep_pix(rep_number); -% -% coded_values = []; -% more_data = 1; -% -% while (more_data) -% -% if (current_pos ~= next_rep) -% -% % Handle literal values between runs. -% -% % Only 128 literal values can be encoded in one literal run. -% while ((next_rep - current_pos) > 128) -% -% coded_values = [coded_values -% 127 -% X(current_pos:(current_pos + 127))]; -% current_pos = current_pos + 128; -% -% end -% -% run_length = next_rep - current_pos; -% coded_values = [coded_values -% (run_length - 1) -% X(current_pos:(next_rep - 1))]; -% -% % All literal values until the next repetitive run are encoded. -% current_pos = next_rep; -% -% else -% -% % Handle repetitive runs. -% -% % Find next run of different values. -% idx = find(all_runs == current_pos); -% -% if (isempty(idx)) -% -% % This run appeared at the very beginning of the data. -% if (isempty(all_runs)) -% -% % There is only one run. -% next_run = max_pos + 1; -% -% else -% -% next_run = all_runs(1); -% -% end -% -% elseif (idx == numel(all_runs)) -% -% % This is the last run. -% next_run = max_pos + 1; -% -% else -% -% next_run = all_runs(idx + 1); -% -% end -% -% while ((next_run - current_pos) > 128) -% -% coded_values = [coded_values -% -127 -% X(current_pos)]; -% current_pos = current_pos + 128; -% -% end -% -% run_length = next_run - current_pos; -% coded_values = [coded_values -% (-run_length + 1) -% X(current_pos)]; -% -% current_pos = current_pos + run_length; -% -% rep_number = rep_number + 1; -% next_rep = rep_pix(rep_number); -% -% end -% -% if (current_pos > max_pos) -% -% more_data = 0; -% -% end -% -% end -% -% % Convert double data to bytestream. -% % -% % The next statement maps the signed values in the range [-128, 255] to -% % [0, 255], the valid range for UINT8. Values in the range [0, 255] are -% % unchanged; values in [-128, -1] are mapped to [128, 255]. -% % -% % Converting negative values is okay because the bit pattern for a -% % converted value as a UINT8 is the same as the negative value's bit -% % pattern as an INT8. The RLE decoder algorithm will read the next byte -% % as a signed or unsigned value based on its own logic; it suffices for -% % this function to write indistinguishable bytes (signed or unsigned). -% coded_bytes = uint8(rem((coded_values + 256), 256)); - - - -function swap = determine_swap -% Determine if endianness of data needs swapped. - -[~, ~, mach] = fopen(1); - -% RLE compressed data must be written to file as IEEE-LE. -if (isempty(strfind(lower(mach), 'ieee-le'))) - swap = 1; -else - swap = 0; -end - diff --git a/CT/private/dicom_encode_rle_segment.mexw64 b/CT/private/dicom_encode_rle_segment.mexw64 deleted file mode 100644 index 9333899..0000000 Binary files a/CT/private/dicom_encode_rle_segment.mexw64 and /dev/null differ diff --git a/CT/private/dicom_generate_uid.m b/CT/private/dicom_generate_uid.m deleted file mode 100644 index 520d062..0000000 --- a/CT/private/dicom_generate_uid.m +++ /dev/null @@ -1,151 +0,0 @@ -function uid = dicom_generate_uid(uid_type) -%DICOM_GENERATE_UID Create a globally unique ID. -% UID = DICOM_GENERATE_UID(TYPE) creates a unique identifier (UID) of -% the specified type. TYPE must be one of the following: -% -% 'instance' - A UID for any arbitrary DICOM object -% 'ipt_root' - The root of the Image Processing Toolbox's UID -% 'series' - A UID for an arbitrary series of DICOM images -% 'study' - A UID for an arbitrary study of DICOM series -% -% See also MWGUIDGEN. - -% Copyright 1993-2012 The MathWorks, Inc. - -% This is the UID root assigned to us. It prevents collisions with UID -% generation schemes from other vendors. -ipt_root = '1.3.6.1.4.1.9590.100.1'; - -switch (uid_type) -case {'ipt_root'} - - uid = ipt_root; - -case {'instance', 'series', 'study'} - - switch (lower(computer())) - case {'pcwin', 'pcwin64'} - - guid_32bit = create_guid_windows(); - uid = guid_to_uid(ipt_root, guid_32bit); - - case {'glnxa64', 'glnx86'} - - guid_32bit = create_guid_linux(); - uid = guid_to_uid(ipt_root, guid_32bit); - - case {'maci', 'maci64'} - - guid_32bit = create_guid_mac(); - uid = guid_to_uid(ipt_root, guid_32bit); - - otherwise - - error(message('images:dicom_generate_uid:unsupportedPlatform')) - - end - -otherwise - - error(message('images:dicom_generate_uid:inputValue', uid_type)); - -end - - - -function guid_32bit = create_guid_linux - -[status, raw_guid] = system('uuidgen'); -if (status ~= 0) - - [status, raw_guid] = system('cat /proc/sys/kernel/random/uuid'); - if (status ~= 0) - - error(message('images:dicom_generate_uid:linuxSystemProblem')) - - end - -end - -tmp_guid = strip_unix_messages(raw_guid); -guid_32bit = sscanf(strrep(tmp_guid, '-', ''), '%08x'); - - - -function guid_32bit = create_guid_mac - -[status, raw_guid] = system('uuidgen'); -if (status ~= 0) - - error(message('images:dicom_generate_uid:macSystemProblem')) - -end - -tmp_guid = strip_unix_messages(raw_guid); -guid_32bit = sscanf(strrep(tmp_guid, '-', ''), '%08x'); - - - -function guid_32bit = create_guid_windows - -% Generate a GUID as a series of 16 UINT8 values. -guid_8bit = mwguidgen; - -% Convert the bytes to four UINT32 values. -guid_32bit = dicom_typecast(guid_8bit, 'uint32'); - - - -function uid = guid_to_uid(ipt_root, guid_32bit) - -% Convert a group of numeric values into a concatenated string. -guid = ''; -for p = 1:length(guid_32bit) - - guid = [guid sprintf('%010.0f', double(guid_32bit(p)))]; %#ok - -end - -% The maximum decimal representation of four concatenated 32-bit values -% is 40 digits long, which is one digit too many for the UID container in -% DICOM (after you add in the UID root). Shorten it to fit in DICOM's -% length requirements by removing a value from the middle. (As a result, -% 1 in every 10^39 values will be a duplicate.) -guid(13) = ''; - -% The DICOM standard requires the digit that follows a dot to be -% nonzero. Removing the leading zeros does not cause duplication. -guid = remove_leading_zeros(guid); - -% Append the GUID to the UID root. The intervening digit is the version -% number of the UID generation scheme. Increment the version number if -% the rule/mechanism for generating "guid" changes. (The next scheme version -% number should be 4; skip 3, which is being used for implementation UIDs.) -uid = [ipt_root '.2.' guid]; - - - -function out = remove_leading_zeros(in) - -out = in; -while (out(1) == '0') - out(1) = ''; -end - - - -function out = strip_unix_messages(in) - -% It's possible that sourcing a shell configuration file (or -% another part of the shell launch) causes a message to appear in -% the system() output. Strip out everything but the GUID value, -% which we must assume to be the last full line. - -out = in; - -newLine = sprintf('\n'); -idx = find(in == newLine); - -if (numel(idx) > 1) - out(1:idx(end-1)) = ''; -end diff --git a/CT/private/dicom_get_msg.m b/CT/private/dicom_get_msg.m deleted file mode 100644 index fab9fa2..0000000 --- a/CT/private/dicom_get_msg.m +++ /dev/null @@ -1,58 +0,0 @@ -function file = dicom_get_msg(file) -%DICOM_GET_MSG Get a pool of potential messages to load later. -% FILE = DICOM_GET_MSG(FILE) processes FILE.Filename to obtain a pool -% of potential DICOM messages to read. After execution, FILE.Filename -% will contain a cell array of messages to read. -% -% Note: When loading a locally stored file, this function just checks -% for the existence of the file. When network contexts are supported, -% the message pool will contain the results of a QUERY operation. -% -% See also DICOM_OPEN_MSG and DICOM_CREATE_FILE_STRUCT. - -% Copyright 1993-2011 The MathWorks, Inc. - -% Verify that file exists. - -if (exist(file.Filename) ~= 2) - - % Look for file with common extensions. - if (exist([file.Filename '.dcm'])) - - file.Filename = [file.Filename '.dcm']; - - elseif (exist([file.Filename '.dic'])) - - file.Filename = [file.Filename '.dic']; - - elseif (exist([file.Filename '.dicom'])) - - file.Filename = [file.Filename '.dicom']; - - elseif (exist([file.Filename '.img'])) - - file.Filename = [file.Filename '.img']; - - else - - file.Filename = ''; - return - - end - -end - -% Get full filename. -fid = fopen(file.Filename); - -if (fid < 0) - - error(message('images:dicom_get_msg:fileOpen', file.Filename)) - -else - - file.Filename = fopen(fid); - -end - -fclose(fid); diff --git a/CT/private/dicom_get_next_tag.m b/CT/private/dicom_get_next_tag.m deleted file mode 100644 index ba23430..0000000 --- a/CT/private/dicom_get_next_tag.m +++ /dev/null @@ -1,35 +0,0 @@ -function [group, element] = dicom_get_next_tag(file) -%DICOM_GET_NEXT_TAG Get the group and element values for the next attribute. -% [GROUP,ELEMENT] = DICOM_GET_NEXT_TAG(MESSAGE) returns the GROUP and -% ELEMENT of the next attribute in MESSAGE. -% -% Note: This function reads the tag and then rewinds to the beginning -% of it. It is then possible to call DICOM_READ_ATTR without changing -% the position in the file. - -% Copyright 1993-2005 The MathWorks, Inc. - -if (~feof(file.FID)) - - [tag, count] = fread(file.FID, 2, 'uint16', file.Current_Endian); - - if (count ~= 2) - - group = -1; - element = -1; - - return - - end - - group = tag(1); - element = tag(2); - - fseek(file.FID, -4, 'cof'); - -else - - group = -1; - element = -1; - -end diff --git a/CT/private/dicom_has_fmeta.m b/CT/private/dicom_has_fmeta.m deleted file mode 100644 index 5791e5e..0000000 --- a/CT/private/dicom_has_fmeta.m +++ /dev/null @@ -1,39 +0,0 @@ -function has_fmeta = dicom_has_fmeta(file) -%DICOM_HAS_FMETA Determines whether a message contains file metadata. -% TF = DICOM_HAS_FMETA(FILE) Returns 1 if FILE has file metadata, 0 -% otherwise. File metadata are attributes whose groups are 2 - 7. - -% Copyright 1993-2010 The MathWorks, Inc. - -fseek(file.FID, 128, 'bof'); - -if (ftell(file.FID) ~= 128) - % File is too short to have 128 byte preamble: no file metadata. - has_fmeta = false; - fseek(file.FID, 0, 'bof'); - - return - -end - -% Look for the format string 'DICM'. -fmt_string = fread(file.FID, 4, 'uchar'); - -has_fmeta = isequal(fmt_string, [68 73 67 77]'); - -% Very rarely a file will have file metadata but not a preamble. -if (~has_fmeta) - - has_fmeta = has_group0002_without_preamble(file); - fseek(file.FID, 0, 'bof'); - -end - - - -function tf = has_group0002_without_preamble(file) - -fseek(file.FID, 0, 'bof'); -group = fread(file.FID, 1, 'uint16=>uint16'); - -tf = ((group == 2) || (swapbytes(group) == 2)); diff --git a/CT/private/dicom_has_overlay_bits.m b/CT/private/dicom_has_overlay_bits.m deleted file mode 100644 index 6d4d2bf..0000000 --- a/CT/private/dicom_has_overlay_bits.m +++ /dev/null @@ -1,46 +0,0 @@ -function overlay_bits = dicom_has_overlay_bits(info) -%DICOM_HAS_OVERLAY_BITS Return overlay bit positions in pixel cells. - -% Copyright 1993-2005 The MathWorks, Inc. - -% Overlay data requires one or more OverlayBitsAllocated attributes to be -% set (60xx,0100). - -info_fields = fieldnames(info); -overlay_fields = strmatch('OverlayBitsAllocated', info_fields); - -% Determine if overlay data is with the pixel data. -if (~isempty(overlay_fields)) - - % Overlay pixels are with Image pixels iff OverlayBitsAllocated and - % BitsAllocated are the same. - - overlay_bits = []; - count = 0; - - % Find overlay bit location for each overlay in pixel cell. - for p = overlay_fields' - - OverlayBitsAllocated = info.(info_fields{p}); - - if (isequal(OverlayBitsAllocated, info.BitsAllocated)) - - % Find position in pixel cell: OverlayBitPosition (60xx,0102). - - count = count + 1; - - OBP_field = strrep(info_fields{p}, 'BitsAllocated', ... - 'BitPosition'); - - overlay_bits(count) = info.(OBP_field); - - end - - end - -else - - % No overlays. - overlay_bits = []; - -end diff --git a/CT/private/dicom_iods.m b/CT/private/dicom_iods.m deleted file mode 100644 index 4989f32..0000000 --- a/CT/private/dicom_iods.m +++ /dev/null @@ -1,1376 +0,0 @@ -function iods = dicom_iods -%DICOM_IODS Repository of information object definitions. -% IODS = DICOM_IODS returns a structure array containing various DICOM -% information object definitions (IODS), which are used to create -% Service-Object Pair (SOP) classes. SOP instances comprise the high- -% level description of the information stored in a DICOM file. -% -% The IODS struct array contains the following fields: -% - Name: An abbreviated name of the IOD -% - UID: The unique identifier of the storage class for this IOD -% - Def_fcn: The function containing the modules' definitions -% - Prep_fcn: The function used to process the raw metadata needed for -% these modules -% - Modules: A cell array describing the modules needed for this IOD. -% -% The Modules cell array contains the name of the modules, the type of -% the module ('M' = mandatory, 'C' = conditional, 'U' = user optional), -% and the condition constant indicating whether the module should be -% built. -% -% See also DICOM_CREATE_IOD, DICOM_MODULES. - -% Copyright 1993-2010 The MathWorks, Inc. - -% The lexicon has changed since we named some of the modules. -% Here's a translation: -% * SpecimenIdentification --> "Clinical Trial Subject" - - -iods = []; - -iods(end+1).Name = 'CRImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.1'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'CRSeries' 'M', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'ContrastBolus' 'C', {} - 'CRImage' 'M', {} - 'OverlayPlane' 'U', {} - 'Curve' 'U', {} - 'ModalityLUT' 'U', {} - 'VOILUT' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'CTImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.2'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = 'PS 3.3 Sec. A.3'; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'FrameOfReference' 'M', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePlane' 'M', {} - 'ImagePixel' 'M', {} - 'ContrastBolus' 'C', {'HAS_BOLUS'} - 'CTImage' 'M', {} - 'OverlayPlane' 'U', {'HAS_OVERLAY'} - 'VOILUT' 'U', {'HAS_VOILUT'} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'MRImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.4'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = 'PS 3.3 Sec. A.4'; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'FrameOfReference' 'M', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePlane' 'M', {} - 'ImagePixel' 'M', {} - 'ContrastBolus' 'C', {'HAS_BOLUS'} - 'MRImage' 'M', {} - 'OverlayPlane' 'U', {'HAS_OVERLAY'} - 'VOILUT' 'U', {'HAS_VOILUT'} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'NMImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.20'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'NMPETPatientOrientation' 'M', {} - 'FrameOfReference' 'U', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'NMImagePixel' 'M', {} - 'MultiFrame' 'M', {} - 'NMMultiFrame' 'M', {} - 'NMImage' 'M', {} - 'NMIsotope' 'M', {} - 'NMDetector' 'M', {} - 'NMTomoAcquisition' 'C', {} - 'NMMultiGatedAcquisition' 'C', {} - 'NMPhase' 'C', {} - 'NMReconstruction' 'C', {} - 'OverlayPlane' 'U', {} - 'MultiFrameOverlay' 'U', {} - 'Curve' 'U', {} - 'VOILUT' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'NMImageRetired'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.5'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'NMSeriesRetired' 'M', {} - 'FrameOfReference' 'U', {} - 'GeneralEquipment' 'M', {} - 'NMEquipmentRetired' 'U', {} - 'GeneralImage' 'M', {} - 'ImagePlane' 'U', {} - 'ImagePixel' 'M', {} - 'Cine' 'C', {} - 'MultiFrame' 'C', {} - 'NMImageRetired' 'M', {} - 'NMSPECTAcquisitionImageRetired' 'C', {} - 'NMMultiGatedAcquisitionImageRetired' 'C', {} - 'OverlayPlane' 'U', {} - 'MultiFrameOverlay' 'U', {} - 'Curve' 'U', {} - 'VOILUT' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'USImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.6.1'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'FrameOfReference' 'U', {} - 'USFrameOfReference' 'C', {} - 'Synchronization' 'U', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'ContrastBolus' 'C', {} - 'PaletteColorLookupTable' 'C', {} - 'USRegionCalibration' 'U', {} - 'USImage' 'M', {} - 'OverlayPlane' 'U', {} - 'VOILUT' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'USMultiFrameImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.3.1'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'FrameOfReference' 'U', {} - 'USFrameOfReference' 'C', {} - 'Synchronization' 'C', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'ContrastBolus' 'C', {} - 'Cine' 'M', {} - 'MultiFrame' 'M', {} - 'PaletteColorLookupTable' 'C', {} - 'USRegionCalibration' 'U', {} - 'USImage' 'M', {} - 'VOILUT' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'USImageRetired'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.6'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'FrameOfReference' 'U', {} - 'USFrameOfReference' 'C', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'ContrastBolus' 'C', {} - 'USRegionCalibration' 'U', {} - 'USImage' 'M', {} - 'OverlayPlane' 'U', {} - 'VOILUT' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'USMultiFrameImageRetired'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.3'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'FrameOfReference' 'U', {} - 'USFrameOfReference' 'C', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'ContrastBolus' 'C', {} - 'Cine' 'C', {} - 'MultiFrame' 'M', {} - 'USRegionCalibration' 'U', {} - 'USImage' 'M', {} - 'VOILUT' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'SCImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.7'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = 'PS 3.3 Sec. A.8.1'; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'GeneralEquipment' 'U', {} - 'SCImageEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'SCImage' 'M', {} - 'OverlayPlane' 'U', {} - 'ModalityLUT' 'U', {} - 'VOILUT' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'MultiframeSingleBitSCImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.7.1'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = 'PS 3.3 Sec. A.8.2'; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'GeneralEquipment' 'U', {} - 'SCImageEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'Cine' 'C', {'NEEDS_SC_CINE'} - 'MultiFrame' 'M', {} - 'FramePointers' 'U', {} - 'SCImage' 'U', {} - 'SCMultiFrameImage' 'M', {} - 'SCMultiFrameVector' 'C', {'IS_MULTIFRAME'} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'MultiframeGrayscaleByteSCImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.7.2'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = 'PS 3.3 Sec. A.8.3'; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'GeneralEquipment' 'U', {} - 'SCImageEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'Cine' 'C', {'NEEDS_SC_CINE'} - 'MultiFrame' 'M', {} - 'FramePointers' 'U', {} - 'SCImage' 'U', {} - 'SCMultiFrameImage' 'M', {} - 'SCMultiFrameVector' 'C', {'IS_MULTIFRAME'} - 'VOILUT' 'C', {'HAS_VOILUT'} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'MultiframeGrayscaleWordSCImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.7.3'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = 'PS 3.3 Sec. A.8.4'; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'GeneralEquipment' 'U', {} - 'SCImageEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'Cine' 'C', {'NEEDS_SC_CINE'} - 'MultiFrame' 'M', {} - 'FramePointers' 'U', {} - 'SCImage' 'U', {} - 'SCMultiFrameImage' 'M', {} - 'SCMultiFrameVector' 'C', {'IS_MULTIFRAME'} - 'VOILUT' 'C', {'HAS_VOILUT'} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'MultiframeTrueColorSCImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.7.4'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = 'PS 3.3 Sec. A.8.5'; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'GeneralEquipment' 'U', {} - 'SCImageEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'Cine' 'C', {'NEEDS_SC_CINE'} - 'MultiFrame' 'M', {} - 'FramePointers' 'U', {} - 'SCImage' 'U', {} - 'SCMultiFrameImage' 'M', {} - 'SCMultiFrameVector' 'C', {'IS_MULTIFRAME'} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'StandaloneOverlay'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.8'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'GeneralEquipment' 'M', {} - 'OverlayIdentification' 'M', {} - 'OverlayPlane' 'M', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'StandaloneCurve'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.9'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'GeneralEquipment' 'M', {} - 'CurveIdentification' 'M', {} - 'Curve' 'M', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'StandaloneModalityLUT'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.10'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'GeneralEquipment' 'M', {} - 'ModalityLUT' 'M', {} - 'LUTIdentification' 'M', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'StandaloneVOILUT'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.11'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'GeneralEquipment' 'M', {} - 'VOILUT' 'M', {} - 'LUTIdentification' 'M', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'XAImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.12.1'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'ContrastBolus' 'C', {} - 'Cine' 'C', {} - 'MultiFrame' 'C', {} - 'FramePointers' 'U', {} - 'Mask' 'C', {} - 'DisplayShutter' 'U', {} - 'Device' 'U', {} - 'Therapy' 'U', {} - 'XRayImage' 'M', {} - 'XRayAcquisition' 'M', {} - 'XRayCollimator' 'U', {} - 'XRayTable' 'C', {} - 'XAPositioner' 'M', {} - 'OverlayPlane' 'U', {} - 'MultiFrameOverlay' 'C', {} - 'Curve' 'U', {} - 'ModalityLUT' 'C', {} - 'VOILUT' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'XABiplaneImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.12.3'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'ContrastBolus' 'C', {} - 'Cine' 'C', {} - 'MultiFrame' 'C', {} - 'FramePointers' 'U', {} - 'Mask' 'C', {} - 'DisplayShutter' 'U', {} - 'XRayAcquisition' 'M', {} - 'XRayCollimator' 'U', {} - 'XAPositioner' 'M', {} - 'VOILUT' 'U', {} - 'Device' 'U', {} - 'Therapy' 'U', {} - 'XRayImage' 'M', {} - 'XRayTable' 'C', {} - 'OverlayPlane' 'U', {} - 'MultiFrameOverlay' 'C', {} - 'BiplaneOverlay' 'C', {} - 'Curve' 'U', {} - 'ModalityLUT' 'C', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'XRFImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.12.2'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'ContrastBolus' 'C', {} - 'Cine' 'C', {} - 'MultiFrame' 'C', {} - 'FramePointers' 'U', {} - 'Mask' 'C', {} - 'XRayImage' 'M', {} - 'XRayAcquisition' 'M', {} - 'XRayCollimator' 'U', {} - 'DisplayShutter' 'U', {} - 'Therapy' 'U', {} - 'Device' 'U', {} - 'XRayTable' 'C', {} - 'XRFPositioner' 'U', {} - 'XRayTomoAcquisition' 'U', {} - 'OverlayPlane' 'U', {} - 'MultiFrameOverlay' 'C', {} - 'Curve' 'U', {} - 'ModalityLUT' 'C', {} - 'VOILUT' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'PETImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.128'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'PETSeries' 'M', {} - 'PETIsotope' 'M', {} - 'PETMultigatedAcquisition' 'C', {} - 'NMPETPatientOrientation' 'M', {} - 'FrameOfReference' 'M', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePlane' 'M', {} - 'ImagePixel' 'M', {} - 'PETImage' 'M', {} - 'OverlayPlane' 'U', {} - 'VOILUT' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'StandalonePETCurve'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.129'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'PETSeries' 'M', {} - 'PETIsotope' 'M', {} - 'PETMultigatedAcquisition' 'C', {} - 'GeneralEquipment' 'M', {} - 'CurveIdentification' 'M', {} - 'Curve' 'M', {} - 'PETCurve' 'M', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'RTImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.481.1'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'RTSeries' 'M', {} - 'FrameOfReference' 'U', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'ContrastBolus' 'C', {} - 'Cine' 'C', {} - 'MultiFrame' 'C', {} - 'RTImage' 'M', {} - 'ModalityLUT' 'U', {} - 'VOILUT' 'U', {} - 'Approval' 'U', {} - 'Curve' 'U', {} - 'Audio' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'RTDose'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.481.2'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'RTSeries' 'M', {} - 'FrameOfReference' 'M', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'C', {} - 'ImagePlane' 'C', {} - 'ImagePixel' 'C', {} - 'MultiFrame' 'C', {} - 'OverlayPlane' 'U', {} - 'MultiFrameOverlay' 'U', {} - 'ModalityLUT' 'U', {} - 'RTDose' 'M', {} - 'RTDVH' 'U', {} - 'StructureSet' 'C', {} - 'ROIContour' 'C', {} - 'RTDoseROI' 'C', {} - 'Audio' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'RTStructureSet'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.481.3'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'RTSeries' 'M', {} - 'GeneralEquipment' 'M', {} - 'StructureSet' 'M', {} - 'ROIContour' 'M', {} - 'RTROIObservations' 'M', {} - 'Approval' 'U', {} - 'Audio' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'RTPlan'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.481.5'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'RTSeries' 'M', {} - 'GeneralEquipment' 'M', {} - 'RTGeneralPlan' 'M', {} - 'RTPrescription' 'U', {} - 'RTToleranceTables' 'U', {} - 'RTPatientSetup' 'U', {} - 'RTFractionScheme' 'U', {} - 'RTBeams' 'C', {} - 'RTBrachyApplicationSetups' 'C', {} - 'Approval' 'U', {} - 'Audio' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'RTBeamsTreatmentRecord'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.481.4'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'RTSeries' 'M', {} - 'GeneralEquipment' 'M', {} - 'RTGeneralTreatmentRecord' 'M', {} - 'RTPatientSetup' 'U', {} - 'RTTreatmentMachineRecord' 'M', {} - 'MeasuredDoseReferenceRecord' 'U', {} - 'CalculatedDoseReferenceRecord' 'U', {} - 'RTBeamsSessionRecord' 'M', {} - 'RTTreatmentSummaryRecord' 'U', {} - 'Curve' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'RTBrachyTreatmentRecord'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.481.6'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'RTSeries' 'M', {} - 'GeneralEquipment' 'M', {} - 'RTGeneralTreatmentRecord' 'M', {} - 'RTPatientSetup' 'U', {} - 'RTTreatmentMachineRecord' 'M', {} - 'MeasuredDoseReferenceRecord' 'U', {} - 'CalculatedDoseReferenceRecord' 'U', {} - 'RTBrachySessionRecord' 'M', {} - 'RTTreatmentSummaryRecord' 'U', {} - 'Curve' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'RTTreatmentSummaryRecord'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.481.7'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'RTSeries' 'M', {} - 'GeneralEquipment' 'M', {} - 'RTGeneralTreatmentRecord' 'M', {} - 'RTTreatmentSummaryRecord' 'U', {} - 'Curve' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'DXImageForProcessing'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.1.1.1'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'ClinicalTrialSubject' 'U', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'DXSeries' 'M', {} - 'FrameOfReference' 'U', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'ContrastBolus' 'U', {} - 'DisplayShutter' 'U', {} - 'Device' 'U', {} - 'Therapy' 'U', {} - 'DXAnatomyImaged' 'M', {} - 'DXImage' 'M', {} - 'DXDetector' 'M', {} - 'XRayCollimator' 'U', {} - 'DXPositioning' 'U', {} - 'XRayTomoAcquisition' 'U', {} - 'XRayAcquisitionDose' 'U', {} - 'XRayGeneration' 'U', {} - 'XRayFiltration' 'U', {} - 'XRayGrid' 'U', {} - 'OverlayPlane' 'C', {} - 'Curve' 'U', {} - 'VOILUT' 'C', {} - 'ImageHistogram' 'U', {} - 'AcquisitionContext' 'M', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'DXImageForPresentation'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.1.1'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'ClinicalTrialSubject' 'U', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'DXSeries' 'M', {} - 'FrameOfReference' 'U', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'ContrastBolus' 'U', {} - 'DisplayShutter' 'U', {} - 'Device' 'U', {} - 'Therapy' 'U', {} - 'DXAnatomyImaged' 'M', {} - 'DXImage' 'M', {} - 'DXDetector' 'M', {} - 'XRayCollimator' 'U', {} - 'DXPositioning' 'U', {} - 'XRayTomoAcquisition' 'U', {} - 'XRayAcquisitionDose' 'U', {} - 'XRayGeneration' 'U', {} - 'XRayFiltration' 'U', {} - 'XRayGrid' 'U', {} - 'OverlayPlane' 'C', {} - 'Curve' 'U', {} - 'VOILUT' 'C', {} - 'ImageHistogram' 'U', {} - 'AcquisitionContext' 'M', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'MammographyImageForProcessing'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.1.2.1'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'ClinicalTrialSubject' 'U', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'DXSeries' 'M', {} - 'MammographySeries' 'M', {} - 'FrameOfReference' 'U', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'ContrastBolus' 'U', {} - 'DisplayShutter' 'U', {} - 'Device' 'U', {} - 'Therapy' 'U', {} - 'DXAnatomyImaged' 'M', {} - 'DXImage' 'M', {} - 'DXDetector' 'M', {} - 'XRayCollimator' 'U', {} - 'DXPositioning' 'U', {} - 'XRayTomoAcquisition' 'U', {} - 'XRayAcquisitionDose' 'U', {} - 'XRayGeneration' 'U', {} - 'XRayFiltration' 'U', {} - 'XRayGrid' 'U', {} - 'MammographyImage' 'M', {} - 'OverlayPlane' 'C', {} - 'Curve' 'U', {} - 'VOILUT' 'C', {} - 'ImageHistogram' 'U', {} - 'AcquisitionContext' 'M', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'MammographyImageForPresentation'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.1.2'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'ClinicalTrialSubject' 'U', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'DXSeries' 'M', {} - 'MammographySeries' 'M', {} - 'FrameOfReference' 'U', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'ContrastBolus' 'U', {} - 'DisplayShutter' 'U', {} - 'Device' 'U', {} - 'Therapy' 'U', {} - 'DXAnatomyImaged' 'M', {} - 'DXImage' 'M', {} - 'DXDetector' 'M', {} - 'XRayCollimator' 'U', {} - 'DXPositioning' 'U', {} - 'XRayTomoAcquisition' 'U', {} - 'XRayAcquisitionDose' 'U', {} - 'XRayGeneration' 'U', {} - 'XRayFiltration' 'U', {} - 'XRayGrid' 'U', {} - 'MammographyImage' 'M', {} - 'OverlayPlane' 'C', {} - 'Curve' 'U', {} - 'VOILUT' 'C', {} - 'ImageHistogram' 'U', {} - 'AcquisitionContext' 'M', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'IntraoralImageForProcessing'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.1.3.1'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'ClinicalTrialSubject' 'U', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'DXSeries' 'M', {} - 'IntraoralSeries' 'M', {} - 'FrameOfReference' 'U', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'ContrastBolus' 'U', {} - 'DisplayShutter' 'U', {} - 'Device' 'U', {} - 'Therapy' 'U', {} - 'DXAnatomyImaged' 'M', {} - 'DXImage' 'M', {} - 'DXDetector' 'M', {} - 'XRayCollimator' 'U', {} - 'DXPositioning' 'U', {} - 'XRayTomoAcquisition' 'U', {} - 'XRayAcquisitionDose' 'U', {} - 'XRayGeneration' 'U', {} - 'XRayFiltration' 'U', {} - 'XRayGrid' 'U', {} - 'IntraoralImage' 'M', {} - 'OverlayPlane' 'C', {} - 'Curve' 'U', {} - 'VOILUT' 'C', {} - 'ImageHistogram' 'U', {} - 'AcquisitionContext' 'M', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'IntraoralImageForPresentation'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.1.3'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'ClinicalTrialSubject' 'U', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'DXSeries' 'M', {} - 'IntraoralSeries' 'M', {} - 'FrameOfReference' 'U', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'ContrastBolus' 'U', {} - 'DisplayShutter' 'U', {} - 'Device' 'U', {} - 'Therapy' 'U', {} - 'DXAnatomyImaged' 'M', {} - 'DXImage' 'M', {} - 'DXDetector' 'M', {} - 'XRayCollimator' 'U', {} - 'DXPositioning' 'U', {} - 'XRayTomoAcquisition' 'U', {} - 'XRayAcquisitionDose' 'U', {} - 'XRayGeneration' 'U', {} - 'XRayFiltration' 'U', {} - 'XRayGrid' 'U', {} - 'IntraoralImage' 'M', {} - 'OverlayPlane' 'C', {} - 'Curve' 'U', {} - 'VOILUT' 'C', {} - 'ImageHistogram' 'U', {} - 'AcquisitionContext' 'M', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'VLEndoscopicImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.77.1.1'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'VLEndoscopicSeriesDummy' 'M', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'AcquisitionContext' 'M', {} - 'VLImage' 'M', {} - 'OverlayPlane' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'VLMicroscopicImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.77.1.2'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'ClinicalTrialSubject' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'VLMicroscopicSeriesDummy' 'M', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'AcquisitionContext' 'M', {} - 'VLImage' 'M', {} - 'OverlayPlane' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'VLSlideCoordinatesMicroscopicImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.77.1.3'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'ClinicalTrialSubject' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'VLSlideCoordinatesMicroscopicSeriesDummy' 'M', {} - 'FrameOfReference' 'M', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'AcquisitionContext' 'M', {} - 'VLImage' 'M', {} - 'SlideCoordinates' 'M', {} - 'OverlayPlane' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'VLPhotographicImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.77.1.4'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'ClinicalTrialSubject' 'C', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'VLPhotographicSeriesDummy' 'M', {} - 'GeneralEquipment' 'M', {} - 'GeneralImage' 'M', {} - 'ImagePixel' 'M', {} - 'AcquisitionContext' 'M', {} - 'VLImage' 'M', {} - 'OverlayPlane' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'BasicVoice'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.9.4.1'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'Synchronization' 'U', {} - 'GeneralEquipment' 'M', {} - 'WaveformIdentification' 'M', {} - 'Waveform' 'M', {} - 'AcquisitionContext' 'M', {} - 'WaveformAnnotation' 'U', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'TwelveLeadECG'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.9.1.1'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'Synchronization' 'U', {} - 'GeneralEquipment' 'M', {} - 'WaveformIdentification' 'M', {} - 'Waveform' 'M', {} - 'AcquisitionContext' 'M', {} - 'WaveformAnnotation' 'C', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'GeneralECG'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.9.1.2'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'Synchronization' 'U', {} - 'GeneralEquipment' 'M', {} - 'WaveformIdentification' 'M', {} - 'Waveform' 'M', {} - 'AcquisitionContext' 'M', {} - 'WaveformAnnotation' 'C', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'AmbulatoryECG'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.9.1.3'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'Synchronization' 'U', {} - 'GeneralEquipment' 'M', {} - 'WaveformIdentification' 'M', {} - 'Waveform' 'M', {} - 'AcquisitionContext' 'M', {} - 'WaveformAnnotation' 'C', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'HemodynamicWaveform'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.9.2.1'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'Synchronization' 'C', {} - 'GeneralEquipment' 'M', {} - 'WaveformIdentification' 'M', {} - 'Waveform' 'M', {} - 'AcquisitionContext' 'M', {} - 'WaveformAnnotation' 'C', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'CardiacElectrophysiologyWaveform'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.9.3.1'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'Synchronization' 'C', {} - 'GeneralEquipment' 'M', {} - 'WaveformIdentification' 'M', {} - 'Waveform' 'M', {} - 'AcquisitionContext' 'M', {} - 'WaveformAnnotation' 'C', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'BasicTextSR'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.88.11'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'ClinicalTrialSubject' 'C', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'SRDocumentSeries' 'M', {} - 'GeneralEquipment' 'M', {} - 'SRDocumentGeneral' 'M', {} - 'SRDocumentContent' 'M', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'EnhancedSR'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.88.22'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'ClinicalTrialSubject' 'C', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'SRDocumentSeries' 'M', {} - 'GeneralEquipment' 'M', {} - 'SRDocumentGeneral' 'M', {} - 'SRDocumentContent' 'M', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'ComprehensiveSR'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.88.33'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'ClinicalTrialSubject' 'C', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'SRDocumentSeries' 'M', {} - 'GeneralEquipment' 'M', {} - 'SRDocumentGeneral' 'M', {} - 'SRDocumentContent' 'M', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'MammographyCADSR'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.88.50'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'ClinicalTrialSubject' 'C', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'SRDocumentSeries' 'M', {} - 'GeneralEquipment' 'M', {} - 'SRDocumentGeneral' 'M', {} - 'SRDocumentContent' 'M', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'KeyObjectSelectionDocument'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.88.59'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'ClinicalTrialSubject' 'C', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'KeyObjectDocumentSeries' 'M', {} - 'GeneralEquipment' 'M', {} - 'KeyObjectDocument' 'M', {} - 'SRDocumentContent' 'M', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'GrayscaleSoftcopyPresentationState'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.11.1'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'GeneralSeries' 'M', {} - 'PresentationSeries' 'M', {} - 'GeneralEquipment' 'M', {} - 'PresentationState' 'M', {} - 'Mask' 'C', {} - 'DisplayShutter' 'C', {} - 'BitmapDisplayShutter' 'C', {} - 'OverlayPlane' 'C', {} - 'OverlayCurveActivation' 'C', {} - 'DisplayedArea' 'M', {} - 'GraphicAnnotation' 'C', {} - 'SpatialTransformation' 'C', {} - 'GraphicLayer' 'C', {} - 'ModalityLUT' 'C', {} - 'SoftcopyVOILUT' 'C', {} - 'SoftcopyPresentationLUT' 'M', {} - 'SOPCommon' 'M', {} -}; - -iods(end+1).Name = 'EnhancedMRImage'; -iods(end).UID = '1.2.840.10008.5.1.4.1.1.4.1'; -iods(end).Def_fcn = 'dicom_modules'; -iods(end).Prep_fcn = 'dicom_prep_metadata'; -iods(end).Spec_part = ''; -iods(end).Modules = { - 'FileMetadata', 'C', {'HAS_FILEMETADATA'} - 'Patient' 'M', {} - 'ClinicalTrialSubject' 'U', {} - 'GeneralStudy' 'M', {} - 'PatientStudy' 'U', {'TRUE'} - 'ClinicalTrialStudy' 'U', {} - 'GeneralSeries' 'M', {} - 'ClinicalTrialSeries' 'U', {} - 'MRSeries' 'M', {} - 'FrameOfReference' 'M', {} - 'Synchronization' 'C', {'IS_TIME_SYNCHRONIZED'} - 'GeneralEquipment' 'M', {} - 'EnhancedGeneralEquipment' 'M', {} - 'ImagePixel' 'M', {} - 'EnhancedContrastBolus' 'C', {} - 'MultiFrameFunctionalGroups' 'M', {} - 'MultiFrameDimension' 'M', {} - 'CardiacSynchronization' 'C', {} - 'RespiratorySynchronization' 'C', {} - 'BulkMotionSynchronization' 'C', {} - 'SupplementalPaletteColorLUT' 'C', {} - 'AcquisitionContext' 'M', {} - 'Device' 'U',{} - 'Specimen' 'U', {} - 'EnhancedMRImage' 'M', {} - 'MRPulseSequence' 'C', {} - 'SOPCommon' 'M', {} -}; diff --git a/CT/private/dicom_load_dictionary.m b/CT/private/dicom_load_dictionary.m deleted file mode 100644 index e6f21bc..0000000 --- a/CT/private/dicom_load_dictionary.m +++ /dev/null @@ -1,257 +0,0 @@ -function [tags, values] = dicom_load_dictionary(dictionary) -%DICOM_LOAD_DICTIONARY Load the DICOM data dictionary into MATLAB - -% Lines in the data dictionary file have the form: -% -% # Comment -% (ABCD,EFO1) \t VR1/VR2/... \t BlanklessName \t VM \n -% -% VM can be a scalar or range (e.g., 1, 3, 1-3, 3-n) - -% The data dictionary in memory is stored as a structure array with one -% entry in the struct for each attribute in the data dictionary. -% Attributes in repeating classes are expanded into the 128 attributes for -% the class. -% -% The entries of the associated 65536-by-65536 sparse lookup table are -% nonzero if a group and element combination correspond to an attribute -% in the data dictionary. The DICOM data dictionary is zero-based, so -% the indices for tag (0x0008,0x0010) are (9,17). Thus, entry (9,17) in -% the sparse array contains the index for attribute (0008,0010) in the -% struct, or 0 if it isn't in the dictionary. - -% Copyright 1993-2011 The MathWorks, Inc. - -if (strfind(dictionary, '.mat')) - - load(dictionary); - return - -end - -MAX_GROUP = 65535; % 0xFFFF -MAX_ELEMENT = 65535; % 0xFFFF - -values = struct([]); - -count = 0; - -% -% Read the dictionary. -% -fmt = '(%4c,%4c)\t%s%s%s'; -[group, element, vr, name, vm] = textread(dictionary, fmt, ... - 'commentstyle', 'shell'); - -% -% Remove duplicate entries from the list. Keep the last. -% - -% Concatenate group and element to make the elements be sorted uniquely. -ge = [group element]; - -% UNIQUE has the property of sorting rows and keeping the last -% duplicate. This is yields the desired behavior of removing entries -% from the data dictionary which have been superceded by later entries. -[ge_sorted, idx] = unique(ge, 'rows'); - -% Separate the sorted group and element values. -group = ge_sorted(:, 1:4); -element = ge_sorted(:, 5:8); - -% Sort and remove duplicates from the value fields using the index from -% UNIQUE. -name = name(idx); -vr = vr(idx); -vm = vm(idx); - -% -% Process VR, VM -% - -for p = 1:length(vr) - - % VR. - - if (~isempty(strfind(vr{p}, '/'))) - % Multiple potential VR's. - - tmp_vr = tokenize(vr{p}, '/'); - - for q = 1:length(tmp_vr) - if (length(tmp_vr{q}) ~= 2) - error(message('images:dicom_load_dictionary:invalidVR', vr{ p }, group( p, : ), element( p, : ))) - end - end - - vr{p} = tmp_vr'; - - else - % Single VR value. - - if (length(vr{p}) ~= 2) - error(message('images:dicom_load_dictionary:invalidVR', vr{ p }, group( p, : ), element( p, : ))) - end - - end - - % - % VM. - % - - % Look for range. - h_pos = strfind(vm{p}, '-'); - - if (~isempty(h_pos)) - % VM is a range. - - if ((length(h_pos) > 1) || ... - (h_pos(1) == 1) || ... - (h_pos(end) == length(vm{p}))) - - error(message('images:dicom_load_dictionary:invalidVM', vm{ p }, group( p, : ), element( p, : ))) - end - - vm_low = vm{p}(1:(h_pos - 1)); - vm_low = sscanf(vm_low, '%d'); - - vm_high = vm{p}((h_pos + 1):end); - - if (strfind(lower(vm_high), 'n')) - vm_high = inf; - else - vm_high = sscanf(vm_high, '%d'); - end - - if (isempty(vm_low) || isempty(vm_high)) - - error(message('images:dicom_load_dictionary:invalidVM', vm{ p }, group( p, : ), element( p, : ))) - - end - - vm{p} = [vm_low vm_high]; - - else - % VM is scalar. - tmp = sscanf(vm{p}, '%d'); - - if (isnan(tmp)) - - error(message('images:dicom_load_dictionary:invalidVM', vm{ p }, group( p, : ), element( p, : ))) - - else - vm{p} = [tmp tmp]; - end - - end - -end % for p ... - -% -% Handle the repeating classes before storing the rest. -% - All of these classes will have a group or element ending in 'xx'. -% - The spec says that new repeating classes are not to be introduced. -% Sequences will be used instead. -% - The range for these values is always 00 to ff (e.g., 5000 - 50ff). -% - Only even group values are part of the repeating group (odd ones are -% private, of course). Repeating elements, on the other hand, can be -% either odd or even. -% - Technically these classes have the same name in the data dictionary, -% but we need to uniquely identify them when placing them in the -% structure. -% - See PS 3.5-2000 Sec. 7.6 for information on repeating groups. -% - Repeating elements are an evil construction present in ACR-NEMA only. -% - -% Find repeating groups and elements. -rep_group = strmatch('xx', fliplr(group)); -rep_element = strmatch('xx', fliplr(element)); - -% Number of all attributes is (regular + repeating). -count_rep_classes = length(rep_group) + length(rep_element); -count_expanded = 128*length(rep_group) + 256*length(rep_element); -total_attr = length(vr) + count_expanded - count_rep_classes; - -% Preallocate variables. -values(total_attr).Name = 'TEMP PLACEHOLDER'; -values(total_attr).VR = {''}; -values(total_attr).VM = 0; - -rows = zeros(total_attr, 1); -cols = zeros(total_attr, 1); - -% Assign values for the Repeating groups. - -for p = 1:length(rep_group) - - % Find the offset of the repeating group (e.g., 6000 or 5000). - offset = sscanf([group(rep_group(p), 1:2) '00'], '%x'); - cur_element = sscanf(element(rep_group(p), 1:4), '%x'); - - % Place the repeating values in the struct. - for q = 1:128 - - count = count + 1; - - values(count).Name = [name{rep_group(p)} '_' sprintf('%X', 2*(q-1))]; - values(count).VR = vr{rep_group(p)}; - values(count).VM = vm{rep_group(p)}; - - end - - % Keep track of group and element values for the allocated attributes. - rows((count - 127):(count)) = (offset + 1):2:(offset + 256); - cols((count - 127):(count)) = cur_element + 1; - -end - -% Repeating elements. - -for p = 1:length(rep_element) - - % Find the offset of the repeating element. - offset = sscanf([element(rep_element(p), 1:2) '00'], '%x'); - cur_group = sscanf(group(rep_element(p), 1:4), '%x'); - - % Place the repeating values in the struct. - for q = 1:256 - - count = count + 1; - - values(count).Name = [name{rep_element(p)} '_' sprintf('%X', (q-1))]; - values(count).VR = vr{rep_group(p)}; - values(count).VM = vm{rep_group(p)}; - - end - - % Keep track of group and element values for the allocated attributes. - rows((count - 255):(count)) = cur_group + 1; - cols((count - 255):(count)) = (offset + 1):(offset + 256); - -end - -% Don't process the repeating values twice. -group([rep_group; rep_element],:) = []; -element([rep_group; rep_element],:) = []; - -name([rep_group; rep_element]) = []; -vr([rep_group; rep_element]) = []; -vm([rep_group; rep_element]) = []; - -% -% Store the remainder of the values. -% - -group = hex2dec(group); -element = hex2dec(element); - -count = count + 1; - -rows(count:end) = group + 1; -cols(count:end) = element + 1; - -tags = sparse(rows, cols, 1:total_attr, MAX_GROUP + 1, MAX_ELEMENT + 1); - -[values(count:total_attr).Name] = deal(name{:}); -[values(count:total_attr).VR] = deal(vr{:}); -[values(count:total_attr).VM] = deal(vm{:}); diff --git a/CT/private/dicom_modules.m b/CT/private/dicom_modules.m deleted file mode 100644 index 1a053e5..0000000 --- a/CT/private/dicom_modules.m +++ /dev/null @@ -1,1835 +0,0 @@ -function module_details = dicom_modules(module_name) -%DICOM_MODULES Repository of DICOM module attributes and details. -% DETAILS = DICOM_MODULES(NAME) returns a structure array of details -% about the module NAME. DETAILS is a structure with fields -% -% - Name The module's name. -% - SpecPart Where this module is defined in the DICOM spec. -% - Attrs The attributes that define a module. A cell array with -% the following meanings attributed to the columns: -% -% (1) Depth in the module. Nonzero indicates a sequence. -% (2) Group -% (3) Element -% (4) Attribute type (see PS 3.3 Sec. 5.4) -% (5) VR mapping -% (6) Enumerated values. If this is present, an attribute's value -% must be one or more of the items in the cell array (or empty if -% type 2 or 2C). -% (7) LISP-like condition if type 1C or 2C. -% -% See also DICOM_IODS, dicom-dict.txt. - -% Copyright 1993-2010 The MathWorks, Inc. -% - -switch (module_name) -case 'FileMetadata' - module_details = build_FileMetadata; -case 'Patient' - module_details = build_Patient; -case 'GeneralStudy' - module_details = build_GeneralStudy; -case 'PatientStudy' - module_details = build_PatientStudy; -case 'GeneralSeries' - module_details = build_GeneralSeries; -case 'FrameOfReference' - module_details = build_FrameOfReference; -case 'GeneralEquipment' - module_details = build_GeneralEquipment; -case 'GeneralImage' - module_details = build_GeneralImage; -case 'ImagePlane' - module_details = build_ImagePlane; -case 'ImagePixel' - module_details = build_ImagePixel; -case 'ContrastBolus' - module_details = build_ContrastBolus; -case 'MRImage' - module_details = build_MRImage; -case 'CTImage' - module_details = build_CTImage; -case 'OverlayPlane' - module_details = build_OverlayPlane; -case 'VOILUT' - module_details = build_VOILUT; -case 'SOPCommon' - module_details = build_SOPCommon; -case 'SCImageEquipment' - module_details = build_SCImageEquipment; -case 'SCImage' - module_details = build_SCImage; -case 'USFrameOfReference' - module_details = build_USFrameOfReference; -case 'PaletteColorLookupTable' - module_details = build_PaletteColorLookupTable; -case 'USRegionCalibration' - module_details = build_USRegionCalibration; -case 'USImage' - module_details = build_USImage; -case 'Cine' - module_details = build_Cine; -case 'MultiFrame' - module_details = build_MultiFrame; -case 'ModalityLUT' - module_details = build_ModalityLUT; -case 'FramePointers' - module_details = build_FramePointers; -case 'Mask' - module_details = build_Mask; -case 'DisplayShutter' - module_details = build_DisplayShutter; -case 'Device' - module_details = build_Device; -case 'Therapy' - module_details = build_Therapy; -case 'XRayImage' - module_details = build_XRayImage; -case 'XRayAcquisition' - module_details = build_XRayAcquisition; -case 'XRayCollimator' - module_details = build_XRayCollimator; -case 'XRayTable' - module_details = build_XRayTable; -case 'XAPositioner' - module_details = build_XAPositioner; -case 'MultiFrameOverlay' - module_details = build_MultiFrameOverlay; -case 'Curve' - module_details = build_Curve; -case 'SCMultiFrameImage' - module_details = build_SCMultiFrameImage; -case 'SCMultiFrameVector' - module_details = build_SCMultiFrameVector; -case 'MRSeries' - module_details = build_MRSeries; -case 'Synchronization' - module_details = build_Synchronization; -case 'EnhancedGeneralEquipment' - module_details = build_EnhancedGeneralEquipment; -case 'ClinicalTrialSeries' - module_details = build_ClinicalTrialSeries; -case 'ClinicalTrialStudy' - module_details = build_ClinicalTrialStudy; -case 'ClinicalTrialSubject' - module_details = build_ClinicalTrialSubject; -case 'EnhancedContrastBolus' - module_details = build_EnhancedContrastBolus; -case 'MultiFrameDimension' - module_details = build_MultiFrameDimension; -case 'CardiacSynchronization' - module_details = build_CardiacSynchronization; -case 'RespiratorySynchronization' - module_details = build_RespiratorySynchronization; -case 'BulkMotionSynchronization' - module_details = build_BulkMotionSynchronization; -case 'SupplementalPaletteColorLUT' - module_details = build_SupplementalPaletteColorLUT; -case 'AcquisitionContext' - module_details = build_AcquisitionContext; -case 'MultiFrameFunctionalGroups' - module_details = build_MultiFrameFunctionalGroups; -case 'Specimen' - module_details = build_Specimen; -case 'MRPulseSequence' - module_details = build_MRPulseSequence; -case 'EnhancedMRImage' - module_details = build_EnhancedMRImage; -case '' - module_details = build_; -otherwise - module_details = []; -end - - - -function details = build_FileMetadata - -details.Name = 'FileMetadata'; -details.SpecPart = 'PS 3.10 Sec. 7.1'; -details.Attrs = { - 0, '0002', '0001', '1', {}, {uint8([0 1])}, {} - 0, '0002', '0002', '1', {}, {}, {} - 0, '0002', '0003', '1', {}, {}, {} - 0, '0002', '0010', '1', {}, {}, {} - 0, '0002', '0012', '1', {}, {}, {} - 0, '0002', '0013', '3', {}, {}, {} - 0, '0002', '0016', '3', {}, {}, {} - 0, '0002', '0100', '3', {}, {}, {} - 0, '0002', '0102', '1C', {}, {}, {'present', '(0002,0100)'} - }; - - -function details = build_Patient - -details.Name = 'Patient'; -details.SpecPart = 'PS 3.3 Sec. C.7.1.1'; -details.Attrs = { - 0, '0010', '0010', '2', {}, {}, {} - 0, '0010', '0020', '2', {}, {}, {} - 0, '0010', '0030', '2', {}, {}, {} - 0, '0010', '0040', '2', {}, {'M' 'F' '0'}, {} - 0, '0008', '1120', '3', {}, {}, {} - 1, '0008', '1150', '1C', {}, {}, {'present', '(0008,1120)'} - 1, '0008', '1155', '1C', {}, {}, {'present', '(0008,1120)'} - 0, '0010', '0032', '3', {}, {}, {} - 0, '0010', '1000', '3', {}, {}, {} - 0, '0010', '1001', '3', {}, {}, {} - 0, '0010', '2160', '3', {}, {}, {} - 0, '0010', '4000', '3', {}, {}, {} - }; - - -function details = build_GeneralStudy - -details.Name = 'GeneralStudy'; -details.SpecPart = 'PS 3.3 Sec. C.7.2.1'; -details.Attrs = { - 0, '0020', '000D', '1', {}, {}, {} - 0, '0008', '0020', '2', {}, {}, {} - 0, '0008', '0030', '2', {}, {}, {} - 0, '0008', '0090', '2', {}, {}, {} - 0, '0020', '0010', '2', {}, {}, {} - 0, '0008', '0050', '2', {}, {}, {} - 0, '0008', '1030', '3', {}, {}, {} - 0, '0008', '1048', '3', {}, {}, {} - 0, '0008', '1060', '3', {}, {}, {} - 0, '0008', '1110', '3', {}, {}, {} - 1, '0008', '1150', '1C', {}, {}, {'present', '(0008,1110)'} - 1, '0008', '1155', '1C', {}, {}, {'present', '(0008,1110)'} - 0, '0008', '1032', '3', {}, {}, {} - 1, 'code', 'sequ', 'X', {}, {}, {} % This is a placeholder. -% 0, % Code sequence macro "No baseline context." - }; - - -function details = build_PatientStudy - -details.Name = 'PatientStudy'; -details.SpecPart = 'PS 3.3 Sec. C.7.2.2'; -details.Attrs = { - 0, '0008', '1080', '3', {}, {}, {} - 0, '0010', '1010', '3', {}, {}, {} - 0, '0010', '1020', '3', {}, {}, {} - 0, '0010', '1030', '3', {}, {}, {} - 0, '0010', '2180', '3', {}, {}, {} - 0, '0010', '21B0', '3', {}, {}, {} - }; - - -function details = build_GeneralSeries - -details.Name = 'GeneralSeries'; -details.SpecPart = 'PS 3.3 Sec. C.7.3.1'; -details.Attrs = { - 0, '0008', '0060', '1', {}, modalityTerms, {} - 0, '0020', '000E', '1', {}, {}, {} - 0, '0020', '0011', '2', {}, {}, {} - 0, '0020', '0060', '2C', {}, {'L', 'R'}, {'and', ... - {'not', {'present', '(0020,0062)'}}, ... - {'present', '(0020,0060)'}} - 0, '0008', '0021', '3', {}, {}, {} - 0, '0008', '0031', '3', {}, {}, {} - 0, '0008', '1050', '3', {}, {}, {} - 0, '0018', '1030', '3', {}, {}, {} - 0, '0008', '103E', '3', {}, {}, {} - 0, '0008', '1070', '3', {}, {}, {} - 0, '0008', '1111', '3', {}, {}, {} - 1, '0008', '1150', '1C', {}, {}, {'present', '(0008,1111)'} - 1, '0008', '1155', '1C', {}, {}, {'present', '(0008,1111)'} - 0, '0018', '0015', '3', {}, bodyPartTerms, {} - 0, '0018', '5100', '2C', {}, patientPositionTerms, {'or', ... - {'equal', '(0008,0016)', '1.2.840.10008.5.1.4.1.1.4'} ... - {'equal', '(0008,0016)', '1.2.840.10008.5.1.4.1.1.2'}} - 0, '0028', '0108', '3', {'(0028,0103)', {0, 'US'}, {1, 'SS'}}, {}, {} - 0, '0028', '0109', '3', {'(0028,0103)', {0, 'US'}, {1, 'SS'}}, {}, {} - 0, '0040', '0275', '3', {}, {}, {} - 1, '0040', '1001', '1C', {}, {}, {'present', '(0040,0275)'} - 1, '0040', '0009', '1C', {}, {}, {'present', '(0040,0275)'} - 1, '0040', '0007', '3', {}, {}, {} - 1, '0040', '0008', '3', {}, {}, {} -% 1, % Code sequence macro "No baseline context." - 0, '0040', '0253', '3', {}, {}, {} - 0, '0040', '0244', '3', {}, {}, {} - 0, '0040', '0245', '3', {}, {}, {} - 0, '0040', '0254', '3', {}, {}, {} - 0, '0040', '0260', '3', {}, {}, {} - 1, 'code', 'sequ', 'X', {}, {}, {} % This is a placeholder. -% 0, % Code sequence macro "No baseline context." - }; - - -function details = build_FrameOfReference - -details.Name = 'FrameOfReference'; -details.SpecPart = 'PS 3.3 Sec. C.7.4.1'; -details.Attrs = { - 0, '0020', '0052', '1', {}, {}, {} - 0, '0020', '1040', '2', {}, {}, {} - }; - - -function details = build_GeneralEquipment - -details.Name = 'GeneralEquipment'; -details.SpecPart = 'PS 3.3 Sec. C.7.5.1'; -details.Attrs = { - 0, '0008', '0070', '2', {}, {}, {} - 0, '0008', '0080', '3', {}, {}, {} - 0, '0008', '0081', '3', {}, {}, {} - 0, '0008', '1010', '3', {}, {}, {} - 0, '0008', '1040', '3', {}, {}, {} - 0, '0008', '1090', '3', {}, {}, {} - 0, '0018', '1000', '3', {}, {}, {} - 0, '0018', '1020', '3', {}, {}, {} - 0, '0018', '1050', '3', {}, {}, {} - 0, '0018', '1200', '3', {}, {}, {} - 0, '0018', '1201', '3', {}, {}, {} - 0, '0028', '0120', '3', {'(0028,0103)', {0, 'US'}, {1, 'SS'}}, {}, {} - }; - - -function details = build_GeneralImage - -details.Name = 'GeneralImage'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.1'; -details.Attrs = { - 0, '0020', '0013', '2', {}, {}, {} - 0, '0020', '0020', '2C', {}, {}, {'or', {'not', {'present', '(0020,0037)'}} ... - {'not', {'present', '(0020,0032)'}}} - 0, '0008', '0023', '2C', {}, {}, {'true'} - 0, '0008', '0033', '2C', {}, {}, {'true'} - 0, '0008', '0008', '3', {}, {}, {} - 0, '0020', '0012', '3', {}, {}, {} - 0, '0008', '0022', '3', {}, {}, {} - 0, '0008', '0032', '3', {}, {}, {} - 0, '0008', '002A', '3', {}, {}, {} - 0, '0008', '1140', '3', {}, {}, {} - 1, '0008', '1150', '1C', {}, {}, {'present', '(0008,1140)'} - 1, '0008', '1155', '1C', {}, {}, {'present', '(0008,1140)'} - 1, '0008', '1160', '3', {}, {}, {} - 0, '0008', '2111', '3', {}, {}, {} - 0, '0008', '2112', '3', {}, {}, {} - 1, '0008', '1150', '1C', {}, {}, {'present', '(0008,2112)'} - 1, '0008', '1155', '1C', {}, {}, {'present', '(0008,2112)'} - 1, '0008', '1160', '3', {}, {}, {} - 0, '0020', '1002', '3', {}, {}, {} - 0, '0020', '4000', '3', {}, {}, {} - 0, '0028', '0300', '3', {}, {'YES' 'NO'}, {} - 0, '0028', '0301', '3', {}, {'YES' 'NO'}, {} - 0, '0028', '2110', '3', {}, {0 1}, {} - 0, '0028', '2112', '3', {}, {}, {} - }; - - -function details = build_ImagePlane - -details.Name = 'ImagePlane'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.2'; -details.Attrs = { - 0, '0028', '0030', '1', {}, {}, {} - 0, '0020', '0037', '1', {}, {}, {} - 0, '0020', '0032', '1', {}, {}, {} - 0, '0018', '0050', '2', {}, {}, {} - 0, '0020', '1041', '3', {}, {}, {} - }; - - -function details = build_ImagePixel - -details.Name = 'ImagePixel'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.3'; -details.Attrs = { - 0, '0028', '0002', '1', {}, {}, {} - 0, '0028', '0004', '1', {}, {}, {} - 0, '0028', '0010', '1', {}, {}, {} - 0, '0028', '0011', '1', {}, {}, {} - 0, '0028', '0100', '1', {}, {}, {} - 0, '0028', '0101', '1', {}, {}, {} - 0, '0028', '0102', '1', {}, {}, {} - 0, '0028', '0103', '1', {}, {0 1}, {} - 0, '7FE0', '0010', '1', {}, {}, {} - 0, '0028', '0006', '1C', {}, {}, {'not', {'equal', '(0028,0002)', 1}} - 0, '0028', '0034', '1C', {}, {}, {'present', '(0028,0034)'} - 0, '0028', '0106', '3', {'(0028,0103)', {0, 'US'}, {1, 'SS'}}, {}, {} - 0, '0028', '0107', '3', {'(0028,0103)', {0, 'US'}, {1, 'SS'}}, {}, {} - 0, '0028', '1101', '1C', {'(0028,0103)', {0, 'US'}, {1, 'SS'}}, {}, ... - {'or', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'} ... - {'equal', '(0028,0004)', 'ARGB'}} - 0, '0028', '1102', '1C', {'(0028,0103)', {0, 'US'}, {1, 'SS'}}, {}, ... - {'or', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'} ... - {'equal', '(0028,0004)', 'ARGB'}} - 0, '0028', '1103', '1C', {'(0028,0103)', {0, 'US'}, {1, 'SS'}}, {}, ... - {'or', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'} ... - {'equal', '(0028,0004)', 'ARGB'}} - 0, '0028', '1201', '1C', {}, {}, {'or', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'} ... - {'equal', '(0028,0004)', 'ARGB'}} - 0, '0028', '1202', '1C', {}, {}, {'or', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'} ... - {'equal', '(0028,0004)', 'ARGB'}} - 0, '0028', '1203', '1C', {}, {}, {'or', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'} ... - {'equal', '(0028,0004)', 'ARGB'}} - 0, '0028', '2000', '3', {}, {}, {} - 0, '0028', '0008', '1C', {}, {}, {'present', '(0028,0008)'} - 0, '0028', '0009', '1C', {}, {}, {'present', '(0028,0009)'} - 0, '0028', '7FE0', '1C', {}, {}, {'present', '(0028,7FE0)'} - 0, '0028', '0121', '1C', {}, {}, {'present', '(0028,0121)'} - }; - - -function details = build_ContrastBolus - -details.Name = 'ContrastBolus'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.4'; -details.Attrs = { - 0, '0018', '0010', '2', {}, {}, {} - 0, '0018', '0012', '3', {}, {}, {} - 1, 'code', 'sequ', 'X', {}, {}, {} % This is a placeholder. -% 1, % Code sequence macro "Baseline context id is 12" - 0, '0018', '1040', '3', {}, {}, {} - 0, '0018', '0014', '3', {}, {}, {} -% 1, % Code sequence macro "Baseline context id is 11" - 1, '0018', '002A', '3', {}, {}, {} -% 2, % Code sequence macro "No baseline context." - 0, '0018', '1041', '3', {}, {}, {} - 0, '0018', '1042', '3', {}, {}, {} - 0, '0018', '1043', '3', {}, {}, {} - 0, '0018', '1044', '3', {}, {}, {} - 0, '0018', '1046', '3', {}, {}, {} - 0, '0018', '1047', '3', {}, {}, {} - 0, '0018', '1048', '3', {}, {'IODINE' - 'GADOLINIUM' - 'CARBON DIOXIDE' - 'BARIUM'}, {} - 0, '0018', '1049', '3', {}, {}, {} - }; - - -function details = build_MRImage - -details.Name = 'MRImage'; -details.SpecPart = 'PS 3.3 Sec. C.8.3.1'; -details.Attrs = { - 0, '0008', '0008', '1', {}, {}, {} - 0, '0028', '0002', '1', {}, {1}, {} - 0, '0028', '0004', '1', {}, {'MONOCHROME1' 'MONOCHROME2'}, {} - 0, '0028', '0100', '1', {}, {16}, {} - 0, '0018', '0020', '1', {}, {'SE' 'IR' 'GR' 'EP' 'RM'}, {} - 0, '0018', '0021', '1', {}, {'SK' 'MTC' 'SS' 'TRSS' 'SP' ... - 'MP' 'OSP' 'NONE'}, {} - 0, '0018', '0022', '1', {}, {'PER' 'RG' 'CG' 'PPG' 'FC' ... - 'PFF' 'PFP' 'SP' 'FS' 'CT'}, {} - 0, '0018', '0023', '1', {}, {'2D' '3D'}, {} - 0, '0018', '0080', '2C', {}, {}, {'not', ... - {'and', ... - {'equal', '(0018,0020)', 'EP'}, ... - {'equal', '(0018,0021)', 'SK'}}} - 0, '0018', '0081', '2', {}, {}, {} - 0, '0018', '0091', '2', {}, {}, {} - 0, '0018', '0082', '2C', {}, {}, {'or', ... - {'equal', '(0018,0020)', 'IR'}, ... - {'present', '(0018,0082)'}} - 0, '0018', '1060', '2C', {}, {}, {'or', ... - {'present', '(0018,1060)'}, ... - {'or', ... - {'equal', '(0018,0022)', 'RG'}, ... - {'equal', '(0018,0022)', 'CG'}, ... - {'equal', '(0018,0022)', 'CT'}, ... - {'equal', '(0018,0022)', 'PPG'}}} - 0, '0018', '0024', '3', {}, {}, {} - 0, '0018', '0025', '3', {}, {'Y' 'N'}, {} - 0, '0018', '0083', '3', {}, {}, {} - 0, '0018', '0084', '3', {}, {}, {} - 0, '0018', '0085', '3', {}, {}, {} - 0, '0018', '0086', '3', {}, {}, {} - 0, '0018', '0087', '3', {}, {}, {} - 0, '0018', '0088', '3', {}, {}, {} - 0, '0018', '0089', '3', {}, {}, {} - 0, '0018', '0093', '3', {}, {}, {} - 0, '0018', '0094', '3', {}, {}, {} - 0, '0018', '0095', '3', {}, {}, {} - 0, '0018', '1062', '3', {}, {}, {} - 0, '0018', '1080', '3', {}, {'Y' 'N'}, {} - 0, '0018', '1081', '3', {}, {}, {} - 0, '0018', '1082', '3', {}, {}, {} - 0, '0018', '1083', '3', {}, {}, {} - 0, '0018', '1084', '3', {}, {}, {} - 0, '0018', '1085', '3', {}, {}, {} - 0, '0018', '1086', '3', {}, {}, {} - 0, '0018', '1088', '3', {}, {}, {} - 0, '0018', '1090', '3', {}, {}, {} - 0, '0018', '1094', '3', {}, {}, {} - 0, '0018', '1100', '3', {}, {}, {} - 0, '0018', '1250', '3', {}, {}, {} - 0, '0018', '1251', '3', {}, {}, {} - 0, '0018', '1310', '3', {}, {}, {} - 0, '0018', '1312', '3', {}, {}, {} - 0, '0018', '1314', '3', {}, {}, {} - 0, '0018', '1316', '3', {}, {}, {} - 0, '0018', '1315', '3', {}, {'Y' 'N'}, {} - 0, '0018', '1318', '3', {}, {}, {} - 0, '0020', '0100', '3', {}, {}, {} - 0, '0020', '0105', '3', {}, {}, {} - 0, '0020', '0110', '3', {}, {}, {} - }; - - - -function details = build_OverlayPlane - -details.Name = 'OverlayPlane'; -details.SpecPart = 'PS 3.3 Sec. C.9.2'; -details.Attrs = { - 0, '60XX', '0010', '1', {}, {}, {} - 0, '60XX', '0011', '1', {}, {}, {} - 0, '60XX', '0040', '1', {}, {'G' 'R'}, {} - 0, '60XX', '0050', '1', {}, {}, {} - 0, '60XX', '0100', '1', {}, {1}, {} - 0, '60XX', '0102', '1', {}, {0}, {} - 0, '60XX', '3000', '1C', {}, {}, {'equal', '(60XX,0100)', 1} - 0, '60XX', '0022', '3', {}, {}, {} - 0, '60XX', '0045', '3', {}, {'USER' 'AUTOMATED'}, {} - 0, '60XX', '1500', '3', {}, {}, {} - 0, '60XX', '1301', '3', {}, {}, {} - 0, '60XX', '1302', '3', {}, {}, {} - 0, '60XX', '1303', '3', {}, {}, {} - }; - - -function details = build_VOILUT - -details.Name = 'VOILUT'; -details.SpecPart = 'PS 3.3 Sec. C.11.2'; -details.Attrs = { - 0, '0028', '3010', '3', {}, {}, {} - 1, '0028', '3002', '1C', {}, {}, {'present', '(0028,3010)'} - 1, '0028', '3003', '3', {}, {}, {} - 1, '0028', '3006', '1C', {}, {}, {'present', '(0028,3010)'} - 0, '0028', '1050', '3', {}, {}, {} - 0, '0028', '1051', '1C', {}, {}, {'present', '(0028,1050)'} - }; - - -function details = build_SOPCommon - -details.Name = 'SOPCommon'; -details.SpecPart = 'PS 3.3 Sec. C.12.1'; -details.Attrs = { - 0, '0008', '0016', '1', {}, {}, {} - 0, '0008', '0018', '1', {}, {}, {} - 0, '0008', '0005', '1C', {}, {}, {'present', '(0008,0005)'} - 0, '0008', '0012', '3', {}, {}, {} - 0, '0008', '0013', '3', {}, {}, {} - 0, '0008', '0014', '3', {}, {}, {} - 0, '0008', '0201', '3', {}, {}, {} - 0, '0020', '0013', '3', {}, {}, {} - 0, '0100', '0410', '3', {}, {'NS' 'OR' 'AO' 'AC'}, {} - 0, '0100', '0420', '3', {}, {}, {} - 0, '0100', '0424', '3', {}, {}, {} - 0, '0100', '0426', '3', {}, {}, {} - }; - - -function details = build_CTImage - -details.Name = 'CTImage'; -details.SpecPart = 'PS 3.3 Sec. C.8.2.1'; -details.Attrs = { - 0, '0008', '0008', '1', {}, {}, {} - 0, '0028', '0002', '1', {}, {1}, {} - 0, '0028', '0004', '1', {}, {'MONOCHROME1' 'MONOCHROME2'}, {} - 0, '0028', '0100', '1', {}, {16}, {} - 0, '0028', '0101', '1', {}, {16}, {} - 0, '0028', '0102', '1', {}, {15}, {} - 0, '0028', '1052', '1', {}, {}, {} - 0, '0028', '1053', '1', {}, {}, {} - 0, '0018', '0060', '2', {}, {}, {} - 0, '0020', '0012', '2', {}, {}, {} - 0, '0018', '0022', '3', {}, {}, {} - 0, '0018', '0090', '3', {}, {}, {} - 0, '0018', '1100', '3', {}, {}, {} - 0, '0018', '1110', '3', {}, {}, {} - 0, '0018', '1111', '3', {}, {}, {} - 0, '0018', '1120', '3', {}, {}, {} - 0, '0018', '1130', '3', {}, {}, {} - 0, '0018', '1140', '3', {}, {'CW', 'CC'}, {} - 0, '0018', '1150', '3', {}, {}, {} - 0, '0018', '1151', '3', {}, {}, {} - 0, '0018', '1152', '3', {}, {}, {} - 0, '0018', '1153', '3', {}, {}, {} - 0, '0018', '1160', '3', {}, {}, {} - 0, '0018', '1170', '3', {}, {}, {} - 0, '0018', '1190', '3', {}, {}, {} - 0, '0018', '1210', '3', {}, {}, {} - }; - - - -function details = build_SCImageEquipment - -details.Name = 'SCImageEquipment'; -details.SpecPart = 'PS 3.3 Sec. C.8.6.1'; -details.Attrs = { - 0, '0008', '0064', '1', {}, conversionTerms, {} - 0, '0008', '0060', '3', {}, modalityTerms, {} - 0, '0018', '1010', '3', {}, {}, {} - 0, '0018', '1016', '3', {}, {}, {} - 0, '0018', '1018', '3', {}, {}, {} - 0, '0018', '1019', '3', {}, {}, {} - 0, '0018', '1022', '3', {}, {}, {} - 0, '0018', '1023', '3', {}, {}, {} - }; - - - -function details = build_SCImage - -details.Name = 'SCImage'; -details.SpecPart = 'PS 3.3 Sec. C.8.6.2'; -details.Attrs = { - 0, '0018', '1012', '3', {}, {}, {} - 0, '0018', '1014', '3', {}, {}, {} - }; - - -function details = build_USFrameOfReference - -details.Name = 'USFrameOfReference'; -details.SpecPart = 'PS 3.3 Sec. C.8.5.4'; -details.Attrs = { - 0, '0018', '6018', '1', {}, {}, {} - 0, '0018', '601A', '1', {}, {}, {} - 0, '0018', '601C', '1', {}, {}, {} - 0, '0018', '601E', '1', {}, {}, {} - 0, '0018', '6024', '1', {}, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ... - 11, 12}, {} - 0, '0018', '6026', '1', {}, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ... - 11, 12}, {} - 0, '0018', '602C', '1', {}, {}, {} - 0, '0018', '602E', '1', {}, {}, {} - 0, '0018', '6020', '3', {}, {}, {} - 0, '0018', '6022', '3', {}, {}, {} - 0, '0018', '6028', '3', {}, {}, {} - 0, '0018', '602A', '3', {}, {}, {} - }; - - - -function details = build_PaletteColorLookupTable - -details.Name = 'PaletteColorLookupTable'; -details.SpecPart = 'PS 3.3 Sec. C.7.9'; -details.Attrs = { - 0, '0028', '1101', '1C', {'(0028,0103)', {0, 'US'}, {1, 'SS'}}, {}, ... - {'or', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'} ... - {'equal', '(0028,0004)', 'ARGB'}} - 0, '0028', '1102', '1C', {'(0028,0103)', {0, 'US'}, {1, 'SS'}}, {}, ... - {'or', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'} ... - {'equal', '(0028,0004)', 'ARGB'}} - 0, '0028', '1103', '1C', {'(0028,0103)', {0, 'US'}, {1, 'SS'}}, {}, ... - {'or', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'} ... - {'equal', '(0028,0004)', 'ARGB'}} - 0, '0028', '1199', '3', {}, {}, {} - 0, '0028', '1201', '1C', {}, {}, {'and', ... - {'or', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'} ... - {'equal', '(0028,0004)', 'ARGB'}}, ... - {'not', {'present', '(0028,1221)'}}} - 0, '0028', '1202', '1C', {}, {}, {'and', ... - {'or', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'} ... - {'equal', '(0028,0004)', 'ARGB'}}, ... - {'not', {'present', '(0028,1221)'}}} - 0, '0028', '1203', '1C', {}, {}, {'and', ... - {'or', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'} ... - {'equal', '(0028,0004)', 'ARGB'}}, ... - {'not', {'present', '(0028,1221)'}}} - 0, '0028', '1221', '1C', {}, {}, {'and', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'}, ... - {'present', '(0028,1221)'}} - 0, '0028', '1222', '1C', {}, {}, {'and', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'}, ... - {'present', '(0028,1222)'}} - 0, '0028', '1223', '1C', {}, {}, {'and', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'}, ... - {'present', '(0028,1223)'}} - }; - - - -function details = build_USRegionCalibration - -details.Name = 'USRegionCalibration'; -details.SpecPart = 'PS 3.3 Sec. C.8.5.5'; -details.Attrs = { - 0, '0018', '6011', '1', {}, {}, {} - 1, '0018', '6018', '1', {}, {}, {} - 1, '0018', '601A', '1', {}, {}, {} - 1, '0018', '601C', '1', {}, {}, {} - 1, '0018', '601E', '1', {}, {}, {} - 1, '0018', '6024', '1', {}, {0 1 2 3 4 5 6 7 8 9 10 11 12}, {} - 1, '0018', '6026', '1', {}, {0 1 2 3 4 5 6 7 8 9 10 11 12}, {} - 1, '0018', '602C', '1', {}, {}, {} - 1, '0018', '602E', '1', {}, {}, {} - 1, '0018', '6020', '3', {}, {}, {} - 1, '0018', '6022', '3', {}, {}, {} - 1, '0018', '6028', '3', {}, {}, {} - 1, '0018', '602A', '3', {}, {}, {} - 1, '0018', '6012', '1', {}, {0 1 2 3 4 5}, {} - 1, '0018', '6014', '1', {}, {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ... - 15 16 17 18}, {} - 1, '0018', '6016', '1', {}, {}, {} - 1, '0018', '6044', '1C', {}, {0 1 2}, {'present', '(0018,6044)'} - 1, '0018', '6046', '1C', {}, {}, {'equal', '(0018,6044)', 0} - 1, '0018', '6048', '1C', {}, {}, {'equal', '(0018,6044)', 1} - 1, '0018', '604A', '1C', {}, {}, {'equal', '(0018,6044)', 1} - 1, '0018', '604C', '1C', {}, {0 1 2 3 4 5 6 7 8 9 10 11 12}, ... - {'present', '(0018,6044)'} - 1, '0018', '604E', '1C', {}, {0 1 2 3 4 5 6 7 8 9}, ... - {'present', '(0018,6044)'} - 1, '0018', '6050', '1C', {}, {}, {'or', ... - {'equal', '(0018,6044)', 0}, ... - {'equal', '(0018,6044)', 1}} - 1, '0018', '6052', '1C', {}, {}, {'or', ... - {'equal', '(0018,6044)', 0}, ... - {'equal', '(0018,6044)', 1}} - 1, '0018', '6054', '1C', {}, {}, {'or', ... - {'equal', '(0018,6044)', 0}, ... - {'equal', '(0018,6044)', 1}} - 1, '0018', '6056', '1C', {}, {}, {'equal', '(0018,6044)', 2} - 1, '0018', '6058', '1C', {}, {}, {'equal', '(0018,6044)', 2} - 1, '0018', '605A', '1C', {}, {}, {'equal', '(0018,6044)', 2} - 1, '0018', '6030', '3', {}, {}, {} - 1, '0018', '6032', '3', {}, {}, {} - 1, '0018', '6034', '3', {}, {}, {} - 1, '0018', '6036', '3', {}, {}, {} - 1, '0018', '6038', '3', {}, {}, {} - 1, '0018', '603A', '3', {}, {}, {} - 1, '0018', '603C', '3', {}, {}, {} - 1, '0018', '603E', '3', {}, {}, {} - 1, '0018', '6040', '3', {}, {}, {} - 1, '0018', '6042', '3', {}, {}, {} - }; - - - -function details = build_USImage - -details.Name = 'USImage'; -details.SpecPart = 'PS 3.3 Sec. C.8.5.6'; -details.Attrs = { - 0, '0028', '0002', '1', {}, {1 3}, {} - 0, '0028', '0004', '1', {}, {'MONOCHROME2' 'PALETTE COLOR' 'RGB' ... - 'YBR_FULL' 'YBR_FULL_422' 'YBR_PARTIAL_422'}, {} - 0, '0028', '0100', '1', {}, {8 16}, {} - 0, '0028', '0101', '1', {}, {8 16}, {} - 0, '0028', '0102', '1', {}, {7 15}, {} - 0, '0028', '0006', '1C', {}, {0 1}, {'not', ... - {'equal', '(0028,0002)', 1}} - 0, '0028', '0103', '1', {}, {0}, {} - 0, '0028', '0009', '1C', {}, frameIncrementTerms, {'present', ... - '(0028,0008)'} - 0, '0008', '0008', '2', {}, {}, {} - 0, '0028', '2110', '1C', {}, {0 1}, {'present', '(0028,2110)'} - 0, '0008', '2124', '2C', {}, {}, {'present', '(0008,2124)'} - 0, '0008', '212A', '2C', {}, {}, {'present', '(0008,212A)'} - 0, '0028', '0014', '3', {}, {0 1}, {} - 0, '0008', '1130', '3', {}, {}, {} - 1, '0008', '1150', '1C', {}, {}, {'present', '(0008,1130)'} - 1, '0008', '1155', '1C', {}, {}, {'present', '(0008,1130)'} - 0, '0008', '1145', '3', {}, {}, {} - 1, '0008', '1150', '1C', {}, {}, {'present', '(0008,1145)'} - 1, '0008', '1155', '1C', {}, {}, {'present', '(0008,1145)'} - 0, '0008', '113A', '3', {}, {}, {} -% 1, % SOP Instance Reference Macro - 1, '0040', 'A170', '1', {}, {}, {} -% 2, % Code Sequence Macro, Defined Context ID is CID 7004 - 0, '0008', '2120', '3', {}, {}, {} - 0, '0040', '000A', '3', {}, {}, {} - 1, 'code', 'sequ', 'X', {}, {}, {} % This is a placeholder. -% 1, % Code Sequence Macro, Baseline Context ID is 12002 - 0, '0008', '2122', '3', {}, {}, {} - 0, '0008', '2127', '3', {}, {}, {} - 0, '0008', '2128', '3', {}, {}, {} - 0, '0008', '2129', '3', {}, {}, {} - 0, '0008', '2130', '3', {}, {}, {} - 0, '0008', '2132', '3', {}, {}, {} - 0, '0008', '2218', '3', {}, {}, {} -% 1, % Code Sequence Macro, Baseline Context ID is 1 - 1, '0008', '2220', '3', {}, {}, {} -% 2, % Code Sequence Macro, Baseline Context ID is 2 - 0, '0008', '2228', '3', {}, {}, {} -% 1, % Code Sequence Macro, Baseline Context ID is 1 - 1, '0008', '2230', '3', {}, {}, {} -% 2, % Code Sequence Macro, Baseline Context ID is 2 - 0, '0008', '2240', '3', {}, {}, {} -% 1, % Code Sequence Macro, Baseline Context ID is 4 - 1, '0008', '2242', '3', {}, {}, {} -% 2, % Code Sequence Macro, Baseline Context ID is 5 - 0, '0008', '2244', '3', {}, {}, {} -% 1, % Code Sequence Macro, Baseline Context ID is 6 - 1, '0008', '2246', '3', {}, {}, {} -% 2, % Code Sequence Macro, Baseline Context ID is 7 - 0, '0008', '002A', '1C', {}, {}, {'or', ... - {'equal', '(0008,0060)', 'IVUS'}, ... - {'present', '(0008,002A)'}} - 0, '0018', '1060', '3', {}, {}, {} - 0, '0018', '1062', '3', {}, {}, {} - 0, '0018', '1080', '3', {}, {'Y', 'N'}, {} - 0, '0018', '1081', '3', {}, {}, {} - 0, '0018', '1082', '3', {}, {}, {} - 0, '0018', '1088', '3', {}, {}, {} - 0, '0018', '3100', '1C', {}, {'MOTOR_PULLBACK', - 'MANUAL_PULLBACK', - 'SELECTIVE', - 'GATED_PULLBACK'}, {'equal', ... - '(0008,0060)', 'IVUS'} - 0, '0018', '3101', '1C', {}, {}, {'equal', '(0018,3100)', 'MOTOR_PULLBACK'} - 0, '0018', '3102', '1C', {}, {}, {'equal', '(0018,3100)', 'GATED_PULLBACK'} - 0, '0018', '3103', '1C', {}, {}, {'or', ... - {'equal', '(0018,3100)', 'GATED_PULLBACK'}, ... - {'equal', '(0018,3100)', 'MOTOR_PULLBACK'}} - 0, '0018', '3104', '1C', {}, {}, {'or', ... - {'equal', '(0018,3100)', 'GATED_PULLBACK'}, ... - {'equal', '(0018,3100)', 'MOTOR_PULLBACK'}} - 0, '0018', '3105', '3', {}, {}, {} - 0, '0018', '5000', '3', {}, {}, {} - 0, '0018', '5010', '3', {}, {}, {} - 0, '0018', '6031', '3', {}, transducerTerms, {} - 0, '0018', '5012', '3', {}, {}, {} - 0, '0018', '5020', '3', {}, {}, {} - 0, '0018', '5022', '3', {}, {}, {} - 0, '0018', '5024', '3', {}, {}, {} - 0, '0018', '5026', '3', {}, {}, {} - 0, '0018', '5027', '3', {}, {}, {} - 0, '0018', '5028', '3', {}, {}, {} - 0, '0018', '5029', '3', {}, {}, {} - 0, '0018', '5050', '3', {}, {}, {} - 0, '0018', '5210', '3', {}, {}, {} - 0, '0018', '5212', '3', {}, {}, {} - 0, '60xx', '0045', '3', {}, {'ACTIVE 2D/BMODE IMAGE AREA'}, {} - }; - - - -function details = build_Cine - -details.Name = 'Cine'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.5'; -details.Attrs = { - 0, '0018', '1244', '3', {}, {0 1}, {} - 0, '0018', '1063', '1C', {}, {}, {'equal', '(0028,0009)', ... - uint16(sscanf('0018 1063', '%x')')} - 0, '0018', '1065', '1C', {}, {}, {'equal', '(0028,0009)', ... - uint16(sscanf('0018 1065', '%x')')} - 0, '0008', '2142', '3', {}, {}, {} - 0, '0008', '2143', '3', {}, {}, {} - 0, '0008', '2144', '3', {}, {}, {} - 0, '0018', '0040', '3', {}, {}, {} - 0, '0018', '1066', '3', {}, {}, {} - 0, '0018', '1067', '3', {}, {}, {} - 0, '0018', '0072', '3', {}, {}, {} - 0, '0018', '1242', '3', {}, {}, {} - }; - - -function details = build_MultiFrame - -details.Name = 'MultiFrame'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.6'; -details.Attrs = { - 0, '0028', '0008', '1', {}, {}, {} - 0, '0028', '0009', '1', {}, {}, {} - }; - - - -function details = build_ModalityLUT - -details.Name = 'ModalityLUT'; -details.SpecPart = 'PS 3.3 Sec. C.11.1'; -details.Attrs = { - 0, '0028', '3000', '1C', {}, {}, {'not', {'present', '(0028,1052)'}} - 1, '0028', '3002', '1C', {'(0028,0103)', {0, 'US'}, {1, 'SS'}}, ... - {}, {'present', '(0028,3000)'} - 1, '0028', '3003', '3', {}, {}, {} - 1, '0028', '3004', '1C', {}, {}, {'present', '(0028,3000)'} - 1, '0028', '3006', '1C', {'(0028,0103)', {0, 'US'}, {1, 'SS'}}, ... - {}, {'present', '(0028,3000)'} - 0, '0028', '1052', '1C', {}, {}, {'not', {'present', '(0028,3000)'}} - 0, '0028', '1053', '1C', {}, {}, {'present', '(0028,1052)'} - 0, '0028', '1054', '1C', {}, {'OD', 'US', 'US'}, ... - {'present', '(0028,1052)'} - }; - - - -function details = build_FramePointers - -details.Name = 'FramePointers'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.9'; -details.Attrs = { - 0, '0028', '6010', '3', {}, {}, {} - 0, '0028', '6020', '3', {}, {}, {} - 0, '0028', '6022', '3', {}, {}, {} - }; - - - -function details = build_Mask - -details.Name = 'Mask'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.10'; -details.Attrs = { - 0, '0028', '6100', '1', {}, {}, {} - 1, '0028', '6101', '1', {}, {'NONE', 'AVG_SUB', 'TID'}, {} - 1, '0028', '6102', '3', {}, {}, {} - 1, '0028', '6110', '1C', {}, {}, {'equal', '(0028,6101)', 'AVG_SUB'} - 1, '0028', '6112', '3', {}, {}, {} - 1, '0028', '6114', '3', {}, {}, {} - 1, '0028', '6120', '2C', {}, {}, {'equal', '(0028,6101)', 'TID'} - 1, '0028', '6190', '3', {}, {}, {} - 0, '0028', '1090', '2', {}, {'SUB', 'NAT'}, {} - }; - - - -function details = build_DisplayShutter - -details.Name = 'DisplayShutter'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.11'; -details.Attrs = { - 0, '0018', '1600', '1', {}, {'RECTANGULAR', 'CIRCULAR', 'POLYGONAL'}, {} - 0, '0018', '1602', '1C', {}, {}, {'equal', '(0018,1600)', 'RECTANGULAR'} - 0, '0018', '1604', '1C', {}, {}, {'equal', '(0018,1600)', 'RECTANGULAR'} - 0, '0018', '1606', '1C', {}, {}, {'equal', '(0018,1600)', 'RECTANGULAR'} - 0, '0018', '1608', '1C', {}, {}, {'equal', '(0018,1600)', 'RECTANGULAR'} - 0, '0018', '1610', '1C', {}, {}, {'equal', '(0018,1600)', 'CIRCULAR'} - 0, '0018', '1612', '1C', {}, {}, {'equal', '(0018,1600)', 'CIRCULAR'} - 0, '0018', '1620', '1C', {}, {}, {'equal', '(0018,1600)', 'POLYGONAL'} - 0, '0018', '1622', '3', {}, {}, {} - }; - - - -function details = build_Device - -details.Name = 'Device'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.12'; -details.Attrs = { - 0, '0050', '0010', '3', {}, {}, {} -% 1, % Code Sequence Macro, Baseline context ID is 8 - 1, '0050', '0014', '3', {}, {}, {} - 1, '0050', '0016', '3', {}, {}, {} - 1, '0050', '0017', '2C', {}, {'FR', 'GA', 'IN', 'MM'}, ... - {'present', '(0050,0016)'} - 1, '0050', '0018', '3', {}, {}, {} - 1, '0050', '0019', '3', {}, {}, {} - 1, '0050', '0020', '3', {}, {}, {} - }; - - - -function details = build_Therapy - -details.Name = 'Therapy'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.13'; -details.Attrs = { - 0, '0018', '0036', '3', {}, {}, {} -% 1, % Code Sequence Macro, Baseline context ID is 9 - 1, '0018', '0038', '2', {}, {'PRE', 'INTERMEDIATE', 'POST', 'NONE'}, {} - 1, '0018', '0029', '3', {}, {}, {} -% 2, % Code Sequence Macro, Baseline context ID is 10 - 1, '0018', '0035', '3', {}, {}, {} - 1, '0018', '0027', '3', {}, {}, {} - 1, '0054', '0302', '3', {}, {}, {} -% 2, % Code Sequence Macro, Baseline context ID is 11 - 1, '0018', '0039', '3', {}, {}, {} - }; - - - -function details = build_XRayImage - -details.Name = 'XRayImage'; -details.SpecPart = 'PS 3.3 Sec. C.8.7.1'; -details.Attrs = { - 0, '0028', '0009', '1C', {}, frameIncrementTerms, {'present', ... - '(0028,0008)'} - 0, '0028', '2110', '1C', {}, {0 1}, {'present', '(0028,2110)'} - 0, '0008', '0008', '1', {}, {}, {} - 0, '0028', '1040', '1', {}, {'LIN', 'LOG', 'DISP'}, {} - 0, '0028', '0002', '1', {}, {1}, {} - 0, '0028', '0004', '1', {}, {'MONOCHROME2'}, {} - 0, '0028', '0100', '1', {}, {8 16}, {} - 0, '0028', '0101', '1', {}, {8 10 12 16}, {} - 0, '0028', '0102', '1', {}, {7 9 11 15}, {} - 0, '0028', '0103', '1', {}, {0}, {} - 0, '0018', '0022', '3', {}, scanOptionsTerms, {} - 0, '0008', '2218', '3', {}, {}, {} -% 1, % Code Sequence Macro, Baseline context ID is 1 - 1, '0008', '2220', '3', {}, {}, {} -% 2, % Code Sequence Macro, Baseline context ID is 2 - 0, '0008', '2228', '3', {}, {}, {} -% 1, % Code Sequence Macro, Baseline context ID is 1 - 1, '0008', '2230', '3', {}, {}, {} -% 2, % Code Sequence Macro, Baseline context ID is 2 - 0, '0028', '6040', '3', {}, {}, {} - 0, '0008', '1140', '1C', {}, {}, {'present', '(0008,1140)'} - 1, '0008', '1150', '1C', {}, {}, {'present', '(0008,1140)'} - 1, '0008', '1155', '1C', {}, {}, {'present', '(0008,1140)'} - 0, '0008', '2111', '3', {}, {}, {} - 0, '0018', '1400', '3', {}, {}, {} - 0, '0050', '0004', '3', {}, {'YES', 'NO'}, {} - }; - - - -function details = build_XRayAcquisition - -details.Name = 'XRayAcquisition'; -details.SpecPart = 'PS 3.3 Sec. C.8.7.2'; -details.Attrs = { - 0, '0018', '0060', '2', {}, {}, {} - 0, '0018', '1155', '1', {}, {'SC', 'GR'}, {} - 0, '0018', '1151', '2C', {}, {}, {'not', {'present', '(0018,1152)'}} - 0, '0018', '1150', '2C', {}, {}, {'not', {'present', '(0018,1152)'}} - 0, '0018', '1152', '2C', {}, {}, {'not', {'and', ... - {'present', '(0018,1150)'}, ... - {'present', '(0018,1151)'}}} - 0, '0018', '1153', '3', {}, {}, {} - 0, '0018', '1166', '3', {}, {'IN', 'NONE'}, {} - 0, '0018', '1154', '3', {}, {}, {} - 0, '0018', '115A', '3', {}, {'CONTINUOUS', 'PULSED'}, {} - 0, '0018', '1161', '3', {}, {}, {} - 0, '0018', '1162', '3', {}, {}, {} - 0, '0018', '1147', '3', {}, {'ROUND', 'RECTANGLE'}, {} - 0, '0018', '1149', '3', {}, {}, {} - 0, '0018', '1164', '3', {}, {}, {} - 0, '0018', '1190', '3', {}, {}, {} - 0, '0018', '115E', '3', {}, {}, {} - }; - - - -function details = build_XRayCollimator - -details.Name = 'XRayCollimator'; -details.SpecPart = 'PS 3.3 Sec. C.8.7.3'; -details.Attrs = { - 0, '0018', '1700', '1', {}, {'RECTANGULAR', 'CIRCULAR', 'POLYGONAL'}, {} - 0, '0018', '1702', '1C', {}, {}, {'equal', '(0018,1600)', 'RECTANGULAR'} - 0, '0018', '1704', '1C', {}, {}, {'equal', '(0018,1600)', 'RECTANGULAR'} - 0, '0018', '1706', '1C', {}, {}, {'equal', '(0018,1600)', 'RECTANGULAR'} - 0, '0018', '1708', '1C', {}, {}, {'equal', '(0018,1600)', 'RECTANGULAR'} - 0, '0018', '1710', '1C', {}, {}, {'equal', '(0018,1600)', 'CIRCULAR'} - 0, '0018', '1712', '1C', {}, {}, {'equal', '(0018,1600)', 'CIRCULAR'} - 0, '0018', '1720', '1C', {}, {}, {'equal', '(0018,1600)', 'POLYGONAL'} - }; - - - -function details = build_XRayTable - -details.Name = 'XRayTable'; -details.SpecPart = 'PS 3.3 Sec. C.8.7.4'; -details.Attrs = { - 0, '0018', '1134', '2', {}, {'STATIC', 'DYNAMIC'}, {} - 0, '0018', '1135', '2C', {}, {}, {'equal', '(0018,1134)', 'DYNAMIC'} - 0, '0018', '1137', '2C', {}, {}, {'equal', '(0018,1134)', 'DYNAMIC'} - 0, '0018', '1136', '2C', {}, {}, {'equal', '(0018,1134)', 'DYNAMIC'} - 0, '0018', '1138', '3', {}, {}, {} - }; - - - -function details = build_XAPositioner - -details.Name = 'XAPositioner'; -details.SpecPart = 'PS 3.3 Sec. C.8.7.5'; -details.Attrs = { - 0, '0018', '1111', '3', {}, {}, {} - 0, '0018', '1110', '3', {}, {}, {} - 0, '0018', '1114', '3', {}, {}, {} - 0, '0018', '1500', '2C', {}, {'STATIC', 'DYNAMIC'}, {'and', ... - {'present', '(0028,0008)'}, ... - {'not', {'equal', '(0028,0008)', 1}}} - 0, '0018', '1510', '2', {}, {}, {} - 0, '0018', '1511', '2', {}, {}, {} - 0, '0018', '1520', '2C', {}, {}, {'equal', '(0018,1500)', 'DYNAMIC'} - 0, '0018', '1521', '2C', {}, {}, {'equal', '(0018,1500)', 'DYNAMIC'} - 0, '0018', '1530', '3', {}, {}, {} - 0, '0018', '1531', '3', {}, {}, {} - }; - - - -function details = build_MultiFrameOverlay - -details.Name = 'MultiFrameOverlay'; -details.SpecPart = 'PS 3.3 Sec. C.9.3'; -details.Attrs = { - 0, '60xx', '0015', '1', {}, {}, {} - 0, '60xx', '0051', '3', {}, {}, {} - }; - - - -function details = build_Curve - -details.Name = 'Curve'; -details.SpecPart = 'PS 3.3 Sec. C.10.2'; -details.Attrs = { - 0, '50xx', '0005', '1', {}, {}, {} - 0, '50xx', '0010', '1', {}, {}, {} - 0, '50xx', '0020', '1', {}, curveTypeTerms, {} - 0, '50xx', '0103', '1', {}, {0 1 2 3 4}, {} - 0, '50xx', '3000', '1', curveVRlut, {}, {} - 0, '50xx', '0022', '3', {}, {}, {} - 0, '50xx', '0030', '3', {}, axisUnitsTerms, {} - 0, '50xx', '0040', '3', {}, {}, {} - 0, '50xx', '0104', '3', {}, {}, {} - 0, '50xx', '0105', '3', {}, {}, {} - 0, '50xx', '0106', '3', {}, {}, {} - 0, '50xx', '0110', '1C', {}, {}, {'present', '(50xx,0110)'} - 0, '50xx', '0112', '1C', curveVRlut, {}, {'present', '(50xx,0110)'} - 0, '50xx', '0114', '1C', curveVRlut, {}, {'present', '(50xx,0110)'} - 0, '50xx', '2500', '3', {}, {}, {} - 0, '50xx', '2600', '3', {}, {}, {} - 1, '0008', '1150', '1C', {}, {}, {'present', '(50xx,2600)'} - 1, '0008', '1155', '1C', {}, {}, {'present', '(50xx,2600)'} - 1, '50xx', '2610', '1C', {}, {}, {'present', '(50xx,2600)'} - }; - - - -function details = build_SCMultiFrameImage - -mono2gray = {'and', ... - {'equal', '(0028,0004)', 'MONOCHROME2'}, ... - {'not', {'equal', '(0028,0101)', 1}}}; - -details.Name = 'SC Multi-Frame Image'; -details.SpecPart = 'PS 3.3 Sec. C.8.6.3'; -details.Attrs = { - 0, '0028', '0301', '1', {}, {}, {} - 0, '2050', '0020', '1C', {}, {'IDENTITY'}, mono2gray - 0, '2010', '015E', '3', {}, {}, {} - 0, '2010', '0160', '3', {}, {}, {} - 0, '0028', '1052', '1C', {}, {}, mono2gray - 0, '0028', '1053', '1C', {}, {}, mono2gray - 0, '0028', '1054', '1C', {}, {}, mono2gray - 0, '0028', '0009', '1C', {}, {}, {'present', '(0028,0008)'} - 0, '0018', '2010', '1C', {}, {}, {'or', ... - {'equal', '(0008,0064)', 'DF'}, ... - {'present', '(0008,0064)'}} - 0, '0018', '2020', '3', {}, {}, {} - 0, '0018', '2030', '3', {}, {}, {} - }; - - - -function details = build_SCMultiFrameVector - -details.Name = 'SC Multi-Frame Vector'; -details.SpecPart = 'PS 3.3 Sec. C.8.6.4'; -details.Attrs = { - 0, '0018', '1065', '1C', {}, {}, {'present', '(0018,1065)'} - 0, '0018', '2001', '1C', {}, {}, {'present', '(0018,2001)'} - 0, '0018', '2002', '1C', {}, {}, {'present', '(0018,2002)'} - 0, '0018', '2003', '1C', {}, {}, {'present', '(0018,2003)'} - 0, '0018', '2004', '1C', {}, {}, {'present', '(0018,2004)'} - 0, '0018', '2005', '1C', {}, {}, {'present', '(0018,2005)'} - 0, '0018', '2006', '1C', {}, {}, {'present', '(0018,2006)'} - }; - - - -function details = build_ClinicalTrialStudy - -details.Name = 'Clinical Trial Study'; -details.SpecPart = 'PS 3.3 Sec. C.7.2.3'; -details.Attrs = { - 0, '0012', '0050', '2', {}, {}, {} - 0, '0012', '0051', '3', {}, {}, {} - 0, '0012', '0083', '3', {}, {}, {} - 1, '0012', '0084', '1C', {}, {}, {'or', ... - {'equal', '(0012,0085)', 'YES'}, ... - {'equal', '(0012,0085)', 'WITHDRAWN'}} - 1, '0012', '0020', '1C', {}, {}, {'equal', '(0012,0084)', 'NAMED_PROTOCOL'} - 1, '0012', '0085', '1', {}, {}, {} - }; - - - -function details = build_ClinicalTrialSubject - -details.Name = 'Clinical Trial Subject'; -details.SpecPart = 'PS 3.3 Sec. C.7.1.3'; -details.Attrs = { - 0, '0012', '0010', '1', {}, {}, {} - 0, '0012', '0020', '1', {}, {}, {} - 0, '0012', '0021', '2', {}, {}, {} - 0, '0012', '0030', '2', {}, {}, {} - 0, '0012', '0031', '2', {}, {}, {} - 0, '0012', '0040', '1C', {}, {}, {'or', ... - {'present', '(0012,0040)'}, ... - {'not', {'present', '(0012,0042)'}}} - 0, '0012', '0042', '1C', {}, {}, {'or', ... - {'present', '(0012,0042)'}, ... - {'not', {'present', '(0012,0040)'}}} - 0, '0012', '0081', '1C', {}, {}, {'present', '(0012,0082)'} - 0, '0012', '0082', '3', {}, {}, {} - }; - - - -function details = build_ClinicalTrialSeries - -details.Name = 'Clinical Trial Series'; -details.SpecPart = 'PS 3.3 Sec. C.7.3.2'; -details.Attrs = { - 0, '0012', '0060', '2', {}, {}, {} - 0, '0012', '0071', '3', {}, {}, {} - 0, '0012', '0072', '3', {}, {}, {} - }; - - - -function details = build_MRSeries - -details.Name = 'MR Series'; -details.SpecPart = 'PS 3.3 Sec. C.8.13.6'; -details.Attrs = { - 0, '0008', '0060', '1', {}, {}, {} - 0, '0008', '1111', '1C', {}, {}, {'present', '(0008,1111)'} - 1, '0008', '1150', '1', {}, {}, {} - 1, '0008', '1155', '1', {}, {}, {} - }; - - - -function details = build_Synchronization - -details.Name = 'Synchronization'; -details.SpecPart = 'PS 3.3 Sec. C.7.4.2'; -details.Attrs = { - 0, '0020', '0200', '1', {}, {}, {} - 0, '0018', '106A', '1', {}, {}, {} - 0, '0018', '1061', '3', {}, {}, {} - 0, '0018', '106C', '1C', {}, {}, {'present', '(0018,106C)'} - 0, '0018', '1800', '1', {}, {}, {} - 0, '0018', '1801', '3', {}, {}, {} - 0, '0018', '1802', '3', {}, {}, {} - 0, '0018', '1803', '3', {}, {}, {} - }; - - - -function details = build_EnhancedGeneralEquipment - -details.Name = 'Enhanced General Equipment'; -details.SpecPart = 'PS 3.3 Sec. C.7.5.2'; -details.Attrs = { - 0, '0008', '0070', '1', {}, {}, {} - 0, '0008', '1090', '1', {}, {}, {} - 0, '0018', '1000', '1', {}, {}, {} - 0, '0018', '1020', '1', {}, {}, {} - }; - - - -function details = build_EnhancedContrastBolus - -details.Name = 'Enhanced Contrast Bolus'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.4b'; -details.Attrs = [ - {0, '0018', '0012', '1', {}, {}, {}} - createCodeSequenceMacro(1) - {1, '0018', '9337', '1', {}, {}, {} - 1, '0018', '0014', '1', {}, {}, {}} - createCodeSequenceMacro(2) - {1, '0018', '9338', '1', {}, {}, {}} - createCodeSequenceMacro(2) - {1, '0018', '1041', '2', {}, {}, {} - 1, '0018', '1049', '2', {}, {}, {} - 1, '0018', '9425', '3', {}, {}, {} - 1, '0018', '9340', '3', {}, {}, {} - 2, '0018', '1041', '2', {}, {}, {} - 2, '0018', '1042', '3', {}, {}, {} - 2, '0018', '1043', '3', {}, {}, {} - 2, '0018', '1046', '3', {}, {}, {} - 2, '0018', '1047', '3', {}, {}, {}} - ]; - - - -function details = build_MultiFrameDimension - -details.Name = 'Multi-frame Dimension'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.17'; -details.Attrs = { - 0, '0020', '9221', '1', {}, {}, {} - 1, '0020', '9164', '1', {}, {}, {} - 0, '0020', '9311', '3', {}, {}, {} - 0, '0020', '9222', '1', {}, {}, {} - 1, '0020', '9165', '1', {}, {}, {} - 1, '0020', '9213', '1C', {}, {}, {'present', '(0020,9213)'} - 1, '0020', '9167', '1C', {}, {}, {'present', '(0020,9167)'} - 1, '0020', '9238', '1C', {}, {}, {'present', '(0020,9238)'} - 1, '0020', '9164', '1C', {}, {}, {'present', '(0020,9164)'} - 1, '0020', '9241', '3', {}, {}, {} - }; - - - -function details = build_CardiacSynchronization - -details.Name = 'Cardiac Synchronization'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.18.1'; -details.Attrs = { - 0, '0018', '9037', '1C', {}, {}, {'present', '(0018,9037)'} - 0, '0018', '9085', '1C', {}, {}, {'present', '(0018,9085)'} - 0, '0018', '9070', '1C', {}, {}, {'present', '(0018,9070)'} - 0, '0018', '9169', '1C', {}, {}, {'present', '(0018,9169)'} - 0, '0018', '1081', '2C', {}, {}, {'present', '(0018,1081)'} - 0, '0018', '1082', '2C', {}, {}, {'present', '(0018,1082)'} - 0, '0018', '1083', '2C', {}, {}, {'present', '(0018,1083)'} - 0, '0018', '1084', '2C', {}, {}, {'present', '(0018,1084)'} - 0, '0018', '1086', '3', {}, {}, {} - 0, '0018', '1064', '1C', {}, {}, {'present', '(0018,1064)'} - }; - - - -function details = build_RespiratorySynchronization - -details.Name = 'Respiratory Synchronization'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.18.2'; -details.Attrs = { - 0, '0018', '9170', '1C', {}, {}, {'present', '(0018,9170)'} - 0, '0018', '9171', '1C', {}, {}, {'present', '(0018,9171)'} - 0, '0020', '9256', '1C', {}, {}, {'present', '(0020,9256)'} - 0, '0020', '9250', '1C', {}, {}, {'present', '(0020,9250)'} - }; - - - -function details = build_BulkMotionSynchronization - -details.Name = 'Bulk Motion Synchronization'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.18.2'; -details.Attrs = { - 0, '0018', '9172', '1C', {}, {}, {'present', '(0018,9172)'} - 0, '0018', '9173', '1C', {}, {}, {'present', '(0018,9173)'} - }; - - - -function details = build_SupplementalPaletteColorLUT - -details.Name = 'Supplemental Palette Color Lookup Table'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.19'; -details.Attrs = { - 0, '0028', '1101', '1', {}, {}, {} - 0, '0028', '1102', '1', {}, {}, {} - 0, '0028', '1103', '1', {}, {}, {} - 0, '0028', '1201', '1', {}, {}, {} - 0, '0028', '1202', '1', {}, {}, {} - 0, '0028', '1203', '1', {}, {}, {} - }; - - - -function details = build_AcquisitionContext - -details.Name = 'Acquisition Context'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.14'; -details.Attrs = [... - {0, '0040', '0555', '2', {}, {}, {} - 1, '0040', 'A040', '3', {}, {}, {} - 1, '0040', 'A043', '1', {}, {}, {}} - createCodeSequenceMacro(2) - {1, '0040', 'A136', '1C', {}, {}, {'present', '(0040,A136)'} - 1, '0040', 'A30A', '1C', {}, {}, {'present', '(0040,A30A)'} - 1, '0040', '08EA', '1C', {}, {}, {'present', '(0040,A30A)'}} - createCodeSequenceMacro(2) - {1, '0040', 'A121', '1C', {}, {}, {'present', '(0040,A121)'} - 1, '0040', 'A122', '1C', {}, {}, {'present', '(0040,A122)'} - 1, '0040', 'A123', '1C', {}, {}, {'present', '(0040,A123)'} - 1, '0040', 'A160', '1C', {}, {}, {'present', '(0040,A160)'} - 1, '0040', 'A168', '1C', {}, {}, {'present', '(0040,A168)'}} - createCodeSequenceMacro(2) - {0, '0040', '0556', '3', {}, {}, {}} - ]; - - - -function details = build_MultiFrameFunctionalGroups - -details.Name = 'Multi-frame Functional Groups'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.16'; -details.Attrs = [... - {0, '5200', '9229', '2', {}, {}, {}} - createPixelMeasuresMacro(0) - createFrameContentMacro(0) - % Insert 0 or 1 functional group macros here. - {0, '5200', '9230', '1', {}, {}, {} - % Insert "number of frames" functional group macros here. - 0, '0020', '0013', '1', {}, {}, {} - 0, '0008', '0023', '1', {}, {}, {} - 0, '0008', '0033', '1', {}, {}, {} - 0, '0028', '0008', '1', {}, {}, {} - 0, '0020', '9228', '1C', {}, {}, {'present', '(0020,9161)'} - 0, '0028', '6010', '3', {}, {}, {} - 0, '0020', '9161', '1C', {}, {}, {'present', '(0020,9161)'} - 0, '0020', '0242', '1C', {}, {}, {'present', '(0020,9161)'} - 0, '0020', '9162', '1C', {}, {}, {'present', '(0020,9161)'} - 0, '0020', '9163', '3', {}, {}, {}} - ]; - - - -function details = build_Specimen - -details.Name = 'Specimen'; -details.SpecPart = 'PS 3.3 Sec. C.7.6.22'; -details.Attrs = [ - {0, '0040', '0512', '1', {}, {}, {} - 0, '0040', '0513', '2', {}, {}, {}} - createHL7v2HierarchicDesignator(1) - {0, '0040', '0515', '3', {}, {}, {} - 1, '0040', '0512', '1', {}, {}, {} - 1, '0040', '0513', '2', {}, {}, {}} - createHL7v2HierarchicDesignator(2) - {0, '0040', '0518', '2', {}, {}, {}} - createCodeSequenceMacro(1) - {0, '0040', '051A', '3', {}, {}, {} - 0, '0040', '0520', '3', {}, {}, {} - 1, '0050', '0012', '1', {}, {}, {}} - createCodeSequenceMacro(2) - {1, '0008', '0070', '3', {}, {}, {} - 1, '0008', '1090', '3', {}, {}, {} - 1, '0050', '001B', '3', {}, {}, {} - 1, '0050', '001C', '3', {}, {}, {} - 1, '0050', '0015', '3', {}, {}, {} - 1, '0050', '001D', '3', {}, {}, {} - 1, '0050', '0013', '3', {}, {}, {} - 1, '0050', '001A', '3', {}, {}, {} - 1, '0050', '001E', '3', {}, {}, {} - 0, '0040', '0560', '1', {}, {}, {} - 1, '0040', '0551', '1', {}, {}, {} - 1, '0040', '0562', '2', {}, {}, {}} - createHL7v2HierarchicDesignator(2) - {1, '0040', '0554', '1', {}, {}, {} - 1, '0040', '059A', '3', {}, {}, {}} - createCodeSequenceMacro(2) - {1, '0040', '0600', '3', {}, {}, {} - 1, '0040', '0602', '3', {}, {}, {} - 1, '0040', '0610', '2', {}, {}, {} - 2, '0040', '0612', '1', {}, {}, {}} - createContentItemMacro(3) - {1, '0008', '2228', '3', {}, {}, {}} % Primary Anatomic Structure Macro - createCodeSequenceMacro(2) % Primary Anatomic Structure Macro - {2, '0008', '2230', '3', {}, {}, {}} % Primary Anatomic Structure Macro - createCodeSequenceMacro(3) % Primary Anatomic Structure Macro - {1, '0040', '0620', '1C', {}, {}, {'present', '(0040,0620)'}} - createContentItemMacro(2) - ]; - - - -function details = build_MRPulseSequence - -details.Name = 'MR Pulse Sequence'; -details.SpecPart = 'PS 3.3 Sec. C.8.13.4'; -details.Attrs = { - 0, '0018', '9005', '1C', {}, {}, {'present', '(0018,9005)'} - 0, '0018', '0023', '1C', {}, {}, {'present', '(0018,9023)'} - 0, '0018', '9008', '1C', {}, {}, {'present', '(0018,9028)'} - 0, '0018', '9011', '1C', {}, {}, {'present', '(0018,9011)'} - 0, '0018', '9012', '1C', {}, {}, {'present', '(0018,9012)'} - 0, '0018', '9014', '1C', {}, {}, {'present', '(0018,9014)'} - 0, '0018', '9015', '1C', {}, {}, {'present', '(0018,9015)'} - 0, '0018', '9017', '1C', {}, {}, {'present', '(0018,9017)'} - 0, '0018', '9018', '1C', {}, {}, {'present', '(0018,9018)'} - 0, '0018', '9024', '1C', {}, {}, {'present', '(0018,9024)'} - 0, '0018', '9025', '1C', {}, {}, {'present', '(0018,9025)'} - 0, '0018', '9029', '1C', {}, {}, {'present', '(0018,9029)'} - 0, '0018', '9032', '1C', {}, {}, {'present', '(0018,9032)'} - 0, '0018', '9034', '1C', {}, {}, {'present', '(0018,9034)'} - 0, '0018', '9033', '1C', {}, {}, {'present', '(0018,9033)'} - 0, '0018', '9094', '1C', {}, {}, {'present', '(0018,9094)'} - 0, '0018', '9093', '1C', {}, {}, {'present', '(0018,9093)'} - }; - - - -function details = build_EnhancedMRImage - -details.Name = 'Enhanced MR Image'; -details.SpecPart = 'PS 3.3 Sec. C.8.13.1'; -details.Attrs = [ - createMRImageAndSpectroscopyInstance(0) - {0, '0008', '0008', '1', {}, {}, {}} - createMRImageDescription(0) - {0, '0028', '0002', '1', {}, {}, {} - 0, '0028', '0004', '1', {}, {}, {} - 0, '0028', '0100', '1', {}, {}, {} - 0, '0028', '0101', '1', {}, {}, {} - 0, '0028', '0102', '1', {}, {}, {} - 0, '0028', '0103', '1', {}, {}, {} - 0, '0028', '0006', '1C', {}, {}, {'not', {'equal', '(0028,0002)', 1}} - 0, '0018', '0088', '3', {}, {}, {} - 0, '0028', '0301', '1', {}, {'NO'}, {} - 0, '0028', '2110', '1', {}, {}, {} - 0, '0028', '2112', '1C', {}, {}, {'equal', '(0028,2110)', '01'} - 0, '0028', '2114', '1C', {}, {}, {'equal', '(0028,2110)', '01'} - 0, '2050', '0020', '1C', {}, {}, {'equal', '(0028,0004)', 'MONOCHROME2'} - 0, '0088', '0200', '3', {}, {}, {}} - createImagePixelMacro(1) - ]; - - - -function macro = createImagePixelMacro(level) - -macro = { - level, '0028', '0002', '1', {}, {}, {} - level, '0028', '0004', '1', {}, {}, {} - level, '0028', '0010', '1', {}, {}, {} - level, '0028', '0011', '1', {}, {}, {} - level, '0028', '0100', '1', {}, {}, {} - level, '0028', '0101', '1', {}, {}, {} - level, '0028', '0102', '1', {}, {}, {} - level, '0028', '0103', '1', {}, {0 1}, {} - level, '7FE0', '0010', '1', {}, {}, {} - level, '0028', '0006', '1C', {}, {}, {'not', {'equal', '(0028,0002)', 1}} - level, '0028', '0034', '1C', {}, {}, {'present', '(0028,0034)'} - level, '0028', '0106', '3', {'(0028,0103)', {0, 'US'}, {1, 'SS'}}, {}, {} - level, '0028', '0107', '3', {'(0028,0103)', {0, 'US'}, {1, 'SS'}}, {}, {} - level, '0028', '1101', '1C', {'(0028,0103)', {0, 'US'}, {1, 'SS'}}, {}, ... - {'or', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'} ... - {'equal', '(0028,0004)', 'ARGB'}} - level, '0028', '1102', '1C', {'(0028,0103)', {0, 'US'}, {1, 'SS'}}, {}, ... - {'or', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'} ... - {'equal', '(0028,0004)', 'ARGB'}} - level, '0028', '1103', '1C', {'(0028,0103)', {0, 'US'}, {1, 'SS'}}, {}, ... - {'or', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'} ... - {'equal', '(0028,0004)', 'ARGB'}} - level, '0028', '1201', '1C', {}, {}, {'or', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'} ... - {'equal', '(0028,0004)', 'ARGB'}} - level, '0028', '1202', '1C', {}, {}, {'or', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'} ... - {'equal', '(0028,0004)', 'ARGB'}} - level, '0028', '1203', '1C', {}, {}, {'or', ... - {'equal', '(0028,0004)', 'PALETTE COLOR'} ... - {'equal', '(0028,0004)', 'ARGB'}} - level, '0028', '2000', '3', {}, {}, {} - level, '0028', '0008', '1C', {}, {}, {'present', '(0028,0008)'} - level, '0028', '0009', '1C', {}, {}, {'present', '(0028,0009)'}}; - -function macro = createMRImageAndSpectroscopyInstance(level) - -% See PS 3.3 Table C.8-81. -macro = [... - {level, '0020', '0012', '3', {}, {}, {} - level, '0008', '002A', '1C', {}, {}, {'present', '(0008,002A)'} - level, '0018', '9073', '1C', {}, {}, {'present', '(0018,9073)'} - level, '0008', '9121', '3', {}, {}, {}} - createHierarchicalSOPInstanceRefMacro(level+1) - {level, '0008', '113A', '3', {}, {}, {}} - createHierarchicalSOPInstanceRefMacro(level+1) - {level, '0008', '9092', '1C', {}, {}, {'present', '(0008,1140)'}} - createHierarchicalSOPInstanceRefMacro(level+1) - {level, '0008', '9154', '1C', {}, {}, {'present', '(0008,2112)'}} - createHierarchicalSOPInstanceRefMacro(level+1) - {level, '0008', '9237', '1C', {}, {}, {'present', '(0008,9237)'}} - createHierarchicalSOPInstanceRefMacro(level+1) - {level, '0018', '9004', '1', {}, {}, {} - level, '0018', '9100', '1C', {}, {}, {'present', '(0018,9100)'} - level, '0018', '9064', '1C', {}, {}, {'present', '(0018,9064)'} - level, '0018', '0087', '1C', {}, {}, {'present', '(0018,0087)'} - level, '0018', '9174', '1', {}, {}, {} - level, '0018', '9175', '3', {}, {}, {} - level, '0020', '4000', '3', {}, {}, {}} - ]; - - - -function macro = createCodeSequenceMacro(level) - -contextGroupCondition = {'and', ... - {'present', '(0008,010B)'}, ... - {'equals', '(0008,010B)', 'Y'}}; - -CodeSequenceMacro = {... - '0008', '0100', '1', {}, {}, {} - '0008', '0102', '1', {}, {}, {} - '0008', '0103', '1C', {}, {}, {'present', '(0008,0103)'} - '0008', '0104', '1', {}, {}, {} - '0008', '010F', '3', {}, {}, {} - '0008', '0117', '3', {}, {}, {} - '0008', '0105', '1C', {}, {}, {'present', '(0008,010F)'} - '0008', '0106', '1C', {}, {}, {'present', '(0008,010F)'} - '0008', '010B', '3', {}, {}, {} - '0008', '0107', '1C', {}, {}, contextGroupCondition - '0008', '010D', '1C', {}, {}, contextGroupCondition - }; - -n = size(CodeSequenceMacro, 1); -macro = [repmat({level}, [n 1]), CodeSequenceMacro]; - - - -function macro = createHL7v2HierarchicDesignator(level) - -designatorMacro = {... - '0040', '0031', '1C', {}, {}, {'not', {'present', '(0040,0032)'}} - '0040', '0032', '1C', {}, {}, {'not', {'present', '(0040,0031)'}} - '0040', '0033', '1C', {}, {}, {'present', '(0040,0032)'} - }; - -n = size(designatorMacro, 1); -macro = [repmat({level}, [n 1]), designatorMacro]; - - - -function macro = createContentItemMacro(level) - -ContentItemMacro = [... - {level, '0040', 'A040', '1', {}, {}, {} - level, '0040', 'A043', '1', {}, {}, {}} - createCodeSequenceMacro(level+1) - {level, '0040', 'A120', '1C', {}, {}, {'equal', '(0040,A040)', 'DATETIME'} - level, '0040', 'A121', '1C', {}, {}, {'equal', '(0040,A040)', 'DATE'} - level, '0040', 'A122', '1C', {}, {}, {'equal', '(0040,A040)', 'TIME'} - level, '0040', 'A123', '1C', {}, {}, {'equal', '(0040,A040)', 'PNAME'} - level, '0040', 'A124', '1C', {}, {}, {'equal', '(0040,A040)', 'UIDREF'} - level, '0040', 'A160', '1C', {}, {}, {'equal', '(0040,A040)', 'TEXT'} - level, '0040', 'A168', '1C', {}, {}, {'equal', '(0040,A040)', 'CODE'}} - createCodeSequenceMacro(level+1) - {level, '0040', 'A30A', '1C', {}, {}, {'equal', '(0040,A040)', 'NUMERIC'} - level, '0040', '08EA', '1C', {}, {}, {'equal', '(0040,A040)', 'NUMERIC'}} - createCodeSequenceMacro(level+1) - {level, '0040', '1199', '1C', {}, {}, {'or', ... - {'equal', '(0040,A040)', 'COMPOSITE'}, ... - {'equal', '(0040,A040)', 'IMAGE'}} - level+1, '0008', '1150', '1', {}, {}, {} - level+1, '0008', '1155', '1', {}, {}, {} - level+1, '0008', '1160', '1C', {}, {}, {'present', '0008', '1160'} - level+1, '0062', '000B', '1C', {}, {}, {'present', '0062', '000B'}} - ]; - - - -function macro = createHierarchicalSOPInstanceRefMacro(level) - -% See PS 3.3 Table C.17-3 -macro = [... - {level, '0020', '000D', '1', {}, {}, {} - level, '0008', '1115', '1', {}, {}, {}} - createHierarchicalSeriesRefMacro(level+1) - ]; - - - -function macro = createHierarchicalSeriesRefMacro(level) - -% See PS 3.3 Table C.17-3a -macro = [... - {level, '0020', '000E', '1', {}, {}, {} - level, '0008', '0054', '3', {}, {}, {} - level, '0040', 'E011', '3', {}, {}, {} - level, '0088', '0130', '3', {}, {}, {} - level, '0088', '0140', '3', {}, {}, {} - level, '0008', '1199', '1', {}, {}, {}} - createSOPInstanceRefMacro(level+1) - {level+1, '0040', 'A170', '3', {}, {}, {}} - createCodeSequenceMacro(level+2) - {level+1, '0400', '0402', '3', {}, {}, {} - level+2, '0400', '0100', '1', {}, {}, {} - level+2, '0400', '0120', '1', {}, {}, {} - level+1, '0400', '0403', '3', {}, {}, {} - level+2, '0400', '0010', '1', {}, {}, {} - level+2, '0400', '0015', '1', {}, {}, {} - level+2, '0400', '0020', '1', {}, {}, {} - level+2, '0400', '0404', '1', {}, {}, {}} - ]; - - - -function macro = createSOPInstanceRefMacro(level) - -% See PS 3.3 Table 10-11 -macro = {... - level, '0008', '1150', '1', {}, {}, {} - level, '0008', '1155', '1', {}, {}, {} - }; - - - -function macro = createMRImageDescription(level) - -% See PS 3.3 Table C.8-82 -macro = {... - level, '0008', '9208', '1', {}, {}, {} - level, '0008', '9209', '1', {}, {}, {} - }; - - -function macro = createPixelMeasuresMacro(level) - -% See PS 3.3 Sec. C.7.6.16.2.1 -macro = {... - level, '0028', '9110', '1C', {}, {}, {'present', '(0028,9110)'} - level+1, '0028', '0030', '1C', {}, {}, {'present', '(0028,0030)'} - level+1, '0018', '0050', '1C', {}, {}, {'present', '(0018,0050)'} - }; - - -function macro = createFrameContentMacro(level) - -% See PS 3.3 Sec. C.7.6.16.2.2 -n = level+1; -macro = {... - level, '0028', '9111', '1C', {}, {}, {'present', '(0028,9111)'} - n, '0020', '9156', '3', {}, {}, {} - n, '0018', '9151', '1C', {}, {}, {'present', '(0018,9151)'} - n, '0018', '9074', '1C', {}, {}, {'present', '(0018,9074)'} - n, '0018', '9220', '1C', {}, {}, {'present', '(0018,9220)'} - n, '0018', '9236', '3', {}, {}, {} - n, '0018', '9214', '3', {}, {}, {} - n, '0020', '9157', '1C', {}, {}, {'present', '(0020,9157)'} - n, '0020', '9128', '1C', {}, {}, {'present', '(0020,9128)'} - n, '0020', '9056', '1C', {}, {}, {'present', '(0020,9056)'} - n, '0020', '9057', '1C', {}, {}, {'present', '(0020,9056)'} - n, '0020', '9158', '3', {}, {}, {} - n, '0020', '9453', '3', {}, {}, {} - }; - - -function macro = createPlanePositionPatientMacro(level) - -% See PS 3.3 Sec. C.7.6.16.2.3 -macro = {... - level, '0020', '9113', '1C', {}, {}, {'present', '(0020,9113)'} - level+1, '0020', '0032', '1C', {}, {}, {'present', '(0020,0032)'} - }; - - - -function terms = modalityTerms -%MODALITYDEFINEDTERMS Modality defined terms -% -% See PS 3.3 Sec. C.7.3.1.1.1 - -terms = {'CR', 'MR', 'US', 'BI', 'DD', 'ES', 'MA', 'PT', 'ST', 'XA', ... - 'RTIMAGE', 'RTSTRUCT', 'RTRECORD', 'DX', 'IO', 'GM', 'XC', 'AU', ... - 'EPS', 'SR', 'CT', 'NM', 'OT', 'CD', 'DG', 'LS', 'MS', 'RG', 'TG', ... - 'RF', 'RTDOSE', 'RTPLAN', 'HC', 'MG', 'PX', 'SM', 'PR', 'ECG', ... - 'HD'}; - - - -function terms = bodyPartTerms -%BODYPARTTERMS Body part defined terms -% -% See PS 3.3 Sec. C.7.3.1 - -terms = {'SKULL', 'CSPINE', 'TSPINE', 'LSPINE', 'SSPINE', 'COCCYX', 'CHEST', ... - 'CLAVICLE', 'BREAST', 'ABDOMEN', 'PELVIS', 'HIP', 'SHOULDER', ... - 'ELBOX', 'KNEE', 'ANKLE', 'HAND', 'FOOT', 'EXTREMITY', 'HEAD', ... - 'HEART', 'NECK', 'LEG', 'ARM', 'JAW'}; - - - -function terms = patientPositionTerms -%PATIENTPOSITIONTERMS Patient position defined terms -% -% See PS 3.3 Sec. C.7.3.1.1.2 - -terms = {'HFP', 'HFS', 'HFDR', 'HFDL', 'FFDR', 'FFDL', 'FFP', 'FFS'}; - - - -function terms = conversionTerms -%CONVERSIONTERMS Secondary Capture conversion type defined terms -% -% See PS 3.3 Sec. C.8.6.1 - -terms = {'DV', 'DI', 'DF', 'WSD', 'SD', 'SI', 'DRW', 'SYN'}; - - - -function terms = transducerTerms -%TRANSDUCERTERMS Transducer type defined terms -% -% See PS 3.3 Sec. C.8.5.6 - -terms = {'SECTOR_PHASED', 'SECTOR_MECH', 'SECTOR_ANNULAR', 'LINEAR', ... - 'CURVED LINEAR', 'SINGLE CRYSTAL', 'SPLIT XTAL CWD', 'IV_PHASED', ... - 'IV_ROT XTAL', 'IV_ROT MIRROR', 'ENDOCAV_PA', 'ENDOCAV_MECH', ... - 'ENDOCAV_CLA', 'ENDOCAV_AA', 'ENDOCAV_LINEAR', 'VECTOR_PHASED'}; - - - -function tmers = frameIncrementTerms -%FRAMEINCREMENTTERMS Frame increment pointer defined values -% -% See PS 3.3 Sec. C.8.5.6.1.4 - -terms = {uint16(sscanf('0018 1063', '%x')'), ... - uint16(sscanf('0018 1065', '%x')')}; - - - -function terms = scanOptionsTerms -%SCANOPTIONSTERMS Scan Options defined terms -% -% See PS 3.3 Sec. C.8.7.1.1.4 - -terms = {'EKG', 'PHY', 'TOMO', 'CHASE', 'STEP', 'ROTA'}; - - - -function terms = curveTypeTerms -%CURVETYPETERMS Type of Data for curves defined terms -% -% See PS 3.3 Sec. C.10.2.1.1 - -terms = {'TAC', 'PROF', 'HIST', 'ROI', 'TABL', 'FILT', 'POLY', 'ECG', ... - 'PRESSURE', 'FLOW', 'PHYSIO', 'RESP'}; - - - -function terms = axisUnitsTerms -%AXISUNITSTERMS Axis Units defined terms -% -% See PS 3.3 Sec. C.10.2.1.3 - -terms = {'SEC', 'CNTS', 'MM', 'PIXL', 'NONE', 'BPM', 'CM', 'CMS', 'CM2', ... - 'CM2S', 'CM3', 'CM3S', 'CMS2', 'DB', 'DBS', 'DEG', 'GM', 'GMM2', ... - 'HZ', 'IN', 'KG', 'LMIN', 'LMINM2', 'M2', 'MS2', 'MLM2', 'MILS', ... - 'MILV', 'MMHG', 'PCNT', 'LB'}; - - - -function lut = curveVRlut -%CURVEVRLUT VR lookup table for curve-related data - -lut = {'(50xx,0103)', {0, 'US'}, {1, 'SS'}, {2, 'FL'}, {3, 'FD'}, {4, 'SL'}}; diff --git a/CT/private/dicom_name_lookup.m b/CT/private/dicom_name_lookup.m deleted file mode 100644 index 8ecc6ef..0000000 --- a/CT/private/dicom_name_lookup.m +++ /dev/null @@ -1,24 +0,0 @@ -function name = dicom_name_lookup(groupStr, elementStr, dictionary) -%DICOM_NAME_LOOKUP Get an attribute's from the DICOM data dictionary. -% NAME = DICOM_NAME_LOOKUP(GROUP, ELEMENT, DICTIONARY) returns the NAME -% of the DICOM attribute with the GROUP and ELEMENT specified as strings. -% -% The purpose of this function is to avoid hardcoding mutable attribute -% names into access and modification functions. -% -% Example: -% dicom_name_lookup('7fe0','0010', dictionary) returns 'PixelData' -% (provided that its name is PixelData in the data dictionary). -% -% See also DICOM_DICT_LOOKUP, DICOM_GET_DICTIONARY. - -% Copyright 1993-2010 The MathWorks, Inc. -% - -attr = dicom_dict_lookup(groupStr, elementStr, dictionary); - -if (isempty(attr)) - name = ''; -else - name = attr.Name; -end diff --git a/CT/private/dicom_open_msg.m b/CT/private/dicom_open_msg.m deleted file mode 100644 index 5b96156..0000000 --- a/CT/private/dicom_open_msg.m +++ /dev/null @@ -1,45 +0,0 @@ -function file = dicom_open_msg(file, mode) -%DICOM_OPEN_MSG Open the next DICOM message in the pool for processing. -% FILE = DICOM_OPEN_MSG(FILE, 'r') opens the next DICOM message in the -% pool for reading. -% -% FILE = DICOM_OPEN_MSG(FILE, 'w') opens the next DICOM message in the -% pool for writing. -% -% Note: The pool of messages is generated by DICOM_GET_MSG. - -% Copyright 1993-2010 The MathWorks, Inc. - -% Open the message. -switch (lower(mode)) -case 'r' - - file.FID = fopen(file.Filename, 'r', 'ieee-le'); - - if (file.FID < 0) - - error(message('images:dicom_open_msg:fileOpenRead', file.Filename{ file.Current_Message })); - - end - -case 'w' - - file.FID = fopen(file.Filename, 'w', 'ieee-le'); - - if (file.FID < 0) - - error(message('images:dicom_open_msg:fileOpenWrite', file.Filename)); - - end - -otherwise - - error(message('images:dicom_open_msg:openMode')) - -end - -% Set local files to default transfer syntax (for fragments). -% DICOM_SET_MMETA_ENCODING will change this if appropriate. -file.Current_Endian = 'ieee-le'; -file.Pixel_Endian = 'ieee-le'; -file.Current_VR = 'Implicit'; diff --git a/CT/private/dicom_prep_FileMetadata.m b/CT/private/dicom_prep_FileMetadata.m deleted file mode 100644 index 6f15ce7..0000000 --- a/CT/private/dicom_prep_FileMetadata.m +++ /dev/null @@ -1,62 +0,0 @@ -function metadata = dicom_prep_FileMetadata(metadata, IOD_UID, txfr, dictionary) -%DICOM_PREP_FILEMETADATA Fill necessary file metadata information. -% -% See PS 3.10 Sec. 7.1 - -% Copyright 1993-2010 The MathWorks, Inc. - -metadata.(dicom_name_lookup('0002', '0001', dictionary)) = uint8([0 1]); -metadata.(dicom_name_lookup('0002', '0002', dictionary)) = IOD_UID; -metadata.(dicom_name_lookup('0002', '0003', dictionary)) = ... - metadata.(dicom_name_lookup('0008', '0018', dictionary)); -metadata.(dicom_name_lookup('0002', '0010', dictionary)) = txfr; - -[uid, name] = get_implementation_details; -metadata.(dicom_name_lookup('0002', '0012', dictionary)) = uid; -metadata.(dicom_name_lookup('0002', '0013', dictionary)) = name; - - - -function [implementation_UID, implementation_name] = get_implementation_details -%GET_IMPLEMENTATION_DETAILS Create implementation class UID and name. - -% The Implementation Class UID (0002,0012) is a UID that we create which -% identifies the modality (i.e., the Image Processing Toolbox) writing -% the file. The Implementation Version Name (0002,0013 is a description -% of the modality (16 characters max). These values must be updated -% together. - -% Class UIDs generated by the Image Processing Toolbox have the following -% structure: -% -% IPT_UID_ROOT.3.x.y -% -% Where 3 is the (new) constant value for class UIDs, x is the constant class, -% and y is the individual instance of the class. - -ipt_root = dicom_generate_uid('ipt_root'); -ipt_uid_definitions = '3'; -imp_class_constant = '100'; - -% This is quite slow and does not compile. Hard-code the value until its -% performance improves. - -% ipt_ver = ver('images'); -% -% if (isempty(ipt_ver)) -% error('images:dicom_prep_FileMetadata:unknownIPT', 'Unrecognized Image Processing Toolbox version.') -% end -% -% idx = find(ipt_ver(1).Version > '9'); -% if (~isempty(idx)) -% ipt_ver(1).Version(idx(1):end) = ''; -% end -ipt_ver(1).Version = '7.1'; - -implementation_UID = [ipt_root, '.', ... - ipt_uid_definitions, '.', ... - imp_class_constant, '.', ... - ipt_ver(1).Version]; - -implementation_name = ['MATLAB IPT ' ipt_ver(1).Version]; - diff --git a/CT/private/dicom_prep_FrameOfReference.m b/CT/private/dicom_prep_FrameOfReference.m deleted file mode 100644 index 66c4c97..0000000 --- a/CT/private/dicom_prep_FrameOfReference.m +++ /dev/null @@ -1,12 +0,0 @@ -function metadata = dicom_prep_FrameOfReference(metadata, dictionary) -%DICOM_PREP_FRAMEOFREFERENCE Fill necessary values for Frame of Reference. -% -% See PS 3.3 Sec C.7.4.1 - -% Copyright 1993-2010 The MathWorks, Inc. -% - -name = dicom_name_lookup('0020', '0052', dictionary); -if (~isfield(metadata, name)) - metadata.(name) = dicomuid; -end diff --git a/CT/private/dicom_prep_GeneralImage.m b/CT/private/dicom_prep_GeneralImage.m deleted file mode 100644 index 714c09d..0000000 --- a/CT/private/dicom_prep_GeneralImage.m +++ /dev/null @@ -1,41 +0,0 @@ -function metadata = dicom_prep_GeneralImage(metadata, dictionary) -%DICOM_PREP_GENERALIMAGE Set necessary values for General Image module -% -% See PS 3.3 Sec C.7.6.1 - -% Copyright 1993-2010 The MathWorks, Inc. -% - -image_time = now; - -ImageDate_name = dicom_name_lookup('0008', '0023', dictionary); -ImageTime_name = dicom_name_lookup('0008', '0033', dictionary); - -if (~isfield(metadata, ImageDate_name)) - metadata.(ImageDate_name) = convert_date(image_time, 'DA'); -end - -if (~isfield(metadata, ImageTime_name)) - metadata.(ImageTime_name) = convert_date(image_time, 'TM'); -end - - - -function dicomDate = convert_date(ML_date, formatString) -%CONVERT_DATE Convert a MATLAB datenum to a DICOM date/time string -% -% See PS 3.5 Sec. 6.2 for DICOM date/time formats. - -vec = datevec(ML_date); - -switch (formatString) -case 'DA' - % YYYYMMDD - dicomDate = sprintf('%04d%02d%02d', vec(1:3)); -case 'DT' - % YYYYMMDDHHMMSS.FFFFFF - dicomDate = sprintf('%04d%02d%02d%02d%02d%09.6f', vec); -case 'TM' - %HHMMSS.FFFFFF - dicomDate = sprintf('%02d%02d%09.6f', vec(4:6)); -end diff --git a/CT/private/dicom_prep_GeneralSeries.m b/CT/private/dicom_prep_GeneralSeries.m deleted file mode 100644 index df26a3c..0000000 --- a/CT/private/dicom_prep_GeneralSeries.m +++ /dev/null @@ -1,16 +0,0 @@ -function metadata = dicom_prep_GeneralSeries(metadata, dictionary) -%DICOM_PREP_DICOM_PREP_GENERALSERIES Fill values for General Study module. -% -% See PS 3.3 Sec. C.7.2.1 - -% Copyright 1993-2010 The MathWorks, Inc. - -name = dicom_name_lookup('0008', '0060', dictionary); -if (~isfield(metadata, name)) - metadata.(name) = 'OT'; -end - -name = dicom_name_lookup('0020', '000E', dictionary); -if (~isfield(metadata, name)) - metadata.(name) = dicomuid; -end diff --git a/CT/private/dicom_prep_GeneralStudy.m b/CT/private/dicom_prep_GeneralStudy.m deleted file mode 100644 index 87d9823..0000000 --- a/CT/private/dicom_prep_GeneralStudy.m +++ /dev/null @@ -1,11 +0,0 @@ -function metadata = dicom_prep_GeneralStudy(metadata, dictionary) -%DICOM_PREP_DICOM_PREP_GENERALSTUDY Fill values for General Study module. -% -% See PS 3.3 Sec. C.7.2.1 - -% Copyright 1993-2010 The MathWorks, Inc. - -name = dicom_name_lookup('0020', '000D', dictionary); -if (~isfield(metadata, name)) - metadata.(name) = dicomuid; -end diff --git a/CT/private/dicom_prep_ImagePixel.m b/CT/private/dicom_prep_ImagePixel.m deleted file mode 100644 index 0bef522..0000000 --- a/CT/private/dicom_prep_ImagePixel.m +++ /dev/null @@ -1,404 +0,0 @@ -function metadata = dicom_prep_ImagePixel(metadata, X, map, txfr, useExistingBitDepths, dictionary) -%DICOM_PREP_IMAGEPIXEL Set necessary values for Image Pixel module. -% -% See PS 3.3 Sec C.7.6.3 - -% Copyright 1993-2014 The MathWorks, Inc. - -metadata(1).(dicom_name_lookup('0028', '0002', dictionary)) = size(X, 3); -metadata.(dicom_name_lookup('0028', '0004', dictionary)) = getPhotometricInterp(metadata, X, map, txfr, dictionary); -metadata.(dicom_name_lookup('0028', '0010', dictionary)) = size(X, 1); -metadata.(dicom_name_lookup('0028', '0011', dictionary)) = size(X, 2); - -[ba, bs, hb, pr] = getPixelStorage(X, txfr, useExistingBitDepths, metadata, dictionary); -metadata.(dicom_name_lookup('0028', '0100', dictionary)) = ba; -metadata.(dicom_name_lookup('0028', '0101', dictionary)) = bs; -metadata.(dicom_name_lookup('0028', '0102', dictionary)) = hb; -metadata.(dicom_name_lookup('0028', '0103', dictionary)) = pr; - -metadata.(dicom_name_lookup('7FE0', '0010', dictionary)) = encodePixelData(metadata, X, map, txfr, dictionary); - -% Values that depend on the number of samples present. -if (metadata.(dicom_name_lookup('0028', '0002', dictionary)) > 1) - - metadata.(dicom_name_lookup('0028', '0006', dictionary)) = 0; % Interleaved pixels. - -else - - % Only include min/max pixel value for single-sample (grayscale) images. - switch class(X) - case {'single', 'double', 'logical'} - % The min/max values will have changed during prep. - data = metadata.(dicom_name_lookup('7FE0', '0010', dictionary)); - metadata.(dicom_name_lookup('0028', '0106', dictionary)) = min(data(:)); - metadata.(dicom_name_lookup('0028', '0107', dictionary)) = max(data(:)); - otherwise - metadata.(dicom_name_lookup('0028', '0106', dictionary)) = min(X(:)); - metadata.(dicom_name_lookup('0028', '0107', dictionary)) = max(X(:)); - end - -end - -if (~isempty(map)) - [rdes, gdes, bdes, rdata, gdata, bdata] = processColormap(X, map); - metadata.(dicom_name_lookup('0028', '1101', dictionary)) = rdes; - metadata.(dicom_name_lookup('0028', '1102', dictionary)) = gdes; - metadata.(dicom_name_lookup('0028', '1103', dictionary)) = bdes; - metadata.(dicom_name_lookup('0028', '1201', dictionary)) = rdata; - metadata.(dicom_name_lookup('0028', '1202', dictionary)) = gdata; - metadata.(dicom_name_lookup('0028', '1203', dictionary)) = bdata; -end - -% Technically (0028,0008) isn't part of the Image Pixel module, but it's -% fundamental to several overlapping, optional modules that we don't -% have "prep" functions for yet; and we need to put the right value when -% copying metadata. -if ((isfield(metadata, dicom_name_lookup('0028', '0008', dictionary))) || ... - (size(X,4) > 1)) - - % Add the attribute if it isn't present and there's more than one frame. - metadata.(dicom_name_lookup('0028', '0008', dictionary)) = size(X, 4); - -end - - -function pInt = getPhotometricInterp(metadata, X, map, txfr, dictionary) -%GETPHOTOMETRICINTERP Get the string code for the image's photometric interp - -if (isempty(map)) - - if (size(X, 3) == 1) - - % 0 is black. Grayscale images should always have a value of - % 'MONOCHROME1' or 'MONOCHROME2', regardless of compression. The - % default should be consistent with IPT's interpretation that the - % "minimum is black," which is 'MONOCHROME2'. - pIntFieldname = dicom_name_lookup('0028', '0004', dictionary); - if isfield(metadata, pIntFieldname) - switch (metadata.(pIntFieldname)) - case {'MONOCHROME1', 'MONOCHROME2'} - pInt = metadata.(pIntFieldname); - otherwise - pInt = 'MONOCHROME2'; - end - else - pInt = 'MONOCHROME2'; - end - - elseif (size(X, 3) == 3) - - switch (txfr) - case {'1.2.840.10008.1.2.4.50' - '1.2.840.10008.1.2.4.51' - '1.2.840.10008.1.2.4.52' - '1.2.840.10008.1.2.4.53' - '1.2.840.10008.1.2.4.54' - '1.2.840.10008.1.2.4.55' - '1.2.840.10008.1.2.4.56' - '1.2.840.10008.1.2.4.57' - '1.2.840.10008.1.2.4.58' - '1.2.840.10008.1.2.4.59' - '1.2.840.10008.1.2.4.60' - '1.2.840.10008.1.2.4.61' - '1.2.840.10008.1.2.4.62' - '1.2.840.10008.1.2.4.63' - '1.2.840.10008.1.2.4.64' - '1.2.840.10008.1.2.4.65' - '1.2.840.10008.1.2.4.66' - '1.2.840.10008.1.2.4.70' - '1.2.840.10008.1.2.4.80' - '1.2.840.10008.1.2.4.81'} - - pInt = 'YBR_FULL_422'; - - case {'1.2.840.10008.1.2.4.90' - '1.2.840.10008.1.2.4.92'} - - % See PS 3.5 Sec. 8.2.4 - pInt = 'YBR_RCT'; - - case {'1.2.840.10008.1.2.4.91' - '1.2.840.10008.1.2.4.93'} - - % See PS 3.5 Sec. 8.2.4 - pInt = 'YBR_ICT'; - - otherwise - - pInt = 'RGB'; - - end - - else - - error(message('images:dicom_prep_ImagePixel:photoInterp')) - - end - -else - - if (size(X, 3) == 1) - pInt = 'PALETTE COLOR'; - elseif (size(X, 3) == 4) - pInt = 'RGBA'; - else - error(message('images:dicom_prep_ImagePixel:photoInterp')) - end - -end - - - -function [ba, bs, hb, pr] = getPixelStorage(X, txfr, useExistingBitDepths, metadata, dictionary) -%GETPIXELSTORAGE Get details about the pixel cells. - -switch (class(X)) -case {'uint8', 'logical'} - ba = 8; - bs = 8; - pr = 0; - -case {'int8'} - ba = 8; - bs = 8; - pr = 1; - -case {'uint16'} - ba = 16; - bs = 16; - pr = 0; - -case {'int16'} - ba = 16; - bs = 16; - pr = 1; - -case {'uint32'} - ba = 32; - bs = 32; - pr = 0; - -case {'int32'} - ba = 32; - bs = 32; - pr = 1; - -case {'double'} - - switch (txfr) - case '1.2.840.10008.1.2.4.50' - ba = 8; - bs = 8; - pr = 0; - - otherwise - % Customers report that UINT8 data isn't large enough. - ba = 16; - bs = 16; - pr = 0; - - end - -otherwise - - error(message('images:dicom_prep_ImagePixel:bitDepth')) - -end - -hb = ba - 1; - -% Override values if the user requested it and the metadata is there. -computedBitsRequired = ba; - -if (useExistingBitDepths) - % BitsAllocated - if isfield(metadata, dicom_name_lookup('0028', '0100', dictionary)) - ba = metadata.(dicom_name_lookup('0028', '0100', dictionary)); - end - - % BitsStored - if isfield(metadata, dicom_name_lookup('0028', '0101', dictionary)) - bs = metadata.(dicom_name_lookup('0028', '0101', dictionary)); - end - - % HighBit - if isfield(metadata, dicom_name_lookup('0028', '0102', dictionary)) - hb = metadata.(dicom_name_lookup('0028', '0102', dictionary)); - end -end - -% Ensure that the metadata values are reasonable. (Technically, there's -% nothing wrong with having a BA or BS value of less than 8 if the data is -% in an 8-bit integer type.) -if (bs > ba) - - error(message('images:dicom_prep_ImagePixel:bitsStoredTooBig', ... - dicom_name_lookup('0028', '0101', dictionary), ... - dicom_name_lookup('0028', '0100', dictionary))) - -elseif (hb >= ba) - - error(message('images:dicom_prep_ImagePixel:highBitTooBig', ... - dicom_name_lookup('0028', '0102', dictionary), ... - dicom_name_lookup('0028', '0100', dictionary))) - -elseif ((computedBitsRequired == 32) && (bs <= 16)) - - error(message('images:dicom_prep_ImagePixel:bitsStoredTooSmall', ... - dicom_name_lookup('0028', '0101', dictionary))) - -elseif ((computedBitsRequired == 16) && (bs <= 8)) - - error(message('images:dicom_prep_ImagePixel:bitsStoredTooSmall', ... - dicom_name_lookup('0028', '0101', dictionary))) - -end - - - -function [rdes, gdes, bdes, rdata, gdata, bdata] = processColormap(~, map) -%PROCESSCOLORMAP Turn a MATLAB colormap into a DICOM colormap. - -% Always use 16-bits. - -% First descriptor: number of rows in the table. -map_rows = size(map, 1); - -if (map_rows == (2^16)) - map_rows = 0; -end - -% Second descriptor: index to start row mapping. Always 0 for MATLAB's use -% of colormaps. - -% Third descriptor: bit-depth. -map_bits = 16; - -rdes = [map_rows 0 map_bits]; -gdes = rdes; -bdes = rdes; - -% PS 3.3 Sec. C.7.6.3.1.6 says data must span the full range. -rdata = uint16(map(:, 1) .* (2 ^ map_bits - 1)); -gdata = uint16(map(:, 2) .* (2 ^ map_bits - 1)); -bdata = uint16(map(:, 3) .* (2 ^ map_bits - 1)); - - - -function pixelData = encodePixelData(metadata, X, map, txfr, dictionary) -%ENCODEPIXELCELLS Turn a MATLAB image into DICOM-encoded pixel data. - -% -% Rescale logical and double data. -% -switch (txfr) -case {'1.2.840.10008.1.2.4.50' - '1.2.840.10008.1.2.4.51' - '1.2.840.10008.1.2.4.52' - '1.2.840.10008.1.2.4.53' - '1.2.840.10008.1.2.4.54' - '1.2.840.10008.1.2.4.55' - '1.2.840.10008.1.2.4.56' - '1.2.840.10008.1.2.4.57' - '1.2.840.10008.1.2.4.58' - '1.2.840.10008.1.2.4.59' - '1.2.840.10008.1.2.4.60' - '1.2.840.10008.1.2.4.61' - '1.2.840.10008.1.2.4.62' - '1.2.840.10008.1.2.4.63' - '1.2.840.10008.1.2.4.64' - '1.2.840.10008.1.2.4.65' - '1.2.840.10008.1.2.4.66' - '1.2.840.10008.1.2.4.70' - '1.2.840.10008.1.2.4.80' - '1.2.840.10008.1.2.4.81' - '1.2.840.10008.1.2.4.90' - '1.2.840.10008.1.2.4.91'} - - % Let IMWRITE handle all of the transformations. - pixelCells = X; - -otherwise - - % Handle the special syntaxes where endianness changes for pixels. - X = changePixelEndian(X, txfr, metadata, dictionary); - - pixelCells = dicom_encode_pixel_cells(X, map, ... - metadata.(dicom_name_lookup('0028', '0100', dictionary)), ... - metadata.(dicom_name_lookup('0028', '0101', dictionary)), ... - metadata.(dicom_name_lookup('0028', '0102', dictionary))); - -end - -% -% Encode pixels. -% -uid_details = dicom_uid_decode(txfr); -if (uid_details.Compressed) - - % Compress the pixel cells and add delimiters. - pixelData = dicom_compress_pixel_cells(pixelCells, txfr, ... - metadata.(dicom_name_lookup('0028','0100', dictionary)), ... - size(X)); - pixelData = dicom_encode_attrs(pixelData, txfr, dicom_uid_decode(txfr)); - pixelData = pixelData{1}; % Encoding produces a cell array. - -else - - % Create the (possibly packed) pixel cells. - pixelData = pixelCells; - -end - - - -function out = changePixelEndian(in, txfr, metadata, dictionary) -%CHANGEPIXELENDIAN Swap pixel bytes for special transfer syntaxes - -uid_details = dicom_uid_decode(txfr); - -% After this function, the pixel data should be in the right order so that -% dicom_encode_attr can translate it directly to the output endianness. -% Special syntaxes where (a) the pixel endianness doesn't match the -% endianness of the rest of the metadata or (b) 32-bit data is being -% written on a big-endian machine to a little-endian transfer syntax -% require "pre-work" on the pixels to allow correct encoding later. -in_class = class(in); -if (~isequal(uid_details.Endian, uid_details.PixelEndian)) - - % Pixel data is stored OB (unswapped) iff bits/sample <= 8, otherwise - % it's stored OW (swapped). When swapping OW data, words are swapped - % not the entire data. So a 32-bit sample with bytes (ABCD) becomes - % (BADC). - - if (metadata.(dicom_name_lookup('0028', '0100', dictionary)) <= 16) % BitsAllocated - out = dicom_typecast(in(:), 'uint8', true); - out = dicom_typecast(out, in_class); - else - out = dicom_typecast(in(:), 'uint16', false); - out = dicom_typecast(out, 'uint8', true); - out = dicom_typecast(out, in_class); - end - - out = reshape(out, size(in)); - -else - - [~, ~, endian] = computer; - if (isequal(endian, 'B') && ... - isequal(uid_details.PixelEndian, 'ieee-le') && ... - metadata.(dicom_name_lookup('0028', '0100', dictionary)) > 16) - - % The pixels need to look like the final little-endian - % representation, which will then be undone and redone. - out = dicom_typecast(in(:), 'uint16', true); - out = dicom_typecast(out, 'uint8', true); - out = dicom_typecast(out, in_class); - - out = reshape(out, size(in)); - - else - out = in; - end - -end diff --git a/CT/private/dicom_prep_MRMultiFrame.m b/CT/private/dicom_prep_MRMultiFrame.m deleted file mode 100644 index 48e7624..0000000 --- a/CT/private/dicom_prep_MRMultiFrame.m +++ /dev/null @@ -1,104 +0,0 @@ -function metadata = dicom_prep_MRMultiFrame(metadata, X, txfr, dictionary) -%DICOM_PREP_MRMULTIFRAME Set multi-frame frame pointer, etc. -% -% See PS 3.3 Sec C.8.13.6 - -% Copyright 2010 The MathWorks, Inc. - -% Make sure that the Shared Functional Groups Sequnece and -% Per-frame Functional Groups Sequence attributes are provided. -% We can't make these values out of whole cloth. -if (~isfield(metadata, dicom_name_lookup('5200','9229', dictionary))) - - error(message('images:dicom_prep_MRMultiFrame:missingSharedSequence', dicom_name_lookup( '5200', '9229', dictionary ))) - -elseif (~isfield(metadata, dicom_name_lookup('5200','9230', dictionary))) - - error(message('images:dicom_prep_MRMultiFrame:missingPerFrameSequence', dicom_name_lookup( '5200', '9230', dictionary ))) - -elseif (~isfield(metadata, dicom_name_lookup('0008','0008', dictionary))) - - error(message('images:dicom_prep_MRMultiFrame:missingImageType', dicom_name_lookup( '0008', '0008', dictionary ))) - -end - - -numFrames = size(X,4); -% MultiFrame - C.7.6.6 -if (numFrames > 1) - metadata.(dicom_name_lookup('0028', '0008', dictionary)) = size(X,4); -end - - -% Make sure that (0028,0009) has a value. -framePointerName = dicom_name_lookup('0028', '0009', dictionary); -if (~isfield(metadata, framePointerName)) - - % To Do. Fill this. - -end - - -% Fill what values we can invent if they're missing. -if (~isfield(metadata, dicom_name_lookup('0020','0013', dictionary))) % Instance number - - metadata.(dicom_name_lookup('0020','0013', dictionary)) = '1'; - -end - -when = now; - -if (~isfield(metadata, dicom_name_lookup('0008','0023', dictionary))) % Content date - - metadata.(dicom_name_lookup('0008','0023', dictionary)) = datestr(when, 'yyyymmdd'); - -end - -if (~isfield(metadata, dicom_name_lookup('0008','0033', dictionary))) % Content time - - metadata.(dicom_name_lookup('0008','0033', dictionary)) = datestr(when, 'HHMMSS'); - -end - -details = dicom_uid_decode(txfr); -if (hasLossyCompression(details, metadata, dictionary)) - - metadata.(dicom_name_lookup('0028','2110', dictionary)) = '01'; - metadata.(dicom_name_lookup('0028','2114', dictionary)) = details.CompressionType; - -else - - metadata.(dicom_name_lookup('0028','2110', dictionary)) = '00'; - -end - - -if (isequal(metadata.(dicom_name_lookup('0028','0004', dictionary)), ... - 'MONOCHROME2')) - - metadata.(dicom_name_lookup('2050', '0020', dictionary)) = 'IDENTITY'; - -end - - - -function tf = hasLossyCompression(details, metadata, dictionary) - -lossyAttrName = dicom_name_lookup('0028','2110', dictionary); - -if (details.LossyCompression) - - % This compression will be lossy. - tf = true; - -elseif (isfield(metadata, lossyAttrName)) - - % Lossy-ness can't be shaken. It has to be passed along. - tf = isequal(metadata.(lossyAttrName), '01'); - -else - - tf = false; - -end - diff --git a/CT/private/dicom_prep_SCImageEquipment.m b/CT/private/dicom_prep_SCImageEquipment.m deleted file mode 100644 index 28ac440..0000000 --- a/CT/private/dicom_prep_SCImageEquipment.m +++ /dev/null @@ -1,22 +0,0 @@ -function metadata = dicom_prep_SCImageEquipment(metadata, dictionary) -%DICOM_PREP_SCIMAGEEQUIPMENT Set necessary values for Image Pixel module -% -% See PS 3.3 Sec C.8.1 - -% Copyright 1993-2010 The MathWorks, Inc. - -name = dicom_name_lookup('0008', '0064', dictionary); -if (~isfield(metadata, name)) - metadata(1).(name) = 'WSD'; -end - -name = dicom_name_lookup('0018', '1016', dictionary); -if (~isfield(metadata, name)) - metadata.(name) = 'MathWorks'; -end - -name = dicom_name_lookup('0018', '1018', dictionary); -if (~isfield(metadata, name)) - metadata.(name) = 'MATLAB'; -end - diff --git a/CT/private/dicom_prep_SCMultiFrame.m b/CT/private/dicom_prep_SCMultiFrame.m deleted file mode 100644 index 936f366..0000000 --- a/CT/private/dicom_prep_SCMultiFrame.m +++ /dev/null @@ -1,30 +0,0 @@ -function metadata = dicom_prep_SCMultiFrame(metadata, X, dictionary) -%DICOM_PREP_SCMULTIFRAME Set multi-frame frame pointer, etc. -% -% See PS 3.3 Sec C.8.6.4 - -% Copyright 2010 The MathWorks, Inc. - -numFrames = size(X,4); -% MultiFrame - C.7.6.6 -if (numFrames > 1) - metadata.(dicom_name_lookup('0028', '0008', dictionary)) = size(X,4); -end - - -% Make sure that (0028,0009) has a value. -framePointerName = dicom_name_lookup('0028', '0009', dictionary); -if (~isfield(metadata, framePointerName)) - - % The most generic thing we can do is create values for - % (0018,2002) "Frame Label Vector." - value = sprintf('Frame %d\\', 1:numFrames); - value(end) = ''; % Remove trailing slash. - - metadata.(dicom_name_lookup('0018', '2002', dictionary)) = value; - - % Make (0028,0009) point at (0018,2002). - metadata.(framePointerName) = uint16(sscanf('0018,2002', '%x,%x')); - -end - diff --git a/CT/private/dicom_prep_SOPCommon.m b/CT/private/dicom_prep_SOPCommon.m deleted file mode 100644 index 0c9931f..0000000 --- a/CT/private/dicom_prep_SOPCommon.m +++ /dev/null @@ -1,10 +0,0 @@ -function metadata = dicom_prep_SOPCommon(metadata, IOD_UID, dictionary) -%DICOM_PREP_DICOM_PREP_SOPCOMMON Fill necessary values for Frame of Reference. -% -% See PS 3.3 Sec. C.12.1 - -% Copyright 1993-2010 The MathWorks, Inc. -% - -metadata.(dicom_name_lookup('0008', '0016', dictionary)) = IOD_UID; -metadata.(dicom_name_lookup('0008', '0018', dictionary)) = dicomuid; diff --git a/CT/private/dicom_prep_metadata.m b/CT/private/dicom_prep_metadata.m deleted file mode 100644 index 4aa64f1..0000000 --- a/CT/private/dicom_prep_metadata.m +++ /dev/null @@ -1,162 +0,0 @@ -function metadata = dicom_prep_metadata(IOD_UID, metadata, X, map, txfr, useMetadataBitDepths, dictionary) -%DICOM_PREP_METADATA Set the necessary metadata values for this IOD. -% METADATA = DICOM_PREP_METADATA(UID, METADATA, X, MAP, TXFR) sets all -% of the type 1 and type 2 metadata derivable from the image (e.g. bit -% depths) or that must be unique (e.g. UIDs). This function also -% builds the image pixel data. - -% Copyright 1993-2014 The MathWorks, Inc. - -switch (IOD_UID) -case '1.2.840.10008.5.1.4.1.1.2' - metadata(1).(dicom_name_lookup('0008', '0060', dictionary)) = 'CT'; - - metadata = dicom_prep_ImagePixel(metadata, X, map, txfr, useMetadataBitDepths, dictionary); - metadata = dicom_prep_FrameOfReference(metadata, dictionary); - metadata = dicom_prep_SOPCommon(metadata, IOD_UID, dictionary); - metadata = dicom_prep_FileMetadata(metadata, IOD_UID, txfr, dictionary); - metadata = dicom_prep_GeneralStudy(metadata, dictionary); - metadata = dicom_prep_GeneralSeries(metadata, dictionary); - metadata = dicom_prep_GeneralImage(metadata, dictionary); - -case '1.2.840.10008.5.1.4.1.1.4' - metadata(1).(dicom_name_lookup('0008', '0060', dictionary)) = 'MR'; - - metadata = dicom_prep_ImagePixel(metadata, X, map, txfr, useMetadataBitDepths, dictionary); - metadata = dicom_prep_FrameOfReference(metadata, dictionary); - metadata = dicom_prep_SOPCommon(metadata, IOD_UID, dictionary); - metadata = dicom_prep_FileMetadata(metadata, IOD_UID, txfr, dictionary); - metadata = dicom_prep_GeneralStudy(metadata, dictionary); - metadata = dicom_prep_GeneralSeries(metadata, dictionary); - metadata = dicom_prep_GeneralImage(metadata, dictionary); - -case '1.2.840.10008.5.1.4.1.1.4.1' - metadata(1).(dicom_name_lookup('0008', '0060', dictionary)) = 'MR'; - - metadata = dicom_prep_ImagePixel(metadata, X, map, txfr, useMetadataBitDepths, dictionary); - metadata = dicom_prep_FrameOfReference(metadata, dictionary); - metadata = dicom_prep_SOPCommon(metadata, IOD_UID, dictionary); - metadata = dicom_prep_FileMetadata(metadata, IOD_UID, txfr, dictionary); - metadata = dicom_prep_GeneralStudy(metadata, dictionary); - metadata = dicom_prep_GeneralSeries(metadata, dictionary); - metadata = dicom_prep_GeneralImage(metadata, dictionary); - metadata = dicom_prep_MRMultiFrame(metadata, X, txfr, dictionary); - -case '1.2.840.10008.5.1.4.1.1.7' - name = dicom_name_lookup('0008', '0060', dictionary); - if (~isfield(metadata, name)) - metadata(1).(name) = 'OT'; - end - - metadata = dicom_prep_ImagePixel(metadata, X, map, txfr, useMetadataBitDepths, dictionary); - metadata = dicom_prep_FrameOfReference(metadata, dictionary); - metadata = dicom_prep_SOPCommon(metadata, IOD_UID, dictionary); - metadata = dicom_prep_FileMetadata(metadata, IOD_UID, txfr, dictionary); - metadata = dicom_prep_GeneralStudy(metadata, dictionary); - metadata = dicom_prep_GeneralSeries(metadata, dictionary); - metadata = dicom_prep_GeneralImage(metadata, dictionary); - metadata = dicom_prep_SCImageEquipment(metadata, dictionary); - -case {'1.2.840.10008.5.1.4.1.1.7.1' - '1.2.840.10008.5.1.4.1.1.7.2' - '1.2.840.10008.5.1.4.1.1.7.3' - '1.2.840.10008.5.1.4.1.1.7.4'} - name = dicom_name_lookup('0008', '0060', dictionary); - if (~isfield(metadata, name)) - metadata(1).(name) = 'OT'; - end - - metadata = dicom_prep_ImagePixel(metadata, X, map, txfr, useMetadataBitDepths, dictionary); - metadata = dicom_prep_FrameOfReference(metadata, dictionary); - metadata = dicom_prep_SOPCommon(metadata, IOD_UID, dictionary); - metadata = dicom_prep_FileMetadata(metadata, IOD_UID, txfr, dictionary); - metadata = dicom_prep_GeneralStudy(metadata, dictionary); - metadata = dicom_prep_GeneralSeries(metadata, dictionary); - metadata = dicom_prep_GeneralImage(metadata, dictionary); - metadata = dicom_prep_SCImageEquipment(metadata, dictionary); - - % This needs to come last. - metadata = dicom_prep_SCMultiFrame(metadata, X, dictionary); - - checkSC(IOD_UID, metadata, X, dictionary); - -otherwise - - % Unsupported SOP Class in verification mode. Display a message. - if (usejava('Desktop') && desktop('-inuse')) - docRef = 'help dicomwrite'; - else - docRef = 'help dicomwrite'; - end - - error(message('images:dicom_prep_metadata:unsupportedClass', ... - IOD_UID, docRef)) - -end - - - -function checkSC(IOD_UID, metadata, X, dictionary) -%checkSC Make sure that the metadata matches what it should. - -photometricInterp = metadata.(dicom_name_lookup('0028','0004', dictionary)); - -switch (IOD_UID) -case '1.2.840.10008.5.1.4.1.1.7.1' - - if (metadata.(dicom_name_lookup('0028', '0100', dictionary)) ~= 1) - error(message('images:dicom_prep_metadata:bitDepthForLogicalSC', IOD_UID, 1)) - - elseif (size(X,3) ~= 1) - error(message('images:dicom_prep_metadata:numSamplesForLogicalSC', IOD_UID)) - - elseif (~isequal(photometricInterp, 'MONOCHROME2')) - error(message('images:dicom_prep_metadata:photoInterpForLogicalSC', IOD_UID)) - - end - -case '1.2.840.10008.5.1.4.1.1.7.2' - - if (metadata.(dicom_name_lookup('0028', '0100', dictionary)) ~= 8) - error(message('images:dicom_prep_metadata:bitDepthFor8bitSC', IOD_UID, 8)) - - elseif (size(X,3) ~= 1) - error(message('images:dicom_prep_metadata:numSamplesFor8bitSC', IOD_UID)) - - elseif (~isequal(photometricInterp, 'MONOCHROME2')) - error(message('images:dicom_prep_metadata:photoInterpFor8bitSC', IOD_UID)) - - end - -case '1.2.840.10008.5.1.4.1.1.7.3' - - if (metadata.(dicom_name_lookup('0028', '0100', dictionary)) ~= 16) - error(message('images:dicom_prep_metadata:bitDepthFor16bitSC', IOD_UID, 16)) - - elseif (size(X,3) ~= 1) - error(message('images:dicom_prep_metadata:numSamplesFor16bitSC', IOD_UID)) - - elseif (~isequal(photometricInterp, 'MONOCHROME2')) - error(message('images:dicom_prep_metadata:photoInterpFor16bitSC', IOD_UID)) - - end - -case '1.2.840.10008.5.1.4.1.1.7.4' - - if (metadata.(dicom_name_lookup('0028', '0100', dictionary)) ~= 8) - - error(message('images:dicom_prep_metadata:bitDepthForColorSC', IOD_UID, 8)) - - elseif (size(X,3) ~= 3) - - error(message('images:dicom_prep_metadata:numSamplesForColorSC', IOD_UID)) - - elseif (~isequal(photometricInterp, 'RGB') && ... - ~isequal(photometricInterp, 'YBR_FULL_422')) - - error(message('images:dicom_prep_metadata:photoInterpForColorSC', IOD_UID)) - - end - -end - diff --git a/CT/private/dicom_set_imfinfo_values.m b/CT/private/dicom_set_imfinfo_values.m deleted file mode 100644 index 4da0ee6..0000000 --- a/CT/private/dicom_set_imfinfo_values.m +++ /dev/null @@ -1,57 +0,0 @@ -function out = dicom_set_imfinfo_values(in, file) -%DICOM_SET_IMFINFO_VALUES Get IMFINFO-specific values from DICOM data. - -% Copyright 1993-2010 The MathWorks, Inc. - -out = in; - -if (nargin == 2) - - % Allow Info struct to act as input to DICOMREAD. - out.FileStruct = file; - out.FileStruct.FID = -1; - out.StartOfPixelData = ftell(file.FID); - -end - -% Fill other IMFINFO-specific values - -if (isfield(in, 'Columns')) - out.Width = in.Columns; -end - -if (isfield(in, 'Rows')) - out.Height = in.Rows; -end - -if (isfield(in, 'BitsStored')) - out.BitDepth = in.BitsStored; -end - -if (isfield(in, 'PhotometricInterpretation')) - - % See PS 3.3-1999 Sec. C.7.6.3.1.2. - - switch (in.PhotometricInterpretation) - case {'MONOCHROME1', 'MONOCHROME2'} - out.ColorType = 'grayscale'; - - case {'PALETTE COLOR'} - out.ColorType = 'indexed'; - - case {'RGB', 'HSV', 'ARGB', 'CMYK', 'YBR_FULL', 'YBR_FULL_422', ... - 'YBR_PARTIAL_422'} - out.ColorType = 'truecolor'; - - end - -end - -if (isfield(in, 'RecognitionCode')) - - % This retired code (0008,0010) should only be present in ACR-NEMA. - - out.Format = 'ACR/NEMA'; - out.FormatVersion = in.RecognitionCode; - -end diff --git a/CT/private/dicom_strmatch.m b/CT/private/dicom_strmatch.m deleted file mode 100644 index dfc1fc9..0000000 --- a/CT/private/dicom_strmatch.m +++ /dev/null @@ -1,8 +0,0 @@ -function idx = dicom_strmatch(str, cellOfStrings) -%DICOM_STRMATCH Find substrings at beginning of larger string. -% IDX = DICOM_STRMATCH(STR, CELLOFSTRINGS) looks and acts like -% STRMATCH but isn't STRMATCH. - -% Copyright 2011 The MathWorks, Inc. - -idx = find(strncmpi(str, cellOfStrings, numel(str))); diff --git a/CT/private/dicom_supported_txfr_syntax.m b/CT/private/dicom_supported_txfr_syntax.m deleted file mode 100644 index 87210c2..0000000 --- a/CT/private/dicom_supported_txfr_syntax.m +++ /dev/null @@ -1,97 +0,0 @@ -function [supported, encapsulated, name] = dicom_supported_txfr_syntax(txfr_uid) -%DICOM_SUPPORTED_TXFR_SYNTAX Determine if a transfer syntax is supported. -% [TF, ENCAP, NAME] = DICOM_SUPPORTED_TXFR_SYNTAX(UID) uses the unique -% identifier UID of transfer syntax NAME to see if it is supported. If -% UID is supported TF has a value of 1; TF will be 0 otherwise. ENCAP -% is 1 if the syntax is used for uncapsulated data, which is usually -% compressed. -% -% If UID belongs to an unknown transfer syntax, TF is 0 and ENCAP is 1, -% as all native transfer syntaxes are specified. -% -% See also DICOM_UID_DECODE. - -% Copyright 1993-2005 The MathWorks, Inc. - - -% Get details about the syntax. -uid = dicom_uid_decode(txfr_uid); - -switch (txfr_uid) -case {'1.2.840.10008.1.2'} - - % Default syntax. All applications must support it. - supported = 1; - encapsulated = 0; - name = uid.Name; - - -case {'1.2.840.10008.1.2.1' - '1.2.840.10008.1.2.2' - '1.2.840.113619.5.2'} - - % Other uncompressed formats. - supported = 1; - encapsulated = 0; - name = uid.Name; - -case {'1.2.840.10008.1.2.5'} - - % RLE. - supported = 1; - encapsulated = 1; - name = uid.Name; - -case {'1.2.840.10008.1.2.4.57' - '1.2.840.10008.1.2.4.65' - '1.2.840.10008.1.2.4.70'} - - % JPEG lossless syntaxes. - supported = 1; - encapsulated = 1; - name = uid.Name; - -case {'1.2.840.10008.1.2.4.50' - '1.2.840.10008.1.2.4.51' - '1.2.840.10008.1.2.4.53' - '1.2.840.10008.1.2.4.55' - '1.2.840.10008.1.2.4.59' - '1.2.840.10008.1.2.4.61' - '1.2.840.10008.1.2.4.63'} - - % JPEG lossy syntaxes. - supported = 1; - encapsulated = 1; - name = uid.Name; - -case {'1.2.840.10008.1.2.4.52' - '1.2.840.10008.1.2.4.54' - '1.2.840.10008.1.2.4.56' - '1.2.840.10008.1.2.4.58' - '1.2.840.10008.1.2.4.60' - '1.2.840.10008.1.2.4.62' - '1.2.840.10008.1.2.4.64' - '1.2.840.10008.1.2.4.66'} - - % JPEG lossy syntaxes with arithmetic coding. - supported = 0; - encapsulated = 1; - name = uid.Name; - -otherwise - - % Some other transfer syntax. Unsupported. - supported = 0; - encapsulated = 1; - - if (~isempty(uid)) - - name = uid.Name; - - else - - name = txfr_uid; - - end - -end diff --git a/CT/private/dicom_tag_lookup.m b/CT/private/dicom_tag_lookup.m deleted file mode 100644 index 051d5b7..0000000 --- a/CT/private/dicom_tag_lookup.m +++ /dev/null @@ -1,117 +0,0 @@ -function tag = dicom_tag_lookup(attr_name, dictionary) -%DICOM_TAG_LOOKUP Look up the data dictionary tag from a attribute name. - -% Copyright 1993-2011 The MathWorks, Inc. - -persistent all_names all_tags prev_dictionary tag_cache; -mlock - -if ((isempty(all_names)) || (~isequal(prev_dictionary, dictionary))) - - [all_names, all_tags] = get_dictionary_info(dictionary); - prev_dictionary = dictionary; - tag_cache = struct([]); - -end - -% As an optimization, attributes are cached the first time they're found. -% Query the cache. -if (isfield(tag_cache, attr_name)) - tag = tag_cache.(attr_name); - return -end - -% Look for the name among the attributes. -idx = find(strcmp(attr_name, all_names)); - -if (isempty(idx)) - - if (~isempty(strfind(lower(attr_name), 'private_'))) - - % It's private. Parse out the group and element values. - tag = parse_private_name(attr_name); - - else - - % It's not a DICOM attribute. - tag = []; - - end - -else - - if (numel(idx) > 1) - - warning(message('images:dicom_tag_lookup:multipleAttrib', attr_name)); - - idx = idx(1); - - end - - % Look for the index in the sparse array. - % (row, column) values are (group + 1, element + 1) - [group, element] = find(all_tags == idx); - tag = [group element] - 1; - -end - -tag_cache(1).(attr_name) = tag; - - - -function [all_names, all_tags] = get_dictionary_info(dictionary) -%GET_DICTIONARY_INFO Get necessary details from the data dictionary - -if (findstr('.mat', dictionary)) - - dict = load(dictionary); - - all_names = {dict.values(:).Name}; - all_tags = dict.tags; - -else - - [all_tags, values] = dicom_load_dictionary(dictionary); - - all_names = {values(:).Name}; - -end - - - -function tag = parse_private_name(attr_name) -%PARSE_PRIVATE_NAME Get the group and element from a private attribute. - -attr_name = lower(attr_name); -idx = find(attr_name == '_'); - -if (~isempty(strfind(lower(attr_name), 'creator'))) - - % (gggg,0010-00ff) are Private Creator Data attributes: - % "Private_gggg_eexx_Creator" --> (gggg,00ee). - - if (isempty(idx)) - tag = []; - return; - end - - group = sscanf(attr_name((idx(1) + 1):(idx(1) + 4)), '%x'); - element = sscanf(attr_name((idx(2) + 1):(idx(2) + 4)), '%x'); - - tag = [group element]; - -elseif (~isempty(strfind(lower(attr_name), 'grouplength'))) - - % Skip Private Group Length attributes. - group = sscanf(attr_name(9:12), '%x'); - tag = [group 0]; - -else - - % Normal private data attributes: "Private_gggg_eeee". - group = sscanf(attr_name((idx(1) + 1):(idx(1) + 4)), '%x'); - element = sscanf(attr_name((idx(2) + 1):(idx(2) + 4)), '%x'); - - tag = [group element]; - -end diff --git a/CT/private/dicom_typecast.m b/CT/private/dicom_typecast.m deleted file mode 100644 index d29922a..0000000 --- a/CT/private/dicom_typecast.m +++ /dev/null @@ -1,47 +0,0 @@ -function out = dicom_typecast(in, datatype, varargin) -%DICOM_TYPECAST Convert datatypes, swapping as requested. -% Y = DICOM_TYPECAST(X, DATATYPE) calls to MATLAB's TYPECAST function -% and does not swap data endianness. -% -% Y = DICOM_TYPECAST(X, DATATYPE, SWAP) calls MATLAB's TYPECAST -% function and changes the endianness if SWAP is true and leaves the -% bytes alone otherwise. -% -% Note: DATATYPE must be one of 'UINT8', 'INT8', 'UINT16', 'INT16', -% 'UINT32', 'INT32', 'SINGLE', or 'DOUBLE'. -% - -% Copyright 1993-2005 The MathWorks, Inc. - -% Determine whether to swap. -if (nargin == 2) - - swap = false; - -else - - swap = varargin{1}; - -end - -% Change the type and swap as required. -if (swap) - - % Byte-sized inputs need to be swapped after casting. Others - % should be swapped first. - switch (class(in)) - case {'uint8', 'int8'} - - out = swapbytes(typecast(in, datatype)); - - otherwise - - out = typecast(swapbytes(in), datatype); - - end - -else - - out = typecast(in, datatype); - -end diff --git a/CT/private/dicom_uid_decode.m b/CT/private/dicom_uid_decode.m deleted file mode 100644 index 015ee54..0000000 --- a/CT/private/dicom_uid_decode.m +++ /dev/null @@ -1,742 +0,0 @@ -function UID_details = dicom_uid_decode(UID_string) -%DICOM_UID_DECODE Get information about a Unique Identifier (UID). -% DETAILS = DICOM_UID_DECODE(UID) get DETAILS about the DICOM unique -% identifier contained in the string UID. -% -% DETAILS contains the Name of the UID and its type (SOP class, -% transfer syntax, etc.). If UID corresponds to a transfer syntax, -% DETAILS also contains the endianness and VR necessary for reading the -% image pixels and whether these pixels are compressed. -% -% Note: Only UID's listed in PS 3.6-1999 are included here. -% Along with a few additions from PS 3.6-2009. - -% Copyright 1993-2013 The MathWorks, Inc. - -if ((~ischar(UID_string)) || (numel(UID_string) ~= length(UID_string))) - - UID_details = struct([]); - return - -end - -UID_details.Value = UID_string; -UID_details.Name = ''; -UID_details.Type = ''; -UID_details.Compressed = []; -UID_details.Endian = ''; -UID_details.PixelEndian = ''; -UID_details.VR = ''; -UID_details.LossyCompression = false; -UID_details.CompressionType = ''; - -switch (UID_string) - % SOP classes - -case '1.2.840.10008.1.1' - UID_details.Name = 'Verification SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.1.3.10' - UID_details.Name = 'Media Storage Directory Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.1.9' - UID_details.Name = 'Basic Study Content Notification SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.1.20.1' - UID_details.Name = 'Storage Commitment Push Model SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.1.20.2' - UID_details.Name = 'Storage Commitment Pull Model SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.3.1.2.1.1' - UID_details.Name = 'Detached Patient Management SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.3.1.2.2.1' - UID_details.Name = 'Detached Visit Management SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.3.1.2.3.1' - UID_details.Name = 'Detached Study Management SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.3.1.2.3.2' - UID_details.Name = 'Study Component Management SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.3.1.2.3.3' - UID_details.Name = 'Modality Performed Procedure Step SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.3.1.2.3.4' - UID_details.Name = 'Modality Performed Procedure Step Retrieve SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.3.1.2.3.5' - UID_details.Name = 'Modality Performed Procedure Step Notification SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.3.1.2.5.1' - UID_details.Name = 'Detached Results Management SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.3.1.2.6.1' - UID_details.Name = 'Detached Interpretation Management SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.1.1' - UID_details.Name = 'Basic Film Session SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.1.2' - UID_details.Name = 'Basic Film Box SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.1.4' - UID_details.Name = 'Basic Grayscale Image Box SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.1.4.1' - UID_details.Name = 'Basic Color Image Box SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.1.4.2' - UID_details.Name = 'Referenced Image Box SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.1.14' - UID_details.Name = 'Print Job SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.1.15' - UID_details.Name = 'Basic Annotation Box SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.1.16' - UID_details.Name = 'Printer SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.1.22' - UID_details.Name = 'VOI LUT Box SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.1.23' - UID_details.Name = 'Presentation LUT SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.1.24' - UID_details.Name = 'Image Overlay Box SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.1.24.1' - UID_details.Name = 'Basic Print Image Overlay Box SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.1.26' - UID_details.Name = 'Print Queue Management SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.1.27' - UID_details.Name = 'Stored Print Storage SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.1.29' - UID_details.Name = 'Hardcopy Grayscale Image Storage SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.1.30' - UID_details.Name = 'Hardcopy Color Image Storage SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.1.31' - UID_details.Name = 'Pull Print Request SOP Class'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.1' - UID_details.Name = 'Computed Radiography Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.1.1' - UID_details.Name = 'Digital X-Ray Image Storage - For Presentation'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.1.1.1' - UID_details.Name = 'Digital X-Ray Image Storage - For Processing'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.1.2' - UID_details.Name = 'Digital Mammography X-Ray Image Storage - For Presentation'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.1.2.1' - UID_details.Name = 'Digital Mammography X-Ray Image Storage - For Processing'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.1.3' - UID_details.Name = 'Digital Intra-oral X-Ray Image Storage - For Presentation'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.1.3.1' - UID_details.Name = 'Digital Intra-oral X-Ray Image Storage - For Processing'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.2' - UID_details.Name = 'CT Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.3' - UID_details.Name = 'Ultrasound Multi-frame Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.3.1' - UID_details.Name = 'Ultrasound Multi-frame Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.4' - UID_details.Name = 'MR Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.4.1' - UID_details.Name = 'Enhanced MR Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.4.2' - UID_details.Name = 'MR Spectroscopy Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.4.3' - UID_details.Name = 'Enhanced MR Color Image'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.5' - UID_details.Name = 'Nuclear Medicine Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.6' - UID_details.Name = 'Ultrasound Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.6.1' - UID_details.Name = 'Ultrasound Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.7' - UID_details.Name = 'Secondary Capture Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.7.1' - UID_details.Name = 'Multi-frame Single Bit Secondary Capture Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.7.2' - UID_details.Name = 'Multi-frame Grayscale Byte Secondary Capture Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.7.3' - UID_details.Name = 'Multi-frame Grayscale Word Secondary Capture Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.7.4' - UID_details.Name = 'Multi-frame True Color Secondary Capture Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.8' - UID_details.Name = 'Standalone Overlay Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.9' - UID_details.Name = 'Standalone Curve Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.10' - UID_details.Name = 'Standalone Modality LUT Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.11' - UID_details.Name = 'Standalone VOI LUT Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.12.1' - UID_details.Name = 'X-Ray Angiographic Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.12.2' - UID_details.Name = 'X-Ray Radiofluoroscopic Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.12.3' - UID_details.Name = 'X-Ray Angiographic Bi-Plane Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.20' - UID_details.Name = 'Nuclear Medicine Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.77.1' - UID_details.Name = 'VL Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.77.2' - UID_details.Name = 'VL Multi-frame Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.77.1.1' - UID_details.Name = 'VL Endoscopic Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.77.1.2' - UID_details.Name = 'VL Microscopic Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.77.1.3' - UID_details.Name = 'VL Slide-Coordinates Microscopic Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.77.1.4' - UID_details.Name = 'VL Photographic Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.128' - UID_details.Name = 'Positron Emission Tomography Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.129' - UID_details.Name = 'Standalone PET Curve Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.481.1' - UID_details.Name = 'RT Image Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.481.2' - UID_details.Name = 'RT Dose Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.481.3' - UID_details.Name = 'RT Structure Set Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.481.4' - UID_details.Name = 'RT Beams Treatment Record Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.481.5' - UID_details.Name = 'RT Plan Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.481.6' - UID_details.Name = 'RT Brachy Treatment Record Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.1.481.7' - UID_details.Name = 'RT Treatment Summary Record Storage'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.2.1.1' - UID_details.Name = 'Patient Root Query/Retrieve Information Model - FIND'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.2.1.2' - UID_details.Name = 'Patient Root Query/Retrieve Information Model - MOVE'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.2.1.3' - UID_details.Name = 'Patient Root Query/Retrieve Information Model - GET'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.2.2.1' - UID_details.Name = 'Study Root Query/Retrieve Information Model - FIND'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.2.2.2' - UID_details.Name = 'Study Root Query/Retrieve Information Model - MOVE'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.2.2.3' - UID_details.Name = 'Study Root Query/Retrieve Information Model - GET'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.2.3.1' - UID_details.Name = 'Patient/Study Only Query/Retrieve Information Model - FIND'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.2.3.2' - UID_details.Name = 'Patient/Study Only Query/Retrieve Information Model - MOVE'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.1.2.3.3' - UID_details.Name = 'Patient/Study Only Query/Retrieve Information Model - GET'; - UID_details.Type = 'SOP Class'; - -case '1.2.840.10008.5.1.4.31' - UID_details.Name = 'Modality Worklist Information Model - FIND'; - UID_details.Type = 'SOP Class'; - - % Well-known SOP Instances -case '1.2.840.10008.1.20.1.1' - UID_details.Name = 'Storage Commitment Push Model SOP Instance'; - UID_details.Type = 'Well-known SOP Instance'; - -case '1.2.840.10008.1.20.2.1' - UID_details.Name = 'Storage Commitment Pull Model SOP Instance'; - UID_details.Type = 'Well-known SOP Instance'; - - - - % Application Context Names -case '1.2.840.10008.3.1.1.1' - UID_details.Name = 'DICOM Application Context Name'; - UID_details.Type = 'Application Context Name'; - - % Meta SOP Classes -case '1.2.840.10008.3.1.2.1.4' - UID_details.Name = 'Detached Patient Management Meta SOP Class'; - UID_details.Type = 'Meta SOP Class'; - -case '1.2.840.10008.3.1.2.5.4' - UID_details.Name = 'Detached Results Management Meta SOP Class'; - UID_details.Type = 'Meta SOP Class'; - -case '1.2.840.10008.3.1.2.5.5' - UID_details.Name = 'Detached Study Management Meta SOP Class'; - UID_details.Type = 'Meta SOP Class'; - -case '1.2.840.10008.5.1.1.9' - UID_details.Name = 'Basic Grayscale Print Management Meta SOP Class'; - UID_details.Type = 'Meta SOP Class'; - -case '1.2.840.10008.5.1.1.9.1' - UID_details.Name = 'Referenced Grayscale Print Management Meta SOP Class'; - UID_details.Type = 'Meta SOP Class'; - -case '1.2.840.10008.5.1.1.18' - UID_details.Name = 'Basic Color Print Management Meta SOP Class'; - UID_details.Type = 'Meta SOP Class'; - -case '1.2.840.10008.5.1.1.18.1' - UID_details.Name = 'Referenced Color Print Management Meta SOP Class'; - UID_details.Type = 'Meta SOP Class'; - -case '1.2.840.10008.5.1.1.32' - UID_details.Name = 'Pull Stored Print Management Meta SOP Class'; - UID_details.Type = 'Meta SOP Class'; - - % Well-known Printer SOP Instance -case '1.2.840.10008.5.1.1.16.376' - UID_details.Name = 'Printer Configuration Retrieval SOP Class'; - UID_details.Type = 'Well-known Printer SOP Instance'; - -case '1.2.840.10008.5.1.1.17' - UID_details.Name = 'Printer SOP Instance'; - UID_details.Type = 'Well-known Printer SOP Instance'; - -case '1.2.840.10008.5.1.1.17.376' - UID_details.Name = 'Printer Configuration Retrieval SOP Instance'; - UID_details.Type = 'Well-known Printer SOP Instance'; - - - % Well-known Print Queue SOP Instance -case '1.2.840.10008.5.1.1.25' - UID_details.Name = 'Print Queue SOP Instance'; - UID_details.Type = 'Well-known Print Queue SOP Instance'; - - - % Transfer Syntaxes -case '1.2.840.10008.1.2' - UID_details.Name = 'Implicit VR Little Endian'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 0; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Implicit'; - UID_details.LossyCompression = false; - -case '1.2.840.10008.1.2.1' - UID_details.Name = 'Explicit VR Little Endian'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 0; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = false; - -case '1.2.840.10008.1.2.2' - UID_details.Name = 'Explicit VR Big Endian'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 0; - UID_details.Endian = 'ieee-be'; - UID_details.PixelEndian = 'ieee-be'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = false; - -case '1.2.840.10008.1.2.4.50' - UID_details.Name = 'JPEG Baseline (Process 1)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = true; - UID_details.CompressionType = 'ISO_10918_1'; - -case '1.2.840.10008.1.2.4.51' - UID_details.Name = 'JPEG Extended (Process 2 & 4)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = true; - UID_details.CompressionType = 'ISO_10918_1'; - -case '1.2.840.10008.1.2.4.52' - UID_details.Name = 'JPEG Extended (Process 3 & 5)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = true; - UID_details.CompressionType = 'ISO_10918_1'; - -case '1.2.840.10008.1.2.4.53' - UID_details.Name = 'JPEG Spectral Selection, Non-Hierarchical (Process 6 & 8)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = true; - UID_details.CompressionType = 'ISO_10918_1'; - -case '1.2.840.10008.1.2.4.54' - UID_details.Name = 'JPEG Spectral Selection, Non-Hierarchical (Process 7 & 9)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = true; - UID_details.CompressionType = 'ISO_10918_1'; - -case '1.2.840.10008.1.2.4.55' - UID_details.Name = 'JPEG Full Progression, Non-Hierarchical (Process 10 & 12)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = true; - UID_details.CompressionType = 'ISO_10918_1'; - -case '1.2.840.10008.1.2.4.56' - UID_details.Name = 'JPEG Full Progression, Non-Hierarchical (Process 11 & 13)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = true; - UID_details.CompressionType = 'ISO_10918_1'; - -case '1.2.840.10008.1.2.4.57' - UID_details.Name = 'JPEG Lossless, Non-Hierarchical (Process 14)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = false; - -case '1.2.840.10008.1.2.4.58' - UID_details.Name = 'JPEG Lossless, Non-Hierarchical (Process 15)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = false; - -case '1.2.840.10008.1.2.4.59' - UID_details.Name = 'JPEG Extended, Hierarchical (Process 16 & 18)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = true; - UID_details.CompressionType = 'ISO_10918_1'; - -case '1.2.840.10008.1.2.4.60' - UID_details.Name = 'JPEG Extended, Hierarchical (Process 17 & 19)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = true; - UID_details.CompressionType = 'ISO_10918_1'; - -case '1.2.840.10008.1.2.4.61' - UID_details.Name = 'JPEG Spectral Selection, Hierarchical (Process 20 & 22)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = true; - UID_details.CompressionType = 'ISO_10918_1'; - -case '1.2.840.10008.1.2.4.62' - UID_details.Name = 'JPEG Spectral Selection, Hierarchical (Process 21 & 23)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = true; - UID_details.CompressionType = 'ISO_10918_1'; - -case '1.2.840.10008.1.2.4.63' - UID_details.Name = 'JPEG Full Progression, Hierarchical (Process 24 & 26)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = true; - UID_details.CompressionType = 'ISO_10918_1'; - -case '1.2.840.10008.1.2.4.64' - UID_details.Name = 'JPEG Full Progression, Hierarchical (Process 25 & 27)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = true; - UID_details.CompressionType = 'ISO_10918_1'; - -case '1.2.840.10008.1.2.4.65' - UID_details.Name = 'JPEG Lossless, Hierarchical (Process 28)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = false; - -case '1.2.840.10008.1.2.4.66' - UID_details.Name = 'JPEG Lossless, Hierarchical (Process 29)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = false; - -case '1.2.840.10008.1.2.4.70' - UID_details.Name = 'JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 [Selection Value 1])'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = false; - -case '1.2.840.10008.1.2.4.80' - UID_details.Name = 'JPEG-LS Lossless'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = false; - -case '1.2.840.10008.1.2.4.81' - UID_details.Name = 'JPEG-LS Lossy (Near-Lossless)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = true; - UID_details.CompressionType = 'ISO_14495_1'; - -case '1.2.840.10008.1.2.5' - UID_details.Name = 'RLE Lossless'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = false; - -case '1.2.840.113619.5.2' - UID_details.Name = 'GE Implicit VR Little Endian Except Big Endian Pixels'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 0; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-be'; - UID_details.VR = 'Implicit'; - UID_details.LossyCompression = false; - - case '1.2.840.10008.1.2.4.90' - UID_details.Name = 'JPEG 2000 Image Compression (Lossless Only)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = false; - - case '1.2.840.10008.1.2.4.91' - UID_details.Name = 'JPEG 2000 Image Compression'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = true; - UID_details.CompressionType = 'ISO_15444_1'; - - case '1.2.840.10008.1.2.4.92' - UID_details.Name = 'JPEG 2000 Part 2 Multi-component Image Compression (Lossless Only)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = false; - - case '1.2.840.10008.1.2.4.93' - UID_details.Name = 'JPEG 2000 Part 2 Multi-component Image Compression'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = true; - UID_details.CompressionType = 'ISO_15444_1'; - - case '1.3.46.670589.33.1.4.1' - UID_details.Name = 'Philips Explicit VR Little Endian (RLE)'; - UID_details.Type = 'Transfer Syntax'; - UID_details.Compressed = 1; - UID_details.Endian = 'ieee-le'; - UID_details.PixelEndian = 'ieee-le'; - UID_details.VR = 'Explicit'; - UID_details.LossyCompression = false; - - -otherwise - - UID_details.Value = ''; - -end - diff --git a/CT/private/dicom_undefined_length.m b/CT/private/dicom_undefined_length.m deleted file mode 100644 index cf040ba..0000000 --- a/CT/private/dicom_undefined_length.m +++ /dev/null @@ -1,12 +0,0 @@ -function value = dicom_undefined_length -%DICOM_UNDEFINED_LENGTH Return the UINT32 value 0xFFFFFFFF. -% -% VALUE = DICOM_UNDEFINED_LENGTH() returns the constant value -% given by the command uint32(inf). In DICOM, this value -% represents an undefined length. -% -% This function exists to prevent integer overflow warnings. - -% Copyright 1993-2005 The MathWorks, Inc. - -value = uint32(4294967295); % 4294967295 == 0xFFFFFFFF == uint32(inf) diff --git a/CT/private/dicom_write_stream.m b/CT/private/dicom_write_stream.m deleted file mode 100644 index 9a8588f..0000000 --- a/CT/private/dicom_write_stream.m +++ /dev/null @@ -1,47 +0,0 @@ -function [file, msg] = dicom_write_stream(file, data_streams) -%DICOM_WRITE_STREAM Write an encoded stream to a file. -% [FILE, MSG] = DICOM_WRITE_STREAM(FILE, STREAMS) writes the UINT8 data -% streams stored in the cell array STREAMS to the message specified in -% FILE. An updated FILE structure is returned along with any -% diagnostic information in the MSG character array. -% -% See also DICOM_OPEN_MSG, DICOM_GET_MSG. - -% Copyright 1993-2010 The MathWorks, Inc. - - -msg = ''; - -if (file.FID < 0) - - msg = message('images:dicomwrite:invalidFID',... - file.Filename); - return - -end - -% Write the DICOM preamble. -count1 = fwrite(file.FID, repmat(uint8(0), [128 1]), 'uint8'); -count2 = fwrite(file.FID, uint8([68 73 67 77]), 'uint8'); % DICM - -if ((count1 + count2) ~= 132) - - msg = message('images:dicomwrite:preambleTruncated',... - file.Filename); - return - -end - -% Write the data to the file. -for p = 1:length(data_streams) - count = fwrite(file.FID, data_streams{p}, 'uint8'); - - if (count ~= numel(data_streams{p})) - msg = message('images:dicomwrite:dataTruncated',... - file.Filename); - - return - - end - -end diff --git a/CT/private/dicomlookup_actions.m b/CT/private/dicomlookup_actions.m deleted file mode 100644 index 29d931e..0000000 --- a/CT/private/dicomlookup_actions.m +++ /dev/null @@ -1,77 +0,0 @@ -function [value1, value2] = dicomlookup_actions(varargin) -%DICOMLOOKUP_ACTIONS Call dictionary lookup functions without checking. -% -% This function requires correct inputs. Use the public function -% DICOMLOOKUP for error checking. - -% Copyright 2006-2010 The MathWorks, Inc. - -if (nargin == 2) - - % Look up the tag for a given attribute name. - tag = dicom_tag_lookup(varargin{1}, varargin{2}); - - if (~isempty(tag)) - value1 = tag(1); - value2 = tag(2); - else - value1 = []; - value2 = []; - end - -else - - % Look up the name when given a group and an attribute. - group = varargin{1}; - element = varargin{2}; - dictionary = varargin{3}; - - % Look up the attribute. - attr = dicomlookup_helper(group, element, dictionary); - - if (~isempty(attr)) - - % The attribute was in the dictionary; use its name. - name = attr.Name; - - else - - % Construct Private names if the group is odd. - if (rem(group, 2) == 1) - - if (element == 0) - % (gggg,0000) is Private Group Length. - name = sprintf('Private_%04x_GroupLength', group); - - elseif (element < 16) - % (gggg,0001-000f) are not allowed. - name = ''; - - elseif ((element >= 16) && (element <= 255)) - % (gggg,0010-00ff) are Private Creator Data Elements. - - % Private attributes are assigned in blocks of 256. The - % Private Creator Data Elements (gggg,0010-00ff) reserve a - % block. For example, (gggg,0030) reserves elements - % (gggg,3000-30ff). - name = sprintf('Private_%04x_%02xxx_Creator', group, element); - - else - % The rest are normal private metadata. - name = sprintf('Private_%04x_%04x', group, element); - - end - - else - - % The public attribute was not found. - name = ''; - - end - end - - % Assign the output. - value1 = name; - value2 = []; - -end diff --git a/CT/private/dicomlookup_helper.mexw64 b/CT/private/dicomlookup_helper.mexw64 deleted file mode 100644 index 5e22ddd..0000000 Binary files a/CT/private/dicomlookup_helper.mexw64 and /dev/null differ diff --git a/CT/private/dicomparse.mexw64 b/CT/private/dicomparse.mexw64 deleted file mode 100644 index 9ccaf48..0000000 Binary files a/CT/private/dicomparse.mexw64 and /dev/null differ diff --git a/CT/private/h5attput.m b/CT/private/h5attput.m deleted file mode 100644 index 2313a66..0000000 --- a/CT/private/h5attput.m +++ /dev/null @@ -1,187 +0,0 @@ -function h5attput ( h5file, varargin ) -% H5ATTPUT Add HDF5 attribute to existing file. -% -% H5ATTPUT(HDFFILE,VARNAME,ATTNAME,ATTVALUE) creates/overwrites the -% attribute named ATTNAME with the value ATTVALUE. The parent object -% VARNAME can be either an HDF5 variable or group. VARNAME must be a -% complete pathname. -% -% H5ATTPUT(HDFFILE,ATTNAME,ATTVALUE) does the same thing, but the -% complete path to the parent object is embedded within ATTNAME. -% -% Simple strings will be created in a scalar dataspace. - -% Copyright 2008-2011 The MathWorks, Inc. - - -narginchk(3,4) -nargoutchk(0,0) - -[varname, attname, attvalue] = parse_and_validate_inputs ( h5file, varargin{:} ); - -flags = 'H5F_ACC_RDWR'; -plist_id = 'H5P_DEFAULT'; - -file_id = H5F.open ( h5file, flags, plist_id ); - -[parent_id, parent_obj_is_group] = set_parent_id ( file_id, varname ); -dataspace_id = set_dataspace_id ( attvalue ); -datatype_id = set_datatype_id ( attvalue ); -att_id = set_attribute_id ( parent_id, attname, datatype_id, dataspace_id ); - - -H5A.write(att_id,datatype_id,attvalue); - -H5T.close(datatype_id); -H5S.close(dataspace_id); -H5A.close(att_id); - -if parent_obj_is_group - H5G.close(parent_id); -else - H5D.close(parent_id); -end - -H5F.close(file_id); - - -%=============================================================================== -% SET_ATTRIBUTE_ID -% -% Setup the attribute ID. We need to check as to whether or not the attribute -% already exists. -function att_id = set_attribute_id ( parent_id, attname, datatype_id, dataspace_id ) - -try - att_id = H5A.open_name ( parent_id, attname ); -catch - att_id = H5A.create ( parent_id, attname, datatype_id, dataspace_id,'H5P_DEFAULT' ); -end - - -%=============================================================================== -% SET_DATASPACE_ID -% -% Setup the dataspace ID. This just depends on how many elements the -% attribute actually has. -function dataspace_id = set_dataspace_id ( attvalue ) - -if ischar(attvalue) - dataspace_id = H5S.create('H5S_SCALAR'); -else - dims = size(attvalue); - - if (dims(1) ~= numel(attvalue)) - rank = ndims(attvalue); - dims = fliplr(size(attvalue)); - else - rank = 1; - dims = dims(1); - end - - dataspace_id = H5S.create_simple ( rank, dims, dims ); -end - - -%=============================================================================== -% SET_PARENT_ID -% -% If the given variable is "/", then we know we are creating a group attribute. -% Otherwise try to open the variable as a dataset. If that fails, then it -% must be a subgroup. -function [parent_id, parent_obj_is_group] = set_parent_id ( file_id, varname ) -if strcmp(varname,'/') - parent_obj_is_group = true; - parent_id = H5G.open ( file_id, varname ); -else - try - parent_id=H5D.open(file_id,varname); - parent_obj_is_group = false; - catch - parent_id = H5G.open ( file_id, varname ); - parent_obj_is_group = true; - end -end - -%=============================================================================== -% SET_DATATYPE_ID -% -% We need to choose an appropriate HDF5 datatype based upon the attribute -% data. -function datatype_id = set_datatype_id ( attvalue ) -switch class(attvalue) - case 'double' - datatype_id = H5T.copy('H5T_NATIVE_DOUBLE'); - case 'single' - datatype_id = H5T.copy('H5T_NATIVE_FLOAT'); - case 'int64' - datatype_id = H5T.copy('H5T_NATIVE_LLONG'); - case 'uint64' - datatype_id = H5T.copy('H5T_NATIVE_ULLONG'); - case 'int32' - datatype_id = H5T.copy('H5T_NATIVE_INT'); - case 'uint32' - datatype_id = H5T.copy('H5T_NATIVE_UINT'); - case 'int16' - datatype_id = H5T.copy('H5T_NATIVE_SHORT'); - case 'uint16' - datatype_id = H5T.copy('H5T_NATIVE_USHORT'); - case 'int8' - datatype_id = H5T.copy('H5T_NATIVE_SCHAR'); - case 'uint8' - datatype_id = H5T.copy('H5T_NATIVE_UCHAR'); - case 'char' - datatype_id = H5T.copy('H5T_C_S1'); - H5T.set_size(datatype_id,length(attvalue)); - H5T.set_strpad(datatype_id,'H5T_STR_NULLTERM'); - otherwise - error(message('images:H5ATTPUT:unsupportedDatatype', class( attvalue ))); -end -return -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% PARSE_AND_VALIDATE_INPUTS -% -% The VARNAME and ATTNAME values may need to be parsed from one of the inputs, -% and all but the ATTVALUE input must have their datatypes checked. -function [varname,attname,attvalue] = parse_and_validate_inputs(hfile,varargin) - -if ~ischar(hfile) - error(message('images:H5ATTPUT:badFilenameDatatype')); -end - -if nargin == 3 - varname = varargin{1}; - attvalue = varargin{2}; - - slashes = strfind(varname, '/'); - if isempty(slashes) - error (message('images:H5ATTGET:badAttributePath', varname)); - elseif slashes == 1 - - % - % case of "/attname" is different than "/path/to/attname" - attname = varname(2:end); - varname = varname(1); - - else - attname = varname(slashes(end)+1:end); - varname = varname(1:slashes(end)-1); - end - -else - varname = varargin{1}; - attname = varargin{2}; - attvalue = varargin{3}; -end - -if ~ischar(varname) - error(message('images:H5ATTPUT:badVarnameDatatype')); -end - -if ~ischar(attname) - error(message('images:H5ATTPUT:badAttnameDatatype')); -end - - - -return diff --git a/CT/private/isanalyze75.m b/CT/private/isanalyze75.m deleted file mode 100644 index bf199bc..0000000 --- a/CT/private/isanalyze75.m +++ /dev/null @@ -1,78 +0,0 @@ -function TF = isanalyze75(filename) -%ISANALYZE75 Return true for a header file of a Mayo Analyze 7.5 data set. -% -% TF = ISANALYZE75(FILENAME) returns TRUE if FILENAME is a header file of -% a Mayo Analyze 7.5 data set. -% -% FILENAME is considered to be a valid header file of a Mayo Analyze 7.5 -% data set if the header size is 348 bytes. -% -% Example -% ------- -% TF = isanalyze75('brainMRI.hdr'); -% -% See also ANALYZE75INFO, ANALYZE75READ. - -% Copyright 2005-2011 The MathWorks, Inc. - - -% Check the number of input arguments. -narginchk(1,1); - -% Check if filename is a string. -if ~isa(filename,'char') - error(message('images:isanalyze75:invalidInputArgument')) -end - -% Open the HDR file -fid = analyze75open(filename, 'hdr', 'r'); - -% Check headerSize -TF = validateHeaderSize(fid, filename); - -% Close the file -fclose(fid); - - - -%%% -%%% Function validateHeaderSize -%%% -function TF = validateHeaderSize(fid, filename) - -% Analyze 7.5 format standard header size -analyzeHeader = int32(348); -% Interfile header - swapbytes(typecast(uint8('!INT'), 'int32')) -interfileHeader = int32(558452308); -% Possible extended header size -extendedRange = int32([348 2000]); - -% Read headerSize. -headerSize = fread(fid, 1, 'int32=>int32'); -swappedHeaderSize = swapbytes(headerSize); - -% Compare with Standard Analyze 7.5 headerSize. -if ((headerSize == analyzeHeader)||(swappedHeaderSize == analyzeHeader)) - TF = true; -% Compare with Interfile header -elseif ((headerSize == interfileHeader) || ... - (swappedHeaderSize == interfileHeader)) - TF = false; -% Check for extended headerSize -elseif ((headerSize > extendedRange(1)) ... - && (headerSize < extendedRange(2))) ... - || ((swappedHeaderSize > extendedRange(1)) ... - && (swappedHeaderSize < extendedRange(2))) - % Return true but warn that this may not be a valid Analyze 7.5 file - TF = true; - warning(message('images:isanalyze75:incorrectHeaderSize', filename')); -% Invalid headerSize -else - TF = false; -end - - - - - - diff --git a/CT/private/mwguidgen.mexw64 b/CT/private/mwguidgen.mexw64 deleted file mode 100644 index 8dc3b3d..0000000 Binary files a/CT/private/mwguidgen.mexw64 and /dev/null differ diff --git a/CT/private/nitfReadJPEG.m b/CT/private/nitfReadJPEG.m deleted file mode 100644 index dce20f0..0000000 --- a/CT/private/nitfReadJPEG.m +++ /dev/null @@ -1,197 +0,0 @@ -function X = nitfReadJPEG(details, region) -%nitfReadJPEG Extract JPEG-compressed image from NITF file. -% X = nitfReadJPEG(DETAILS, REGION) returns the image X from the NITF -% file described in the DETAILS structure. The REGION argument is -% currently not used. -% -% See MIL-STD-188-198 for details of this scheme. - -% Copyright 2010-2013 The MathWorks, Inc. - -% Currently there's no pixel subsetting for NITF I/O. -if (~isempty(region)) - error(message('images:nitfread:jpegSubsetting')) -end - -% Get the JPEG data from the file. -compData = getJpegStream(details); - -% Get the number of blocks, dimensions and markers. -nColsBlocks = double(swapbytes(typecast(compData(15:16), 'uint16'))); -nRowsBlocks = double(swapbytes(typecast(compData(17:18), 'uint16'))); - -h = details.tileHeight; -w = details.tileWidth; - -[startIdx, stopIdx, maskedBlocks] = getBlockLocations(compData, details, nColsBlocks, nRowsBlocks); - -% Create the full-sized image. -X = createOutputArray(details); - -% Read all of the blocks. -name = [tempname '.jpg']; -cleaner = onCleanup(@() delete(name)); - -idx = 1; -r = 1; -for j = 1:nRowsBlocks - c = 1; - for i = 1:nColsBlocks - - % If the block is masked, update the position and go to the next. - if (maskedBlocks(idx)) - c = c + w; - idx = idx + 1; - continue; - end - - start = startIdx(idx); - stop = stopIdx(idx); - frameData = compData(start:stop); - - % Read the portion of the image and store it. - data = getImageDataFromFrame(name, frameData); - X(r:(r+h-1), c:(c+w-1), :) = data; - - % Update the position. - c = c + w; - idx = idx + 1; - end - - r = r + h; -end - - - -function compData = getJpegStream(details) - -% Open the NITF file. -fid = fopen(details.filename, 'rb'); -if (fid == 0) - error(message('images:nitfread:jpegFileOpen', details.filename)) -else - c = onCleanup(@() fclose(fid)); -end - -% Move to the location in the file where the JPEG stream begins. -details.offsetStart = convertOffsetType(details.offsetStart); - -status = fseek(fid, details.offsetStart, 'bof'); -if (status ~= 0) - error(message('images:nitfread:jpegFseek')); -end - -% Read the JPEG data, which comprises the rest of the NITF file. -compData = fread(fid, inf, 'uint8=>uint8'); - -% Trim leading 0xFF pad values before SOI. -while ((numel(compData > 2)) && (compData(2) == 255)) - compData(1) = []; -end - -% Validate the JPEG stream. It should start with an SOI marker (0xFF 0xD8) -% and then an APP6 marker (0xFF 0xE6). -if (~isequal(compData(1:2), [255; 216])) - error(message('images:nitfread:badEncapsulation')) -end - -if (~isequal(compData(3:4), [255; 230])) - error(message('images:nitfread:missingAppMarker')) -end - - - -function [startIdx, stopIdx, skipIdx] = getBlockLocations(compData, details, nColsBlocks, nRowsBlocks) - -% Find the Image markers -SOIidx = findpattern(compData', sscanf('ff d8', '%x')'); -EOIidx = findpattern(compData', sscanf('ff d9', '%x')'); -SOFidx = sort([findpattern(compData', sscanf('ff c0', '%x')'), ... - findpattern(compData', sscanf('ff c1', '%x')'), ... - findpattern(compData', sscanf('ff c2', '%x')'), ... - findpattern(compData', sscanf('ff c3', '%x')')]); - -if ((numel(SOIidx) ~= numel(EOIidx)) || ... - (numel(SOIidx) ~= numel(SOFidx))) - error(message('images:nitfread:jpegSoiEoiCount')) -end - -% Does the NITF file use block masking, where some tiles are "virtual"? -if (isfield(details, 'blockOffsets')) - blockMasking = true; - skipIdx = (details.blockOffsets == intmax('uint32')); -else - blockMasking = false; - skipIdx = false(nRowsBlocks * nColsBlocks, 1); -end - -if ((numel(SOIidx) ~= (nColsBlocks * nRowsBlocks)) && ~blockMasking) - warning(message('images:nitfread:wrongSOFIndexCount')); -end - -% Compute where each tile's JPEG data starts and ends. -if (~blockMasking) - % If there's no masking, the data starts and stops with each SOI/EOI pair. - startIdx = SOIidx; - stopIdx = EOIidx + 1; -else - % If there is masking, the data start positions are given by the - % blockOffset values. NaN indicates a masked out frame. - startIdx = details.blockOffsets + 1; - startIdx(skipIdx) = NaN; - - % Each tile ends directly before the next one starts. (Masked frames - % are tricky, so just use the end of the stream.) Shift the start - % values one over and subtract one to determine where they end. The - % last stop value is the last compressed value location. - stopIdx = [(startIdx(2:end) - 1) numel(compData)]; - stopIdx(isnan(stopIdx)) = numel(compData); - stopIdx(skipIdx) = NaN; -end - - - -function X = createOutputArray(details) - -imgSize = [details.imageHeight, details.imageWidth, details.samplesPerPixel]; -if (details.bitsPerSample <= 8) - X = zeros(imgSize, 'uint8'); -elseif (details.bitsPerSample <= 16) - X = zeros(imgSize, 'uint16'); -else - error(message('images:nitfread:jpegBitDepth', details.bitsPerSample)); -end - - - -function img = getImageDataFromFrame(name, frameData) - -fid = fopen(name, 'wb'); -if (fid == 0) - error(message('images:nitfread:tmpJpegFileOpen', name)) -else - c = onCleanup(@() fclose(fid)); -end - -fwrite(fid, frameData, 'uint8'); -delete(c); - -img = imread(name, 'jpeg'); - - - -function idx = findpattern(array, pattern) -%FINDPATTERN Find a pattern in an array. - -% Despite its name, "strfind" is very good at finding numeric patterns in -% numeric vectors. -idx = strfind(array, pattern); - - -function out = convertOffsetType(in) - -if (in > intmax('uint32')) - error(message('images:nitfread:offsetTooBigForJPEG')) -end - -out = double(in); diff --git a/CT/private/nitfReadMeta.m b/CT/private/nitfReadMeta.m deleted file mode 100644 index ee2f32b..0000000 --- a/CT/private/nitfReadMeta.m +++ /dev/null @@ -1,38 +0,0 @@ -function meta = nitfReadMeta(meta, fieldsTable, fid) -%nitfReadMeta Append attributes to metadata structure. -% OUTMETA = nitfReadMeta(INMETA, FIELDSTABLE, FID) reads attributes -% from the file with handle FID and append it to INMETA the metadata -% structure. The FIELDSTABLE cell array contains details about the -% attributes, such as short names, long names, and data length. - -% Copyright 2008 The MathWorks, Inc. - -% For the sake of performance, pre-allocate storage for the new -% attributes and then insert attributes into the pre-sized struct array. -% Use "offset" to facilitate adding the new attributes. -metaOffset = numel(meta); -numToAppend = size(fieldsTable, 1); - -meta(metaOffset + numToAppend).value = ''; - -% As an optimization, convert the lengths part of the cell array to a -% numeric array. -dataLengths = [fieldsTable{:,3}]; - -% Read all of the data at once. Extract individual values in the loop. -data = fread(fid, sum(dataLengths), 'uint8=>char')'; - -% Insert the new attributes. -dataOffset = 0; -for p = 1:numToAppend - - start = dataOffset + 1; - stop = dataOffset + dataLengths(p); - - meta(metaOffset + p).name = fieldsTable{p,1}; - meta(metaOffset + p).vname = fieldsTable{p,2}; - meta(metaOffset + p).value = data(start:stop); - - dataOffset = stop; - -end diff --git a/CT/private/nitfReadMetaMulti.m b/CT/private/nitfReadMetaMulti.m deleted file mode 100644 index 8cf864f..0000000 --- a/CT/private/nitfReadMetaMulti.m +++ /dev/null @@ -1,40 +0,0 @@ -function meta = nitfReadMetaMulti(meta, fieldsTable, fid, index) -%nitfReadMetaMulti Append attributes to metadata structure. -% OUTMETA = nitfReadMetaMulti(INMETA, FIELDSTABLE, FID, INDEX) reads -% attributes from the file with handle FID and append it to INMETA the -% metadata structure. The FIELDSTABLE cell array contains details -% about the attributes, such as short names, long names, and data -% length. Unlike nitfReadMeta() the .name and .vname fields are -% templates with sprintf() patterns. - -% Copyright 2008 The MathWorks, Inc. - -% For the sake of performance, pre-allocate storage for the new -% attributes and then insert attributes into the pre-sized struct array. -% Use "offset" to facilitate adding the new attributes. -metaOffset = numel(meta); -numToAppend = size(fieldsTable, 1); - -meta(metaOffset + numToAppend).value = ''; - -% As an optimization, convert the lengths part of the cell array to a -% numeric array. -dataLengths = [fieldsTable{:,3}]; - -% Read all of the data at once. Extract individual values in the loop. -data = fread(fid, sum(dataLengths), 'uint8=>char')'; - -% Insert the new attributes. -dataOffset = 0; -for p = 1:numToAppend - - start = dataOffset + 1; - stop = dataOffset + dataLengths(p); - - meta(metaOffset + p).name = sprintf(fieldsTable{p,1}, index); - meta(metaOffset + p).vname = sprintf(fieldsTable{p,2}, index); - meta(metaOffset + p).value = data(start:stop); - - dataOffset = stop; - -end diff --git a/CT/private/nitfReadMetaNumeric.m b/CT/private/nitfReadMetaNumeric.m deleted file mode 100644 index 3f95745..0000000 --- a/CT/private/nitfReadMetaNumeric.m +++ /dev/null @@ -1,34 +0,0 @@ -function meta = nitfReadMetaNumeric(meta, fieldsTable, fid) -%nitfReadMetaNumeric Append attributes to metadata structure. -% OUTMETA = nitfReadMetaNumeric(INMETA, FIELDSTABLE, FID) reads -% numeric attributes from the file with handle FID and append it to -% INMETA the metadata structure. The FIELDSTABLE cell array contains -% details about the attributes: -% -% * Column 1: short names -% * Column 2: long names -% * Column 3: number of elements (not number of bytes) -% * Column 4: datatype - -% Copyright 2009 The MathWorks, Inc. - -% For the sake of performance, pre-allocate storage for the new -% attributes and then insert attributes into the pre-sized struct array. -% Use "offset" to facilitate adding the new attributes. -metaOffset = numel(meta); -numToAppend = size(fieldsTable, 1); - -meta(metaOffset + numToAppend).value = ''; - -% As an optimization, convert the lengths part of the cell array to a -% numeric array. -dataLengths = [fieldsTable{:,3}]; - -% Read and insert the new attributes. -for p = 1:numToAppend - - meta(metaOffset + p).name = fieldsTable{p,1}; - meta(metaOffset + p).vname = fieldsTable{p,2}; - meta(metaOffset + p).value = fread(fid, dataLengths(p), fieldsTable{p,4}, 'ieee-be'); - -end diff --git a/CT/private/nitfparse20.m b/CT/private/nitfparse20.m deleted file mode 100644 index 7fd8ad5..0000000 --- a/CT/private/nitfparse20.m +++ /dev/null @@ -1,502 +0,0 @@ -function nitf_meta = nitfparse20(fid) -%NITFPARSE20 Parse the fields in an NITF2.0 file. - -% Copyright 2007-2008 The MathWorks, Inc. - -nitf_meta = struct([]); -fields = {'FHDR', 'FileTypeAndVersion', 9 - 'CLEVEL', 'ComplianceLevel', 2 - 'STYPE', 'SystemType', 4 - 'OSTAID', 'OriginatingStationID', 10 - 'FDT', 'FileDateAndTime', 14 - 'FTITLE', 'FileTitle', 80 - 'FSCLAS', 'FileSecurityClassification', 1 - 'FSCODE', 'FileCodewords', 40 - 'FSCTLH', 'FileControlAndHandling', 40 - 'FSREL', 'FileReleasingInstructions', 40 - 'FSCAUT', 'FileClassificationAuthority', 20 - 'FSCTLN', 'FileSecurityControlNumber', 20 - 'FSDWNG', 'FileSecurityDowngrade', 6}; -nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -%FSDWNG is NITF_META(13) and the last item extracted in the loop above. Depending -%on its value there will be an FSDEVT or File Downgrading Event field. -%If FSDWNG is "999998", add the FSDEVT field to the meta data struct -%and insert values. -fsdwng = nitf_meta(end).value; -nitf_meta = checkFDSWNG(fid, nitf_meta, fsdwng); - -%Pull in the next several required fields -fields = {'FSCOP', 'MessageCopyNumber', 5 - 'FSCPYS', 'MessageNumberOfCopies', 5 - 'ENCRYP', 'Encryption', 1 - 'ONAME', 'OriginatorsName', 27 - 'OPHONE', 'OriginatorsPhoneNumber', 18 - 'FL', 'FileLength', 12 - 'HL', 'NITFFileHeaderLength', 6 - 'NUMI', 'NumberOfImages', 3}; -nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -numi = sscanf(nitf_meta(end).value, '%f'); -[nitf_meta, imLengths] = processtopimagesubheadermeta(numi, nitf_meta, fid); - -%Next field gives the number of symbol (graphic) segments. -fields = {'NUMS', 'NumberOfSymbols', 3}; -nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -nums = sscanf(nitf_meta(end).value, '%f'); -[nitf_meta, grLengths] = processtopgraphicsubheadermeta(nums, nitf_meta, fid); - -%Next group is Labels -fields = {'NUML', 'NumberOfLabels', 3}; -nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -numl = sscanf(nitf_meta(end).value, '%f'); -[nitf_meta, laLengths] = processtoplabelsubheadermeta(numl, nitf_meta, fid); - -%Next group is text files -fields = {'NUMT', 'NumberOfTextFiles', 3}; -nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -numt = sscanf(nitf_meta(end).value, '%f'); -[nitf_meta, teLengths] = processtoptextsubheadermeta(numt, nitf_meta, fid); - -%Next group is Data Extension Segments -fields = {'NUMDES', 'NumberOfDataExtensionSegments', 3}; -nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -numdes = sscanf(nitf_meta(end).value, '%f'); -[nitf_meta, deLengths] = processtopdesubheadermeta(numdes, nitf_meta, fid); - -%Next group is Reserved Extension Segments -fields = {'NUMRES', 'NumberOfReservedDataExtensionSegments', 3}; -nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -numres = sscanf(nitf_meta(end).value, '%f'); -[nitf_meta, reLengths, reHeaderLengths] = processtopresubheadermeta(numres, nitf_meta, fid); - -%Next group is User Define Header Segments which contain tagged record extensions. -%Get the Header Data Length -fields = {'UDHDL', 'UserDefinedHeaderDataLength', 5}; -nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -UDHDL = sscanf(nitf_meta(end).value, '%f'); -nitf_meta = processtopudsubheadermeta(UDHDL, nitf_meta, fid); - -%Next group is Extended Header Segments which contain tagged record extensions. -%Get the Header Data Length -fields = {'XHDL', 'ExtendedHeaderDataLength', 5}; -nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -XHDL = sscanf(nitf_meta(end).value, '%f'); -if XHDL > 0 - - % Handle any Extended Header Data - % Note: for our initial release we do not provide explicit support - % for tagged record extensions. All of the contents of the Extended - % Header Data (XHD) field are extracted into a single element. - fields = {'XHDL', 'ExtendedHeaderData', XHDL}; - nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -end - -%Call the image segment metadata parser for each image subheader - -%First, we want the nitf_meta struct to have a ImageSubHeader field. This -%will have the total offset of the subheader(s), and the value will be -%a struct which contains a list of image subheaders. Each subheader in -%the list is displayed table form when the user clicks on the struct -%value. - -%Build the structure of ImageSubHeaders -if numi > 0 - nitf_meta = processImageSubheaders(nitf_meta,numi,fid, imLengths); -end - -%Build the structure of SymbolSubHeaders -if nums > 0 - nitf_meta = processGraphicSubheaders(nitf_meta,nums ,fid, grLengths); -end - -%Build the structure of LabelSubHeaders -if numl > 0 - nitf_meta = processLabelSubheaders(nitf_meta,numl ,fid, laLengths); -end - -%Build the structure of TextSubHeaders -if numt > 0 - nitf_meta = processTextSubheaders(nitf_meta,numt ,fid, teLengths); -end - -%Build the structure of DataExtensionSubHeaders -if numdes > 0 - nitf_meta = processDESubheaders(nitf_meta,numdes ,fid, deLengths); -end - -%Build the structure of ReservedExtensionSubHeaders -if numres > 0 - nitf_meta = processRESubheaders(nitf_meta,numres ,fid, reLengths, reHeaderLengths); -end - - - -function nitf_meta = checkFDSWNG(fid, nitf_meta, fsdwng) -%TODO Factor this and other functions like it out! -fsdwng = sscanf(fsdwng, '%f'); -if (isequal(fsdwng, 999998)) - fields = {'FSDEVT', 'FileDowngradingEvent', 40}; - nitf_meta = nitfReadMeta(nitf_meta, fields, fid); -end - - - -function [nitf_meta, imLengths] = processtopimagesubheadermeta(numi, nitf_meta, fid) -%Add the nth image subheader information to the nitf_meta struct -%This struct contains the image subheader length and image length -%for all the images in the file -imLengths(1).value = ''; - -if (numi > 0) - - % Preallocate the lengths structure. - imLengths(numi).value = ''; - - nitf_meta(end + 1).name = 'ImageAndSubHeaderLengths'; - nitf_meta(end).vname = 'ImageAndImageSubheaderLengths'; - - fields = {'LISH%03d', 'LengthOfNthImageSubheader', 6 - 'LI%010d', 'LengthOfNthImage', 10}; - - for currentImage = 1:numi - - % Setup. - nitf_metaISL(currentImage).name = sprintf('Image%03d', currentImage); - nitf_metaISL(currentImage).vname = [nitf_metaISL(currentImage).name 'ImageAndSubheaderLengths']; - - % Parse the data. - tempStruct = struct([]); - tempStruct = nitfReadMetaMulti(tempStruct, fields, fid, currentImage); - nitf_metaISL(currentImage).value = tempStruct; - - % Update lengths with the value read. - imLengths(currentImage).value = tempStruct(2).value; - - end - - nitf_meta(end).value = nitf_metaISL; - -end - - - -function [nitf_meta, grLengths] = processtopgraphicsubheadermeta(nums,nitf_meta, fid) - -grLengths(1).value = ''; - -if (nums > 0) - - % Preallocate the lengths structure. - grLengths(nums).value = ''; - - nitf_meta(end + 1).name = 'SymbolAndSubHeaderLengths'; - nitf_meta(end).vname = 'SymbolAndSymbolSubheaderLengths'; - - fields = {'LSSH%03d', 'LengthOfNthGraphicSubheader', 4 - 'LS%06d', 'LengthOfNthGraphic', 6}; - - for currentGraphic = 1:nums - - % Setup. - nitf_metaGSL(currentGraphic).name = sprintf('Graphic%03d', currentGraphic); - nitf_metaGSL(currentGraphic).vname = [nitf_metaGSL(currentGraphic).name 'GraphicAndSubheaderLengths']; - - % Parse the data. - tempStruct = struct([]); - tempStruct = nitfReadMetaMulti(tempStruct, fields, fid, currentGraphic); - nitf_metaGSL(currentGraphic).value = tempStruct; - - % Update lengths with the value read. - grLengths(currentGraphic).value = tempStruct(2).value; - - end - - nitf_meta(end).value = nitf_metaGSL; - -end - - - -function [nitf_meta, laLengths] = processtoplabelsubheadermeta(numl, nitf_meta, fid) - -laLengths(1).value = ''; - -if (numl > 0) - - % Preallocate the lengths structure. - laLengths(numl).value = ''; - - nitf_meta(end + 1).name = 'LabelAndSubHeaderLengths'; - nitf_meta(end).vname = 'LabelAndLabelSubheaderLengths'; - - fields = {'LLSH%03d', 'LengthOfNthLabelSubheader', 4 - 'LL%06d', 'LengthOfNthLabel', 3}; - - for currentLabel = 1:numl - - % Setup. - nitf_metaLSL(currentLabel).name = sprintf('Label%03d', currentLabel); - nitf_metaLSL(currentLabel).vname = [nitf_metaLSL(currentLabel).name 'LabelAndSubheaderLengths']; - - % Parse the data. - tempStruct = struct([]); - tempStruct = nitfReadMetaMulti(tempStruct, fields, fid, currentLabel); - nitf_metaLSL(currentLabel).value = tempStruct; - - % Update lengths with the value read. - laLengths(currentLabel).value = tempStruct(2).value; - - end - - nitf_meta(end).value = nitf_metaLSL; - -end - - - -function [nitf_meta, teLengths] = processtoptextsubheadermeta(numt, nitf_meta, fid) - -teLengths(1).value = ''; - -if (numt > 0) - - % Preallocate the lengths structure. - teLengths(numt).value = ''; - - nitf_meta(end + 1).name = 'TextAndSubHeaderLengths'; - nitf_meta(end).vname = 'TextAndTextSubheaderLengths'; - - fields = {'LTSH%03d', 'LengthOfNthTextSubheader', 4 - 'LT%03d', 'LengthOfNthText', 5}; - - for currentText = 1:numt - - % Setup. - nitf_metaLTL(currentText).name = sprintf('Text%03d', currentText); - nitf_metaLTL(currentText).vname = [nitf_metaLTL(currentText).name 'TextAndSubheaderLengths']; - - % Parse the data. - tempStruct = struct([]); - tempStruct = nitfReadMetaMulti(tempStruct, fields, fid, currentText); - nitf_metaLTL(currentText).value = tempStruct; - - % Update lengths with the value read. - teLengths(currentText).value = tempStruct(2).value; - - end - - nitf_meta(end).value = nitf_metaLTL; - -end - - - -function [nitf_meta, deLengths] = processtopdesubheadermeta(numdes, nitf_meta, fid) - -deLengths(1).value = ''; - -if (numdes > 0) - - % Preallocate the lengths structure. - deLengths(numdes).value = ''; - - nitf_meta(end + 1).name = 'DataExtensionsAndSubHeaderLengths'; - nitf_meta(end).vname = 'DataExtensionAndDataExtensionSubheaderLengths'; - - fields = {'LDSH%03d', 'LengthOfNthDataExtensionSubheader', 4 - 'LD%03d', 'LengthOfNthDataExtension', 9}; - - for currentDES = 1:numdes - - % Setup. - nitf_metaDES(currentDES).name = sprintf('DataExtension%03d', currentDES); - nitf_metaDES(currentDES).vname = [nitf_metaDES(currentDES).name 'DataExtensionAndSubheaderLengths']; - - % Parse the data. - tempStruct = struct([]); - tempStruct = nitfReadMetaMulti(tempStruct, fields, fid, currentDES); - nitf_metaDES(currentDES).value = tempStruct; - - % Update lengths with the value read. - deLengths(currentDES).value = tempStruct(2).value; - - end - - nitf_meta(end).value = nitf_metaDES; - -end - - - -function [nitf_meta, reLengths, reHeaderLengths] = processtopresubheadermeta(numres, nitf_meta, fid) - -reLengths(1).value = ''; -reHeaderLengths(1).value = ''; - -if (numres > 0) - - % Preallocate the lengths structure. - reLengths(numres).value = ''; - reHeaderLengths(numres).value = ''; - - nitf_meta(end + 1).name = 'ReservedExtensionsAndSubHeaderLengths'; - nitf_meta(end).vname = 'ReservedExtensionAndReservedExtensionSubheaderLengths'; - - fields = {'LRSH%03d', 'LengthOfNthReservedExtensionSegmentSubheader', 4 - 'LR%03d', 'LengthOfNthReservedExtensionSegmentData', 7}; - - for currentRES = 1:numres - - % Setup. - nitf_metaRES(currentRES).name = sprintf('ReservedExtension%03d', currentRES); - nitf_metaRES(currentRES).vname = [nitf_metaRES(currentRES).name 'ReservedExtensionAndSubheaderLengths']; - - % Parse the data. - tempStruct = struct([]); - tempStruct = nitfReadMetaMulti(tempStruct, fields, fid, currentRES); - nitf_metaRES(currentRES).value = tempStruct; - - % Update lengths with the value read. - reHeaderLengths(currentRES).value = tempStruct(1).value; - reLengths(currentRES).value = tempStruct(2).value; - - end - - nitf_meta(end).value = nitf_metaRES; - -end - - - -function nitf_meta = processtopudsubheadermeta(UDHDL, nitf_meta, fid) - -if (UDHDL > 0) - - fields = {'UDHOFL', 'UserDefinedHeaderOverflow', 3 - 'UDHDL', 'UserDefinedHeaderData', UDHDL - 3}; - nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -end - - - -function nitf_meta = processImageSubheaders(nitf_meta, numi, fid, imLengths) -%Add the nth image subheader to the nitf_meta struct - -nitf_meta(end + 1).name = 'ImageSubHeaders'; -nitf_meta(end).vname = 'ImageSubheaderMetadata'; - -%Preallocate memory for ISnitf_meta -ISnitf_meta(numi).name = ''; - -for imageNumber = 1:numi - ISnitf_meta(imageNumber).name = sprintf('IS%03d', imageNumber); - ISnitf_meta(imageNumber).vname = sprintf('ImageSubheader%03d', imageNumber); - ISnitf_meta(imageNumber).value = parseimagesubheader20( fid, imLengths(imageNumber).value); -end - -nitf_meta(end).value = ISnitf_meta; - - - -function nitf_meta = processGraphicSubheaders(nitf_meta, nums, fid, grLengths) -%Add the nth symbol subheader to the nitf_meta struct - -nitf_meta(end + 1).name = 'SymbolSubHeaders'; -nitf_meta(end).vname = 'SymbolSubheaderMetadata'; - -%Preallocate memory for ISnitf_meta -IGnitf_meta(nums).name = ''; - -for graphicNumber = 1:nums - IGnitf_meta(graphicNumber).name = sprintf('IG%03d', graphicNumber); - IGnitf_meta(graphicNumber).vname = sprintf('SymbolSubheader%03d', graphicNumber); - IGnitf_meta(graphicNumber).value = parsegraphicsubheader20( fid, grLengths(graphicNumber).value); -end - -nitf_meta(end).value = IGnitf_meta; - - - -function nitf_meta = processLabelSubheaders(nitf_meta, numl, fid, laLengths) -%Add the nth text subheader to the nitf_meta struct - -nitf_meta(end + 1).name = 'LabelSubHeaders'; -nitf_meta(end).vname = 'LabelSubheaderMetadata'; - -%Preallocate memory for ILnitf_meta -ILnitf_meta(numl).value = ''; - -for labelNumber = 1:numl - ILnitf_meta(labelNumber).name = sprintf('IL%03d', labelNumber); - ILnitf_meta(labelNumber).vname = sprintf('LabelSubheader%03d', labelNumber); - ILnitf_meta(labelNumber).value = parselabelsubheader20( fid, laLengths(labelNumber).value); -end - -nitf_meta(end).value = ILnitf_meta; - - - -function nitf_meta = processTextSubheaders(nitf_meta, numt, fid, teLengths) -%Add the nth text subheader to the nitf_meta struct - -nitf_meta(end + 1).name = 'TextSubHeaders'; -nitf_meta(end).vname = 'TextSubheaderMetadata'; - -%Preallocate memory for ITnitf_meta -ITnitf_meta(numt).value = ''; - -for textNumber = 1:numt - ITnitf_meta(textNumber).name = sprintf('IT%03d', textNumber); - ITnitf_meta(textNumber).vname = sprintf('TextSubheader%03d', textNumber); - ITnitf_meta(textNumber).value = parsetextsubheader20( fid, teLengths(textNumber).value); -end - -nitf_meta(end).value = ITnitf_meta; - - - -function nitf_meta = processDESubheaders(nitf_meta, numdes, fid, deLengths) -%Add the nth data extension subheader to the nitf_meta struct - -nitf_meta(end + 1).name = 'DataExtensionSubHeaders'; -nitf_meta(end).vname = 'DataExtensionSubheaderMetadata'; - -%Preallocate memory for ITnitf_meta -DEnitf_meta(numdes).value = ''; - -for deNumber = 1:numdes - DEnitf_meta(deNumber).name = sprintf('DE%03d', deNumber); - DEnitf_meta(deNumber).vname = sprintf('DataExtensionSubheader%03d', deNumber); - DEnitf_meta(deNumber).value = parseDEsubheader20( fid, deLengths(deNumber).value); -end - -nitf_meta(end).value = DEnitf_meta; - - - -function nitf_meta = processRESubheaders(nitf_meta, numres, fid, reLengths, reHeaderLengths) -%Add the nth reserved extension header to the nitf_meta struct - -nitf_meta(end + 1).name = 'ReservedExtensionSubHeaders'; -nitf_meta(end).vname = 'ReservedExtensionSubheaderMetadata'; - -%Preallocate memory for ITnitf_meta..How to do this? -REnitf_meta(numres).value = ''; - -for reNumber = 1:numres - REnitf_meta(reNumber).name = sprintf('RE%03d', reNumber); - REnitf_meta(reNumber).vname = sprintf('ReserveExtensionSubheader%03d', reNumber); - REnitf_meta(reNumber).value = parseREsubheader20( fid, reLengths(reNumber).value, reHeaderLengths(reNumber).value); -end - -nitf_meta(end).value = REnitf_meta; diff --git a/CT/private/nitfparse21.m b/CT/private/nitfparse21.m deleted file mode 100644 index 1e85a87..0000000 --- a/CT/private/nitfparse21.m +++ /dev/null @@ -1,435 +0,0 @@ -function nitf_meta = nitfparse21(fid) -%NITFPARSE21 Parse the fields in an NITF2.1 file. - -% Copyright 2007-2008 The MathWorks, Inc. - -nitf_meta = struct([]); -fields = {'FHDR', 'FileProfileNameAndVersion', 9 - 'CLEVEL', 'ComplexityLevel', 2 - 'STYPE', 'StandardType', 4 - 'OSTAID', 'OriginatingStationID', 10 - 'FDT', 'FileDateAndTime', 14 - 'FTITLE', 'FileTitle', 80 - 'FSCLAS', 'FileSecurityClassification', 1 - 'FSCLSY', 'FileSecurityClassificationSystem', 2 - 'FSCODE', 'FileCodewords', 11 - 'FSCTLH', 'FileControlAndHandling', 2 - 'FSREL', 'FileReleasingInstructions', 20 - 'FSDCTP', 'FileDeclassificationType', 2 - 'FSDCDT', 'FileDeclassificationDate', 8 - 'FSDCXM', 'FileDeclassificationExemption', 4 - 'FSDG', 'FileDowngrade', 1 - 'FSDGT', 'FileDowngradeDate', 8 - 'FSCLTX', 'FileClassificationText', 43 - 'FSCATP', 'FileClassificationAuthorityType', 1 - 'FSCAUT', 'FileClassificationAuthority', 40 - 'FSCRSN', 'FileClassificationReason', 1 - 'FSSRDT', 'FileSecuritySourceDate', 8 - 'FSCTLN', 'FileSecurityControlNumber', 15 - 'FSCOP', 'FileCopyNumber', 5 - 'FSCPYS', 'FileNumberOfCopies', 5 - 'ENCRYP', 'Encryption', 1 - 'FBKGC', 'FileBackgroundColor', 3 - 'ONAME', 'OriginatorName', 24 - 'OPHONE', 'OriginatorPhoneNumber', 18 - 'FL', 'FileLength', 12 - 'HL', 'NITFFileHeaderLength', 6 - 'NUMI', 'NumberOfImages', 3}; -nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -numi = sscanf(nitf_meta(end).value, '%f'); -[nitf_meta, imLengths] = processtopimagesubheadermeta(numi, nitf_meta, fid); - -%Next field gives the number of graphics segments. -fields = {'NUMS', 'NumberOfGraphics', 3}; -nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -nums = sscanf(nitf_meta(end).value, '%f'); -[nitf_meta, grLengths] = processtopgraphicsubheadermeta(nums, nitf_meta, fid); - -%Next field is reserved for future use but it is a required field -fields = {'NUMX', 'ReservedForFutureUse', 3}; -nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -%Next group is text files -fields = {'NUMT', 'NumberOfTextFiles', 3}; -nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -numt = sscanf(nitf_meta(end).value, '%f'); -[nitf_meta, teLengths] = processtoptextsubheadermeta(numt, nitf_meta, fid); - -%Next group is Data Extension Segments -fields = {'NUMDES', 'NumberOfDataExtensionSegments', 3}; -nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -numdes = sscanf(nitf_meta(end).value, '%f'); -[nitf_meta, deLengths] = processtopdesubheadermeta(numdes, nitf_meta, fid); - -%Next group is Reserved Extension Segments -fields = {'NUMRES', 'NumberOfReservedDataExtensionSegments', 3}; -nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -numres = sscanf(nitf_meta(end).value, '%f'); -[nitf_meta, reLengths, reHeaderLengths] = processtopresubheadermeta(numres, nitf_meta, fid); - -%Next group is User Define Header Segments which contain tagged record extensions. -%Get the Header Data Length -fields = {'UDHDL', 'UserDefinedHeaderDataLength', 5}; -nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -UDHDL = sscanf(nitf_meta(end).value, '%f'); -nitf_meta = processtopudsubheadermeta(UDHDL, nitf_meta, fid); - -%Next group is Extended Header Segments which contain tagged record extensions. -%Get the Header Data Length -fields = {'XHDL', 'ExtendedHeaderDataLength', 5}; -nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -XHDL = sscanf(nitf_meta(end).value, '%f'); -nitf_meta = processtopxsubheadermeta(XHDL, nitf_meta, fid); - -%Call the image segment metadata parser for each image subheader - -% We want the image subheader(s) to be drilllable from the structure -% editor. Image subheader data will not be visible from command line -% feedback without explicitly accessing the structure. - -%First, we want the nitf_meta struct to have a ImageSubHeader field. This -%will have the total offset of the subheader(s), and the value will be -%a struct which contains a list of image subheaders. Each subheader in -%the list is displayed table form when the user clicks on the struct -%value. - -%Build the structure of ImageSubHeaders -if numi > 0 - nitf_meta = processImageSubheaders(nitf_meta,numi,fid, imLengths); -end - -%Build the structure of SymbolSubHeaders -if nums > 0 - nitf_meta = processGraphicSubheaders(nitf_meta,nums ,fid, grLengths); -end - -%Build the structure of TextSubHeaders -if numt > 0 - nitf_meta = processTextSubheaders(nitf_meta,numt ,fid, teLengths); -end - -%Build the structure of DataExtensionSubHeaders -if numdes > 0 - nitf_meta = processDESubheaders(nitf_meta,numdes ,fid, deLengths); -end - -%Build the structure of ReservedExtensionSubHeaders -if numres > 0 - nitf_meta = processRESubheaders(nitf_meta,numres ,fid, reLengths, reHeaderLengths); -end - - - -function [nitf_meta, imLengths] = processtopimagesubheadermeta(numi, nitf_meta, fid) -%Add the nth image subheader information to the nitf_meta struct -%This struct contains the image subheader length and image length -%for all the images in the file -imLengths(1).value = ''; - -if (numi > 0) - - % Preallocate the lengths structure. - imLengths(numi).value = ''; - - nitf_meta(end + 1).name = 'ImageAndSubHeaderLengths'; - nitf_meta(end).vname = 'ImageAndImageSubheaderLengths'; - - fields = {'LISH%03d', 'LengthOfNthImageSubheader', 6 - 'LI%010d', 'LengthOfNthImage', 10}; - - for currentImage = 1:numi - - % Setup. - nitf_metaISL(currentImage).name = sprintf('Image%03d', currentImage); - nitf_metaISL(currentImage).vname = [nitf_metaISL(currentImage).name 'ImageAndSubheaderLengths']; - - % Parse the data. - tempStruct = struct([]); - tempStruct = nitfReadMetaMulti(tempStruct, fields, fid, currentImage); - nitf_metaISL(currentImage).value = tempStruct; - - % Update lengths with the value read. - imLengths(currentImage).value = tempStruct(2).value; - - end - - nitf_meta(end).value = nitf_metaISL; - -end - - - -function [nitf_meta, grLengths] = processtopgraphicsubheadermeta(nums,nitf_meta, fid) - -grLengths(1).value = ''; - -if (nums > 0) - - % Preallocate the lengths structure. - grLengths(nums).value = ''; - - nitf_meta(end + 1).name = 'GraphicAndSubHeaderLengths'; - nitf_meta(end).vname = 'GraphicAndGraphicSubheaderLengths'; - - fields = {'LSSH%03d', 'LengthOfNthGraphicSubheader', 4 - 'LS%06d', 'LengthOfNthGraphic', 6}; - - for currentGraphic = 1:nums - - % Setup. - nitf_metaGSL(currentGraphic).name = sprintf('Graphic%03d', currentGraphic); - nitf_metaGSL(currentGraphic).vname = [nitf_metaGSL(currentGraphic).name 'GraphicAndSubheaderLengths']; - - % Parse the data. - tempStruct = struct([]); - tempStruct = nitfReadMetaMulti(tempStruct, fields, fid, currentGraphic); - nitf_metaGSL(currentGraphic).value = tempStruct; - - % Update lengths with the value read. - grLengths(currentGraphic).value = tempStruct(2).value; - - end - - nitf_meta(end).value = nitf_metaGSL; - -end - - - -function [nitf_meta, teLengths] = processtoptextsubheadermeta(numt, nitf_meta, fid) - -teLengths(1).value = ''; - -if (numt > 0) - - % Preallocate the lengths structure. - teLengths(numt).value = ''; - - nitf_meta(end + 1).name = 'TextAndSubHeaderLengths'; - nitf_meta(end).vname = 'TextAndTextSubheaderLengths'; - - fields = {'LTSH%03d', 'LengthOfNthTextSubheader', 4 - 'LT%03d', 'LengthOfNthText', 5}; - - for currentText = 1:numt - - % Setup. - nitf_metaLTL(currentText).name = sprintf('Text%03d', currentText); - nitf_metaLTL(currentText).vname = [nitf_metaLTL(currentText).name 'TextAndSubheaderLengths']; - - % Parse the data. - tempStruct = struct([]); - tempStruct = nitfReadMetaMulti(tempStruct, fields, fid, currentText); - nitf_metaLTL(currentText).value = tempStruct; - - % Update lengths with the value read. - teLengths(currentText).value = tempStruct(2).value; - - end - - nitf_meta(end).value = nitf_metaLTL; - -end - - - -function [nitf_meta, deLengths] = processtopdesubheadermeta(numdes, nitf_meta, fid) - -deLengths(1).value = ''; - -if (numdes > 0) - - % Preallocate the lengths structure. - deLengths(numdes).value = ''; - - nitf_meta(end + 1).name = 'DataExtensionsAndSubHeaderLengths'; - nitf_meta(end).vname = 'DataExtensionAndDataExtensionSubheaderLengths'; - - fields = {'LDSH%03d', 'LengthOfNthDataExtensionSubheader', 4 - 'LD%03d', 'LengthOfNthDataExtension', 9}; - - for currentDES = 1:numdes - - % Setup. - nitf_metaDES(currentDES).name = sprintf('DataExtension%03d', currentDES); - nitf_metaDES(currentDES).vname = [nitf_metaDES(currentDES).name 'DataExtensionAndSubheaderLengths']; - - % Parse the data. - tempStruct = struct([]); - tempStruct = nitfReadMetaMulti(tempStruct, fields, fid, currentDES); - nitf_metaDES(currentDES).value = tempStruct; - - % Update lengths with the value read. - deLengths(currentDES).value = tempStruct(2).value; - - end - - nitf_meta(end).value = nitf_metaDES; - -end - - - -function [nitf_meta, reLengths, reHeaderLengths] = processtopresubheadermeta(numres, nitf_meta, fid) - -reLengths(1).value = ''; -reHeaderLengths(1).value = ''; - -if (numres > 0) - - % Preallocate the lengths structure. - reLengths(numres).value = ''; - reHeaderLengths(numres).value = ''; - - nitf_meta(end + 1).name = 'ReservedExtensionsAndSubHeaderLengths'; - nitf_meta(end).vname = 'ReservedExtensionAndReservedExtensionSubheaderLengths'; - - fields = {'LRSH%03d', 'LengthOfNthReservedExtensionSegmentSubheader', 4 - 'LR%03d', 'LengthOfNthReservedExtensionSegmentData', 7}; - - for currentRES = 1:numres - - % Setup. - nitf_metaRES(currentRES).name = sprintf('ReservedExtension%03d', currentRES); - nitf_metaRES(currentRES).vname = [nitf_metaRES(currentRES).name 'ReservedExtensionAndSubheaderLengths']; - - % Parse the data. - tempStruct = struct([]); - tempStruct = nitfReadMetaMulti(tempStruct, fields, fid, currentRES); - nitf_metaRES(currentRES).value = tempStruct; - - % Update lengths with the value read. - reHeaderLengths(currentRES).value = tempStruct(1).value; - reLengths(currentRES).value = tempStruct(2).value; - - end - - nitf_meta(end).value = nitf_metaRES; - -end - - - -function nitf_meta = processtopudsubheadermeta(UDHDL, nitf_meta, fid) - -if (UDHDL > 0) - - fields = {'UDHOFL', 'UserDefinedHeaderOverflow', 3 - 'UDHDL', 'UserDefinedHeaderData', UDHDL - 3}; - nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -end - - - -function nitf_meta = processtopxsubheadermeta(XHDL, nitf_meta, fid) - -if (XHDL > 0) - - fields = {'XHDLOFL', 'UserHeaderDataOverflow', 3 - 'XHDL', 'ExtendedHeaderData', XHDL - 3}; - nitf_meta = nitfReadMeta(nitf_meta, fields, fid); - -end - - - -function nitf_meta = processImageSubheaders(nitf_meta, numi, fid, imLengths) -%Add the nth image subheader to the nitf_meta struct - -nitf_meta(end + 1).name = 'ImageSubHeaders'; -nitf_meta(end).vname = 'ImageSubheaderMetadata'; - -%Preallocate memory for ISnitf_meta -ISnitf_meta(numi).name = ''; - -for imageNumber = 1:numi - ISnitf_meta(imageNumber).name = sprintf('IS%03d', imageNumber); - ISnitf_meta(imageNumber).vname = sprintf('ImageSubheader%03d', imageNumber); - ISnitf_meta(imageNumber).value = parseimagesubheader( fid, imLengths(imageNumber).value); -end - -nitf_meta(end).value = ISnitf_meta; - - - -function nitf_meta = processGraphicSubheaders(nitf_meta, nums, fid, grLengths) -%Add the nth graphic subheader to the nitf_meta struct - -nitf_meta(end + 1).name = 'GraphicSubHeaders'; -nitf_meta(end).vname = 'GraphicSubheaderMetadata'; - -%Preallocate memory for ISnitf_meta -IGnitf_meta(nums).name = ''; - -for graphicNumber = 1:nums - IGnitf_meta(graphicNumber).name = sprintf('IG%03d', graphicNumber); - IGnitf_meta(graphicNumber).vname = sprintf('GraphicSubheader%03d', graphicNumber); - IGnitf_meta(graphicNumber).value = parsegraphicsubheader( fid, grLengths(graphicNumber).value); -end - -nitf_meta(end).value = IGnitf_meta; - - - -function nitf_meta = processTextSubheaders(nitf_meta, numt, fid, teLengths) -%Add the nth text subheader to the nitf_meta struct - -nitf_meta(end + 1).name = 'TextSubHeaders'; -nitf_meta(end).vname = 'TextSubheaderMetadata'; - -%Preallocate memory for ITnitf_meta -ITnitf_meta(numt).value = ''; - -for textNumber = 1:numt - ITnitf_meta(textNumber).name = sprintf('IT%03d', textNumber); - ITnitf_meta(textNumber).vname = sprintf('TextSubheader%03d', textNumber); - ITnitf_meta(textNumber).value = parsetextsubheader( fid, teLengths(textNumber).value); -end - -nitf_meta(end).value = ITnitf_meta; - - - -function nitf_meta = processDESubheaders(nitf_meta, numdes, fid, deLengths) -%Add the nth data extension subheader to the nitf_meta struct - -nitf_meta(end + 1).name = 'DataExtensionSubHeaders'; -nitf_meta(end).vname = 'DataExtensionSubheaderMetadata'; - -%Preallocate memory for ITnitf_meta -DEnitf_meta(numdes).value = ''; - -for deNumber = 1:numdes - DEnitf_meta(deNumber).name = sprintf('DE%03d', deNumber); - DEnitf_meta(deNumber).vname = sprintf('DataExtensionSubheader%03d', deNumber); - DEnitf_meta(deNumber).value = parseDEsubheader( fid, deLengths(deNumber).value); -end - -nitf_meta(end).value = DEnitf_meta; - - - -function nitf_meta = processRESubheaders(nitf_meta, numres, fid, reLengths, reHeaderLengths) -%Add the nth reserved extension header to the nitf_meta struct - -nitf_meta(end + 1).name = 'ReservedExtensionSubHeaders'; -nitf_meta(end).vname = 'ReservedExtensionSubheaderMetadata'; - -%Preallocate memory for ITnitf_meta..How to do this? -REnitf_meta(numres).value = ''; - -for reNumber = 1:numres - REnitf_meta(reNumber).name = sprintf('RE%03d', reNumber); - REnitf_meta(reNumber).vname = sprintf('ReserveExtensionSubheader%03d', reNumber); - REnitf_meta(reNumber).value = parseREsubheader20( fid, reLengths(reNumber).value, reHeaderLengths(reNumber).value); -end - -nitf_meta(end).value = REnitf_meta; diff --git a/CT/private/parseDEsubheader.m b/CT/private/parseDEsubheader.m deleted file mode 100644 index 0941b09..0000000 --- a/CT/private/parseDEsubheader.m +++ /dev/null @@ -1,56 +0,0 @@ -function [ denitf_meta ] = parseDEsubheader( fid, dataLength ) -%PARSEDESUBHEADER Parse the Data Extension subheaders in an NITF file. -% DENITF_META = PARSEDESUBHEADER -% Parse the Data Extension Segment Subheader for an NITF 2.1 file. - -% Copyright 2007-2008 The MathWorks, Inc. - -denitf_meta = struct([]); -fields = {'DE', 'FilePartType', 2 - 'DESTAG', 'UniqueDESTypeIdentifier', 25 - 'DESVER', 'VersionOfTheDataFieldDefinition', 2 - 'DESCLAS', 'DESecurityClassification', 1 - 'DESCLSY', 'DESecurityClassificationSystem', 2 - 'DESCODE', 'DECodewords', 11 - 'DESCTLH', 'DEControlAndHandling', 2 - 'DESREL', 'DEReleasingInstructions', 20 - 'DESDCTP', 'DEDeclassificationType', 2 - 'DESDCDT', 'DEDeclassificationDate', 8 - 'DESDCXM', 'DEDeclassificationExemption', 4 - 'DESDG', 'DEDowngrade', 1 - 'DESDGT', 'DEDowngradeDate', 8 - 'DESCLTX', 'DEClassificationText', 43 - 'DESCATP', 'DEClassificationAuthorityType' 1 - 'DESCAUT', 'DEClassificationAuthority', 40 - 'DESCRSN', 'DEClassificationReason', 1 - 'DESSRDT', 'DESecuritySourceDate', 8 - 'DESCTL', 'DESecurityControlNumber', 15}; -denitf_meta = nitfReadMeta(denitf_meta, fields, fid); - -% DESOFLW is present if DESTAG = TRE_OVERFLOW. -if (isequal(deblank(denitf_meta(2).value), 'TRE_OVERFLOW')) - - fields = {'DESOFLW', 'OverflowedHeaderType', 6 - 'DESITEM', 'DataItemOverflowed', 3}; - denitf_meta = nitfReadMeta(denitf_meta, fields, fid); - -end - -%DESSHL -fields = {'DESSHL', 'LengthOfUserDefinedSubheaderFields', 4}; -denitf_meta = nitfReadMeta(denitf_meta, fields, fid); - -desshl = sscanf(denitf_meta(end).value, '%f'); -if desshl ~= 0 % The we'll have user defined fields - fields = {'DESSHF', 'UserDefinedSubheaderFields', desshl}; - denitf_meta = nitfReadMeta(denitf_meta, fields, fid); -end - -%DESDATA -%Contains either user-defined data or controlled/registered extensions -%Move the cursor through the Extension data. Return as raw bytes. -readforwardbytes = sscanf(dataLength, '%f'); - -denitf_meta(end + 1).name = 'DESDATA'; -denitf_meta(end).vname = 'UserDefinedData'; -denitf_meta(end).value = fread(fid, readforwardbytes, 'uint8=>uint8'); diff --git a/CT/private/parseDEsubheader20.m b/CT/private/parseDEsubheader20.m deleted file mode 100644 index 634d16c..0000000 --- a/CT/private/parseDEsubheader20.m +++ /dev/null @@ -1,50 +0,0 @@ -function denitf_meta = parseDEsubheader20( fid, dataLength ) -%PARSEDESUBHEADER20 Parse the Data Extension subheaders in an NITF file. -% DENITF_META = PARSEDESUBHEADER20 -% Parse the Data Extension Segment Subheader for an NITF 2.0 file. - -% Copyright 2007-2008 The MathWorks, Inc. - -denitf_meta = struct([]); -fields = {'DE', 'FilePartType', 2 - 'DESTAG', 'UniqueDESTypeIdentifier', 25 - 'DESVER', 'VersionOfTheDataFieldDefinition', 2 - 'DESCLAS', 'DESecurityClassification', 1 - 'DESCODE', 'DECodewords', 40 - 'DESCTLH', 'DEControlAndHandling', 40 - 'DESREL', 'DEReleasingInstructions', 40 - 'DESCAUT', 'DEClassificationAuthority', 20 - 'DESCTLN', 'DESecurityControlNumber', 20 - 'DESDWNG', 'DESecurityDowngrade', 6}; -denitf_meta = nitfReadMeta(denitf_meta, fields, fid); - -%DESDWNG is DENITF_META(10) and the last item extracted in the loop above. Depending -%on its value there will be an DESDEVT -desdwng = sscanf(denitf_meta(end).value, '%f'); -if desdwng == 999998 - fields = {'DESDEVT', 'DEDowngradingEvent', 40}; - denitf_meta = nitfReadMeta(denitf_meta, fields, fid); -end - -%The following is conditional on the value of DESTAG which is denitf_meta(2) -destag = deblank(denitf_meta(2).value); -if strcmp(destag, 'Registered Extensions') || strcmp(destag,'Controlled Extensions') - fields = {'DESOFLW', 'OverflowedHeaderType', 6 - 'DESITEM', 'DataItemOverflowed', 3}; - denitf_meta = nitfReadMeta(denitf_meta, fields, fid); -end - -fields = {'DESSHL', 'LengthOfUserDefinedSubheaderFields', 4}; -denitf_meta = nitfReadMeta(denitf_meta, fields, fid); - -desshl = sscanf(denitf_meta(end).value, '%f'); -if desshl ~= 0 % Then we'll have user defined fields - fields = {'DESSHF', 'UserDefinedSubheaderFields', desshl}; - denitf_meta = nitfReadMeta(denitf_meta, fields, fid); -end - -%DESDATA -%Contains either user-defined data or controlled/registered extensions -%Move the cursor through the Extension data -readforwardbytes = sscanf(dataLength, '%f'); -fread(fid, readforwardbytes, 'uint8=>char'); diff --git a/CT/private/parseParameterValuePairs.m b/CT/private/parseParameterValuePairs.m deleted file mode 100644 index 35ec514..0000000 --- a/CT/private/parseParameterValuePairs.m +++ /dev/null @@ -1,58 +0,0 @@ -function options = parseParameterValuePairs(funcName, knownParams, varargin) -%parseParameterValuePairs Get user-provided and default options. -% OPTIONS = parseParameterValuePairs(FUNCNAME, DETAILS, PARAM1, VALUE1, ...) -% parses and validates a set of parameter-value pairs. FUNCNAME is a -% character array containing the name of the function that accepts -% various parameters (PARAM1, etc.) and values (VALUE1, etc.). DETAILS -% is a cell array with one row per known parameter and has the following -% columns: -% -% 1 - Parameter name (character array) -% 2 - Output field name (character array) -% 3 - Default parameter value (any value) -% 4 - Acceptable value type (cell array of MATLAB types) -% 5 - Value parameters (cell array of validateattributes values) -% -% The output value OPTIONS is a structure array whose field names are -% the parameters and whose values are the corresponding values. The -% field names of OPTIONS may not actually match the parameter names -% expected by FUNCNAME, depending on the values in the second column of -% DETAILS. This allows convenient field names for internal use. -% - -% Copyright 2007-2010 The MathWorks, Inc. - -% Create a structure with default values, and map actual param-value pair -% names to convenient names for internal use. - -options = cell2struct(knownParams(:,3), knownParams(:,2), 1); - -if (rem(nargin, 2) ~= 0) - error(message('images:parseParameterValuePairs:paramValuePairs')) -end - -% Loop over the P-V pairs. -for p = 1:2:numel(varargin) - % Get the parameter name. - paramName = varargin{p}; - if (~ischar(paramName)) - error(message('images:parseParameterValuePairs:badParamName')) - end - - % Look for the parameter amongst the possible values. - idx = strmatch(lower(paramName), lower(knownParams(:,1))); - if (isempty(idx)) - error(message('images:parseParameterValuePairs:unknownParamName', paramName)); - elseif (numel(idx) > 1) - error(message('images:parseParameterValuePairs:ambiguousParamName', paramName)); - end - - % Validate the value. - options.(knownParams{idx, 2}) = varargin{p+1}; - validateattributes(varargin{p+1}, ... - knownParams{idx,4}, ... - knownParams{idx,5}, ... - funcName, ... - knownParams{idx,1}, ... - p+2); % p+2 = Param name + 1 + offset to first arg -end diff --git a/CT/private/parseREsubheader20.m b/CT/private/parseREsubheader20.m deleted file mode 100644 index bad5acd..0000000 --- a/CT/private/parseREsubheader20.m +++ /dev/null @@ -1,20 +0,0 @@ -function renitf_meta = parseREsubheader20( fid, dataLength, headerLength ) -%PARSERESUBHEADER20 Process the Reserved Extensions subheaders in an NITF20 file. -% RENITF_META = PARSERESUBHEADER20 -% Parse the Reserved Extension Segment Subheader for an NITF 2.0 file. - -% Copyright 2007-2008 The MathWorks, Inc. - -% Essentially we don't know anything about the extension so we just need -% to pull the header into a struct and read ahead over the data - -% Convert the length from a decimal string to an integer. -headerLength = sscanf(headerLength', '%d'); - -renitf_meta = struct([]); -fields = {'ReservedDataExtensionHeader', 'ReservedDataExtensionHeader', headerLength}; -renitf_meta = nitfReadMeta(renitf_meta, fields, fid); - -%Move the cursor through the Reserved Extension data -readforwardbytes = sscanf(dataLength, '%f'); -fread(fid, readforwardbytes, 'uint8=>char'); diff --git a/CT/private/parsegraphicsubheader.m b/CT/private/parsegraphicsubheader.m deleted file mode 100644 index 1b2d56f..0000000 --- a/CT/private/parsegraphicsubheader.m +++ /dev/null @@ -1,57 +0,0 @@ -function gsnitf_meta = parsegraphicsubheader( fid, dataLength ) -%PARSEGRAPHICSUBHEADER Parse the Graphic subheaders in an NITF file. -% GSNITF_META = PARSEGRAPHICSUBHEADER -% Parse the Graphic Segment Subheader for an NITF 2.1 file. - -% Copyright 2007-2008 The MathWorks, Inc. - -% Initialize the graphic subheader structure -gsnitf_meta = struct([]); -fields = {'SY', 'FilePartType', 2 - 'SID', 'GraphicID', 10 - 'SNAME', 'GraphicName', 20 - 'SSCLAS', 'GraphicSecurityClassification', 1 - 'SSCLSY', 'GraphicSecurityClassificationSystem', 2 - 'SSCODE', 'GraphicCodewords', 11 - 'SSCTLH', 'GraphicControlAndHandling', 2 - 'SSREL', 'GraphicReleasingInstructions', 20 - 'SSDCTP', 'GraphicDeclassificationType', 2 - 'SSDCDT', 'GraphicDeclassificationDate', 8 - 'SSDCXM', 'GraphicDeclassificationExemption', 4 - 'SSDG', 'GraphicDowngrade', 1 - 'SSDGT', 'GraphicDowngradeDate', 8 - 'SSCLTX', 'GraphicClassificationText', 43 - 'SSCATP', 'GraphicClassificationAuthorityType', 1 - 'SSCAUT', 'GraphicClassificationAuthority', 40 - 'SSCRSN', 'GraphicClassificationReason', 1 - 'SSSRDT', 'GraphicSecuritySourceDate', 8 - 'SSCTLN', 'GraphicSecurityControlNumber', 15 - 'ENCRYP', 'Encryption', 1 - 'STYPE', 'GraphicType', 1 - 'SRES1', 'ReservedForFutureUse', 13 - 'SDLVL', 'DisplayLevel', 3 - 'SALVL', 'GraphicAttachmentLevel', 3 - 'SLOC', 'GraphicLocation', 10 - 'SBND1', 'FirstGraphicBoundLocation', 10 - 'SCOLOR', 'GraphicColor', 1 - 'SBND2', 'SecondGraphicBoundLocation', 10 - 'SRES2', 'ReservedForFutureUse', 2 - 'SXSHDL', 'ExtendedSubheaderDataLength', 5}; -gsnitf_meta = nitfReadMeta(gsnitf_meta, fields, fid); - -%SXSHDL is GSNITF_META(30) and the last item extracted in the loop above. Depending -%on its value there will be an SXSOFL or Extended Subheader Overflow field and SXSHD field. -%If SXSHDL is not zeros, add the SXSOFL and SXSHD fields to the meta data struct -%and insert values. - -sxshdl = sscanf(gsnitf_meta(30).value, '%f'); -if sxshdl ~= 0 - fields = {'SXSOFL', 'ExtendedSubheaderOverflow', 3 - 'SXSHD', 'ExtendedSubheaderData', sxshdl - 3}; - gsnitf_meta = nitfReadMeta(gsnitf_meta, fields, fid); -end - - -%Move the cursor through the graphic data -readforwardbytes = sscanf(dataLength, '%f'); -fread(fid, readforwardbytes, 'uint8=>char'); diff --git a/CT/private/parsegraphicsubheader20.m b/CT/private/parsegraphicsubheader20.m deleted file mode 100644 index ee9fdc3..0000000 --- a/CT/private/parsegraphicsubheader20.m +++ /dev/null @@ -1,78 +0,0 @@ -function gsnitf_meta = parsegraphicsubheader20( fid, dataLength ) -%PARSEGRAPHICSUBHEADER Parse the Graphic subheaders in an NITF file. -% GSNITF_META = PARSEGRAPHICSUBHEADER20 -% Parse the Graphic Segment Subheader for an NITF 2.0 file. - -% Copyright 2007-2008 The MathWorks, Inc. - -% Initialize the graphic subheader structure -gsnitf_meta = struct([]); -fields = {'SY', 'FilePartType', 2 - 'SID', 'SymbolID', 10 - 'SNAME', 'SymbolName', 20 - 'SSCLAS', 'SymbolSecurityClassification', 1 - 'SSCODE', 'SymbolCodewords', 40 - 'SSCTLH', 'SymbolControlAndHandling', 40 - 'SSREL', 'SymbolReleasingInstructions', 40 - 'SSCAUT', 'SymbolClassificationAuthority', 20 - 'SSCTLN', 'SymbolSecurityControlNumber', 20 - 'SSDWNG', 'SymbolSecurityDowngrade', 6}; -gsnitf_meta = nitfReadMeta(gsnitf_meta, fields, fid); - -%SSDWNG is GSNITF_META(10) and the last item extracted in the loop above. Depending -%on its value there will be an SSDEVT -ssdwng = sscanf(gsnitf_meta(end).value, '%f'); -if ssdwng == 999998 - - fields = {'SSDEVT', 'SymbolDowngradingEvent', 40}; - gsnitf_meta = nitfReadMeta(gsnitf_meta, fields, fid); - -end - -fields = {'ENCRYP', 'Encryption', 1 - 'STYPE', 'SymbolType', 1 - 'NLIPS', 'NumberOfLinesPerSymbol', 4 - 'NPIXPL', 'NumberOfPixelsPerLine' 4 - 'NWDTH', 'LineWidth', 4 - 'NBPP', 'NumberOfBitsPerPixel', 1 - 'SDLVL', 'DisplayLevel', 3 - 'SALVL', 'SymbolAttachmentLevel', 3 - 'SLOC', 'SymbolLocation', 10 - 'SLOC2', 'SecondSymbolLocation', 10 - 'SCOLOR', 'SymbolColor', 1 - 'SNUM', 'SymbolNumber', 6 - 'SROT', 'SymbolRotation', 3 - 'NELUT', 'NumberOfLUTEntries', 3}; -gsnitf_meta = nitfReadMeta(gsnitf_meta, fields, fid); - - -%DLUT -- This is the actual look-up table which I think constitutes data -% Should we expose it as metadata? -nelut = sscanf(gsnitf_meta(end).value, '%f'); -if nelut ~= 0 - if strcmp(scolor,'C') %Color look-up table - dlutsize = 3 * nelut; - elseif strcmp(scolor,'G') %Gray scale look-up table - dlutsize = nelut; - else - dlutsize = 0; - end - - fields = {'DLUT', 'SymbolLUTData', dlutsize}; - gsnitf_meta = nitfReadMeta(gsnitf_meta, fields, fid); -end - -fields = {'SXSHDL', 'ExtendedSubheaderDataLength', 5}; -gsnitf_meta = nitfReadMeta(gsnitf_meta, fields, fid); - -%SXSOFL and SCSHD -sxshdl = sscanf(gsnitf_meta(end).value, '%f'); -if sxshdl ~= 0 - fields = {'SXSOFL', 'ExtendedSubheaderOverflow', 3 - 'SXSHD', 'ExtendedSubheaderData', sxshdl - 3}; - gsnitf_meta = nitfReadMeta(gsnitf_meta, fields, fid); -end - -%Move the cursor through the graphic data -readforwardbytes = sscanf(dataLength, '%f'); -fread(fid, readforwardbytes, 'uint8=>char'); diff --git a/CT/private/parseimagesubheader.m b/CT/private/parseimagesubheader.m deleted file mode 100644 index dad684a..0000000 --- a/CT/private/parseimagesubheader.m +++ /dev/null @@ -1,280 +0,0 @@ -function isnitf_meta = parseimagesubheader( fid, dataLength ) -%PARSEIMAGESUBHEADER Parse the Image subheaders in an NITF file. -% ISNITF_META = PARSEIMAGESUBHEADER -% Parse the Image Segment Subheader for an NITF 2.1 file. - -% Copyright 2007-2009 The MathWorks, Inc. - -% TODO: refactor common functions between 2.0 and 2.1 into an external file - -% Initialize the image subheader structure -isnitf_meta = struct([]); -fields = {'IM', 'FilePartType', 2 - 'IID1', 'ImageID1', 10 - 'IDATIM', 'ImageDateAndTime', 14 - 'TGTID', 'TargetID', 17 - 'IID2', 'ImageIID2', 80 - 'ISCLAS', 'ImageSecurityClassification', 1 - 'ISCLSY', 'ImageSecurityClassificationSystem', 2 - 'ISCODE', 'ImageCodewords', 11 - 'ISCTLH', 'ImageControlAndHandling', 2 - 'ISREL', 'ImageReleasingInstructions', 20 - 'ISDCTP', 'ImageDeclassificationType', 2 - 'ISDCDT', 'ImageDeclassificationDate', 8 - 'ISDCXM', 'ImageDeclassificationExemption', 4 - 'ISDG', 'ImageDowngrade', 1 - 'ISDGT', 'ImageDowngradeDate', 8 - 'ISCLTX', 'ImageClassificationText', 43 - 'ISCATP', 'ImageClassificationAuthorityType', 1 - 'ISCAUT', 'ImageClassificationAuthority', 40 - 'ISCRSN', 'ImageClassificationReason', 1 - 'ISSRDT', 'ImageSecuritySourceDate', 8 - 'ISCTLN', 'ImageSecurityControlNumber', 15 - 'ENCRYP', 'Encryption', 1 - 'ISORCE', 'ImageSource', 42 - 'NROWS', 'NumberOfSignificantRowsInImage', 8 - 'NCOLS', 'NumberOfSignificantColumnsInImage', 8 - 'PVTYPE', 'PixelValueType', 3 - 'IREP', 'ImageRepresentation', 8 - 'ICAT', 'ImageCategory', 8 - 'ABPP', 'ActualBitsPerPixelPerBand', 2 - 'PJUST', 'PixelJustification', 1 - 'ICORDS', 'ImageCoordinateSystem', 1}; -isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -%ICORDS is the last item extracted in the loop above. Depending -%on its value there will be an IGEOLO or Image Geographic Location field. -%If ICORDS is not a space, add the IGEOLO field to the meta data struct -%and insert values. -icords = deblank(isnitf_meta(end).value); - -isnitf_meta = checkIcords(icords, fid, isnitf_meta); - -%NICOM -%Depending on its value there will be ICOM fields (ICOM1 through ICOMn). -%If NICOM is not zero, add the comment fields to the meta data struct -%and insert their values. - -fields = {'NICOM', 'NumberOfImageComments', 1}; -isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -nicom = sscanf(isnitf_meta(end).value, '%f'); -isnitf_meta = checkNicom(nicom, fid, isnitf_meta); - -%Next field is Image Compression -fields = {'IC', 'ImageCompression', 2}; -isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -%Next field is COMRAT or Compression Rate Code -%If the IC field is not NC or NM the field will have a value. -ic = isnitf_meta(end).value; -if ~strcmp(ic, 'NC') && ~strcmp(ic, 'NM') - fields = {'COMRAT', 'CompressionRateCode', 4}; - isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); -end - -fields = {'NBANDS', 'NumberOfBands', 1}; -isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -nbands = sscanf(isnitf_meta(end).value, '%f'); - -%XBANDS -%If the NBANDS field is 0 XBANDS is the number of bands in a multi-spectral image. -if nbands == 0 - fields = {'XBANDS', 'NumberOfMultiSpectralBands', 5}; - isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - bands = sscanf(isnitf_meta(end).value, '%f'); -else - bands = nbands; -end - -%Set up Band substructure - -isnitf_meta(end + 1).name = 'Band Meta'; -isnitf_meta(end).vname = 'BandMeta'; -%The value will be a structure of band data - -%The next seven fields occur for each band as indicated by BANDS -% Lengths: -% IREPBAND 2, ISUBCAT 6, IFC 1, IMFLT 3, NLUTS 1, NELUT 5 [omitted if NLUTS = 0] -% LUTD contains data for the mth LUT of the nnth band - -nitf_metaBand(bands).value = ''; - -for currentBand = 1: bands - - isBandnitf_meta = struct([]); - - nitf_metaBand(currentBand).name = sprintf('Band%03d', currentBand); - nitf_metaBand(currentBand).vname = [nitf_metaBand(currentBand).name 'Meta']; - nitf_metaBand(currentBand).value = ''; - - fields = {'IREPBAND%02d', 'BandRepresentation%02d', 2 - 'ISUBCAT%02d', 'BandSubcategory%02d', 6 - 'IFC%02d', 'BandImageFilterCondition%02d', 1 - 'IMFLT%02d', 'BandImageFilterCode%02d', 3 - 'NLUTS%02d', 'BandNumberOfLUTS%02d', 1}; - - isBandnitf_meta = nitfReadMetaMulti(isBandnitf_meta, fields, fid, currentBand); - numluts = sscanf(isBandnitf_meta(end).value, '%f'); - - if numluts ~= 0 - %nnth Band Number of LUT Entries - - fields = {'NELUT%02d', 'BandNumberOfLUTEntries%02d', 5}; - isBandnitf_meta = nitfReadMetaMulti(isBandnitf_meta, fields, fid, currentBand); - - numlutentries = sscanf(isBandnitf_meta(end).value', '%f'); - - %The value will be a struct of LUT data - for currentLut = 1 : numluts - isBandnitf_meta(end + 1).name = sprintf('LUTData%1d', currentLut); - isBandnitf_meta(end).vname = sprintf('LUTData%1d', currentLut); - % Note: not converted to char. - isBandnitf_meta(end).value = fread(fid, numlutentries, 'uint8'); - end - end - - nitf_metaBand(currentBand).value = isBandnitf_meta; - -end -isnitf_meta(end).value = nitf_metaBand; - - -fields = {'ISYNC', 'ImageSyncCode', 1 - 'IMODE', 'ImageMode' 1 - 'NBPR', 'NumberOfBlocksPerRow', 4}; -isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); -NBPR = sscanf(isnitf_meta(end).value, '%f'); - -fields = {'NBPC', 'NumberOfBlocksPerColumn', 4}; -isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); -NBPC = sscanf(isnitf_meta(end).value, '%f'); - -fields = {'NPPBH', 'NumberOfPixelsPerBlockHorizontal', 4 - 'NPPBV', 'NumberOfPixelsPerBlockVertical', 4 - 'NBPP', 'NumberOfBitsPerPixelPerBand', 2 - 'IDLVL', 'DisplayLevel', 3 - 'IALVL', 'ImageAttachmentLevel', 3 - 'ILOC', 'ImageLocation', 10 - 'IMAG', 'ImageMagnification', 4}; -isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -% The IMAG value should be converted to a number from the decimal string. -isnitf_meta(end).value = sscanf(isnitf_meta(end).value, '%f'); - -fields = {'UDIDL', 'UserDefinedImageDataLength', 5}; -isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -%If UDIDL is not zeros we'll have values for UDOFL and UDID -UDIDL = sscanf(isnitf_meta(end).value, '%f'); -if UDIDL ~= 0 - - fields = {'UDOFL', 'UserDefinedOverflow', 3 - 'UDID', 'UserDefinedImageData', UDIDL - 3}; - isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -end - -fields = {'IXSHDL', 'ExtendedSubheaderDataLength', 5}; -isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -%If IXSHDL is not zeros we'll have values for IXSOFL and IXSHD -IXSHDL = sscanf(isnitf_meta(end).value, '%f'); -if IXSHDL ~= 0 - - fields = {'IXOFL', 'ExtendedSubheaderOverflow', 3 - 'IXSHD', 'ExtendedSubheaderData', IXSHDL - 3}; - isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -end - -% If the image contains data masking, read those values. (See -% MIL-STD-2500B Table A-3(A). -dataMaskTableLength = 0; -if (hasDataMaskTable(ic)) - - fields = {'IMDATOFF', 'BlockedImageDataOffset', 1, 'int32' - 'BMRLNTH', 'BlockedMaskRecordLength', 1, 'uint16'}; - isnitf_meta = nitfReadMetaNumeric(isnitf_meta, fields, fid); - BMRLNTH = isnitf_meta(end).value; - - fields = {'TMRLNTH', 'PadPixelMaskRecordLength', 1, 'uint16'}; - isnitf_meta = nitfReadMetaNumeric(isnitf_meta, fields, fid); - TMRLNTH = isnitf_meta(end).value; - - fields = {'TPXCDLNTH', 'TransparentOutputPixelCodeLength', 1, 'uint16'}; - isnitf_meta = nitfReadMetaNumeric(isnitf_meta, fields, fid); - TPXCDLNTH = isnitf_meta(end).value; - - dataMaskTableLength = dataMaskTableLength + 4 + 2 + 2 + 2; - - if (TPXCDLNTH ~= 0) - - if (TPXCDLNTH <= 8) - fmt = 'uint8'; - dataMaskTableLength = dataMaskTableLength + 1; - else - fmt = 'uint16'; - dataMaskTableLength = dataMaskTableLength + 2; - end - - fields = {'TPXCD', 'PadOutputPixelCode', 1, fmt}; - isnitf_meta = nitfReadMetaNumeric(isnitf_meta, fields, fid); - - end - - numBlocks = NBPR * NBPC * max(bands, nbands); - - if (BMRLNTH ~= 0) - fields = {'BMRnBNDm', 'BlockNBandMOffset', numBlocks, 'uint32'}; - isnitf_meta = nitfReadMetaNumeric(isnitf_meta, fields, fid); - dataMaskTableLength = dataMaskTableLength + 4 * numBlocks; - end - - if (TMRLNTH ~= 0) - fields = {'TMRnBNDm', 'PadPixelNBandMOffset', numBlocks, 'uint32'}; - isnitf_meta = nitfReadMetaNumeric(isnitf_meta, fields, fid); - dataMaskTableLength = dataMaskTableLength + 4 * numBlocks; - end - -end - -%Move the cursor through the image data -readforwardbytes = sscanf(dataLength, '%f') - dataMaskTableLength; -fseek(fid, readforwardbytes, 'cof'); - - - -function isnitf_meta = checkIcords(icords, fid, isnitf_meta) -if ~strcmp(icords, '') - - fields = {'IGEOLO', 'ImageGeographicLocation', 60}; - isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -end - - - -function isnitf_meta = checkNicom(nicom, fid, isnitf_meta) - -% Parse the Image Comment fields in the image subheader -% The length of the ICOM field is 80. -for currentComment = 1:nicom - - %Pull the Image Comment - fields = {'ICOM%1d', 'ImageComment%1d', 80}; - isnitf_meta = nitfReadMetaMulti(isnitf_meta, fields, fid, currentComment); - -end - - - -function tf = hasDataMaskTable(IC) - -switch (IC) -case {'NM', 'M1', 'M3', 'M4', 'M5'} - tf = true; -otherwise - tf = false; -end diff --git a/CT/private/parseimagesubheader20.m b/CT/private/parseimagesubheader20.m deleted file mode 100644 index 31bb476..0000000 --- a/CT/private/parseimagesubheader20.m +++ /dev/null @@ -1,214 +0,0 @@ -function isnitf_meta = parseimagesubheader20( fid, dataLength ) -%PARSEIMAGESUBHEADER Parse the Image subheaders in an NITF file. -% ISNITF_META = PARSEIMAGESUBHEADER -% Parse the Image Segment Subheader for an NITF 2.0 file. - -% Copyright 2007-2008 The MathWorks, Inc. - -% TODO: complete refactorization around conditionals - -% Initialize the image subheader structure -isnitf_meta = struct([]); -fields = {'IM', 'FilePartType', 2 - 'IID', 'ImageID', 10 - 'IDATIM', 'ImageDateAndTime', 14 - 'TGTID', 'TargetID', 17 - 'ITITLE', 'ImageTitle', 80 - 'ISCLAS', 'ImageSecurityClassification', 1 - 'ISCODE', 'ImageCodewords', 40 - 'ISCTLH', 'ImageControlAndHandling', 40 - 'ISREL', 'ImageReleasingInstructions', 40 - 'ISCAUT', 'ImageClassificationAuthority', 20 - 'ISCTLN', 'ImageSecurityControlNumber', 20 - 'ISDWNG', 'ImageSecurityDowngrade', 6}; -isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -%ISDWNG is the last item extracted in the loop above. Depending -%on its value there will be an ISDEVT or Image Downgrading Event field. -%If ISDWNG is "999998, add the ISDEVT field to the meta data struct -%and insert values. -isdwng = sscanf(isnitf_meta(end).value, '%f'); - -%File downgrade event is conditional on fsdwng -isnitf_meta = checkISDWNG(fid, isnitf_meta, isdwng); - -fields = {'ENCRYP', 'Encryption', 1 - 'ISORCE', 'ImageSource', 42 - 'NROWS', 'NumberOfSignificantRowsInImage', 8 - 'NCOLS', 'NumberOfSignificantColumnsInImage', 8 - 'PVTYPE', 'PixelValueType', 3 - 'IREP', 'ImageRepresentation', 8 - 'ICAT', 'ImageCategory', 8 - 'ABPP', 'ActualBitsPerPixelPerBand', 2 - 'PJUST', 'PixelJustification', 1 - 'ICORDS', 'ImageCoordinateSystem', 1}; -isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -%ICORDS Depending on its value there will be an IGEOLO or Image Geographic Location field. -%If ICORDS is not a space, add the IGEOLO field to the meta data struct -%and insert values. -icords = isnitf_meta(end).value; -isnitf_meta = checkIcords(icords, fid, isnitf_meta); - -%NICOM -%Depending on its value there will be ICOM fields (ICOM1 through ICOMn). -%If NICOM is not zero, add the comment fields to the meta data struct -%and insert their values. - -fields = {'NICOM', 'NumberOfImageComments', 1}; -isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -nicom = sscanf(isnitf_meta(end).value, '%f'); -isnitf_meta = checkNicom(nicom, fid, isnitf_meta); - -%Next field is Image Compression -fields = {'IC', 'ImageCompression', 2}; -isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -%Next field is COMRAT or Compression Rate Code -%If the IC field is not NC or NM the field will have a value. -ic = isnitf_meta(end).value; -if ~strcmp(ic, 'NC') && ~strcmp(ic, 'NM') - fields = {'COMRAT', 'CompressionRateCode', 4}; - isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); -end - -fields = {'NBANDS', 'NumberOfBands', 1}; -isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -bands = sscanf(isnitf_meta(end).value, '%f'); - -%Set up Band substructure - -isnitf_meta(end + 1).name = 'Band Meta'; -isnitf_meta(end).vname = 'BandMeta'; -%The value will be a structure of band data - -%The next seven fields occur for each band as indicated by BANDS -% Lengths: -% IREPBAND 2, ISUBCAT 6, IFC 1, IMFLT 3, NLUTS 1, NELUT 5 [omitted if NLUTS = 0] -% LUTD contains data for the mth LUT of the nnth band - -nitf_metaBand(bands).value = ''; - -for currentBand = 1: bands - - isBandnitf_meta = struct([]); - - nitf_metaBand(currentBand).name = sprintf('Band%03d', currentBand); - nitf_metaBand(currentBand).vname = [nitf_metaBand(currentBand).name 'Meta']; - nitf_metaBand(currentBand).value = ''; - - fields = {'IREPBAND%02d', 'BandRepresentation%02d', 2 - 'ISUBCAT%02d', 'BandSubcategory%02d', 6 - 'IFC%02d', 'BandImageFilterCondition%02d', 1 - 'IMFLT%02d', 'BandImageFilterCode%02d', 3 - 'NLUTS%02d', 'BandNumberOfLUTS%02d', 1}; - - isBandnitf_meta = nitfReadMetaMulti(isBandnitf_meta, fields, fid, currentBand); - numluts = sscanf(isBandnitf_meta(end).value, '%f'); - - if numluts ~= 0 - %nnth Band Number of LUT Entries - - fields = {'NELUT%02d', 'BandNumberOfLUTEntries%02d', 5}; - isBandnitf_meta = nitfReadMetaMulti(isBandnitf_meta, fields, fid, currentBand); - - numlutentries = sscanf(isBandnitf_meta(end).value', '%f'); - - %The value will be a struct of LUT data - for currentLut = 1 : numluts - isBandnitf_meta(end + 1).name = sprintf('LUTData%1d', currentLut); - isBandnitf_meta(end).vname = sprintf('LUTData%1d', currentLut); - % Note: not converted to char. - isBandnitf_meta(end).value = fread(fid, numlutentries, 'uint8'); - end - end - - nitf_metaBand(currentBand).value = isBandnitf_meta; - -end -isnitf_meta(end).value = nitf_metaBand; - - -fields = {'ISYNC', 'ImageSyncCode', 1 - 'IMODE', 'ImageMode' 1 - 'NBPR', 'NumberOfBlocksPerRow', 4 - 'NBPC', 'NumberOfBlocksPerColumn', 4 - 'NPPBH', 'NumberOfPixelsPerBlockHorizontal', 4 - 'NPPBV', 'NumberOfPixelsPerBlockVertical', 4 - 'NBPP', 'NumberOfBitsPerPixelPerBand', 2 - 'IDLVL', 'DisplayLevel', 3 - 'IALVL', 'ImageAttachmentLevel', 3 - 'ILOC', 'ImageLocation', 10 - 'IMAG', 'ImageMagnification', 4}; -isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -% The IMAG value should be converted to a number from the decimal string. -isnitf_meta(end).value = sscanf(isnitf_meta(end).value, '%f'); - -fields = {'UDIDL', 'UserDefinedImageDataLength', 5}; -isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -%If UDIDL is not zeros we'll have values for UDOFL and UDID -UDIDL = sscanf(isnitf_meta(end).value, '%f'); -if UDIDL ~= 0 - - fields = {'UDOFL', 'UserDefinedOverflow', 3 - 'UDID', 'UserDefinedImageData', UDIDL - 3}; - isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -end - -fields = {'IXSHDL', 'ExtendedSubheaderDataLength', 5}; -isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -%If IXSHDL is not zeros we'll have values for IXSOFL and IXSHD -IXSHDL = sscanf(isnitf_meta(end).value, '%f'); -if IXSHDL ~= 0 - - fields = {'IXOFL', 'ExtendedSubheaderOverflow', 3 - 'IXSHD', 'ExtendedSubheaderData', IXSHDL - 3}; - isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -end - -%Move the cursor through the image data -readforwardbytes = sscanf(dataLength, '%f'); -fseek(fid, readforwardbytes, 'cof'); - - - -function isnitf_meta = checkISDWNG(fid, isnitf_meta, fsdwng) - -if fsdwng == 999998 - - fields = {'ISDEVT', 'ImageDowngradingEvent', 40}; - isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -end - - - -function isnitf_meta = checkIcords(icords, fid, isnitf_meta) - -if ~strcmp(icords, 'N') - - fields = {'IGEOLO', 'ImageGeographicLocation', 60}; - isnitf_meta = nitfReadMeta(isnitf_meta, fields, fid); - -end - - - -function isnitf_meta = checkNicom(nicom, fid, isnitf_meta) - -% Parse the Image Comment fields in the image subheader -% The length of the ICOM field is 80. -for currentComment = 1:nicom - - %Pull the Image Comment - fields = {'ICOM%1d', 'ImageComment%1d', 80}; - isnitf_meta = nitfReadMetaMulti(isnitf_meta, fields, fid, currentComment); - -end diff --git a/CT/private/parselabelsubheader20.m b/CT/private/parselabelsubheader20.m deleted file mode 100644 index 8160301..0000000 --- a/CT/private/parselabelsubheader20.m +++ /dev/null @@ -1,50 +0,0 @@ -function lsnitf_meta = parselabelsubheader20( fid, dataLength ) -%PARSELABELSUBHEADER20 Parse the Label subheaders in an NITF file. -% LSNITF_META = PARSELABELSUBHEADER20 -% Parse the Label Segment Subheader for an NITF 2.0 file. - -% Copyright 2007-2008 The MathWorks, Inc. - -lsnitf_meta = struct([]); -fields = {'LA', 'FilePartType', 2 - 'LID', 'LabelID', 10 - 'LSCLAS', 'LabelSecurityClassification', 1 - 'LSCODE', 'LabelCodewords', 40 - 'LSCTLH', 'LabelControlAndHandling', 40 - 'LSREL', 'LabelReleasingInstructions', 40 - 'LSCAUT', 'LabelClassificationAuthority', 20 - 'LSCTLN', 'LabelSecurityControlNumber', 20 - 'LSDWNG', 'LabelSecurityDowngrade', 6}; -lsnitf_meta = nitfReadMeta(lsnitf_meta, fields, fid); - -%LSDWNG is LSnitf_meta(9) and the last item extracted in the loop above. Depending -%on its value there will be an SSDEVT -lsdwng = sscanf(lsnitf_meta(end).value, '%f'); -if lsdwng == 999998 - fields = {'LSDEVT', 'LabelDowngradingEvent', 40}; - lsnitf_meta = nitfReadMeta(lsnitf_meta, fields, fid); -end - -fields = {'ENCRYP', 'Encryption', 1 - 'LFS', 'LabelFontStyle', 1 - 'LCW', 'LabelCellWidth', 2 - 'LCH', 'LabelCellHeight', 2 - 'LDLVL', 'DisplayLevel', 3 - 'LALVL', 'LabelAttachmentLevel', 3 - 'LLOC', 'LabelLocation', 10 - 'LTC', 'LabelTextColor', 3 - 'LBC', 'LabelBackgroundColor', 3 - 'LXSHDL', 'ExtendedSubheaderDataLength', 5}; -lsnitf_meta = nitfReadMeta(lsnitf_meta, fields, fid); - -%LXSOFL and LCSHD -lxshdl = sscanf(lsnitf_meta(end).value, '%f'); -if lxshdl ~= 0 - fields = {'LXSOFL', 'ExtendedSubheaderOverflow', 3 - 'LXSHD', 'ExtendedSubheaderData', lxshdl - 3}; - lsnitf_meta = nitfReadMeta(lsnitf_meta, fields, fid); -end - -%Move the cursor through the Label data -readforwardbytes = sscanf(dataLength, '%f'); -fread(fid, readforwardbytes, 'uint8=>char'); diff --git a/CT/private/parsetextsubheader.m b/CT/private/parsetextsubheader.m deleted file mode 100644 index 2fd27d9..0000000 --- a/CT/private/parsetextsubheader.m +++ /dev/null @@ -1,48 +0,0 @@ -function tsnitf_meta = parsetextsubheader( fid, dataLength ) -%PARSETEXTSUBHEADER Parse the Text subheaders in an NITF file. -% TSNITF_META = PARSETEXTSUBHEADER -% Parse the Text Segment Subheader for an NITF 2.1 file. - -% Copyright 2007-2008 The MathWorks, Inc. - -tsnitf_meta = struct([]); -fields = {'TE', 'FilePartType', 2 - 'TEXTID', 'TextID', 7 - 'TXTALVAL', 'TextAttachmentLevel', 3 - 'TXTDT', 'TextDateAndTime', 14 - 'TXTITL', 'TextTitle', 80 - 'TSCLAS', 'TextSecurityClassification', 1 - 'TSCLSY', 'TextSecurityClassificationSystem', 2 - 'TSCODE', 'TextCodewords', 11 - 'TSCTLH', 'TextControlAndHandling', 2 - 'TSREL', 'TextReleasingInstructions', 20 - 'TSDCTP', 'TextDeclassificationType', 2 - 'TSDCDT', 'TextDeclassificationDate', 8 - 'TSDCXM', 'TextDeclassificationExemption', 4 - 'TSDG', 'TextDowngrade', 1 - 'TSDGT', 'TextDowngradeDate', 8 - 'TSCLTX', 'TextClassificationText', 43 - 'TSCATP', 'TextClassificationAuthorityType', 1 - 'TSCAUT', 'TextClassificationAuthority', 40 - 'TSCRSN', 'TextClassificationReason', 1 - 'TSSRDT', 'TextSecuritySourceDate', 8 - 'TSCTLN', 'TextSecurityControlNumber', 15 - 'ENCRYP', 'Encryption', 1 - 'TXTFMT', 'TextFormat', 3 - 'TXSHDL', 'ExtendedSubheaderDataLength', 5}; -tsnitf_meta = nitfReadMeta(tsnitf_meta, fields, fid); - -%TXSHDL is TSMETA_INFO(24) and the last item extracted in the loop above. Depending -%on its value there will be an TXSOFL or Extended Subheader Overflow field and TXSHD field. -%If TXSHDL is not zeros, add the TXSOFL and TXSHD fields to the meta data struct -%and insert values. -txshdl = sscanf(tsnitf_meta(24).value, '%f'); -if txshdl ~= 0 - fields = {'TXSOFL', 'ExtendedSubheaderOverflow', 3 - 'TXSHD', 'ExtendedSubheaderData', txshdl - 3}; - tsnitf_meta = nitfReadMeta(tsnitf_meta, fields, fid); -end - -%Move the cursor through the Text data -readforwardbytes = sscanf(dataLength, '%f'); -fread(fid, readforwardbytes, 'uint8=>char'); diff --git a/CT/private/parsetextsubheader20.m b/CT/private/parsetextsubheader20.m deleted file mode 100644 index d7e98b4..0000000 --- a/CT/private/parsetextsubheader20.m +++ /dev/null @@ -1,45 +0,0 @@ -function tsnitf_meta = parsetextsubheader20( fid, dataLength ) -%PARSETEXTSUBHEADER20 Parse the Text subheaders in an NITF file. -% TSNITF_META = PARSETEXTSUBHEADER20 -% Parse the Text Segment Subheader for an NITF 2.0 file. - -% Copyright 2007-2008 The MathWorks, Inc. - -tsnitf_meta = struct([]); -fields = {'TE', 'FilePartType', 2 - 'TEXTID', 'TextID', 10 - 'TXTDT', 'TextDateAndTime', 14 - 'TXTITL', 'TextTitle', 80 - 'TSCLAS', 'TextSecurityClassification', 1 - 'TSCODE', 'TextCodewords', 40 - 'TSCTLH', 'TextControlAndHandling', 40 - 'TSREL', 'TextReleasingInstructions', 40 - 'TSCAUT', 'TextClassificationAuthority', 20 - 'TSCTLN', 'TextSecurityControlNumber', 20 - 'TSDWNG', 'TextSecurityDowngrade', 6}; -tsnitf_meta = nitfReadMeta(tsnitf_meta, fields, fid); - -%TSDWNG is TSNITF_META(11) and the last item extracted in the loop above. Depending -%on its value there will be an TSDEVT -tsdwng = sscanf(tsnitf_meta(end).value, '%f'); -if tsdwng == 999998 - fields = {'TSDEVT', 'TextDowngradingEvent', 40}; - tsnitf_meta = nitfReadMeta(tsnitf_meta, fields, fid); -end - -%ENCRYP -fields = {'ENCRYP', 'Encryption', 1 - 'TXTFMT', 'TextFormat', 3 - 'TXSHDL', 'ExtendedSubheaderDataLength', 5}; -tsnitf_meta = nitfReadMeta(tsnitf_meta, fields, fid); - -txshdl = sscanf(tsnitf_meta(end).value, '%f'); -if txshdl ~= 0 - fields = {'TXSOFL', 'ExtendedSubheaderOverflow', 3 - 'TXSHD', 'ExtendedSubheaderData', txshdl - 3}; - tsnitf_meta = nitfReadMeta(tsnitf_meta, fields, fid); -end - -%Move the cursor through the Text data -readforwardbytes = sscanf(dataLength, '%f'); -fread(fid, readforwardbytes, 'uint8=>char'); diff --git a/CT/private/rgb2rgbe.m b/CT/private/rgb2rgbe.m deleted file mode 100644 index 40c03cf..0000000 --- a/CT/private/rgb2rgbe.m +++ /dev/null @@ -1,22 +0,0 @@ -function rgbe = rgb2rgbe(rgb) -%rgb2rgbe Convert RGB HDR pixels to 8-bit RGBE components. -% RGBE = RGB2RGBE(RGB) converts an arry of floating-point, high dynamic -% range (R,G,B) values to an encoded UINT8 array of (R,G,B,E) values. -% -% Reference: Ward, "Real Pixels" (pp. 80-83) in Arvo "Graphics Gems II," 1991. - -% Copyright 2007-2013 The MathWorks, Inc. - -% Reshape the m-by-n-by-3 RGB array into a m*n-by-3 array and find the -% maximum value of each RGB triple. -rgb = reshape(rgb, numel(rgb)/3, 3); - -maxRGB = max(rgb,[],2); -[f,e] = log2(maxRGB); -tmp = f*256./maxRGB; % Reusing maxRGB causes NaN values. -rgbm = bsxfun(@times,rgb,tmp); -rgbe = uint8([rgbm, e+128]); - -% Pixels where max(rgb) < 1e-38 must become (0,0,0,0). -mask = find(maxRGB < 1e-38); -rgbe(mask, :) = repmat([0 0 0 0], [numel(mask), 1]); diff --git a/CT/private/rgbe2rgb.m b/CT/private/rgbe2rgb.m deleted file mode 100644 index f7bcc58..0000000 --- a/CT/private/rgbe2rgb.m +++ /dev/null @@ -1,23 +0,0 @@ -function rgb = rgbe2rgb(rgbe) -%rgbe2rgb Convert RGBE values to floating-point RGB. -% RGB = RGBE2RGB(RGBE) converts an arry of (R,G,B,E) encoded values to -% an array of floating-point (R,G,B) high dynamic range values. -% -% Reference: Ward, "Real Pixels" (pp. 80-83) in Arvo "Graphics Gems II," 1991. - -% Copyright 2007-2013 The MathWorks, Inc. - -dims = size(rgbe); - -% Separate the 1-D scanline into separate columns of (R,G,B,E) values. -rgbe = reshape(rgbe, dims(1), 4); - -rgb = bsxfun(@times, single(rgbe(:, 1:3)) ./ 256, ... - 2.^(single(rgbe(:,4)) - 128)); - -% Esnure that (0,0,0,0) maps to (0,0,0). -mask = max(rgbe, [], 2) == 0; -rgb(mask,:) = 0; - -% Separate into color planes suitable for storage. -rgb = reshape(rgb, [dims(1), 1, 3]); diff --git a/CT/private/rleCoder.m b/CT/private/rleCoder.m deleted file mode 100644 index d98c8dd..0000000 --- a/CT/private/rleCoder.m +++ /dev/null @@ -1,14 +0,0 @@ -function scanline = rleCoder(data, dataLength) -%rleCoder Compress data using HDR adaptive run-length encoding. - -% Unlike the description in Graphics Gems II.8 (p.89), code values greater -% than 128 correspond to repeated runs, while smaller code values are -% literal dumps. See the following web site for more details: -% . -% The adaptive RLE used by HDR also does not shift code values by one. -% There can be only 127 elements in a run. - -scanline = rleCoder_mex(uint8(data), dataLength); - -% Crop the scanline to exclude the unused buffer. -scanline(isnan(scanline)) = []; \ No newline at end of file diff --git a/CT/private/rleCoder_mex.mexw64 b/CT/private/rleCoder_mex.mexw64 deleted file mode 100644 index d4a7334..0000000 Binary files a/CT/private/rleCoder_mex.mexw64 and /dev/null differ diff --git a/CT/private/rleDecoder.m b/CT/private/rleDecoder.m deleted file mode 100644 index 931f1f2..0000000 --- a/CT/private/rleDecoder.m +++ /dev/null @@ -1,74 +0,0 @@ -function [decodedData, decodedBytes] = rleDecoder(encodedData, ... - scanlineWidth) -%rleDecoder Decompress data using HDR adaptive run-length encoding. -% [decodedData, decodedBytes] = rleCoder(encodedData, scanlineWidth) -% decompresses the RLE-compressed values in encodedData and places the -% result in decodedData. At most scanlineWidth values are decoded, -% and decodedBytes contains the number of values in encodedData that -% were used during decompression. - -% Copyright 2007-2013 The MathWorks, Inc. - -% Unlike the description in Graphics Gems II.8 (p.89), code values greater -% than 128 correspond to repeated runs, while smaller code values are -% literal dumps. See the following web site for more details: -% . -% The adaptive RLE used by HDR also does not shift code values by one. - -if (isempty(encodedData) || (scanlineWidth == 0)) - decodedData = []; - decodedBytes = 0; - return -end - -% Create a temporary buffer for the decoded data. -decodedData = zeros(1, scanlineWidth, class(encodedData)); - -% Loop over the compressed data until this part of the scanline is full. -inputPtr = 1; -outputPtr = 1; -while (outputPtr <= scanlineWidth) - if (encodedData(inputPtr) > 128) - - % A run of the same value. - runLength = double(encodedData(inputPtr)) - 128; - - if ((runLength - 1) > (scanlineWidth - outputPtr)) - - warning(message('images:rleDecoder:badRunLength')); - - end - - decodedData(outputPtr:(outputPtr + runLength - 1)) = ... - encodedData(inputPtr + 1); - - inputPtr = inputPtr + 2; - outputPtr = outputPtr + runLength; - - else - - % A run of literal data. - runLength = double(encodedData(inputPtr)); - inputPtr = inputPtr + 1; - - if ((runLength == 0) || ... - ((runLength - 1) > (scanlineWidth - outputPtr))) - - warning(message('images:rleDecoder:badRunLength')); - - end - - if ((inputPtr + runLength - 1) > numel(encodedData)) - error(message('images:rleDecoder:notEnoughEncodedData')) - end - - decodedData(outputPtr:(outputPtr + runLength - 1)) = ... - encodedData(inputPtr:(inputPtr + runLength - 1)); - - inputPtr = inputPtr + runLength; - outputPtr = outputPtr + runLength; - - end -end - -decodedBytes = inputPtr - 1; diff --git a/CT/private/rnitfc.mexw64 b/CT/private/rnitfc.mexw64 deleted file mode 100644 index 0bef42e..0000000 Binary files a/CT/private/rnitfc.mexw64 and /dev/null differ diff --git a/CT/private/tobits.mexw64 b/CT/private/tobits.mexw64 deleted file mode 100644 index 95ae626..0000000 Binary files a/CT/private/tobits.mexw64 and /dev/null differ diff --git a/CT/private/tokenize.m b/CT/private/tokenize.m deleted file mode 100644 index 33babf4..0000000 --- a/CT/private/tokenize.m +++ /dev/null @@ -1,22 +0,0 @@ -function tokens = tokenize( input_string, delimiters ) -%TOKENIZE Divide a string into tokens. -% TOKENS = TOKENIZE(STRING, DELIMITERS) divides STRING into tokens -% using the characters in the string DELIMITERS. The result is stored -% in a single-column cell array of strings. -% -% Examples: -% -% tokenize('The quick fox jumped',' ') returns {'The'; 'quick'; 'fox'; 'jumped'}. -% -% tokenize('Ann, Barry, Charlie',' ,') returns {'Ann'; 'Barry'; 'Charlie'}. -% -% tokenize('George E. Forsyth,Michael A. Malcolm,Cleve B. Moler',',') returns -% {'George E. Forsyth'; 'Michael A. Malcolm'; 'Cleve B. Moler'} - -% Copyright 1993-2005 The MathWorks, Inc. - -if (~isempty(input_string)) - tokens = strread(input_string,'%s',-1,'delimiter',delimiters); -else - tokens = {}; -end diff --git a/LBODicomViewer.fig b/LBODicomViewer.fig deleted file mode 100644 index 300ce53..0000000 Binary files a/LBODicomViewer.fig and /dev/null differ diff --git a/LBODicomViewer.m b/LBODicomViewer.m deleted file mode 100644 index 0fd01d4..0000000 --- a/LBODicomViewer.m +++ /dev/null @@ -1,104 +0,0 @@ -function varargout = LBODicomViewer(varargin) -% LBODICOMVIEWER MATLAB code for LBODicomViewer.fig -% LBODICOMVIEWER, by itself, creates a new LBODICOMVIEWER or raises the existing -% singleton*. -% -% H = LBODICOMVIEWER returns the handle to a new LBODICOMVIEWER or the handle to -% the existing singleton*. -% -% LBODICOMVIEWER('CALLBACK',hObject,eventData,handles,...) calls the local -% function named CALLBACK in LBODICOMVIEWER.M with the given input arguments. -% -% LBODICOMVIEWER('Property','Value',...) creates a new LBODICOMVIEWER or raises the -% existing singleton*. Starting from the left, property value pairs are -% applied to the GUI before LBODicomViewer_OpeningFcn gets called. An -% unrecognized property name or invalid value makes property application -% stop. All inputs are passed to LBODicomViewer_OpeningFcn via varargin. -% -% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one -% instance to run (singleton)". -% -% See also: GUIDE, GUIDATA, GUIHANDLES - -% Edit the above text to modify the response to help LBODicomViewer - -% Last Modified by GUIDE v2.5 26-Mar-2018 14:01:57 - -% Begin initialization code - DO NOT EDIT -gui_Singleton = 1; -gui_State = struct('gui_Name', mfilename, ... - 'gui_Singleton', gui_Singleton, ... - 'gui_OpeningFcn', @LBODicomViewer_OpeningFcn, ... - 'gui_OutputFcn', @LBODicomViewer_OutputFcn, ... - 'gui_LayoutFcn', [] , ... - 'gui_Callback', []); -if nargin && ischar(varargin{1}) - gui_State.gui_Callback = str2func(varargin{1}); -end - -if nargout - [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); -else - gui_mainfcn(gui_State, varargin{:}); -end -% End initialization code - DO NOT EDIT - - -% --- Executes just before LBODicomViewer is made visible. -function LBODicomViewer_OpeningFcn(hObject, eventdata, handles, varargin) -% This function has no output args, see OutputFcn. -% hObject handle to figure -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) -% varargin command line arguments to LBODicomViewer (see VARARGIN) - -% Choose default command line output for LBODicomViewer -handles.output = hObject; - -% Update handles structure -guidata(hObject, handles); - -% UIWAIT makes LBODicomViewer wait for user response (see UIRESUME) -% uiwait(handles.figure1); - - -% --- Outputs from this function are returned to the command line. -function varargout = LBODicomViewer_OutputFcn(hObject, eventdata, handles) -% varargout cell array for returning output args (see VARARGOUT); -% hObject handle to figure -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - -% Get default command line output from handles structure -varargout{1} = handles.output; - - -% --- Executes on button press in sourceFolder. -function sourceFolder_Callback(hObject, eventdata, handles) -% hObject handle to sourceFolder (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - "Button 'load' pushed" - sourceF = uigetdir('C:\') - [V,spatial,dim] = dicomreadVolume(sourceF); - v=squeeze(V); - volumeViewer(v) - - - -% --- Executes on button press in outputFolder. -function outputFolder_Callback(hObject, eventdata, handles) -% hObject handle to outputFolder (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - "Button 'Select Output directory' pushed" - outputF = uigetdir('C:\') - - -% --- Executes on button press in copy. -function copy_Callback(hObject, eventdata, handles) -% hObject handle to copy (see GCBO) -% eventdata reserved - to be defined in a future version of MATLAB -% handles structure with handles and user data (see GUIDATA) - get(handles.outputFolder) - diff --git a/README.md b/README.md index eb2dcc8..95806ac 100755 --- a/README.md +++ b/README.md @@ -1,127 +1,118 @@ # Shoulder Database handling and measurements ## Introduction This repository contains Matlab codes to import anonymised clinical cases in a shoulder database (shoulderDB), and update this database with complementary clinical, radiological, morphological, or biomechanical data. This project is a collaboration between Laboratory of Biomechanical Orthopedics of the Ecole Polytechnique Federal de Lausanne (EPFL-LBO), the Orthopedic Service of the University Hospital of Lausanne (CHUV-OTR), and the Radiological Department of the University Hospital of Lausanne (CHUV-RAD). ## Setup ### Download Clone or download [this repository](https://c4science.ch/diffusion/8218/). Open MATLAB, set the working directory to be the downladed repository and add its folders and subfolders to the MATLAB path. To do the latter part, once the working directory has been set you can run the following command: addapth(genpath(pwd)); ### Write the config file The base folder must contain a "config.txt" with the following fields: * maxSCaseIDDigits: This is the maximum allowed number of digits in the SCase IDs. With maxSCaseIDDigits = 3, 'P123' is a valid ID, 'P1234' is not valid. * SCaseIDValidTypes: These are the allowed letters used as a prefix in the SCase IDs. With SCaseIDValidTypes = 'NP', 'P123' is a valid ID, 'Z1234' is not valid. * pythonDir: This is the path to the rotator cuff segmentation system. * dataDir: This is the root path to the data used i.e. /shoulder/dataDev or /shoulder/data on lbovenus.epfl.ch A full config.txt example for a system working on lbovenus.epfl.ch contains the four following lines: maxSCaseIDDigits = 3 SCaseIDValidTypes = 'NP' pythonDir = '/shoulder/methods/python/rcseg' dataDir = '/shoulder/dataDev' ## How to use There are four main main features within this system. ### Access data The data related to a specific case can be accessed thanks to the ShoulderCaseLoader class. For example: database = ShoulderCaseLoader(); SCase = database.loadCase('P527'); Will load the data related to the case 'P527' into the variable SCase. The ShoulderCaseLoader class features many other methods to access the data. To get the list of all the available cases run: database = ShoulderCaseLoader(); SCaseList = database.getAllCasesIDs(); To load all the available cases in an cell array run: database = ShoulderCaseLoader(); AllTheSCases = database.loadAllCases(); ### Visualize data All the measured data are directly available in a loaded ShoulderCase's properties. To observe a cases's geometrical data in a 3D plot run: SCase.plot(); SCase.plot('auto'); Add the argument 'auto' to see the automatically measured data. Another way to create the same visualisations is: SCase.shoulderManual.plot(); SCase.shoulderAuto.plot(); To observe the results of the rotator cuff muscles' segmentation run: SCase.shoulderManual.muscles.plot(); SCase.shoulderAuto.muscles.plot(); ### Update data To update the measured values of the shoulder cases use the function measureSCase(). Refer to the function's documentation for further informations. ### Import new data To import new cases (basically add a CT-files folder at the right place) use the importSCase GUI. The importSCase code is located in the sub-directory importSCase. Its description is detailed there. It currently only work for Windows. ## Documentation Should be added here: * datastructure design * class diagram ## Files/Folders ### Folders - **./anatomy** contains scripts used by Amira manual measurements and what looks like deprecated scripts that are now part of the Scapula class. -- **./CT** contains what look like a bunch of dicom-related MATLAB functions and one LBO-made script (infoCT.m). Removable according to former README. - **./ShoulderCase** contains the class and scripts used to update and access to the data. See here [how are organized class files and folders](https://ch.mathworks.com/help/matlab/matlab_oop/class-files-and-folders.html). - **./ImportSCase** contains the GUI used to import new data into the database. - **./Generated_Amira_TCL_Scripts** used to store TCL scripts. Not tracked by git. - **./log** contains log files. -- **./muscles** contains muscle related scripts. Probably removable since the creation of muscle related classes in **./ShoulderCase**. - **./XLS_MySQL_DB** contains scripts used to read data in .xls files and write in SQL database. - **./upsert** contains a script to update and insert data in a database. Looks like it's an external not LBO-made feature. ### Files - *config.txt* is mandatory. - *csv2xlxSCase.m* Matlab script to transform CSV files into XLS files - *dicominfoSCase.m* Matlab script used after new SCase importations. Check utility in ImportSCase SOP -- *LBODicomViewer.fig* Probably removable -- *LBODicomViewer.m* Probably removable. - *listSCase.m* Matlab script that create a list of SCases. Deprecated, should be replaced by ShoulderCaseLoader methods everywhere. -- *listSCase_before20190211.m* version of *listSCase.m* previous to 2019.02.11. Removable. - *loadDicomCTscan* Looks like a worksheet. Probably removable. - *measureSCase.m* Matlab Script used to update data. (check SOP for more details) - *openConfigFile.m* Deprecated, should be replaced by the ConfigFileExtractor methods everywhere. -- *openConfigFile_before20190211* version of *openConfigFile.m* previous to 2019.02.11. Removable. - *openLogFile.m* Deprecated, should be replaced by the Logger methods everywhere. - *plotSCase.m* Deprecated, should be replaced by ShoulderCase.plot() method everywhere. -- *readDicomMetaData* very specific script. Removable. -- *README_importSCaseDev_fServer.md* Temp notes, removable -- *statSCase.m* Statistical analysis on all the cases. Probably deprecated. -- *tempInfo.mat* temporal file created by ImportSCase (removable) \ No newline at end of file +- *statSCase.m* Statistical analysis on all the cases. Probably deprecated. \ No newline at end of file diff --git a/README_importSCaseDev_fServer.md b/README_importSCaseDev_fServer.md deleted file mode 100644 index 77bbaac..0000000 --- a/README_importSCaseDev_fServer.md +++ /dev/null @@ -1,8 +0,0 @@ -# Description of imporsCaseDev_fServer - -## Global Variables - - **handles.baseDir** = *.../shoulder/data/* - - **handles.patient_dir** = this is the new patient directory that contains the set of CTs to be imported - - **handles.dicomdir** -> directory of the last set of CTs loaded - - **handles.dicomSet** -> - - **handles._3Dview** -> logic variable to allow or deactivate the 3D Viewer diff --git a/listSCase_before20190211.m b/listSCase_before20190211.m deleted file mode 100644 index f9bf487..0000000 --- a/listSCase_before20190211.m +++ /dev/null @@ -1,232 +0,0 @@ -function SCaseList = listSCase(varargin)%SCase_type,dataDir) -%LISTSCASE output list of sCases (id and path), accordind to inputList or -%filter arguments. - -% Each sCase directory should at least contain at -% directory with a name staring with 'CT' and ending with either -% '-1' : preop/shoulder/sharp/noPhantom -% '-2' : preop/shoulder/smooth/noPhantom -% '-3' : preop/shoulder/sharp/phantom -% '-4' : preop/shoulder/smooth/phantom -% and containing a 'dicom' subdirectory. The priority is '1', '2', '3', '4', -% unless there is a amira folder already present in one of these diretories. -% -% The optional input argument inputList if an array of SCaseID, or 'N' or -% 'P'. If empty, listSCase will search for all SCaseID. The optional -% input argument filter can restrict le list. - -% The fonction can be run from server (lbovenus) with -% cd /home/shoulder/methods/matlab/database; matlab -nojvm -nodisplay -nosplash -r "listSCase;quit" -% For 700 cases, it takes less than 60 seconds (when executed from server) - -% Progress can be be checked throuhth log file with following shell command -% cd /home/shoulder/methods/matlab/database;tail -f log/listSCase.log - -% Input: -% inputArg: can be nothing (=all), 'N', 'P', or SCase(s) -% -% Output: -% outputArg: 1 if ok and 0 otherwise -% -% Example: listSCase, listSCase('P'), listSCase('P001','P002') -% Other M-files required: None -% Subfunctions: None -% See also: Used by dicominfoSCase, measureSCase, -% -% Author: Alexandre Terrier -% EPFL-LBO -% Creation date: 2018-07-01 -% Revision date: 2018-12-30 -% -% TODO -% Two main looops might be merged in one, to avoid duplicagte post -% treatment - -%% Check input parameters - -dirL0Array = ''; -SCaseListIn = {}; - -if nargin == 0 - dirL0Array = ['N';'P']; % All SCase, default when no argument - fprintf(logFileID, '\nGet list of all SCase with a valid dicom folder'); -elseif nargin == 1 - if strcmp(varargin,'N') % All normal SCase - dirL0Array = 'N'; - fprintf(logFileID, '\nGet list of all normal SCase with a valid dicom folder'); - elseif strcmp(varargin,'P') % All pathological SCase - dirL0Array = 'P'; - fprintf(logFileID, '\nGet list of all pathological SCase with a valid dicom folder'); - else % A specific SCase - fprintf(logFileID, '\nGet list of a SCase with a valid dicom folder'); - SCaseListIn = varargin; - end -else % list of multiple SCase given in varargin - fprintf(logFileID, '\nGet list of a SCase with a valid dicom folder'); - SCaseListIn = varargin; -end - - -%% Open log file -logFileID = openLogFile('listSCase.log'); - -%% Set the data directory from the configuration file config.txt -dataDir = openConfigFile('config.txt', logFileID); - -%% Struct contains id and associated directory -SCaseList = struct(... - 'id' ,[],... - 'dir' ,[],... - 'comment' ,[]... % Might be used later - ); - - -%% Only one of the two loops below are performed -SCaseListIdx = 0; % Used in one of two loops below - -%% Loop over SCase (N, P, or both), if length(dirL0Array) > 1 -for dirL0idx = 1:length(dirL0Array) % N or P - for dirL1idx = 0:9 % Hunderts dir - for dirL2idx = 0:9 % Tens dir - dirL0Str = dirL0Array(dirL0idx); - dirL1Str = num2str(dirL1idx); - dirL2Str = num2str(dirL2idx); - dirTens = [dataDir '/' dirL0Str '/' dirL1Str '/' dirL2Str]; - dirTensList = dir(dirTens); % List all directories in tens dir - dirTensList = dirTensList(~ismember({dirTensList.name},{'.','..'})); % Remove . and .. - % We might add here a filter (only diretories, {N/P} followed - % by digits - for dirL3idx = 1:numel(dirTensList) - sCaseDirName = dirTensList(dirL3idx).name; % Root directory of this case - sCaseDirPath = dirTensList(dirL3idx).folder; - % Check if this SCaseID has a CT dir [CT?*-?] with a valid preoprative CT - SCaseID = strtok(sCaseDirName, '-'); % Get chars before '-' - CTdirList = dir([sCaseDirPath '/' sCaseDirName '/CT-*']); % List directories with CT - iCTdirAmira = 0; - iCTdir2use = 0; - for iCTdirList = length(CTdirList):-1:1 % Loop from last to first (4 to 1) - CTdir = CTdirList(iCTdirList); - % Check that dir name ends with -1,-2,-3,-4 - dirName = CTdir.name; - if strcmp(dirName(end-1),'-') % Exclude postoperative 'p' CT - CTnum = str2num(dirName(end)); - if CTnum <= 4 % Exlude non shoulder (elbow) CT - % Check that the dir contains a dicom dir - CTdir = [CTdir.folder '/' CTdir.name]; - dicomDir = [CTdir '/dicom']; - if exist(dicomDir, 'dir') - % Chech if amira dir exist - amiraDir = [CTdir '/amira']; - if exist(amiraDir, 'dir') - % This is the CT folder to use - iCTdirAmira = iCTdirList; - end - iCTdir2use = iCTdirList; - end - end - end - end - if iCTdir2use == 0 - fprintf(logFileID, ['\n', SCaseID, ' has no valid dicom directory']); - else - if iCTdirAmira % If amira dir exist, use it - iCTdir2use = iCTdirAmira; - end - CTdir = CTdirList(iCTdir2use); - SCaseListIdx = SCaseListIdx + 1; - SCaseList(SCaseListIdx).id = SCaseID; - CTdirPath = [CTdir.folder '/' CTdir.name]; - SCaseList(SCaseListIdx).dir = CTdirPath; - if CTnum ~= 1 - fprintf(logFileID, ['\n', SCaseID, ' dicom directory is CT-' num2str(CTnum)]); - end - end - end - end - end -end - -%% Loop over input SCase list (given as input argument), if length(SCaseListIn) > 0 -for iSCaseListIn = 1:length(SCaseListIn) - % Check if there is a valid dicom directory for this SCaseID - - SCaseID = char(SCaseListIn{iSCaseListIn}); - % Build directory from SCaseID (as in function ShoulderCase.path) - - % The validity of the format should be either Pnnn or Nnnn. - if (numel(regexp(SCaseID,'^[PN]\d{1,3}$')) == 0) - error(['Invalid format of SCaseID: ' SCaseID{1} '. CaseID must start with "P" or "N" and be followed by 1 to 3 digits.']); - end - - % Set the folder of the SCaseID - SCaseDirLevelPN = SCaseID(1); % Either 'P' or 'N' - strLengthSCaseID = strlength(SCaseID(2:end)); - if (strLengthSCaseID < 2) - SCaseDirLevel2 = '0'; % Hunderets - SCaseDirLevel1 = '0'; % Dozent - elseif (strLengthSCaseID < 3) - SCaseDirLevel2 = '0'; % Hunderets - SCaseDirLevel1 = SCaseID(2); % Dozent - else - SCaseDirLevel2 = SCaseID(2); % Hunderets - SCaseDirLevel1 = SCaseID(3); % Dozent - end - % Set SCaseID with fixed 3 digits after P/N (needed when id < - % 10 inloading of data in amira directory. - SCaseID4C = [SCaseDirLevelPN SCaseDirLevel2 SCaseDirLevel1 SCaseID(end)]; - - % Check if a (!unique! to be done) directory exists for this SCaseID - FindSCaseIDFolder = dir([dataDir '/' SCaseDirLevelPN '/' SCaseDirLevel2 '/' SCaseDirLevel1 '/' SCaseID '*']); - if (isempty(FindSCaseIDFolder)) % No directory for this SCaseID - error(['Missing directory for SCaseID: ' SCaseID]); - end - SCaseDirLevel0 = FindSCaseIDFolder.name; - SCaseDir = [dataDir '/' SCaseDirLevelPN '/' SCaseDirLevel2 '/' SCaseDirLevel1 '/' SCaseDirLevel0]; - - % Check if this SCaseID has a CT directory with a valid preoprative CT - CTdirList=dir([SCaseDir '/CT-*']); % List directories with CT - iCTdirAmira = 0; - iCTdir2use = 0; - for iCTdirList = length(CTdirList):-1:1 % Loop from last to first (4 to 1) - CTdir = CTdirList(iCTdirList); - % Check that dir name ends with -1,-2,-3,-4 - dirName = CTdir.name; - if strcmp(dirName(end-1),'-') % Exclude postoperative 'p' CT - CTnum = str2num(dirName(end)); - if CTnum <= 4 % Exlude non shoulder (elbow) CT - % Check that the dir contains a dicom dir - CTdir = [CTdir.folder '/' CTdir.name]; - dicomDir = [CTdir '/dicom']; - if exist(dicomDir, 'dir') - % Chech if amira dir exist - amiraDir = [CTdir '/amira']; - if exist(amiraDir, 'dir') - % This is the CT folder to use - iCTdirAmira = iCTdirList; - end - iCTdir2use = iCTdirList; - end - end - end - end - if iCTdir2use == 0 - fprintf(logFileID, ['\n', SCaseID, ' has no valid dicom directory']); - else - if iCTdirAmira % If amira dir exist, use it - iCTdir2use = iCTdirAmira; - end - CTdir = CTdirList(iCTdir2use); - SCaseListIdx = SCaseListIdx + 1; - SCaseList(SCaseListIdx).id = SCaseID; - CTdirPath = [CTdir.folder '/' CTdir.name]; - SCaseList(SCaseListIdx).dir = CTdirPath; - if CTnum ~= 1 - fprintf(logFileID, ['\n', SCaseID, ' dicom directory is CT-' num2str(CTnum)]); - end - end -end - -fprintf(logFileID, ['\nNumber of SCase: ' num2str(length(SCaseList))]); -fclose(logFileID); % Close log file -end - diff --git a/muscles/MuscleInfoListPatient.m b/muscles/MuscleInfoListPatient.m deleted file mode 100644 index a9ec509..0000000 --- a/muscles/MuscleInfoListPatient.m +++ /dev/null @@ -1,401 +0,0 @@ -% This script runs through the list of patients for which muscle % degeneration values were calculated (i.e. already put in Database) -% This script first creates a list of these patients and runs the script "muscleDegeneration" -% This script outputs a table where the values for each muscle is given in this way: -% Example for SS muscle: -% muscle.caseID = caseID; -% muscle.Stot %Stot: total area of the muscle fossa, manually delimited contours) -% muscle.Satrophy % Sa: area of the atrophy (Stot - Sm) -% muscle.Sinfiltration % Si: area of fat infiltration -% muscle.Sosteochondroma % So: area of osteochondroma -% muscle.Sdegeneration % Sm: area of the degenerated muscle, without atrophy, fat infiltration and osteochondroma -% muscle.atrophy % ratio of muscle atrophy (area atrophy over total area of muscle fossa) -% muscle.infiltration % ratio of fat infiltration in the muscle (area fat infiltration over total area of muscle fossa) -% muscle.osteochondroma % ratio of osteochondroma in the muscle (area osteochondroma over total area of muscle fossa) -% muscle.degeneration % the ratio of degeneration of the muscle -% are saved. For more details, check the function "muscleDegeneration" -% Important: Check location of your database!!! -% created with MATLAB ver.: 9.2.0.556344 (R2017a) on Windows 7 -% Author: K. Cosendey and Y. Boulanaache -% Date: 16-Oct-2017 - -HUThresholdMuscle = 0; -HUThresholdFat = 30; -HUThresholdOsteochondroma = 166; -listPatientNumber =[]; -listPathologic = []; -MatrixPCSA_SS = []; -MatrixPCSA_IS = []; -MatrixPCSA_SC = []; -MatrixPCSA_TM = []; - -AveragePCSA_SS=0; -AveragePCSA_IS=0; -AveragePCSA_SC=0; -AveragePCSA_TM=0; - -tabMuscle_SS=[]; -tabMuscle_IS=[]; -tabMuscle_SC=[]; -tabMuscle_TM=[]; - -% mainFolder = dir('../../../../'); -% %mainFolder = mainFolder(1).folder; %original -% -% XLSShoulderDatabaseLocation = [mainFolder '/methods/matlab/database/muscles/'];original -% %XLSShoulderDatabaseLocation = pwd; -% %output a column with only numbers in it -% -% CTDatabaseLocation = '../../../data'; % Location of the CT database -XLSShoulderDatabaseLocation = '../../../data/Excel/'; % Location of the XLS ShoulderDatabase - - -[~,~,raw] = xlsread([XLSShoulderDatabaseLocation '\ShoulderDataBase.xlsx'],2,'A:A'); -A= raw; % outputs all values, numbers and text - -%Now read out SS degeneration to check if this patient had a calculated degeneration of muscle or not -%If SS was calculated then the other muscles as well. -[~,~,raw] = xlsread([XLSShoulderDatabaseLocation '\ShoulderDataBase.xlsx'],2,'CD:CD'); -B = raw; %outputs all -%make a 2-columns matrix that has caseID and corresponding muscle values - -%Now create a list which contains only patients that have muscle values. -listCases = [A,B]; %for each non-number B value, we have corresponding value in column A. - -%Loop through -i=1; -while isnan(listCases{i,1}) == 0 - if isnumeric(listCases{i,2})==1 - listPathologic = [ listPathologic; listCases{i,1}(1)]; - listPatientNumber=[ listPatientNumber; str2num(listCases{i,1}(2:end))]; - - end - i=i+1; -end - -listPatient = cell(size(listPathologic,1),1); -listPatientCaseID = cell(size(listPathologic,1),1); - -for i=1:size(listPathologic,1) - if listPatientNumber(i) < 100 - if listPatientNumber(i)<10 - listPatient{i,1} = [listPathologic(i) '00' num2str(listPatientNumber(i))]; - else - listPatient{i,1} = [listPathologic(i) '0' num2str(listPatientNumber(i))]; - end - else - listPatient{i,1} = [listPathologic(i) num2str(listPatientNumber(i))]; - end - - listPatientCaseID{i,1} = [listPathologic(i) num2str(listPatientNumber(i))]; - -end -%FOR SUPRASPINATUS -muscleName = 'SS'; - - for i=1:size(listPatient,1) - - caseID = listPatientCaseID{i,1}; - caseID2 = listPatient{i,1}; - - %inputFile = [mainFolder 'data\' caseID2(1) '\' caseID2(2) '\' caseID2(3) '\' caseID '*']; - inputFile = ['Y:\data\' caseID2(1) '\' caseID2(2) '\' caseID2(3) '\' caseID '*']; - FindCaseCTFolder = dir(inputFile); - - CaseID_IPP = FindCaseCTFolder.name; -% CaseCTFolder = [mainFolder 'data\' caseID2(1) '\' caseID2(2) '\' caseID2(3) '\' CaseID_IPP '\CT-' CaseID_IPP '-1']; - CaseCTFolder = ['Y:\data\' caseID2(1) '\' caseID2(2) '\' caseID2(3) '\' CaseID_IPP '\CT-' CaseID_IPP '-1']; - - CaseMuscleFolder = [ CaseCTFolder '\muscles']; - %Launch script "muscleDegeneration.m" - muscle = muscleDegeneration (caseID, muscleName ,HUThresholdMuscle,HUThresholdFat,HUThresholdOsteochondroma, CaseMuscleFolder); - - CaseAmiraFolder = [CaseCTFolder '\amira']; - muscle.pixel = infoPixel(CaseAmiraFolder); - muscle.pixeldetail=muscle.pixel(1,1); - muscle.totalarea=muscle.Stot*(muscle.pixeldetail*muscle.pixeldetail)*0.01; %multiply total area by number of pixels. Result in cm2 - muscle.ratio=muscle.degeneration; %take the percentage degenerated - muscle.degenerationarea=muscle.totalarea*muscle.ratio; %this is the degenerated area - muscle.effectivePCSA=muscle.totalarea-muscle.degenerationarea; %the effective usable PCSA - tabMuscle_SS=[tabMuscle_SS; muscle]; - - - end - - %Because of ambiguity in pixelsize for some cases, chosen manually the pixel size - tabMuscle_SS(1).totalarea=0.01*tabMuscle_SS(1).Stot*(0.244955)^2; %P2, , chose "new" for all - tabMuscle_SS(3).totalarea=0.01*tabMuscle_SS(3).Stot*(0.310913)^2; %P6 -% tabMuscle(30).totalarea=0.01*tabMuscle(30).Stot*()^2; %P64: no data! -% tabMuscle(31).totalarea=0.01*tabMuscle(31).Stot*()^2; %P65: no data! -% tabMuscle(32).totalarea=0.01*tabMuscle(32).Stot*()^2; %P68: no data! -% tabMuscle(34).totalarea=0.01*tabMuscle(34).Stot*()^2; %P73: no data! -% tabMuscle(35).totalarea=0.01*tabMuscle(35).Stot*()^2; %P75: no data! -% tabMuscle(36).totalarea=0.01*tabMuscle(36).Stot*()^2; %P76: no data! -% tabMuscle(38).totalarea=0.01*tabMuscle(38).Stot*()^2; %P78: no data! -% tabMuscle(41).totalarea=0.01*tabMuscle(41).Stot*()^2; %P89: no data! -% tabMuscle(42).totalarea=0.01*tabMuscle(42).Stot*()^2; %P90: no data! -% tabMuscle(43).totalarea=0.01*tabMuscle(43).Stot*()^2; %P91: no data! -% tabMuscle(44).totalarea=0.01*tabMuscle(44).Stot*()^2; %P92: no data! -% tabMuscle(45).totalarea=0.01*tabMuscle(45).Stot*()^2; %P93: no data! - tabMuscle_SS(46).totalarea=0.01*tabMuscle_SS(46).Stot*(0.277493)^2; %P103 - tabMuscle_SS(47).totalarea=0.01*tabMuscle_SS(47).Stot*(0.290182)^2; %P105 - tabMuscle_SS(48).totalarea=0.01*tabMuscle_SS(48).Stot*(0.31551)^2; %P107 - tabMuscle_SS(61).totalarea=0.01*tabMuscle_SS(61).Stot*(0.271774)^2; %P145 - tabMuscle_SS(69).totalarea=0.01*tabMuscle_SS(69).Stot*(0.28785)^2; %P163 - tabMuscle_SS(73).totalarea=0.01*tabMuscle_SS(73).Stot*(0.334435)^2; %P170 - tabMuscle_SS(75).totalarea=0.01*tabMuscle_SS(75).Stot*(0.230255)^2; %P173 - tabMuscle_SS(78).totalarea=0.01*tabMuscle_SS(78).Stot*(0.280144)^2; %P176 - tabMuscle_SS(83).totalarea=0.01*tabMuscle_SS(83).Stot*(0.155813)^2; %P188 - -for i=1:size(tabMuscle_SS) - %update the degeneration information - tabMuscle_SS(i).degenerationarea=tabMuscle_SS(i).totalarea*tabMuscle_SS(i).ratio; %this is the new degenerated area - tabMuscle_SS(i).effectivePCSA=tabMuscle_SS(i).totalarea-tabMuscle_SS(i).degenerationarea; - MatrixPCSA_SS=[MatrixPCSA_SS;tabMuscle_SS(i).totalarea,tabMuscle_SS(i).effectivePCSA,tabMuscle_SS(i).ratio]; -end -% %Update MatrixPCSA as well -% MatrixPCSA(1,1)=tabMuscle(1).totalarea; -% MatrixPCSA(3,1)=tabMuscle(3).totalarea; -% % tabMuscle(30).totalarea=0.01*tabMuscle(30).Stot*()^2; %P64: no data! -% % tabMuscle(31).totalarea=0.01*tabMuscle(31).Stot*()^2; %P65: no data! -% % tabMuscle(32).totalarea=0.01*tabMuscle(32).Stot*()^2; %P68: no data! -% % tabMuscle(34).totalarea=0.01*tabMuscle(34).Stot*()^2; %P73: no data! -% % tabMuscle(35).totalarea=0.01*tabMuscle(35).Stot*()^2; %P75: no data! -% % tabMuscle(36).totalarea=0.01*tabMuscle(36).Stot*()^2; %P76: no data! -% % tabMuscle(38).totalarea=0.01*tabMuscle(38).Stot*()^2; %P78: no data! -% % tabMuscle(41).totalarea=0.01*tabMuscle(41).Stot*()^2; %P89: no data! -% % tabMuscle(42).totalarea=0.01*tabMuscle(42).Stot*()^2; %P90: no data! -% % tabMuscle(43).totalarea=0.01*tabMuscle(43).Stot*()^2; %P91: no data! -% % tabMuscle(44).totalarea=0.01*tabMuscle(44).Stot*()^2; %P92: no data! -% % tabMuscle(45).totalarea=0.01*tabMuscle(45).Stot*()^2; %P93: no data! -% MatrixPCSA(46,1)=tabMuscle(46).totalarea; -% MatrixPCSA(47,1)=tabMuscle(47).totalarea; -% MatrixPCSA(48,1)=tabMuscle(48).totalarea; -% MatrixPCSA(61,1)=tabMuscle(61).totalarea; -% MatrixPCSA(69,1)=tabMuscle(69).totalarea; -% MatrixPCSA(73,1)=tabMuscle(73).totalarea; -% MatrixPCSA(75,1)=tabMuscle(75).totalarea; -% MatrixPCSA(78,1)=tabMuscle(78).totalarea; -% MatrixPCSA(83,1)=tabMuscle(83).totalarea; - - AveragePCSA_SS = mean(MatrixPCSA_SS); %Result Oct2017: 5.62615579051498 - StdDev_PCSA_SS = std (MatrixPCSA_SS); %Result Oct2017: 2.41206345030003 - -disp('end SS') - -%FOR Infraspinatus -muscleName = 'IS'; - - for i=1:size(listPatient,1) - - caseID = listPatientCaseID{i,1}; - caseID2 = listPatient{i,1}; - - %inputFile = [mainFolder 'data\' caseID2(1) '\' caseID2(2) '\' caseID2(3) '\' caseID '*']; - inputFile = ['Y:\data\' caseID2(1) '\' caseID2(2) '\' caseID2(3) '\' caseID '*']; - FindCaseCTFolder = dir(inputFile); - - CaseID_IPP = FindCaseCTFolder.name; -% CaseCTFolder = [mainFolder 'data\' caseID2(1) '\' caseID2(2) '\' caseID2(3) '\' CaseID_IPP '\CT-' CaseID_IPP '-1']; - CaseCTFolder = ['Y:\data\' caseID2(1) '\' caseID2(2) '\' caseID2(3) '\' CaseID_IPP '\CT-' CaseID_IPP '-1']; - - CaseMuscleFolder = [ CaseCTFolder '\muscles']; - %Launch script "muscleDegeneration.m" - muscle = muscleDegeneration (caseID, muscleName ,HUThresholdMuscle,HUThresholdFat,HUThresholdOsteochondroma, CaseMuscleFolder); - - CaseAmiraFolder = [CaseCTFolder '\amira']; - muscle.pixel = infoPixel(CaseAmiraFolder); - muscle.pixeldetail=muscle.pixel(1,1); - muscle.totalarea=muscle.Stot*(muscle.pixeldetail*muscle.pixeldetail)*0.01; %multiply total area by number of pixels. Result in cm2 - muscle.ratio=muscle.degeneration; %take the percentage degenerated - muscle.degenerationarea=muscle.totalarea*muscle.ratio; %this is the degenerated area - muscle.effectivePCSA=muscle.totalarea-muscle.degenerationarea; %the effective usable PCSA - tabMuscle_IS=[tabMuscle_IS; muscle]; - - - end - - %Because of ambiguity in pixelsize for some cases, chosen manually the pixel size - tabMuscle_IS(1).totalarea=0.01*tabMuscle_IS(1).Stot*(0.244955)^2; %P2, , chose "new" for all - tabMuscle_IS(3).totalarea=0.01*tabMuscle_IS(3).Stot*(0.310913)^2; %P6 -% tabMuscle(30).totalarea=0.01*tabMuscle(30).Stot*()^2; %P64: no data! -% tabMuscle(31).totalarea=0.01*tabMuscle(31).Stot*()^2; %P65: no data! -% tabMuscle(32).totalarea=0.01*tabMuscle(32).Stot*()^2; %P68: no data! -% tabMuscle(34).totalarea=0.01*tabMuscle(34).Stot*()^2; %P73: no data! -% tabMuscle(35).totalarea=0.01*tabMuscle(35).Stot*()^2; %P75: no data! -% tabMuscle(36).totalarea=0.01*tabMuscle(36).Stot*()^2; %P76: no data! -% tabMuscle(38).totalarea=0.01*tabMuscle(38).Stot*()^2; %P78: no data! -% tabMuscle(41).totalarea=0.01*tabMuscle(41).Stot*()^2; %P89: no data! -% tabMuscle(42).totalarea=0.01*tabMuscle(42).Stot*()^2; %P90: no data! -% tabMuscle(43).totalarea=0.01*tabMuscle(43).Stot*()^2; %P91: no data! -% tabMuscle(44).totalarea=0.01*tabMuscle(44).Stot*()^2; %P92: no data! -% tabMuscle(45).totalarea=0.01*tabMuscle(45).Stot*()^2; %P93: no data! - tabMuscle_IS(46).totalarea=0.01*tabMuscle_IS(46).Stot*(0.277493)^2; %P103 - tabMuscle_IS(47).totalarea=0.01*tabMuscle_IS(47).Stot*(0.290182)^2; %P105 - tabMuscle_IS(48).totalarea=0.01*tabMuscle_IS(48).Stot*(0.31551)^2; %P107 - tabMuscle_IS(61).totalarea=0.01*tabMuscle_IS(61).Stot*(0.271774)^2; %P145 - tabMuscle_IS(69).totalarea=0.01*tabMuscle_IS(69).Stot*(0.28785)^2; %P163 - tabMuscle_IS(73).totalarea=0.01*tabMuscle_IS(73).Stot*(0.334435)^2; %P170 - tabMuscle_IS(75).totalarea=0.01*tabMuscle_IS(75).Stot*(0.230255)^2; %P173 - tabMuscle_IS(78).totalarea=0.01*tabMuscle_IS(78).Stot*(0.280144)^2; %P176 - tabMuscle_IS(83).totalarea=0.01*tabMuscle_IS(83).Stot*(0.155813)^2; %P188 - -for i=1:size(tabMuscle_IS) - %update the degeneration information - tabMuscle_IS(i).degenerationarea=tabMuscle_IS(i).totalarea*tabMuscle_IS(i).ratio; %this is the new degenerated area - tabMuscle_IS(i).effectivePCSA=tabMuscle_IS(i).totalarea-tabMuscle_IS(i).degenerationarea; - MatrixPCSA_IS=[MatrixPCSA_IS;tabMuscle_IS(i).totalarea,tabMuscle_IS(i).effectivePCSA,tabMuscle_IS(i).ratio]; -end - - AveragePCSA_IS = mean(MatrixPCSA_IS); - StdDev_PCSA_IS = std (MatrixPCSA_IS); - -disp('end IS') - - -%FOR Subscapularis -muscleName = 'SC'; - - for i=1:size(listPatient,1) - - caseID = listPatientCaseID{i,1}; - caseID2 = listPatient{i,1}; - - %inputFile = [mainFolder 'data\' caseID2(1) '\' caseID2(2) '\' caseID2(3) '\' caseID '*']; - inputFile = ['Y:\data\' caseID2(1) '\' caseID2(2) '\' caseID2(3) '\' caseID '*']; - FindCaseCTFolder = dir(inputFile); - - CaseID_IPP = FindCaseCTFolder.name; -% CaseCTFolder = [mainFolder 'data\' caseID2(1) '\' caseID2(2) '\' caseID2(3) '\' CaseID_IPP '\CT-' CaseID_IPP '-1']; - CaseCTFolder = ['Y:\data\' caseID2(1) '\' caseID2(2) '\' caseID2(3) '\' CaseID_IPP '\CT-' CaseID_IPP '-1']; - - CaseMuscleFolder = [ CaseCTFolder '\muscles']; - muscle = muscleDegeneration (caseID, muscleName ,HUThresholdMuscle,HUThresholdFat,HUThresholdOsteochondroma, CaseMuscleFolder); - - CaseAmiraFolder = [CaseCTFolder '\amira']; - muscle.pixel = infoPixel(CaseAmiraFolder); - muscle.pixeldetail=muscle.pixel(1,1); - muscle.totalarea=muscle.Stot*(muscle.pixeldetail*muscle.pixeldetail)*0.01; %multiply total area by number of pixels. Result in cm2 - muscle.ratio=muscle.degeneration; %take the percentage degenerated - muscle.degenerationarea=muscle.totalarea*muscle.ratio; %this is the degenerated area - muscle.effectivePCSA=muscle.totalarea-muscle.degenerationarea; %the effective usable PCSA - tabMuscle_SC=[tabMuscle_SC; muscle]; - - - end - - %Because of ambiguity in pixelsize for some cases, chosen manually the pixel size - tabMuscle_SC(1).totalarea=0.01*tabMuscle_SC(1).Stot*(0.244955)^2; %P2, , chose "new" for all - tabMuscle_SC(3).totalarea=0.01*tabMuscle_SC(3).Stot*(0.310913)^2; %P6 -% tabMuscle(30).totalarea=0.01*tabMuscle(30).Stot*()^2; %P64: no data! -% tabMuscle(31).totalarea=0.01*tabMuscle(31).Stot*()^2; %P65: no data! -% tabMuscle(32).totalarea=0.01*tabMuscle(32).Stot*()^2; %P68: no data! -% tabMuscle(34).totalarea=0.01*tabMuscle(34).Stot*()^2; %P73: no data! -% tabMuscle(35).totalarea=0.01*tabMuscle(35).Stot*()^2; %P75: no data! -% tabMuscle(36).totalarea=0.01*tabMuscle(36).Stot*()^2; %P76: no data! -% tabMuscle(38).totalarea=0.01*tabMuscle(38).Stot*()^2; %P78: no data! -% tabMuscle(41).totalarea=0.01*tabMuscle(41).Stot*()^2; %P89: no data! -% tabMuscle(42).totalarea=0.01*tabMuscle(42).Stot*()^2; %P90: no data! -% tabMuscle(43).totalarea=0.01*tabMuscle(43).Stot*()^2; %P91: no data! -% tabMuscle(44).totalarea=0.01*tabMuscle(44).Stot*()^2; %P92: no data! -% tabMuscle(45).totalarea=0.01*tabMuscle(45).Stot*()^2; %P93: no data! - tabMuscle_SC(46).totalarea=0.01*tabMuscle_SC(46).Stot*(0.277493)^2; %P103 - tabMuscle_SC(47).totalarea=0.01*tabMuscle_SC(47).Stot*(0.290182)^2; %P105 - tabMuscle_SC(48).totalarea=0.01*tabMuscle_SC(48).Stot*(0.31551)^2; %P107 - tabMuscle_SC(61).totalarea=0.01*tabMuscle_SC(61).Stot*(0.271774)^2; %P145 - tabMuscle_SC(69).totalarea=0.01*tabMuscle_SC(69).Stot*(0.28785)^2; %P163 - tabMuscle_SC(73).totalarea=0.01*tabMuscle_SC(73).Stot*(0.334435)^2; %P170 - tabMuscle_SC(75).totalarea=0.01*tabMuscle_SC(75).Stot*(0.230255)^2; %P173 - tabMuscle_SC(78).totalarea=0.01*tabMuscle_SC(78).Stot*(0.280144)^2; %P176 - tabMuscle_SC(83).totalarea=0.01*tabMuscle_SC(83).Stot*(0.155813)^2; %P188 - -for i=1:size(tabMuscle_SC) - %update the degeneration information - tabMuscle_SC(i).degenerationarea=tabMuscle_SC(i).totalarea*tabMuscle_SC(i).ratio; %this is the new degenerated area - tabMuscle_SC(i).effectivePCSA=tabMuscle_SC(i).totalarea-tabMuscle_SC(i).degenerationarea; - MatrixPCSA_SC=[MatrixPCSA_SC;tabMuscle_SC(i).totalarea,tabMuscle_SC(i).effectivePCSA,tabMuscle_SC(i).ratio]; -end - - AveragePCSA_SC = mean(MatrixPCSA_SC); - StdDev_PCSA_SC = std (MatrixPCSA_SC); - -disp('end SC') - - -%FOR Teres Minor -muscleName = 'TM'; - - for i=1:size(listPatient,1) - - caseID = listPatientCaseID{i,1}; - caseID2 = listPatient{i,1}; - - %inputFile = [mainFolder 'data\' caseID2(1) '\' caseID2(2) '\' caseID2(3) '\' caseID '*']; - inputFile = ['Y:\data\' caseID2(1) '\' caseID2(2) '\' caseID2(3) '\' caseID '*']; - FindCaseCTFolder = dir(inputFile); - - CaseID_IPP = FindCaseCTFolder.name; -% CaseCTFolder = [mainFolder 'data\' caseID2(1) '\' caseID2(2) '\' caseID2(3) '\' CaseID_IPP '\CT-' CaseID_IPP '-1']; - CaseCTFolder = ['Y:\data\' caseID2(1) '\' caseID2(2) '\' caseID2(3) '\' CaseID_IPP '\CT-' CaseID_IPP '-1']; - - CaseMuscleFolder = [ CaseCTFolder '\muscles']; - muscle = muscleDegeneration (caseID, muscleName ,HUThresholdMuscle,HUThresholdFat,HUThresholdOsteochondroma, CaseMuscleFolder); - - CaseAmiraFolder = [CaseCTFolder '\amira']; - muscle.pixel = infoPixel(CaseAmiraFolder); - muscle.pixeldetail=muscle.pixel(1,1); - muscle.totalarea=muscle.Stot*(muscle.pixeldetail*muscle.pixeldetail)*0.01; %multiply total area by number of pixels. Result in cm2 - muscle.ratio=muscle.degeneration; %take the percentage degenerated - muscle.degenerationarea=muscle.totalarea*muscle.ratio; %this is the degenerated area - muscle.effectivePCSA=muscle.totalarea-muscle.degenerationarea; %the effective usable PCSA - tabMuscle_TM=[tabMuscle_TM; muscle]; - - - end - - %Because of ambiguity in pixelsize for some cases, chosen manually the pixel size - tabMuscle_TM(1).totalarea=0.01*tabMuscle_TM(1).Stot*(0.244955)^2; %P2, , chose "new" for all - tabMuscle_TM(3).totalarea=0.01*tabMuscle_TM(3).Stot*(0.310913)^2; %P6 -% tabMuscle(30).totalarea=0.01*tabMuscle(30).Stot*()^2; %P64: no data! -% tabMuscle(31).totalarea=0.01*tabMuscle(31).Stot*()^2; %P65: no data! -% tabMuscle(32).totalarea=0.01*tabMuscle(32).Stot*()^2; %P68: no data! -% tabMuscle(34).totalarea=0.01*tabMuscle(34).Stot*()^2; %P73: no data! -% tabMuscle(35).totalarea=0.01*tabMuscle(35).Stot*()^2; %P75: no data! -% tabMuscle(36).totalarea=0.01*tabMuscle(36).Stot*()^2; %P76: no data! -% tabMuscle(38).totalarea=0.01*tabMuscle(38).Stot*()^2; %P78: no data! -% tabMuscle(41).totalarea=0.01*tabMuscle(41).Stot*()^2; %P89: no data! -% tabMuscle(42).totalarea=0.01*tabMuscle(42).Stot*()^2; %P90: no data! -% tabMuscle(43).totalarea=0.01*tabMuscle(43).Stot*()^2; %P91: no data! -% tabMuscle(44).totalarea=0.01*tabMuscle(44).Stot*()^2; %P92: no data! -% tabMuscle(45).totalarea=0.01*tabMuscle(45).Stot*()^2; %P93: no data! - tabMuscle_TM(46).totalarea=0.01*tabMuscle_TM(46).Stot*(0.277493)^2; %P103 - tabMuscle_TM(47).totalarea=0.01*tabMuscle_TM(47).Stot*(0.290182)^2; %P105 - tabMuscle_TM(48).totalarea=0.01*tabMuscle_TM(48).Stot*(0.31551)^2; %P107 - tabMuscle_TM(61).totalarea=0.01*tabMuscle_TM(61).Stot*(0.271774)^2; %P145 - tabMuscle_TM(69).totalarea=0.01*tabMuscle_TM(69).Stot*(0.28785)^2; %P163 - tabMuscle_TM(73).totalarea=0.01*tabMuscle_TM(73).Stot*(0.334435)^2; %P170 - tabMuscle_TM(75).totalarea=0.01*tabMuscle_TM(75).Stot*(0.230255)^2; %P173 - tabMuscle_TM(78).totalarea=0.01*tabMuscle_TM(78).Stot*(0.280144)^2; %P176 - tabMuscle_TM(83).totalarea=0.01*tabMuscle_TM(83).Stot*(0.155813)^2; %P188 - -for i=1:size(tabMuscle_TM) - %update the degeneration information - tabMuscle_TM(i).degenerationarea=tabMuscle_TM(i).totalarea*tabMuscle_TM(i).ratio; %this is the new degenerated area - tabMuscle_TM(i).effectivePCSA=tabMuscle_TM(i).totalarea-tabMuscle_TM(i).degenerationarea; - MatrixPCSA_TM=[MatrixPCSA_TM;tabMuscle_TM(i).totalarea,tabMuscle_TM(i).effectivePCSA,tabMuscle_TM(i).ratio]; -end - - AveragePCSA_TM = mean(MatrixPCSA_TM); - StdDev_PCSA_TM = std (MatrixPCSA_TM); - -disp('endTM') - -%Save data just in case -save('D:\Data\FromdropboxOUtmemory\muscles\tabMuscle_SS.mat','tabMuscle_SS'); -save('D:\Data\FromdropboxOUtmemory\muscles\tabMuscle_IS.mat','tabMuscle_IS'); -save('D:\Data\FromdropboxOUtmemory\muscles\tabMuscle_SC.mat','tabMuscle_SC'); -save('D:\Data\FromdropboxOUtmemory\muscles\tabMuscle_TM.mat','tabMuscle_TM'); - -save('D:\Data\FromdropboxOUtmemory\muscles\MatrixPCSA_SS.mat','MatrixPCSA_SS'); -save('D:\Data\FromdropboxOUtmemory\muscles\MatrixPCSA_IS.mat','MatrixPCSA_IS'); -save('D:\Data\FromdropboxOUtmemory\muscles\MatrixPCSA_SC.mat','MatrixPCSA_SC'); -save('D:\Data\FromdropboxOUtmemory\muscles\MatrixPCSA_TM.mat','MatrixPCSA_TM'); \ No newline at end of file diff --git a/muscles/ShoulderDataBaseTest.xlsx b/muscles/ShoulderDataBaseTest.xlsx deleted file mode 100644 index 358e508..0000000 Binary files a/muscles/ShoulderDataBaseTest.xlsx and /dev/null differ diff --git a/muscles/degenerationAll.m b/muscles/degenerationAll.m deleted file mode 100644 index 033bf2d..0000000 --- a/muscles/degenerationAll.m +++ /dev/null @@ -1,166 +0,0 @@ -function muscles_results = degenerationAll(caseID, musclesList) -%%DEGENERATIONALL returns a structure array containing muscle -% measurements for each case ID entered as input and fills the Shoulder -% database with muscle degeneration measurements -% -% This function fills the Shoulder database with the muscle degeneration -% values of the case given as input. The measurements are stored in a XLS -% file and in the MySQL database. -% -% USE: degenerationAll(caseID, musclesList) -% -% INPUT caseID: Case IDs for which you want to compute muscle degeneration. -% Cell array that stores the case IDs as a char in the form 'P###' or -% 'N###' (starts with "P" or "N" followed by 1 to 3 digits). -% -% musclesList: List of muscles which you want to compute muscle -% degeneration. Cell array that stores each msucle name as a char. -% -% OUTPUT muscles_results: structure array containing fields 'Case_ID', -% and fields "muscle name" with muscle measurements for the -% current patient: areas : 'Stot', 'Satrophy', 'Sinfiltration', -% 'Sosteochondroma' and 'Sdegeneration', and ratios: 'atrophy', -% 'infiltration', 'osteochondroma' and 'degeneration' -% -% REMARKS The muscle values (ratios) are saved in the muscles.xls file -% and in the shoulder MySQL database. -% -% created with MATLAB ver.: 9.2.0.556344 (R2017a) on Windows 7 -% Author: EPFL-LBO-VMC -% Date: 27-Jun-2017 -% - - CTDatabaseLocation = '../../../data'; % Location of the CT database - XLSShoulderDatabaseLocation = '../../../data/Excel/'; % Location of the XLS ShoulderDatabase - - HUThresholdMuscle = 0; %#ok - HUThresholdFat = 30; %#ok - HUThresholdOsteochondroma = 166; %#ok - - % Check validity of input argument (cell array) - validateattributes(caseID,{'cell'},{'nonempty'}); - - % Check that imput case IDs are unique - [caseIDNames,~,uniqueCaseID] = unique(caseID); - countOfCaseID = hist(uniqueCaseID,unique(uniqueCaseID))'; - freqCaseIDs = struct('name',caseIDNames,'freq',num2cell(countOfCaseID)); - repeatedValues = find([freqCaseIDs.freq] > 1); - - if(~isempty(repeatedValues)) - warning('Input contains repeated Case ID: %s. Repeated occurences of that Case ID will be omitted. \n', freqCaseIDs(repeatedValues).name) - caseID = caseIDNames'; - end - - % open mySQL connection - conn = openSQL(); - - % Get the list of exisiting cases in XLS database - [~,~,currDatabase] = xlsread([XLSShoulderDatabaseLocation 'xlsFromMatlab/muscles.xls']); - currDatabaseCaseIDlist = currDatabase(2:end,1); - - %Initialize structure array for results - muscles_results = []; - muscles_results = setfield(muscles_results,{length(caseID),1},'Case_ID',[]); - - % Compute muscle degeneration values and fill database - for i = 1:length(caseID) - - % Check validity of input arguments (char and format 'P###' or 'N###') - validateattributes(caseID{i},{'char'},{'nonempty'}); - - if (numel(regexp(caseID{i},'^[PN]\d{1,3}$')) == 0) - error(['Invalid format of CaseID: ' caseID{i} '. CaseID must start with "P" or "N" and be followed by 1 to 3 digits.']); - end - - % Find CT folder for the given Case ID - levelDir1 = caseID{i}(1); - - if (length(caseID{i}(2:end)) < 2) - levelDir2 = '0'; - levelDir3 = '0'; - elseif (length(caseID{i}(2:end)) < 3) - levelDir2 = '0'; - levelDir3 = caseID{i}(2); - else - levelDir2 = caseID{i}(2); - levelDir3 = caseID{i}(3); - end - - FindCaseCTFolder = dir([CTDatabaseLocation '/' levelDir1 '/' levelDir2 '/' levelDir3 '/' caseID{i} '*']); - if (isempty(FindCaseCTFolder)) - error(['Missing CT directory for CaseID: ' caseID{i}]); - end - - CaseID_IPP = FindCaseCTFolder.name; - CaseCTFolder = [CTDatabaseLocation '/' levelDir1 '/' levelDir2 '/' levelDir3 '/' CaseID_IPP]; - - % Compute musle degeneration values and store in the XLS database - if exist([CaseCTFolder '/CT-' CaseID_IPP '-1/muscles'],'dir') == 7 %if a folder "muscles" exist, the patient name is added to the "measured" column - - muscleDirectory = [CaseCTFolder '/CT-' CaseID_IPP '-1/muscles']; %#ok - - muscles_results(i).Case_ID = caseID{i}; - - for j=1:length(musclesList) - - disp(caseID{i}); - % Compute muscle degeneration values - eval([musclesList{j} '= muscleDegeneration(caseID{i}, musclesList{j},HUThresholdMuscle,HUThresholdFat,HUThresholdOsteochondroma,muscleDirectory);']); - eval(['muscles_results = setfield(muscles_results,{i,1}, musclesList{j}, ' musclesList{j} ');']); - - end - - muscles = cellstr(muscles_results(i).Case_ID)'; - for j = 1:length(musclesList) - eval(['muscles = horzcat(muscles, transpose(struct2cell(muscles_results(i).' musclesList{j} ')));']); - end - - % Write to XLS file - % Replace line if already existing or append - if(any(strcmp(currDatabaseCaseIDlist, caseID{i}))) - xlswrite([XLSShoulderDatabaseLocation 'xlsFromMatlab/muscles.xls'],muscles(:,[1,8:11,18:21,28:31,38:41]),'Feuil1',['A' int2str(find(strcmp(currDatabaseCaseIDlist, caseID{i}))+1)]); - else - xlswrite([XLSShoulderDatabaseLocation 'xlsFromMatlab/muscles.xls'],muscles(:,[1,8:11,18:21,28:31,38:41]),'Feuil1',['A' int2str(length(currDatabaseCaseIDlist)+1+i)]); - end - - %ORIGINAL but weird results coz shifted - correction by Yasmine in Aug2018 -% if(any(strcmp(currDatabaseCaseIDlist, caseID{i}))) -% xlswrite([XLSShoulderDatabaseLocation 'xlsFromMatlab/muscles_test.xls'],muscles(:,[1,7:10,16:19,25:28,34:37]),'Feuil1',['A' int2str(find(strcmp(currDatabaseCaseIDlist, caseID{i}))+1)]); -% else -% xlswrite([XLSShoulderDatabaseLocation 'xlsFromMatlab/muscles_test.xls'],muscles(:,[1,7:10,16:19,25:28,34:37]),'Feuil1',['A' int2str(length(currDatabaseCaseIDlist)+1+i)]); -% end - - % Write to MySQL database - % Replace line if already existing or issue warning message - sqlquery = ['SELECT CT_id FROM CT WHERE shoulder_id IN (SELECT shoulder_id FROM sCase WHERE folder_name = "' caseID{i} '")']; - curs = exec(conn,sqlquery); - if ~isempty(curs.Message) - fprintf('\nMessage: %s\n', curs.Message); - end - - curs=fetch(curs); - sqlresult = curs.Data; - - if isnumeric(sqlresult{1}) - - % Update data in table 'muscle' - data = {sqlresult{1} ... - muscles_results(i).SS.atrophy muscles_results(i).SS.infiltration muscles_results(i).SS.osteochondroma muscles_results(i).SS.degeneration ... - muscles_results(i).IS.atrophy muscles_results(i).IS.infiltration muscles_results(i).IS.osteochondroma muscles_results(i).IS.degeneration ... - muscles_results(i).SC.atrophy muscles_results(i).SC.infiltration muscles_results(i).SC.osteochondroma muscles_results(i).SC.degeneration ... - muscles_results(i).TM.atrophy muscles_results(i).TM.infiltration muscles_results(i).TM.osteochondroma muscles_results(i).TM.degeneration}; - fieldNames = {'CT_id','SSA','SSI','SSO','SSD','ISA','ISI','ISO','ISD','SCA','SCI','SCO','SCD', 'TMA', 'TMI', 'TMO', 'TMD'}; - upsert(conn, 'muscle', fieldNames, [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], data); - - else - error(['No entry for caseID ' caseID{i} ' was found in the ' conn.Instance ' MySQL database.']); - end - - else - error(['"muscles" folder missing for CaseID: ' caseID{i}]); - end - - end - - -end diff --git a/muscles/degenerationAll3D.m b/muscles/degenerationAll3D.m deleted file mode 100644 index a849f8f..0000000 --- a/muscles/degenerationAll3D.m +++ /dev/null @@ -1,193 +0,0 @@ -function muscles_results = degenerationAll3D(caseID, musclesList) -%%DEGENERATIONALL3D returns a structure array containing muscle -% measurements for each case ID entered as input and fills the Shoulder -% database with muscle degeneration measurements -% -% This function fills the Shoulder database with the muscle degeneration -% values of the case given as input, for all CT slices available. -% The measurements are stored in a XLS file and in the MySQL database. -% -% USE: degenerationAll3D(caseID, musclesList) -% -% INPUT caseID: Case IDs for which you want to compute muscle degeneration. -% Cell array that stores the case IDs as a char in the form 'P###' or -% 'N###' (starts with "P" or "N" followed by 1 to 3 digits). -% -% musclesList: List of muscles which you want to compute muscle -% degeneration. Cell array that stores each msucle name as a char. -% -% OUTPUT muscles_results: structure array containing fields 'Case_ID', -% and structure array field "muscle name" with muscle -% measurements for each slice for the current patient: 'Stot', -% 'Satrophy', 'Sinfiltration', 'Sosteochondroma' and -% 'Sdegeneration', 'atrophy', 'infiltration', 'osteochondroma' -% and 'degeneration' -% -% REMARKS The muscle values (ratios) for all available CT slices are -% saved in the muscles.xls file and in the shoulder MySQL -% database. -% -% created with MATLAB ver.: 9.2.0.556344 (R2017a) on Windows 7 -% Author: EPFL-LBO-VMC -% Date: 29-kun-2017 -% - - CTDatabaseLocation = '../../../data'; % Location of the CT database - - % XLSShoulderDatabaseLocation = 'C:/Users/vmalfroy/Dropbox/shoulderDatabase/'; % Location of the XLS ShoulderDatabase - XLSShoulderDatabaseLocation = '../../../data/Excel/'; % Location of the XLS ShoulderDatabase - HUThresholdMuscle = 0; %#ok - HUThresholdFat = 30; %#ok - HUThresholdOsteochondroma = 166; %#ok - - % Check validity of input argument (cell array) - validateattributes(caseID,{'cell'},{'nonempty'}); - - % Check that imput case IDs are unique - [caseIDNames,~,uniqueCaseID] = unique(caseID); - countOfCaseID = hist(uniqueCaseID,unique(uniqueCaseID))'; - freqCaseIDs = struct('name',caseIDNames,'freq',num2cell(countOfCaseID)); - repeatedValues = find([freqCaseIDs.freq] > 1); - - if(~isempty(repeatedValues)) - warning('Input contains repeated Case ID: %s. Repeated occurences of that Case ID will be omitted. \n', freqCaseIDs(repeatedValues).name) - caseID = caseIDNames'; - end - - % open mySQL connection - conn = openSQL(); - - % Get the list of exisiting cases in XLS database - [~,~,currDatabase] = xlsread([XLSShoulderDatabaseLocation 'xlsFromMatlab/muscles.xls']); - currDatabaseCaseIDlist = currDatabase(2:end,1); - - %Initialize structure array for results - muscles_results = []; - muscles_results = setfield(muscles_results,{length(caseID),1},'Case_ID',[]); - - % Compute muscle degeneration values and fill database - for i = 1:length(caseID) - - % Check validity of input arguments (char and format 'P###' or 'N###') - validateattributes(caseID{i},{'char'},{'nonempty'}); - - if (numel(regexp(caseID{i},'^[PN]\d{1,3}$')) == 0) - error(['Invalid format of CaseID: ' caseID{i} '. CaseID must start with "P" or "N" and be followed by 1 to 3 digits.']); - end - - % Find CT folder for the given Case ID - levelDir1 = caseID{i}(1); - - if (length(caseID{i}(2:end)) < 2) - levelDir2 = '0'; - levelDir3 = '0'; - elseif (length(caseID{i}(2:end)) < 3) - levelDir2 = '0'; - levelDir3 = caseID{i}(2); - else - levelDir2 = caseID{i}(2); - levelDir3 = caseID{i}(3); - end - - FindCaseCTFolder = dir([CTDatabaseLocation '/' levelDir1 '/' levelDir2 '/' levelDir3 '/' caseID{i} '*']); - if (isempty(FindCaseCTFolder)) - error(['Missing CT directory for CaseID: ' caseID{i}]); - end - - CaseID_IPP = FindCaseCTFolder.name; - CaseCTFolder = [CTDatabaseLocation '/' levelDir1 '/' levelDir2 '/' levelDir3 '/' CaseID_IPP]; - - % Compute musle degeneration values and store in the XLS database - if exist([CaseCTFolder '/CT-' CaseID_IPP '-1/muscles'],'dir') == 7 %if a folder "muscles" exist, the patient name is added to the "measured" column - - muscleDirectory = [CaseCTFolder '/CT-' CaseID_IPP '-1/muscles']; - - slicesList = dir(muscleDirectory); - slicesList = slicesList(3:end); - - muscles_results(i).Case_ID = caseID{i}; - - field2sort = 'SliceNumber'; %#ok - - for j=1:length(slicesList) - - for k=1:length(musclesList) - - disp(caseID{i}); - - % Compute muscle degeneration values - eval([musclesList{k} '= muscleDegeneration3D(caseID{i}, musclesList{k},HUThresholdMuscle,HUThresholdFat,HUThresholdOsteochondroma,muscleDirectory);']); - eval(['muscles_results = setfield(muscles_results,{i,1}, musclesList{k}, ' musclesList{k} ');']); - - % Sort muscle field by slice number - eval(['[~,I] = sort(arrayfun (@(x) x.(field2sort), muscles_results(i,1).' musclesList{k} '));']); - eval(['muscles_results(i,1).' musclesList{k} ' = muscles_results(i,1).' musclesList{k} '(I);']); - - end - - end - - muscles = cellstr(muscles_results(i).CT_id)'; - - - for k = 1:length(musclesList) - eval(['muscles = horzcat(muscles, transpose(struct2cell(muscles_results.' musclesList{k} ')));']); - end - - % Write to XLS file - % Replace line if already existing or append - if(any(strcmp(currDatabaseCaseIDlist, caseID{i}))) - xlswrite([XLSShoulderDatabaseLocation 'xlsFromMatlab/muscles.xls'],muscles,'Feuil1',['A' int2str(find(strcmp(currDatabaseCaseIDlist, caseID{i}))+1)]); - else - xlswrite([XLSShoulderDatabaseLocation 'xlsFromMatlab/muscles.xls'],muscles,'Feuil1',['A' int2str(length(currDatabaseCaseIDlist)+1+i)]); - end - % Write to MySQL database - % Replace line if already existing or issue warning message - sqlquery = ['SELECT CT_id FROM CT WHERE shoulder_id IN (SELECT shoulder_id FROM sCase WHERE folder_name = "' caseID{i} '")']; - curs = exec(conn,sqlquery); - if ~isempty(curs.Message) - fprintf('\nMessage: %s\n', curs.Message); - end - - curs=fetch(curs); - sqlresult = curs.Data; - - if isnumeric(sqlresult{1}) - - SS_atrophy = sum([muscles_results(i).SS(:).Satrophy])/sum([muscles_results(i).SS(:).Stot]); - SS_infiltration = sum([muscles_results(i).SS(:).Sinfiltration])/sum([muscles_results(i).SS(:).Stot]); - SS_osteochondroma = sum([muscles_results(i).SS(:).Sosteochondroma])/sum([muscles_results(i).SS(:).Stot]); - SS_degeneration = (sum([muscles_results(i).SS(:).Stot]) - sum([muscles_results(i).SS(:).Sdegeneration]))/sum([muscles_results(i).SS(:).Stot]); - - IS_atrophy = sum([muscles_results(i).IS(:).Satrophy])/sum([muscles_results(i).IS(:).Stot]); - IS_infiltration = sum([muscles_results(i).IS(:).Sinfiltration])/sum([muscles_results(i).IS(:).Stot]); - IS_osteochondroma = sum([muscles_results(i).IS(:).Sosteochondroma])/sum([muscles_results(i).IS(:).Stot]); - IS_degeneration = (sum([muscles_results(i).IS(:).Stot]) - sum([muscles_results(i).IS(:).Sdegeneration]))/sum([muscles_results(i).IS(:).Stot]); - - SC_atrophy = sum([muscles_results(i).SC(:).Satrophy])/sum([muscles_results(i).SC(:).Stot]); - SC_infiltration = sum([muscles_results(i).SC(:).Sinfiltration])/sum([muscles_results(i).SC(:).Stot]); - SC_osteochondroma = sum([muscles_results(i).SC(:).Sosteochondroma])/sum([muscles_results(i).SC(:).Stot]); - SC_degeneration = (sum([muscles_results(i).SC(:).Stot]) - sum([muscles_results(i).SC(:).Sdegeneration]))/sum([muscles_results(i).SC(:).Stot]); - - TM_atrophy = sum([muscles_results(i).TM(:).Satrophy])/sum([muscles_results(i).TM(:).Stot]); - TM_infiltration = sum([muscles_results(i).TM(:).Sinfiltration])/sum([muscles_results(i).TM(:).Stot]); - TM_osteochondroma = sum([muscles_results(i).TM(:).Sosteochondroma])/sum([muscles_results(i).TM(:).Stot]); - TM_degeneration = (sum([muscles_results(i).TM(:).Stot]) - sum([muscles_results(i).TM(:).Sdegeneration]))/sum([muscles_results(i).TM(:).Stot]); - - % Update data in table 'muscle' - data = {sqlresult{1} SS_atrophy SS_infiltration SS_osteochondroma SS_degeneration IS_atrophy IS_infiltration IS_osteochondroma IS_degeneration SC_atrophy SC_infiltration SC_osteochondroma SC_degeneration TM_atrophy TM_infiltration TM_osteochondroma TM_degeneration}; - fieldNames = {'CT_id','SSA','SSI','SSO','SSD','ISA','ISI','ISO','ISD','SCA','SCI','SCO','SCD', 'TMA', 'TMI', 'TMO', 'TMD'}; - upsert(conn, 'muscle', fieldNames, [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], data); - - else - error(['No entry for caseID ' caseID{i} ' was found in the ' conn.Instance ' MySQL database.']); - end - - else - error(['"muscles" folder missing for CaseID: ' caseID{i}]); - end - - end - - -end diff --git a/muscles/infoPixel.m b/muscles/infoPixel.m deleted file mode 100644 index 95fee89..0000000 --- a/muscles/infoPixel.m +++ /dev/null @@ -1,57 +0,0 @@ -% Put the good CaseCTFolder (\amira) - -function pixel = infoPixel (CaseCTFolder) - - fileTif = [ CaseCTFolder '\*.tif']; - - numberInfoTif = dir (fileTif); - pixel = []; - numberLineTabPixel= 0; - - for i = 1: size(numberInfoTif,1) - - inputFile = [CaseCTFolder '\' numberInfoTif(i).name(1:end-3) 'info']; - - fileID = fopen(inputFile); - - if fileID ~= -1 - while size(pixel,1) <= numberLineTabPixel - - tline = fgetl(fileID); - - if length(tline)>4 - if strcmp (tline(1:5),'pixel') - - k = strfind (tline, ' '); - pixel = [pixel; str2num(tline(k(1)+1:k(1)+5)) str2num(tline(k(2)+1:k(2)+5))]; - - end - end - end - numberLineTabPixel= numberLineTabPixel+1; - fclose (fileID); - end - - end - - if isempty(pixel) - pixel = [0 0]; - end - - if size(pixel,1)>1 - - for j = 2:size(pixel,1) - - if abs(pixel(j-1,1)-pixel(j,1))>0.01 || abs(pixel(j-1,2)-pixel(j,2))>0.01 - - pixel(1,:)= 0; - - end - - end - - end - - pixel = pixel(1,:); - -end \ No newline at end of file diff --git a/muscles/muscleContours.m b/muscles/muscleContours.m deleted file mode 100644 index e4e18f8..0000000 --- a/muscles/muscleContours.m +++ /dev/null @@ -1,148 +0,0 @@ -%% muscleContours - -% This script allows to select the contours on Tiff images of the four -% cuff rotator muscles: Supraspinatus (SS), Infraspinatus (IS), Subscapularis (SC) -% and Teres Minor (TM). -% - -% INPUT: -% subject: ### subject number -% type: 'normal' or 'pathologic' - -% Author: EPFL-LBO -% Date: 2016-09-05 -%% - -function [] = muscleContours(subject,type) - -directory = '../../../data'; % Location of the CT database -location = 'P'; -CTn = sprintf('P%03d',subject) - -listDirInCurrDir = dir([directory '/' CTn(1) '/' CTn(2) '/' CTn(3)]) -listDirInCurrDir = listDirInCurrDir(3:end); - -for i=1:length(listDirInCurrDir) - if ~isempty(regexp(listDirInCurrDir(i).name,['^[PN]\d{0,2}[' CTn(4) '][-]\w*'], 'once')) - - listDirInCaseFolder = dir([listDirInCurrDir(i).folder '\' listDirInCurrDir(i).name]); - listDirInCaseFolder = listDirInCaseFolder(3:end); - - % In all CT folders in the current Case Folder, find CT #1 - for j=1:length(listDirInCaseFolder) - if ~isempty(regexp(listDirInCaseFolder(j).name,'^[C][T][-][PN]\d{1,3}[-]\d*[-][1]', 'once')) - outputPath = [listDirInCaseFolder(j).folder '\' listDirInCaseFolder(j).name]; - end - end - end -end - - -pathologic_list = dir(sprintf('%s/%s/P*', directory, location)); %Create the case list -for i = 1:1:numel(pathologic_list) % Loop over the list of patients and extract the complete name of the specific patient - name = pathologic_list(i).name; - t = strfind(name,CTn); - if t == 1; - patient_name = name; - end -end - -finaldirectory = [outputPath '\amira\*tif']; -muscleName = cellstr(['SS';'IS';'SC';'TM']); - -close all; % Close all figure windows except those created by imtool. -imtool close all; % Close all figure windows created by imtool. -workspace; % Make sure the workspace panel is showing. -fontSize = 16; -imageWindow = [-100 200]; - -% Choose file -[inputFile, inputPath] = uigetfile(finaldirectory,'Select the image for muscle atrophy measurement'); -whereisp = strfind(inputFile, 'P'); -if isempty(whereisp) - whereisp = strfind(inputFile, 'N'); - if isempty(whereisp) - return - end -end -subject = inputFile(whereisp:whereisp+3); - -% Read gray scale image. -inputImage = imread(sprintf('%s%s',inputPath,inputFile)); - -if size(inputImage,3) == 3 -% Calculate the monochrome luminance by combining the RGB values according to the NTSC standard - inputImage = 0.2989*inputImage(:,:,1)... - +0.5870*inputImage(:,:,2)... - +0.1140*inputImage(:,:,3); -end - -for i=1:4; - - finished = 'Redo'; - while strcmp('Redo',finished) - msg = 0; % 0 = no message - % clc; % Clear command window. - close all; % Close all figure windows except those created by imtool. - imtool close all; % Close all figure windows created by imtool. - imshow(inputImage,imageWindow); - imagetitle = sprintf('Select %s ideal section', char(muscleName(i))); - title(imagetitle, 'FontSize', fontSize); - set(gcf, 'Position', get(0,'Screensize')); % Maximize figure. - - if msg == 1 - message = sprintf('Select the ideal section of your muscle in the image. \nLeft click to place points and draw a polygon. Click again on the first point to close the shape.\nYou can move the points once the line is closed. Double-click or right-click and "Create Mask" to finish.'); - msg = 0; - uiwait(msgbox(message)); - end - - binaryImage1 = roipoly(); - - if isempty(binaryImage1) - error('Invalid selection or interface closed') - end - - binaryImage1 = bwmorph(binaryImage1,'majority'); - % Get coordinates of the boundary of the polygonal drawn region. - structBoundaries1 = bwboundaries(binaryImage1); - xy1 = structBoundaries1{1}; % Get n by 2 array of x,y coordinates. - x1 = xy1(:, 2); % Columns. - y1 = xy1(:, 1); % Rows. - hold on - plot(x1, y1, 'color','green'); - - % check contours - finished = questdlg('Please verify the contours. Press "Save" if they are satisfactory or "Redo" if you would like to redo the selection. ',... - 'Contour verification','Save','Redo','Save'); - end - - %% Report results - % mkdir('./results',subject); - if exist([outputPath '\muscles'],'dir') == 0 - mkdir(outputPath,'muscles'); - end - - outputPath2 = [outputPath '\muscles\' char(muscleName(i)) '\']; - mkdir(outputPath2); - outputFile = sprintf('ssContours%s',subject); - - % Check for overwriting - overwrite = exist(sprintf('%s%s.mat',outputPath2,outputFile), 'file'); - switch overwrite - case 2 - isoverwrite = questdlg('Overwrite existing file ?', 'Warning', 'No', 'Yes', 'No'); - switch isoverwrite - case 'Yes' - save(sprintf('%s%s.mat',outputPath2,outputFile), 'inputImage','binaryImage1') - saveas(gcf,sprintf('%s%s.tif',outputPath2,outputFile)) - fprintf('%s%s.mat\n%s%s.tif\n',outputPath2,outputFile,outputPath2,outputFile); - end - - case 0 - save(sprintf('%s%s.mat',outputPath2,outputFile), 'inputImage','binaryImage1') - saveas(gcf,sprintf('%s%s.tif',outputPath2,outputFile)) - fprintf('%s%s.mat\n%s%s.tif\n',outputPath2,outputFile,outputPath2,outputFile); - end -end -close all; -end \ No newline at end of file diff --git a/muscles/muscleDegeneration.m b/muscles/muscleDegeneration.m deleted file mode 100644 index 0d7aa07..0000000 --- a/muscles/muscleDegeneration.m +++ /dev/null @@ -1,227 +0,0 @@ -function muscle = muscleDegeneration(caseID,muscleName,HUThresholdMuscle,HUThresholdFat,HUThresholdOsteochondroma,muscleDirectory) -%%MUSCLEDEGENERATION computes degeneration parameters from muscle contours -% -% This function returns muscle atrophy, fat infiltration, osteochondroma -% and degeneration values for a given muscle -% -% USE: muscleDegeneration(caseID,muscleName,HUThresholdMuscle,HUThresholdOsteochondroma,muscleDirectory) -% -% INPUT caseID: patient number -% muscleName: name of the rotator cuff muscle being measured (SS,IS, SC or TM) -% HUThresholdMuscle: HU threshold used for muscle segmentation (atrophied muscle limit) -% HUThresholdFat: HU threshold used for fat infiltration segmentation (fat-muscle limit) -% HUThresholdOsteochondroma:HU threshold used for osteochondroma segmentation (muscle-osteochondroma limit) -% muscleDirectory: Path to 'muscles' directory where contours and output images are stored -% -% OUTPUT muscle: structure containing fields 'Stot', 'Satrophy', -% 'Sinfiltration', 'Sosteochondroma' and 'Sdegeneration', -% 'atrophy', 'infiltration', 'osteochondroma' and 'degeneration' -% -% REMARKS An image of the segmentation of atrophied muscle, fat -% infiltration and osteochondroma is saved in muscles directory, -% in the 'muscleName' folder. -% -% created with MATLAB ver.: 9.2.0.556344 (R2017a) on Windows 7 -% Author: EPFL-LBO-VMC -% Date: 27-Jun-2017 -% - -inputFile = ['ssContours' caseID '.mat']; -contouredMuscle = load([muscleDirectory '\' muscleName '\' inputFile]); - -% --Plot CT slice with all contours-- - -fontSize = 14; -visualizationWindow = [-100 200]; - -imshow(contouredMuscle.inputImage,visualizationWindow); - -hold on - -% --Atrophied muscle segmentation-- - -% MATLAB does not accept to threshold an image with a negative value, as is -% the case when using HU scale. CT scanners usually have a CT range from -% -1000 HU to 1000 HU or -2000 HU to 2000 HU for modern scanners. In this -% case, we're not using HU values lower than -1000 and higher than +1000 so -% all pixel intensity values of the input image< -1000 HU are set to -1000 -% HU, and values > 1000 HU are set to 1000 HU. Then, the input image is -% mapped to the [0 1] range -1000->0 1000->1, as are the thresholds for -% muscle and osteochondroma. - -% Normalize image and thresholds - -contouredMuscle.inputImage(contouredMuscle.inputImage < -1000) = -1000; -contouredMuscle.inputImage(contouredMuscle.inputImage > 1000) = 1000; - -rangeHU = double([-1000 1000]); - -% Binarization of images works so that pixel value > threshold is kept. So -% if you condier that a msucle is normal for 30 HU and abnormal for 29 HU, -% the threshold should be set at 29 HU. -normalizedThresholdMuscle = ((HUThresholdMuscle - 1)-rangeHU(1))/(rangeHU(2)-rangeHU(1)); -normalizedThresholdFat = ((HUThresholdFat - 1)-rangeHU(1))/(rangeHU(2)-rangeHU(1)); -normalizedThresholdOsteochondroma = ((HUThresholdOsteochondroma - 1)-rangeHU(1))/(rangeHU(2)-rangeHU(1)); - -normalizedInputImage = (double(contouredMuscle.inputImage)-rangeHU(1))/(rangeHU(2)-rangeHU(1)); - -% Mask image using muscle fossa contours -maskedImage = normalizedInputImage; -maskedImage(~contouredMuscle.binaryImage1) = 0; - -% Plot muscle fossa contours. -structBoundaries = bwboundaries(contouredMuscle.binaryImage1); -xy=structBoundaries{1}; % Get n by 2 array of x,y coordinates. -x = xy(:, 2); % Columns. -y = xy(:, 1); % Rows. -p = plot(x, y, 'color','green','DisplayName','Muscle fossa'); -p_count = 1; - -% Segment using muscle threshold -myMuscle = imbinarize(maskedImage,normalizedThresholdMuscle); -myMuscle = imfill(myMuscle, 'holes'); % Fill holes - -% Keep only the biggest connected component (i.e. remove islands) -CC = bwconncomp(myMuscle); -numPixels = cellfun(@numel,CC.PixelIdxList); -[~,idx] = max(numPixels); -myMuscle(:,:) = 0; -myMuscle(CC.PixelIdxList{idx}) = 1; - -% Plot atrophied muscle contours -structBoundaries = bwboundaries(myMuscle); - -if size(structBoundaries,1) > 0 - p_count = p_count+1; -end - -for i = 1:size(structBoundaries,1) - xy = structBoundaries{i}; % Get n by 2 array of x,y coordinates. - x = xy(:, 2); % Columns. - y = xy(:, 1); % Rows. - hold on; % Keep the image. - p(p_count) = plot(x, y, 'color','blue','DisplayName','Atrophied Muscle'); -end - -% --Fat infiltration segmentation-- - -% Mask image using atrophied muscle segmentation -maskedImage = normalizedInputImage; -maskedImage(~myMuscle) = 0; - -% Segment using fat threshold -myMuscleNoFat = imbinarize(maskedImage,normalizedThresholdFat); -myFat = ~myMuscleNoFat; -myFat(~myMuscle) = 0; - -% Plot fat infiltration surfaces -structBoundaries = bwboundaries(myFat); - -% The 'fill' function cannot handle hollow polygons (with holes = 2 -% boundaries). To overcome this difficulty, fat infiltration is plotted as -% a coloured overlay image with transparency zero outside fat regions and -% transparency 0.25 in fat regions. - -myFatAlpha = double(myFat); -myFatAlpha(myFat) = 0.25; -red=zeros(size(myFat,1),size(myFat,2),3); -red(:,:,1)=1; -h=imshow(red); -set(h,'AlphaData',myFatAlpha); - -if size(structBoundaries,1) > 0 - p_count = p_count+1; - p(p_count) = fill(0, 0,'red','EdgeColor','none','FaceAlpha', 0.25,'DisplayName','Fat infiltration'); % plot a filled patch outside the plot region to add to the legend -end - -% --Osteochondroma segmentation-- - -%Segment using osteochondroma threshold -myOsteo = imbinarize(maskedImage,normalizedThresholdOsteochondroma); -myOsteo = imfill(myOsteo, 'holes'); % Fill holes - -% Plot osteochondroma surfaces -structBoundaries = bwboundaries(myOsteo); - -% The 'fill' function cannot handle hollow polygons (with holes = 2 -% boundaries). To overcome this difficulty, osteochondroma are plotted as -% a coloured overlay image with transparency zero outside osteochondroma -% and transparency 0.25 in osteochondroma regions. - -myOsteoAlpha = double(myOsteo); -myOsteoAlpha(myOsteo) = 0.5; -yellow=zeros(size(myOsteo,1),size(myOsteo,2),3); -yellow(:,:,1)=1; -yellow(:,:,2)=1; -h=imshow(yellow); -set(h,'AlphaData',myOsteoAlpha); - -if size(structBoundaries,1) > 0 - p_count = p_count+1; - p(p_count) = fill(0, 0,'yellow','EdgeColor','none','FaceAlpha', 0.5,'DisplayName','Osteochondroma'); % plot a filled patch outside the plot region to add to the legend -end - -% --Measure atrophy and degeneration so that Stot = Sa + Sm + Si + So-- - -muscle.caseID = caseID; -muscle.Stot = bwarea(contouredMuscle.binaryImage1); % Stot: total area of the muscle fossa (manually delimited contours) -muscle.Satrophy = bwarea(contouredMuscle.binaryImage1) - bwarea(myMuscle); % Sa: area of the atrophy (Stot - Sm) -muscle.Sinfiltration = bwarea(myFat); % Si: area of fat infiltration -muscle.Sosteochondroma = bwarea(myOsteo); % So: area of osteochondroma -muscle.Sdegeneration = muscle.Stot-muscle.Satrophy-muscle.Sinfiltration-muscle.Sosteochondroma; % Sm: area of the degenerated muscle, without atrophy, fat infiltration and osteochondroma - -muscle.atrophy = muscle.Satrophy/muscle.Stot; % ratio of muscle atrophy (area atrophy over total area of muscle fossa) -muscle.infiltration = muscle.Sinfiltration/muscle.Stot; % ratio of fat infiltration in the muscle (area fat infiltration over total area of muscle fossa) -muscle.osteochondroma = muscle.Sosteochondroma/muscle.Stot; % ratio of osteochondroma in the muscle (area osteochondroma over total area of muscle fossa) -muscle.degeneration = (muscle.Stot-muscle.Sdegeneration)/muscle.Stot; % the ratio of degeneration of the muscle (sum of atrophy, fat infiltration and osteochondroma over total area of muscle fossa) - - -% --Save images-- - -title({['Case ID: ' caseID]; [muscleName ' Muscle threshold: ' sprintf('%d',HUThresholdMuscle) ' HU']; sprintf('Muscle atrophy: %.2f%%, Muscle infiltration: %.2f%%, Osteochondroma: %.2f%%', ... - muscle.atrophy*100,muscle.infiltration*100,muscle.osteochondroma*100)}, 'FontSize', fontSize); -fig = get(groot,'CurrentFigure'); -fig.OuterPosition = [-1140 -1 871 1028]; -hLegend = legend(p); -set(hLegend.BoxFace, 'ColorType','truecoloralpha', 'ColorData',uint8(255*[.8;.8;.8;.8])); -hLegend.EdgeColor = 'none'; - -% % This piece of code can be used to make the rectangle patches in the -% legend have the correct alpha value (transparency) as used in the plot. -% Unfortunately, it doesnt work in MATLAB r2017a because calling the -% 'legend' function with multiple output arguments results in a graphics -% bug and prevent the rectangular patches to display. I keep this piece of -% code here, as this bug might be solved in a future version. -% -% VMC-29-Jun-2017 -% -% % Get handles of all patch objects in current axis: -% hla = findobj(gca,'type','patch'); -% -% % Get alpha properties of the current plotted patches: -% hlaFA = get(hla,'FaceAlpha'); -% hlaFC = get(hla,'FaceColor'); -% -% % Create a legend: -% [hLegend,oLegend,~,~]= legend(p); -% set(hLegend.BoxFace, 'ColorType','truecoloralpha', 'ColorData',uint8(255*[.8;.8;.8;.8])); -% hLegend.EdgeColor = 'none'; -% -% % Get handles of patch objects in the legend: -% hlp = findobj(oLegend,'type','patch'); -% -% % Set alpha values: -% for k = 1:length(hlp) -% set(hlp(k),'facec',hlaFC(k,:)); -% set(hlp(k),'facea',hlaFA(k)); -% end - -outputFile = sprintf('%sDegeneration%s_%d',char(muscleName),char(caseID),HUThresholdMuscle); -% saveas(gcf,sprintf('%s%s.png',[muscleDirectory '/' muscleName '/'],outputFile)) - -close all - -end - - - diff --git a/muscles/muscleDegeneration3D.m b/muscles/muscleDegeneration3D.m deleted file mode 100644 index b874fdb..0000000 --- a/muscles/muscleDegeneration3D.m +++ /dev/null @@ -1,235 +0,0 @@ -function muscle = muscleDegeneration3D(caseID,muscleName,HUThresholdMuscle,HUThresholdFat,HUThresholdOsteochondroma,muscleDirectory) -%%MUSCLEDEGENERATION3D computes degeneration parameters from muscle contours -% -% This function returns muscle atrophy, fat infiltration, osteochondroma -% and degeneration values computed from a CT slice for a given muscle -% -% USE: muscleDegeneration3D(caseID,muscleName,HUThresholdMuscle,HUThresholdOsteochondroma,muscleDirectory) -% -% INPUT caseID: patient number -% muscleName: name of the rotator cuff muscle being measured (SS,IS, SC or TM) -% HUThresholdMuscle: HU threshold used for muscle segmentation (atrophied muscle limit) -% HUThresholdFat: HU threshold used for fat infiltration segmentation (fat-muscle limit) -% HUThresholdOsteochondroma:HU threshold used for osteochondroma segmentation (muscle-osteochondroma limit) -% muscleDirectory: Path to 'muscles' directory where contours and output images are stored -% -% OUTPUT muscle: structure containing fields 'Stot', 'Satrophy', -% 'Sinfiltration', 'Sosteochondroma' and 'Sdegeneration', -% 'atrophy', 'infiltration', 'osteochondroma' and 'degeneration' -% -% REMARKS An image of the segmentation of atrophied muscle, fat -% infiltration and osteochondroma is saved in muscles directory, -% in the 'muscleName' folder. -% -% created with MATLAB ver.: 9.2.0.556344 (R2017a) on Windows 7 -% Author: EPFL-LBO-VMC -% Date: 29-Jun-2017 -% - -% Get slice number -segments = textscan(muscleDirectory,'%s','Delimiter','\'); -segments = segments{1}; -sliceNum = segments(end); - -% Find contours -inputFile = ['ssContours' caseID '_' sliceNum{1} '.mat']; -contouredMuscle = load([muscleDirectory '\' muscleName '\' inputFile]); - -% --Plot CT slice with all contours-- - -fontSize = 14; -visualizationWindow = [-100 200]; - -imshow(contouredMuscle.inputImage,visualizationWindow); - -hold on - -% --Atrophied muscle segmentation-- - -% MATLAB does not accept to threshold an image with a negative value, as is -% the case when using HU scale. CT scanners usually have a CT range from -% -1000 HU to 1000 HU or -2000 HU to 2000 HU for modern scanners. In this -% case, we're not using HU values lower than -1000 and higher than +1000 so -% all pixel intensity values of the input image< -1000 HU are set to -1000 -% HU, and values > 1000 HU are set to 1000 HU. Then, the input image is -% mapped to the [0 1] range -1000->0 1000->1, as are the thresholds for -% muscle and osteochondroma. - -% Normalize image and thresholds - -contouredMuscle.inputImage(contouredMuscle.inputImage < -1000) = -1000; -contouredMuscle.inputImage(contouredMuscle.inputImage > 1000) = 1000; - -rangeHU = double([-1000 1000]); - -% Binarization of images works so that pixel value > threshold is kept. So -% if you condier that a msucle is normal for 30 HU and abnormal for 29 HU, -% the threshold should be set at 29 HU. -normalizedThresholdMuscle = ((HUThresholdMuscle - 1)-rangeHU(1))/(rangeHU(2)-rangeHU(1)); -normalizedThresholdFat = ((HUThresholdFat - 1)-rangeHU(1))/(rangeHU(2)-rangeHU(1)); -normalizedThresholdOsteochondroma = ((HUThresholdOsteochondroma - 1)-rangeHU(1))/(rangeHU(2)-rangeHU(1)); - -normalizedInputImage = (double(contouredMuscle.inputImage)-rangeHU(1))/(rangeHU(2)-rangeHU(1)); - -% Mask image using muscle fossa contours -maskedImage = normalizedInputImage; -maskedImage(~contouredMuscle.binaryImage1) = 0; - -% Plot muscle fossa contours. -structBoundaries = bwboundaries(contouredMuscle.binaryImage1); -xy=structBoundaries{1}; % Get n by 2 array of x,y coordinates. -x = xy(:, 2); % Columns. -y = xy(:, 1); % Rows. -p = plot(x, y, 'color','green','DisplayName','Muscle fossa'); -p_count = 1; - -% Segment using muscle threshold -myMuscle = imbinarize(maskedImage,normalizedThresholdMuscle); -myMuscle = imfill(myMuscle, 'holes'); % Fill holes - -% Keep only the biggest connected component (i.e. remove islands) -CC = bwconncomp(myMuscle); -numPixels = cellfun(@numel,CC.PixelIdxList); -[~,idx] = max(numPixels); -myMuscle(:,:) = 0; -myMuscle(CC.PixelIdxList{idx}) = 1; - -% Plot atrophied muscle contours -structBoundaries = bwboundaries(myMuscle); - -if size(structBoundaries,1) > 0 - p_count = p_count+1; -end - -for i = 1:size(structBoundaries,1) - xy = structBoundaries{i}; % Get n by 2 array of x,y coordinates. - x = xy(:, 2); % Columns. - y = xy(:, 1); % Rows. - hold on; % Keep the image. - p(p_count) = plot(x, y, 'color','blue','DisplayName','Atrophied Muscle'); -end - -% --Fat infiltration segmentation-- - -% Mask image using atrophied muscle segmentation -maskedImage = normalizedInputImage; -maskedImage(~myMuscle) = 0; - -% Segment using fat threshold -myMuscleNoFat = imbinarize(maskedImage,normalizedThresholdFat); -myFat = ~myMuscleNoFat; -myFat(~myMuscle) = 0; - -% Plot fat infiltration surfaces -structBoundaries = bwboundaries(myFat); - -% The 'fill' function cannot handle hollow polygons (with holes = 2 -% boundaries). To overcome this difficulty, fat infiltration is plotted as -% a coloured overlay image with transparency zero outside fat regions and -% transparency 0.25 in fat regions. - -myFatAlpha = double(myFat); -myFatAlpha(myFat) = 0.25; -red=zeros(size(myFat,1),size(myFat,2),3); -red(:,:,1)=1; -h=imshow(red); -set(h,'AlphaData',myFatAlpha); - -if size(structBoundaries,1) > 0 - p_count = p_count+1; - p(p_count) = fill(0, 0,'red','EdgeColor','none','FaceAlpha', 0.25,'DisplayName','Fat infiltration'); % plot a filled patch outside the plot region to add to the legend -end - -% --Osteochondroma segmentation-- - -%Segment using osteochondroma threshold -myOsteo = imbinarize(maskedImage,normalizedThresholdOsteochondroma); -myOsteo = imfill(myOsteo, 'holes'); % Fill holes - -% Plot osteochondroma surfaces -structBoundaries = bwboundaries(myOsteo); - -% The 'fill' function cannot handle hollow polygons (with holes = 2 -% boundaries). To overcome this difficulty, osteochondroma are plotted as -% a coloured overlay image with transparency zero outside osteochondroma -% and transparency 0.25 in osteochondroma regions. - -myOsteoAlpha = double(myOsteo); -myOsteoAlpha(myOsteo) = 0.5; -yellow=zeros(size(myOsteo,1),size(myOsteo,2),3); -yellow(:,:,1)=1; -yellow(:,:,2)=1; -h=imshow(yellow); -set(h,'AlphaData',myOsteoAlpha); - -if size(structBoundaries,1) > 0 - p_count = p_count+1; - p(p_count) = fill(0, 0,'yellow','EdgeColor','none','FaceAlpha', 0.5,'DisplayName','Osteochondroma'); % plot a filled patch outside the plot region to add to the legend -end - -% --Measure atrophy and degeneration so that Stot = Sa + Sm + Si + So-- - -muscle.SliceNumber = str2double(sliceNum); - -muscle.Stot = bwarea(contouredMuscle.binaryImage1); % Stot: total area of the muscle fossa (manually delimited contours) -muscle.Satrophy = bwarea(contouredMuscle.binaryImage1) - bwarea(myMuscle); % Sa: area of the atrophy (Stot - Sm) -muscle.Sinfiltration = bwarea(myFat); % Si: area of fat infiltration -muscle.Sosteochondroma = bwarea(myOsteo); % So: area of osteochondroma -muscle.Sdegeneration = muscle.Stot-muscle.Satrophy-muscle.Sinfiltration-muscle.Sosteochondroma; % Sm: area of the degenerated muscle, without atrophy, fat infiltration and osteochondroma - -muscle.atrophy = muscle.Satrophy/muscle.Stot; % ratio of muscle atrophy (area atrophy over total area of muscle fossa) -muscle.infiltration = muscle.Sinfiltration/muscle.Stot; % ratio of fat infiltration in the muscle (area fat infiltration over total area of muscle fossa) -muscle.osteochondroma = muscle.Sosteochondroma/muscle.Stot; % ratio of osteochondroma in the muscle (area osteochondroma over total area of muscle fossa) -muscle.degeneration = (muscle.Stot-muscle.Sdegeneration)/muscle.Stot; % the ratio of degeneration of the muscle (sum of atrophy, fat infiltration and osteochondroma over total area of muscle fossa) - - -% --Save images-- - -title({['Case ID: ' caseID ', Slice #: ' sliceNum{1}]; [muscleName ' Muscle threshold: ' sprintf('%d',HUThresholdMuscle) ' HU']; sprintf('Muscle atrophy: %.2f%%, Muscle infiltration: %.2f%%, Osteochondroma: %.2f%%', ... - muscle.atrophy*100,muscle.infiltration*100,muscle.osteochondroma*100)}, 'FontSize', fontSize); -fig = get(groot,'CurrentFigure'); -fig.OuterPosition = [-1140 -1 871 1028]; -hLegend = legend(p); -set(hLegend.BoxFace, 'ColorType','truecoloralpha', 'ColorData',uint8(255*[.8;.8;.8;.8])); -hLegend.EdgeColor = 'none'; - -% % This piece of code can be used to make the rectangle patches in the -% legend have the correct alpha value (transparency) as used in the plot. -% Unfortunately, it doesnt work in MATLAB r2017a because calling the -% 'legend' function with multiple output arguments results in a graphics -% bug and prevent the rectangular patches to display. I keep this piece of -% code here, as this bug might be solved in a future version. -% -% VMC-29-Jun-2017 -% -% % Get handles of all patch objects in current axis: -% hla = findobj(gca,'type','patch'); -% -% % Get alpha properties of the current plotted patches: -% hlaFA = get(hla,'FaceAlpha'); -% hlaFC = get(hla,'FaceColor'); -% -% % Create a legend: -% [hLegend,oLegend,~,~]= legend(p); -% set(hLegend.BoxFace, 'ColorType','truecoloralpha', 'ColorData',uint8(255*[.8;.8;.8;.8])); -% hLegend.EdgeColor = 'none'; -% -% % Get handles of patch objects in the legend: -% hlp = findobj(oLegend,'type','patch'); -% -% % Set alpha values: -% for k = 1:length(hlp) -% set(hlp(k),'facec',hlaFC(k,:)); -% set(hlp(k),'facea',hlaFA(k)); -% end - -sliceNum = sprintf(num2str(str2double(sliceNum{1}),'%03i')); -outputFile = sprintf('%sDegeneration%s_%s',muscleName,caseID,sliceNum); -saveas(gcf,sprintf('%s%s.png',[muscleDirectory '\'],outputFile)); - -close all - -end - - - diff --git a/muscles/rebuildDatabaseMuscleMeasurements.m b/muscles/rebuildDatabaseMuscleMeasurements.m deleted file mode 100644 index 1006673..0000000 --- a/muscles/rebuildDatabaseMuscleMeasurements.m +++ /dev/null @@ -1,25 +0,0 @@ -% This script builds a cell array listing all caseIDs in the CT database -% for which an Amira folder exists and scapula measurements can be -% computed. Then computes scapula anatomical data for these cases. - -CTDatabaseLocation = 'Z://data'; % Location of the CT database -CaseType = ['P';'N']; % Folders to be reconstructed - -CaseIDsList = cell(0,0); - -for i=1:length(CaseType) %Loop - for j=0:9 - for k=0:9 - listDirInCurrDir = dir([CTDatabaseLocation '/' CaseType(i) '/' int2str(j) '/' int2str(k) '/' CaseType(i) '*']); - if (~isempty(listDirInCurrDir)) - for m=1:length(listDirInCurrDir) - if exist([CTDatabaseLocation '/' CaseType(i) '/' int2str(j) '/' int2str(k) '/' listDirInCurrDir(m).name '/CT-' listDirInCurrDir(m).name '-1/muscles'],'dir') == 7 %if a folder "muscles" exist, the case ID is added to the list - CaseIDsList{end+1,1} = strtok(listDirInCurrDir(m).name,'-'); - end - end - end - end - end -end - -degenerationAll(CaseIDsList,[{'IS'};{'SC'};{'SS'};{'TM'}]); \ No newline at end of file diff --git a/openConfigFile_before20190211.m b/openConfigFile_before20190211.m deleted file mode 100644 index a02eef6..0000000 --- a/openConfigFile_before20190211.m +++ /dev/null @@ -1,40 +0,0 @@ -function dataDir = openConfigFile(configFile, logFileID) -%OPENCONFIGFILE open file config.txt and read dataDir -% Config file must follow specific/restrictive rules - -% The file config.txt should be writen as below. -% One line should contain dataDir = - -%{ -% This configuration file contains the definition of variable dataDir for database access. -% It is used by functions: listSCase.m, measureSCase.m, plotScase.m -% /home/shoulder/data <-- acces data dir from lbovenus or lbomars (default) -% /home/shoulder/dataDev <-- acces dataDev dir from lbovenus or lbomars -% /Volumes/shoulder/data <-- acces data dir from lbovenus/lbomars mounted on macos -% /Volumes/shoulder/dataDev <-- acces dataDev dir from lbovenus mounted on macos -% Z:\data <-- acces data dir from lbovenus/lbomars mounted on windows -% Z:\dataDev <-- acces dataDev dir from lbovenus mounted on windows -dataDir = /Volumes/shoulder/dataDev -%} - -% Author: AT -% Date: 2019-01-15 -% TODO: Less restrict rules for writting config.txt - -if ~exist(configFile, 'file') - error([configFile, ' required']); -end -fileID = fopen(configFile,'r'); -dataDir = fscanf(fileID, '%s'); % Read config file without spaces -fclose(fileID); -k = strfind(dataDir, 'dataDir='); % Find definition of dataDir -k = k + 8; % Remove 'dataDir=' -dataDir = dataDir(k:end); % Assume that config file ends with dataDir content -% Check if dataDir exists -if ~exist(dataDir, 'dir') - fprintf(logFileID, ['Data directory not found, check ' configFile]); - error(['Data directory not found, check ' configFile]); -end - -end - diff --git a/readDicomMetaData.m b/readDicomMetaData.m deleted file mode 100644 index dfab71f..0000000 --- a/readDicomMetaData.m +++ /dev/null @@ -1,111 +0,0 @@ -%% Import data from text file. -% Script for importing data from the following text file: -% -% Y:\data\P\4\1\P411-2584882\dicomInfo411-3.txt -% -% To extend the code to different selected data or a different text file, -% generate a function instead of a script. - -% Auto-generated by MATLAB on 2018/09/26 15:05:09 - -basedir = '//lbovenus.epfl.ch/shoulder/data/'; -casedir = [basedir 'P/4/1/P411-2584882/']; -CTdir = [casedir 'CT-P411-2584882-2/']; -dicomFileName=[CTdir 'dicom/P411-2584882_CA-soft.0001.dcm']; - -dicomMetaData=evalc('dicomdisp(dicomFileName)'); -fid=fopen([CTdir 'metadata.txt'],'wt'); -fprintf(fid,'%s',string(dicomMetaData)); -fclose(fid); - - -%% Initialize variables. -filename = [CTdir 'metadata.txt']%'Y:\data\P\4\1\P411-2584882\dicomInfo411-3.txt'; -delimiter = {'\t',' '}; -startRow = 3; - -%% Read columns of data as text: -% For more information, see the TEXTSCAN documentation. -formatSpec = '%s%s%s%s%s%s%s%s%s%s%s%s%s%[^\n\r]'; - -%% Open the text file. -fileID = fopen(filename,'r'); - -%% Read columns of data according to the format. -% This call is based on the structure of the file used to generate this -% code. If an error occurs for a different file, try regenerating the code -% from the Import Tool. -dataArray = textscan(fileID, formatSpec, 'Delimiter', delimiter, 'MultipleDelimsAsOne', true, 'TextType', 'string', 'HeaderLines' ,startRow-1, 'ReturnOnError', false, 'EndOfLine', '\r\n'); - -%% Close the text file. -fclose(fileID); - -%% Convert the contents of columns containing numeric text to numbers. -% Replace non-numeric text with NaN. -raw = repmat({''},length(dataArray{1}),length(dataArray)-1); -for col=1:length(dataArray)-1 - raw(1:length(dataArray{col}),col) = mat2cell(dataArray{col}, ones(length(dataArray{col}), 1)); -end -numericData = NaN(size(dataArray{1},1),size(dataArray,2)); - -for col=[1,2,3,5] - % Converts text in the input cell array to numbers. Replaced non-numeric - % text with NaN. - rawData = dataArray{col}; - for row=1:size(rawData, 1) - % Create a regular expression to detect and remove non-numeric prefixes and - % suffixes. - regexstr = '(?.*?)(?([-]*(\d+[\,]*)+[\.]{0,1}\d*[eEdD]{0,1}[-+]*\d*[i]{0,1})|([-]*(\d+[\,]*)*[\.]{1,1}\d+[eEdD]{0,1}[-+]*\d*[i]{0,1}))(?.*)'; - try - result = regexp(rawData(row), regexstr, 'names'); - numbers = result.numbers; - - % Detected commas in non-thousand locations. - invalidThousandsSeparator = false; - if numbers.contains(',') - thousandsRegExp = '^\d+?(\,\d{3})*\.{0,1}\d*$'; - if isempty(regexp(numbers, thousandsRegExp, 'once')) - numbers = NaN; - invalidThousandsSeparator = true; - end - end - % Convert numeric text to numbers. - if ~invalidThousandsSeparator - numbers = textscan(char(strrep(numbers, ',', '')), '%f'); - numericData(row, col) = numbers{1}; - raw{row, col} = numbers{1}; - end - catch - raw{row, col} = rawData{row}; - end - end -end - - -%% Split data into numeric and string columns. -rawNumericColumns = raw(:, [1,2,3,5]); -rawStringColumns = string(raw(:, [4,6,7,8,9,10,11,12,13])); - - -%% Replace non-numeric cells with NaN -R = cellfun(@(x) ~isnumeric(x) && ~islogical(x),rawNumericColumns); % Find non-numeric cells -rawNumericColumns(R) = {NaN}; % Replace non-numeric cells - -%% Make sure any text containing is properly converted to an categorical -for catIdx = [1,2,3,6] - idx = (rawStringColumns(:, catIdx) == ""); - rawStringColumns(idx, catIdx) = ""; -end - -%% Create output variable -dicomMetaData = table; -dicomMetaData.Location = cell2mat(rawNumericColumns(:, 1)); -dicomMetaData.Level = cell2mat(rawNumericColumns(:, 2)); -dicomMetaData.Tag = cell2mat(rawNumericColumns(:, 3)); -dicomMetaData.VR = categorical(rawStringColumns(:, 1)); -dicomMetaData.Size = cell2mat(rawNumericColumns(:, 4)); -dicomMetaData.Name = categorical(rawStringColumns(:, 4)); -dicomMetaData.Data = categorical(rawStringColumns(:, 5)); - -%% Clear temporary variables -clearvars filename delimiter startRow formatSpec fileID dataArray ans raw col numericData rawData row regexstr result numbers invalidThousandsSeparator thousandsRegExp rawNumericColumns rawStringColumns R catIdx idx; \ No newline at end of file diff --git a/tempInfo.mat b/tempInfo.mat deleted file mode 100644 index 5714719..0000000 Binary files a/tempInfo.mat and /dev/null differ