From 8da7d3725f3b22fb88fbe544d0bb49ec62d7bf9c Mon Sep 17 00:00:00 2001 From: jpr Date: Wed, 25 Jan 2006 11:08:17 +0000 Subject: [PATCH] Add MagnetomVisionToBrucker Fix PhilipsToBrucker2 --- Example/CMakeLists.txt | 3 +- Example/MagnetomVisionToBrucker.cxx | 530 ++++++++++++++++++++++++++++ Example/PhilipsToBrucker2.cxx | 6 +- 3 files changed, 535 insertions(+), 4 deletions(-) create mode 100755 Example/MagnetomVisionToBrucker.cxx diff --git a/Example/CMakeLists.txt b/Example/CMakeLists.txt index d306878f..b98cf114 100644 --- a/Example/CMakeLists.txt +++ b/Example/CMakeLists.txt @@ -29,7 +29,8 @@ SET(EXAMPLE_SOURCES AnonymizeNoLoad # without loading the Pixel Data PatchHeader PhilipsToBrucker - PhilipsToBrucker2 + PhilipsToBrucker2 + MagnetomVisionToBrucker ReWrite RawToDicom TestValidate diff --git a/Example/MagnetomVisionToBrucker.cxx b/Example/MagnetomVisionToBrucker.cxx new file mode 100755 index 00000000..123eaaf7 --- /dev/null +++ b/Example/MagnetomVisionToBrucker.cxx @@ -0,0 +1,530 @@ +/*========================================================================= + + Program: gdcm + Module: $RCSfile: MagnetomVisionToBrucker.cxx,v $ + Language: C++ + Date: $Date: 2006/01/25 11:08:17 $ + Version: $Revision: 1.1 $ + + Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de + l'Image). All rights reserved. See Doc/License.txt or + http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "gdcmDocEntry.h" +#include "gdcmDicomDir.h" +#include "gdcmDicomDirPatient.h" +#include "gdcmFile.h" +#include "gdcmFileHelper.h" +#include "gdcmDirList.h" +#include "gdcmDebug.h" +#include "gdcmArgMgr.h" +#include "gdcmUtil.h" +#include "gdcmSerieHelper.h" + +#include + +/** + * \brief + * - explores recursively the given directory + * - keeps the requested series + * - orders the gdcm-readable found Files + * according to their Patient/Study/Serie/Image characteristics + * - fills a single level Directory with *all* the files, + * converted into a Brucker-like Dicom, Intags compliant + * + */ + +typedef std::map SortedFiles; + +int main(int argc, char *argv[]) +{ + START_USAGE(usage) + " \n MagnetomVisionToBrucker :\n ", + " - explores recursively the given directory, ", + " - keeps the requested series/ drops the unrequested series ", + " - orders the gdcm-readable found Files according to their ", + " (0x0010, 0x0010) Patient's Name ", + " (0x0020, 0x000e) Series Instance UID ", + " (0x0020, 0x0032) Image Position (RET) ", + " (0x0018, 0x1060) Trigger Time ", + " - fills a single level (*) Directory with *all* the files, ", + " converted into a Brucker-like Dicom, InTags compliant ", + " (*) actually : creates as many directories as Patients ", + " -that shouldn't appear, but being carefull is better ! -", + " or ", + " - fills a tree-like structure of directories as : ", + " - Patient ", + " -- Serie ", + " --- Position ", + " Images are (sorted by Trigger Time / ", + " Encoding Direction (Row, Column) ", + " use : ", + " 0x0021, 0x1020 : 'SLICE INDEX' ", + " 0x0021, 0x1040 : 'FRAME INDEX' ", + " 0x0020, 0x0012 : 'SESSION INDEX' (Acquisition Number) ", + " usage: ", + " PhilipsToBrucker dirin=rootDirectoryName ", + " dirout=outputDirectoryName ", + " { [keep= list of seriesNumber to process] ", + " | [drop= list of seriesNumber to ignore] } ", + " [input = {ACR|DCM}] ", + " [extent=image suffix (.IMA, .NEMA, .DCM, ...)] ", + " [listonly] [split] ", + " [noshadowseq][noshadow][noseq] [verbose] [debug] ", + " ", + " dirout : will be created if doesn't exist ", + " keep : if user wants to process a limited number of series ", + " he gives the list of 'SeriesNumber' (tag 0020|0011) ", + " drop : if user wants to ignore a limited number of series ", + " he gives the list of 'SeriesNumber' (tag 0020|0011) ", + " SeriesNumber are short enough to be human readable ", + " e.g : 1030,1035,1043 ", + " extent : DO NOT forget the leading '.' ! ", + " split: creates a tree-like structure of directories as : ", + " - Patient ", + " -- Serie ", + " --- Position ", + " Images are (sorted by Trigger Time / ", + " noshadowseq: user doesn't want to load Private Sequences ", + " noshadow : user doesn't want to load Private groups (odd number) ", + " noseq : user doesn't want to load Sequences ", + " verbose : user wants to run the program in 'verbose mode' ", + " debug : *developer* wants to run the program in 'debug mode' ", + FINISH_USAGE + + // ----- Initialize Arguments Manager ------ + + gdcm::ArgMgr *am = new gdcm::ArgMgr(argc, argv); + + if (argc == 1 || am->ArgMgrDefined("usage")) + { + am->ArgMgrUsage(usage); // Display 'usage' + delete am; + return 0; + } + + char *dirNamein; + dirNamein = am->ArgMgrGetString("dirin",(char *)"."); + + char *dirNameout; + dirNameout = am->ArgMgrGetString("dirout",(char *)"."); + + int loadMode = gdcm::LD_ALL; + if ( am->ArgMgrDefined("noshadowseq") ) + loadMode |= gdcm::LD_NOSHADOWSEQ; + else + { + if ( am->ArgMgrDefined("noshadow") ) + loadMode |= gdcm::LD_NOSHADOW; + if ( am->ArgMgrDefined("noseq") ) + loadMode |= gdcm::LD_NOSEQ; + } + + if (am->ArgMgrDefined("debug")) + gdcm::Debug::DebugOn(); + + bool verbose = am->ArgMgrDefined("verbose"); + bool split = am->ArgMgrDefined("split"); + bool listonly = am->ArgMgrDefined("listonly"); + + int nbSeriesToKeep; + int *seriesToKeep = am->ArgMgrGetListOfInt("keep", &nbSeriesToKeep); + int nbSeriesToDrop; + int *seriesToDrop = am->ArgMgrGetListOfInt("drop", &nbSeriesToDrop); + + if ( nbSeriesToKeep!=0 && nbSeriesToDrop!=0) + { + std::cout << "KEEP and DROP are mutually exclusive !" << std::endl; + delete am; + return 0; + } + + char *extent = am->ArgMgrGetString("extent",".DCM"); + + char *input = am->ArgMgrGetString("input","DCM"); + + // if unused Param we give up + if ( am->ArgMgrPrintUnusedLabels() ) + { + am->ArgMgrUsage(usage); + delete am; + return 0; + } + delete am; // we don't need Argument Manager any longer + + // ----- Begin Processing ----- + + if ( ! gdcm::DirList::IsDirectory(dirNamein) ) + { + std::cout << "KO : [" << dirNamein << "] is not a Directory." << std::endl; + exit(0); + } + else + { + std::cout << "OK : [" << dirNamein << "] is a Directory." << std::endl; + } + + std::string systemCommand; + + std::cout << "Check for output directory :[" << dirNameout << "]." + <SetDirectory(dirNamein, true); // true : recursive exploration + s->SetUseSeriesDetails(true); + s->AddSeriesDetail(0x0018, 0x1312); + s->Print(); +*/ + + gdcm::File *f; + gdcm::FileHelper *fh; +/* + std::cout << "---------------Print Unique Series identifiers---------" + << std::endl; + std::string uniqueSeriesIdentifier; + + for (gdcm::DirListType::iterator it = fileNames.begin(); + it != fileNames.end(); + ++it) + { + std::cout << "File Name : " << *it << std::endl; + f = gdcm::File::New(); + f->SetLoadMode(gdcm::LD_ALL); + f->SetFileName( *it ); + f->Load(); + + uniqueSeriesIdentifier=s->CreateUniqueSeriesIdentifier(f); + std::cout << " [" << + uniqueSeriesIdentifier << "]" << std::endl; + f->Delete(); + } +*/ + + if (verbose) + std::cout << "------------------Print Break levels-----------------" << std::endl; + + std::string userFileIdentifier; + SortedFiles sf; + + s->AddSeriesDetail(0x0010, 0x0010, false); // Patient's Name + s->AddSeriesDetail(0x0020, 0x0010, false); // Study ID - Siemens, in that time! + s->AddSeriesDetail(0x0020, 0x0030, false); // Image Position (RET) + s->AddSeriesDetail(0x0020, 0x0013, false); // Instance Number + //(called 'Trigger Time' in order not to change too much the code) + + for (gdcm::DirListType::iterator it = fileNames.begin(); + it != fileNames.end(); + ++it) + { + f = gdcm::File::New(); + f->SetLoadMode(loadMode); + f->SetFileName( *it ); + f->Load(); + + // keep only requested Series + std::string strSeriesNumber; + int seriesNumber; + int j; + + bool keep = false; + if (nbSeriesToKeep != 0) + { + strSeriesNumber = f->GetEntryString(0x0020, 0x0011 ); + seriesNumber = atoi( strSeriesNumber.c_str() ); + for (j=0;jDelete(); + continue; + } + } + // drop all unrequested Series + bool drop = false; + if (nbSeriesToDrop != 0) + { + strSeriesNumber = f->GetEntryString(0x0020, 0x0011 ); + seriesNumber = atoi( strSeriesNumber.c_str() ); + for (j=0;jDelete(); + continue; + } + } + + userFileIdentifier=s->CreateUserDefinedFileIdentifier(f); + // userFileIdentifier += "_"; + //userFileIdentifier += *it; + std::cout << " [" << + userFileIdentifier << "]" << std::endl; + + // storing in a map ensures automatic sorting ! + sf[userFileIdentifier] = f; + } + + std::vector tokens; + std::string fullFilename, lastFilename; + std::string previousPatientName, currentPatientName; + std::string previousSerieInstanceUID, currentSerieInstanceUID; + std::string previousImagePosition, currentImagePosition; + //std::string previousPhaseEncodingDirection, currentPhaseEncodingDirection; + std::string previousTriggerTime, currentTriggerTime; + + std::string writeDir, currentWriteDir; + std::string currentPatientWriteDir, currentSerieWriteDir, + currentPositionWriteDir; // currentPhaseEncodingDirectionWriteDir; + + std::string fullWriteFilename; + std::string strExtent(extent); + + writeDir = gdcm::Util::NormalizePath(dirNameout); + SortedFiles::iterator it2; + + previousPatientName = ""; + previousSerieInstanceUID = ""; + previousImagePosition = ""; + //previousPhaseEncodingDirection = ""; + previousTriggerTime = ""; + + int sliceIndex = 1; + int frameIndex = 1; + int flag = 0; + + gdcm::File *currentFile; + + for (it2 = sf.begin() ; it2 != sf.end(); ++it2) + { + currentFile = it2->second; + + fullFilename = currentFile->GetFileName(); + lastFilename = gdcm::Util::GetName( fullFilename ); + std::cout << "Try to write" <first, tokens, "_"); + + currentPatientName = tokens[0]; + currentSerieInstanceUID = tokens[1]; + currentImagePosition = tokens[2]; + currentTriggerTime = tokens[3]; + //currentPhaseEncodingDirection = tokens[4]; + + if ( currentImagePosition[0] == '-') + currentImagePosition[0] = 'M'; + if ( currentImagePosition[0] == '+') + currentImagePosition[0] = 'P'; + + if (previousPatientName != currentPatientName) + { + previousPatientName = currentPatientName; + if (verbose) + std::cout << "==== new Patient [" << currentPatientName << "]" << std::endl; + + previousPatientName = currentPatientName; + previousSerieInstanceUID = ""; //currentSerieInstanceUID; + previousImagePosition = ""; //currentImagePosition; + previousTriggerTime = ""; + // previousPhaseEncodingDirection = ""; //currentPhaseEncodingDirection; + + currentPatientWriteDir = writeDir + currentPatientName; + //if ( ! gdcm::DirList::IsDirectory(currentPatientWriteDir) ) + { + systemCommand = "mkdir " + currentPatientWriteDir; + if (verbose) + std::cout << systemCommand << std::endl; + system ( systemCommand.c_str() ); + } + } + + if (previousSerieInstanceUID != currentSerieInstanceUID) + { + if (verbose) + std::cout << "==== === new Serie [" << currentSerieInstanceUID << "]" + << std::endl; + if (split) + { + currentSerieWriteDir = currentPatientWriteDir + gdcm::GDCM_FILESEPARATOR + + currentSerieInstanceUID; + systemCommand = "mkdir " + currentSerieWriteDir; + system (systemCommand.c_str()); + } + previousSerieInstanceUID = currentSerieInstanceUID; + previousImagePosition = ""; //currentImagePosition; + //previousPhaseEncodingDirection = ""; //currentPhaseEncodingDirection; + } + + if (previousImagePosition != currentImagePosition) + { + frameIndex = 1; + flag = 0; + if (verbose) + std::cout << "=== === === new Position [" << currentImagePosition << "]" + << std::endl; + if (split) + { + currentPositionWriteDir = currentSerieWriteDir + gdcm::GDCM_FILESEPARATOR + + currentImagePosition; + systemCommand = "mkdir " + currentPositionWriteDir; + system (systemCommand.c_str()); + } + previousImagePosition = currentImagePosition; + //previousPhaseEncodingDirection = ""; //currentPhaseEncodingDirection; + sliceIndex += 1; + } + +// We don't split on Row/Column! +/* + if (previousPhaseEncodingDirection != currentPhaseEncodingDirection) + { + if (verbose) + std::cout << "==== === === === new PhaseEncodingDirection [" + << currentPhaseEncodingDirection << "]" << std::endl; + + if (split) + { + currentPhaseEncodingDirectionWriteDir = currentPositionWriteDir + + gdcm::GDCM_FILESEPARATOR + + currentPhaseEncodingDirection; + systemCommand = "mkdir " + currentPhaseEncodingDirectionWriteDir; + system (systemCommand.c_str()); + } + + previousPhaseEncodingDirection = currentPhaseEncodingDirection; + } +*/ + + if (verbose) + std::cout << "--- --- --- --- --- " << (it2->second)->GetFileName() + << std::endl; + + if ( gdcm::Debug::GetDebugFlag()) + std::cout << "--- --- --- --- --- " << it2->first << " " + << (it2->second)->GetFileName() << " " + << gdcm::Util::GetName( fullFilename ) << std::endl; + + // Transform the image to be 'Brucker-Like' + // ---------------------------------------- + + // Deal with 0x0019, 0x1000 : 'FOV' + int nX = currentFile->GetXSize(); + int nY = currentFile->GetYSize(); + float pxSzX = currentFile->GetXSpacing(); + float pxSzY = currentFile->GetYSpacing(); + char fov[64]; + sprintf(fov, "%f\\%f",nX*pxSzX, nY*pxSzY); + currentFile->InsertEntryString(fov, 0x0019, 0x1000, "DS"); + + // Deal with 0x0020, 0x0012 : 'SESSION INDEX' (Acquisition Number) + std::string chSessionIndex = "1"; + /* + if (currentPhaseEncodingDirection == "ROW") + chSessionIndex = "1"; + else + chSessionIndex = "2"; // suppose it's "COLUMN" ! + currentFile->InsertEntryString(chSessionIndex, 0x0020, 0x0012, "IS"); + */ + // Deal with 0x0021, 0x1020 : 'SLICE INDEX' + char chSliceIndex[5]; + sprintf(chSliceIndex, "%04d", sliceIndex); + std::string strChSliceIndex(chSliceIndex); + currentFile->InsertEntryString(strChSliceIndex, 0x0021, 0x1020, "IS"); + + // Deal with 0x0021, 0x1040 : 'FRAME INDEX' + char chFrameIndex[5]; + sprintf(chFrameIndex, "%04d", frameIndex); + currentFile->InsertEntryString(chFrameIndex, 0x0021, 0x1040, "IS"); + + if (flag == 0) + { + flag = 1; + } + else + { + frameIndex++; + flag = 0; + } + + if (split) + + //fullWriteFilename = currentPhaseEncodingDirectionWriteDir + gdcm::GDCM_FILESEPARATOR + // + lastFilename + strExtent; + fullWriteFilename = currentPositionWriteDir + gdcm::GDCM_FILESEPARATOR + + lastFilename + strExtent; + else + fullWriteFilename = currentPatientWriteDir + gdcm::GDCM_FILESEPARATOR + + lastFilename + strExtent; + + /* + systemCommand = "cp " + fullFilename + " " + fullWriteFilename; + std::cout << systemCommand << std::endl; + system ( systemCommand.c_str() ); + */ + + // Load the pixels in RAM. + + fh = gdcm::FileHelper::New(currentFile); + fh->GetImageDataRaw(); // Don't convert (Gray Pixels + LUT) into (RGB pixels) ?!? + fh->SetWriteTypeToDcmExplVR(); + if (!fh->Write(fullWriteFilename)) + { + std::cout << "Fail to write :[" << fullWriteFilename << "]" + << std::endl; + } + fh->Delete(); + } + } diff --git a/Example/PhilipsToBrucker2.cxx b/Example/PhilipsToBrucker2.cxx index d8709c8d..50395e58 100755 --- a/Example/PhilipsToBrucker2.cxx +++ b/Example/PhilipsToBrucker2.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: PhilipsToBrucker2.cxx,v $ Language: C++ - Date: $Date: 2006/01/24 03:06:46 $ - Version: $Revision: 1.5 $ + Date: $Date: 2006/01/25 11:08:18 $ + Version: $Revision: 1.6 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -341,7 +341,7 @@ int main(int argc, char *argv[]) previousPhaseEncodingDirection = ""; previousTriggerTime = ""; - int sliceIndex = 1; + int sliceIndex = 0; // Is incremented *at the beginning* of processing int frameIndex = 1; int flag = 0; -- 2.45.1