From: jean-pierre roux Date: Wed, 13 May 2009 15:37:43 +0000 (+0000) Subject: Initial revision X-Git-Tag: initial-import~1 X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?p=creaBruker.git;a=commitdiff_plain;h=0194cf3ca5e4249a389cc809d3de6fae07249fa4 Initial revision --- 0194cf3ca5e4249a389cc809d3de6fae07249fa4 diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..5e463bc --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,70 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +################################### +PROJECT(creaBruker) +################################### + +#================================== +# The project version +SET(PROJECT_MAJOR_VERSION 1) +SET(PROJECT_MINOR_VERSION 0) +SET(PROJECT_BUILD_VERSION 0) +#================================== + +#================================== +# Find crea (mandatory to use macros) +SET(CREA_VERBOSE_CMAKE TRUE) +FIND_PACKAGE(crea REQUIRED) +IF (crea_FOUND) + INCLUDE(${crea_USE_FILE}) +ENDIF(crea_FOUND) +#================================== + +#================================== +# Do not allow to build inside the source tree +CREA_PREVENT_IN_SOURCE_BUILD() +#================================== + +#================================== +# Libraries/tools used +# Note : Set USE_CREA to ON +# if you need to LINK against crea +# (and not only use its macros) +SET(USE_CREA ON) +SET(USE_GDCM ON) +SET(USE_GDCM_VTK OFF) +SET(USE_GDCM2 OFF) +SET(USE_WXWIDGETS OFF) +SET(USE_KWWIDGETS OFF) +SET(USE_VTK OFF) +SET(USE_ITK OFF) +SET(USE_BOOST ON) +SET(USE_DOXYGEN ON) +SET(USE_LATEX OFF) +SET(USE_TTH OFF) + +CREA_FIND_AND_USE_LIBRARIES() +#================================== + +#================================== +# Where to put executables and libs +SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}) +SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}) +MARK_AS_ADVANCED( + CMAKE_BACKWARDS_COMPATIBILITY + EXECUTABLE_OUTPUT_PATH + LIBRARY_OUTPUT_PATH + ) +#================================== + + SET(LIBNAME $(PROJECT_NAME)) + INCLUDE_DIRECTORIES( + ${PROJECT_BINARY_DIR} + ${PROJECT_SOURCE_DIR}/lib/src1 + ) +#================================== +# Subdirs +SUBDIRS(lib) +SUBDIRS(appli) + +#================================== diff --git a/appli/CMakeLists.txt b/appli/CMakeLists.txt new file mode 100644 index 0000000..282a754 --- /dev/null +++ b/appli/CMakeLists.txt @@ -0,0 +1,22 @@ + +SUBDIRS( +# ==> mettez ici la liste des directories qui contiennent +# ==> les fichiers sources de chacune de vos applications +# ==> Selon que l'application utilise ou non wX, vous duppliquerez +# ==> l'un ou l'autre des directories WithWx ou WithoutWx +# +# ==> Here, the list of the directories that hold +# ==> the source files of each one of your applications +# ==> Depending on the use or not of Wx, +# ==> You will dupplicate WithWx or WithoutWx +# + essaiDenis + #SimpleBrukerToMhdDcm + PrintParameterFile + #exObjectVaryingProperties + testBruker2Dicom + #appli1_WithoutWx + #appli2_WithWx + + # some more directories, if you have more appli +) diff --git a/appli/PrintParameterFile/CMakeLists.txt b/appli/PrintParameterFile/CMakeLists.txt new file mode 100755 index 0000000..17dc39b --- /dev/null +++ b/appli/PrintParameterFile/CMakeLists.txt @@ -0,0 +1,42 @@ + + #---------------------------------------------------------------------------- +# SET THE NAME OF YOUR EXECUTABLE +SET ( EXE_NAME PrintParameterFile ) +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# EXECUTABLE SOURCES (TO BE COMPILED) +# EITHER LIST ALL .cxx, *.cpp, *.cc IN CURRENT DIR USING NEXT LINE: +FILE(GLOB ${EXE_NAME}_SOURCES *.cxx *.cpp *.cc) +# OR MANUALLY LIST YOUR FILES WITH NEXT COMMAND (WITHOUT EXTENSION) +# SET ( ${EXE_NAME}_SOURCES +# +# ) +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# DEPENDENCIES (LIBRARIES TO LINK WITH) +SET ( ${EXE_NAME}_LINK_LIBRARIES + ${crea_LIBRARIES} + # ${WXWIDGETS_LIBRARIES} + # ${KWWidgets_LIBRARIES} + # ${VTK_LIBRARIES} + # ${ITK_LIBRARIES} + ${GDCM_LIBRARIES} + ${BOOST_LIBRARIES} + + creaBruker + ) + +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# CREATES AND INSTALLS THE EXE +# Set to ON if your appli has a GUI (to build as a Win32 app on windows) +SET(${EXE_NAME}_HAS_GUI OFF) +# Set to ON if your appli has a GUI but you also want a msdos console on windows +SET(${EXE_NAME}_CONSOLE OFF) +CREA_ADD_EXECUTABLE( ${EXE_NAME} ) +#---------------------------------------------------------------------------- + + diff --git a/appli/PrintParameterFile/PrintParameterFile.cxx b/appli/PrintParameterFile/PrintParameterFile.cxx new file mode 100644 index 0000000..dd4f3df --- /dev/null +++ b/appli/PrintParameterFile/PrintParameterFile.cxx @@ -0,0 +1,69 @@ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include "brukerdataset.h" +//#include "brukerkspaceobject.h" + +#include "gdcmArgMgr.h" +#include "gdcmDebug.h" +//#include "gdcmUtil.h" + + +int main(int argc, char *argv[]) +{ + START_USAGE(usage) + " \n PrintParameterFile : \n ", + " - explores the given Bruker parameter file, ", + " - prints its content, ", + " usage: BrukerToMhd filein=rukerParameterFile ", + " [debug] [verbose] ", + " ", + " debug : developper wants to run the program in 'debug mode' ", + FINISH_USAGE + +// ------------ Initialize Arguments Manager ---------------- + GDCM_NAME_SPACE::ArgMgr *am= new GDCM_NAME_SPACE::ArgMgr(argc, argv); + + if (argc == 1 || am->ArgMgrDefined("usage") ) + { + am->ArgMgrUsage(usage); // Display 'usage' + delete am; + return 1; + } + + const char *fileNamein; + fileNamein = am->ArgMgrWantString("filein",usage); + + if (am->ArgMgrDefined("debug")) + GDCM_NAME_SPACE::Debug::DebugOn(); + + /* if unused Param we give up */ + if ( am->ArgMgrPrintUnusedLabels() ) + { + am->ArgMgrUsage(usage); + delete am; + return 1; + } + + delete am; // we don't need Argument Manager any longer + + // ----------- End Arguments Manager --------- + + BrukerDataSet br1; + //BrukerKspaceObject bro1(br1); + std::string file2Read(fileNamein); + br1.LoadFile(file2Read); +std::cout << "=============== FillMap =================" << std::endl; + br1.FillMap(); +std::cout << "=============== End FillMap =================" << std::endl; + + std::cout << "=============== PrintSelf =================" << std::endl; + br1.PrintSelf(); + std::cout << "=============== End PrintSelf =============" << std::endl; + + return EXIT_SUCCESS; +} diff --git a/appli/PrintParameterFile/README.txt b/appli/PrintParameterFile/README.txt new file mode 100755 index 0000000..595b892 --- /dev/null +++ b/appli/PrintParameterFile/README.txt @@ -0,0 +1,7 @@ + # ==> + # ==> Dans ce directory : les fichiers sources qui composent l'application (sans Wx) + # + # ==> In this directory : the source files that compose the (Wx less) application + # ==> + + diff --git a/appli/README.txt b/appli/README.txt new file mode 100644 index 0000000..e2c0ab8 --- /dev/null +++ b/appli/README.txt @@ -0,0 +1,14 @@ +Une 'vraie' application (contrairement `a un 'exemple') est succeptible d'^etre +r'epartie sur plusieurs fichiers sources. +Par convention, nous consid`ererons qu'il y a un directory par application. +Le nom de l'executable sera celui du directory qui contient les fichiers sources +Une application ne se compile pas exactement de la meme maniere selon qu'elle utilise ou WxWidgets +Nous avons laisse ici un squelette de programme pour chaque cas. + +A 'true application' (as opposed to 'examples') may be be held within more than +one file. +Here, we consider there is one directory per application. +Application name will be the one of the directory holding all the application +source files. +An application is not compiled the same way, if it uses or not WxWidgets. +Therefore, there are two different 'skeletons'. diff --git a/appli/essaiDenis/CMakeLists.txt b/appli/essaiDenis/CMakeLists.txt new file mode 100644 index 0000000..d8a7c06 --- /dev/null +++ b/appli/essaiDenis/CMakeLists.txt @@ -0,0 +1,40 @@ +#---------------------------------------------------------------------------- +# SET THE NAME OF YOUR EXECUTABLE +SET ( EXE_NAME essaiDenis ) +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# EXECUTABLE SOURCES (TO BE COMPILED) +# EITHER LIST ALL .cxx, *.cpp, *.cc IN CURRENT DIR USING NEXT LINE: +FILE(GLOB ${EXE_NAME}_SOURCES *.cxx *.cpp *.cc) +# OR MANUALLY LIST YOUR FILES WITH NEXT COMMAND (WITHOUT EXTENSION) +# SET ( ${EXE_NAME}_SOURCES +# +# ) +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# DEPENDENCIES (LIBRARIES TO LINK WITH) +SET ( ${EXE_NAME}_LINK_LIBRARIES + ${crea_LIBRARIES} + # ${WXWIDGETS_LIBRARIES} + # ${KWWidgets_LIBRARIES} + # ${VTK_LIBRARIES} + # ${ITK_LIBRARIES} + ${GDCM_LIBRARIES} + ${BOOST_LIBRARIES} + + creaBruker + ) +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# CREATES AND INSTALLS THE EXE +# Set to ON if your appli has a GUI (to build as a Win32 app on windows) +SET(${EXE_NAME}_HAS_GUI OFF) +# Set to ON if your appli has a GUI but you also want a msdos console on windows +SET(${EXE_NAME}_CONSOLE OFF) +CREA_ADD_EXECUTABLE( ${EXE_NAME} ) +#---------------------------------------------------------------------------- + + diff --git a/appli/essaiDenis/README.txt b/appli/essaiDenis/README.txt new file mode 100755 index 0000000..595b892 --- /dev/null +++ b/appli/essaiDenis/README.txt @@ -0,0 +1,7 @@ + # ==> + # ==> Dans ce directory : les fichiers sources qui composent l'application (sans Wx) + # + # ==> In this directory : the source files that compose the (Wx less) application + # ==> + + diff --git a/appli/essaiDenis/essaiDenis.cpp b/appli/essaiDenis/essaiDenis.cpp new file mode 100644 index 0000000..792751f --- /dev/null +++ b/appli/essaiDenis/essaiDenis.cpp @@ -0,0 +1,134 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include "brukerdataset.h" +#include "brukerkspaceobject.h" +#include "brukerimage.h" + + +int main(int argc, char *argv[]) +{ + BrukerDataSet acqp1, reco1; + std::string file2Read1("/home/denis/TestDicom/kiwidicom.QZ1/3/acqp"); + std::string file2Read2("/home/denis/TestDicom/kiwidicom.QZ1/3/pdata/1/reco"); + //std::string file2Read("/home/denis/TestDicom/mcao31a.pc1-exam_fabien/6/acqp"); + //std::string file2Read("/home/denis/TestDicom/mcao31a.pc1-exam_fabien/6/pdata/1/reco"); + //std::string file2Read("/home/denis/TestDicom/mcao31a.pc1-exam_fabien/6/acqp"); + acqp1.LoadFile(file2Read1); + reco1.LoadFile(file2Read2); + std::cout << "=============== acqp1 FillMap =================" << std::endl; + acqp1.FillMap(); + acqp1.PrintSelf(); + std::cout << "=============== End acqp1 FillMap =================" << std::endl; + std::cout << "=============== reco1 FillMap =================" << std::endl; + reco1.FillMap(); + reco1.PrintSelf(); + std::cout << "=============== End reco1 FillMap =================" << std::endl; + + + + std::cout << "=============== BuildLoopStructure =================" << std::endl; + +// LoopStructure is used to control the way the loops can be unrolled (in ObjectsLineList) + acqp1.SetLoopStructure(); + std::vector TempVect = acqp1.GetLoopStructure() ; + for(int i=0;i > TempMat=acqp1.GetBrukerObjectsLineList(); + std::map Map=acqp1.GetBrukerHeaderMap(); + +//ObjectVaryingProperties is a method centralizing the access to "all" the varying properties of images like position, orientation, echo time, ..... +//It needs the BrukerHeaderMap and the LoopStructure as input + + bool result=acqp1.ObjectVaryingProperties.init(Map,TempVect); + int Reordered,i,j,k,l; + std::vector > TempMat2; + for(int i=0;iBrukerObjectsLineList[*][2] + Reordered=acqp1.ObjectVaryingProperties.getAcquisitionOrder(TempMat[i][2]); + std::cout<<" TE = "<=2]) + std::cout<<" [R,P,S]xyz = ["< > BrukerImageList=acqp1.GetBrukerImageList(); + std::vector > BrukerImageList2; + for(int i=0;i ImageSet; + + for(int i=0;i + # ==> Dans ce directory : les fichiers sources qui composent l'application (sans Wx) + # + # ==> In this directory : the source files that compose the (Wx less) application + # ==> + + diff --git a/appli/exObjectVaryingProperties/main.cxx b/appli/exObjectVaryingProperties/main.cxx new file mode 100644 index 0000000..582f06a --- /dev/null +++ b/appli/exObjectVaryingProperties/main.cxx @@ -0,0 +1,132 @@ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include "brukerdataset.h" +#include "brukerkspaceobject.h" +#include "brukerimage.h" + + +int main(int argc, char *argv[]) +{ + BrukerDataSet acqp1, reco1; + std::string file2Read1("/home/denis/TestDicom/kiwidicom.QZ1/3/acqp"); + std::string file2Read2("/home/denis/TestDicom/kiwidicom.QZ1/3/pdata/1/reco"); + //std::string file2Read("/home/denis/TestDicom/mcao31a.pc1-exam_fabien/6/acqp"); + //std::string file2Read("/home/denis/TestDicom/mcao31a.pc1-exam_fabien/6/pdata/1/reco"); + //std::string file2Read("/home/denis/TestDicom/mcao31a.pc1-exam_fabien/6/acqp"); + acqp1.LoadFile(file2Read1); + reco1.LoadFile(file2Read2); + std::cout << "=============== acqp1 FillMap =================" << std::endl; + acqp1.FillMap(); + acqp1.PrintSelf(); + std::cout << "=============== End acqp1 FillMap =================" << std::endl; + std::cout << "=============== reco1 FillMap =================" << std::endl; + reco1.FillMap(); + reco1.PrintSelf(); + std::cout << "=============== End reco1 FillMap =================" << std::endl; + + + + std::cout << "=============== BuildLoopStructure =================" << std::endl; + +// LoopStructure is used to control the way the loops can be unrolled (in ObjectsLineList) + acqp1.SetLoopStructure(); + std::vector TempVect = acqp1.GetLoopStructure() ; + for(int i=0;i > TempMat=acqp1.GetBrukerObjectsLineList(); + std::map Map=acqp1.GetBrukerHeaderMap(); + +//ObjectVaryingProperties is a method centralizing the access to "all" the varying properties of images like position, orientation, echo time, ..... +//It needs the BrukerHeaderMap and the LoopStructure as input + + bool result=acqp1.ObjectVaryingProperties.init(Map,TempVect); + int Reordered,i,j,k,l; + std::vector > TempMat2; + for(int i=0;iBrukerObjectsLineList[*][2] + Reordered=acqp1.ObjectVaryingProperties.getAcquisitionOrder(TempMat[i][2]); + std::cout<<" TE = "<=2]) + std::cout<<" [R,P,S]xyz = ["< > BrukerImageList=acqp1.GetBrukerImageList(); + std::vector > BrukerImageList2; + for(int i=0;i ImageSet; + + for(int i=0;iArgMgrDefined("usage") ) + { + am->ArgMgrUsage(usage); // Display 'usage' + delete am; + return 1; + } + + // create the devilish object! + Bruker2Dicom b2d; + + const char *dirNamein; + dirNamein = am->ArgMgrGetString("dirin","."); + + const char *dirNameout; + dirNameout = am->ArgMgrGetString("dirout","."); + +// note : Big Endian / Little Endian pb not yet dealt with. +// not a great issue, since everybody (?) works on Intell procs + int b = am->ArgMgrDefined("b"); + int l = am->ArgMgrDefined("l"); + + if (am->ArgMgrDefined("debug")) + GDCM_NAME_SPACE::Debug::DebugOn(); + + b2d.verbose = am->ArgMgrDefined("verbose"); + int listonly = am->ArgMgrDefined("listonly"); + + int dicom = am->ArgMgrDefined("D"); + int mhd = am->ArgMgrDefined("M"); + + if (dicom) + b2d.SetConvertModeToDicom(); + if (mhd) + b2d.SetConvertModeToMhd(); + + /* if unused Param we give up */ + if ( am->ArgMgrPrintUnusedLabels() ) + { + am->ArgMgrUsage(usage); + delete am; + return 1; + } + +// patientName : found in Bruker parameter files +// patientName = am->ArgMgrGetString("patientname", "Patient^Name"); + +// b2d.day : unused ... + b2d.day = am->ArgMgrGetString("day", "You_forget_the_Day"); + + delete am; // we don't need Argument Manager any longer + + // ----------- End Arguments Manager --------- + + + // ----- Begin Processing ----- + + b2d.SetInputDirectory(dirNamein); + b2d.SetOutputDirectory(dirNameout); + + /// \TODO : *do* use exceptions in the methods! + + try { + b2d.Execute(); + } + catch (int) + { + std::cout << "Exception was thrown :-( " << std::endl; + } + +} + + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt new file mode 100644 index 0000000..e04cd35 --- /dev/null +++ b/lib/CMakeLists.txt @@ -0,0 +1,2 @@ +# Add a SUBDIRS command for each one of your libraries + SUBDIRS(src1) diff --git a/lib/src1/CMakeLists.txt b/lib/src1/CMakeLists.txt new file mode 100644 index 0000000..c0c03a5 --- /dev/null +++ b/lib/src1/CMakeLists.txt @@ -0,0 +1,59 @@ +#---------------------------------------------------------------------------- +# SET THE NAME OF YOUR LIBRARY +SET ( LIBRARY_NAME creaBruker ) +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# CREATES A USER OPTION IN CMAKE +OPTION ( BUILD_${LIBRARY_NAME} "Build ${LIBRARY_NAME} library ?" ON) +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +IF ( BUILD_${LIBRARY_NAME} ) +#---------------------------------------------------------------------------- + + #---------------------------------------------------------------------------- + # BUILD LIBRARY + #---------------------------------------------------------------------------- + + #---------------------------------------------------------------------------- + # LIBRARY HEADERS (TO BE INSTALLED) + # EITHER LIST ALL .h IN CURRENT DIR USING NEXT LINE: + FILE(GLOB ${LIBRARY_NAME}_HEADERS "*.h") + # OR MANUALLY LIST YOUR HEADERS WITH NEXT COMMAND + # SET ( ${LIBRARY_NAME}_HEADERS + # + # ) + #---------------------------------------------------------------------------- + + #---------------------------------------------------------------------------- + # LIBRARY SOURCES (TO BE COMPILED) + # EITHER LIST ALL .cxx, *.cpp, *.cc IN CURRENT DIR USING NEXT LINE: + FILE(GLOB ${LIBRARY_NAME}_SOURCES *.cxx *.cpp *.cc) + # OR MANUALLY LIST YOUR FILES WITH NEXT COMMAND (WITHOUT EXTENSION) + # SET ( ${LIBRARY_NAME}_SOURCES + # + # ) + #---------------------------------------------------------------------------- + + #---------------------------------------------------------------------------- + # LIBRARY DEPENDENCIES (LIBRARIES TO LINK WITH) + SET ( ${LIBRARY_NAME}_LINK_LIBRARIES + ${crea_LIBRARIES} + # ${WXWIDGETS_LIBRARIES} + # ${VTK_LIBRARIES} + # ${ITK_LIBRARIES} + ${GDCM_LIBRARIES} + ${BOOST_LIBRARIES} + ) + #---------------------------------------------------------------------------- + + + #---------------------------------------------------------------------------- + # MACRO WHICH DOES ALL THE JOB : BUILD AND INSTALL + CREA_ADD_LIBRARY( ${LIBRARY_NAME} ) + #---------------------------------------------------------------------------- + + + #--------------------------------------------------------------------------- +ENDIF ( BUILD_${LIBRARY_NAME} ) diff --git a/lib/src1/bruker2dicom.cxx b/lib/src1/bruker2dicom.cxx new file mode 100644 index 0000000..b41186a --- /dev/null +++ b/lib/src1/bruker2dicom.cxx @@ -0,0 +1,1271 @@ +#include "bruker2dicom.h" + + + +bool Bruker2Dicom::Execute() +{ + // ----- Begin Processing ----- + + bool bigEndian = GDCM_NAME_SPACE::Util::IsCurrentProcessorBigEndian(); + + if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(InputDirName) ) + { + std::cout << "KO : [" << InputDirName << "] is not a Directory." << std::endl; + return 0; + } + else + { + if (verbose) + std::cout << "OK : [" << InputDirName << "] is a Directory." << std::endl; + } + + std::string strDirNameOut(OutputDirName); + bool res=CreateDirectory(strDirNameOut); + if (!res) { + std::cout << "[" << OutputDirName << "] Directory creation failure " << std::endl; + exit (0); + } + + std::string strDirNamein(InputDirName); + GDCM_NAME_SPACE::DirList dirList(strDirNamein, false, true); // DON'T get recursively the list of files + std::string strDirNameout(OutputDirName); + +/* + if (listonly) + { + std::cout << "------------List of found files ------------" << std::endl; + dirList.Print(); + std::cout << std::endl; + return 1; + } +*/ + +// +// e.g : at level 0, in : B67d1.Bp1 +// +// 1 2 3 4 5 6 AdjStatePerStudy subject +// + + GDCM_NAME_SPACE::DirListType fileNames; + fileNames = dirList.GetFilenames(); + bool canOpen; + std::string outputFileName; + + // BrukerDataSet br_subject; + std::string subject; + subject = GDCM_NAME_SPACE::Util::GetPath(*(fileNames.begin()))+ + GDCM_NAME_SPACE::GDCM_FILESEPARATOR + + "subject"; + if (verbose) + std::cout << " Subject : [" << subject << "]" << std::endl; + canOpen =br_subject.LoadFile(subject); + + if (!canOpen) + { + std::cout << "Hopeless! no 'subject' found" << std::endl; + exit(0); /// \TODO throw an exception ! + } + else + { + br_subject.FillMap(); + } + //br_subject.PrintSelf(); + + // get info for 'Study Description' + + /* + BrukerFieldData b_protocol_location=br_acqp.GetFieldData("ACQ_protocol_location"); + acqp_protocol_location = b_protocol_location.GetStringValue()[0]; + cleanString(acqp_protocol_location); +*/ + BrukerFieldData b_name=br_subject.GetFieldData("SUBJECT_name_string"); + std::string subject_name = b_name.GetStringValue()[0]; + strPatientName = subject_name; + cleanString(subject_name); + + BrukerFieldData b_entry=br_subject.GetFieldData("SUBJECT_entry"); + std::string subject_entry = b_entry.GetStringValue()[0]; + //cleanString(subject_entry); + subject_entry = subject_entry.substr(11, subject_entry.size()-11); + + BrukerFieldData b_position=br_subject.GetFieldData("SUBJECT_position"); + std::string subject_position = b_position.GetStringValue()[0]; + //cleanString(subject_position); + subject_position = subject_position.substr(9, subject_position.size()-9); + + BrukerFieldData b_date=br_subject.GetFieldData("SUBJECT_date"); + std::string subject_date = b_date.GetStringValue()[0]; + strStudyTimeDate = subject_date; + cleanString(subject_date); + + BrukerFieldData b_study_name=br_subject.GetFieldData("SUBJECT_study_name"); + std::string subject_study_name = b_study_name.GetStringValue()[0]; + subject_study_name = subject_study_name.substr(1, subject_study_name.size()-2); + cleanString(subject_date); + + strStudyDescr = subject_name + "-" + subject_study_name + "-" + subject_entry + "-" + subject_position + "-" + subject_date; + + char outputDirName[(unsigned int) PATH_MAX+2]; + + strStudyUID = GDCM_NAME_SPACE::Util::CreateUniqueUID(); + + // ----------------------------------------------------- + // Iterate to ALL the objets(files/directories) found in the input directory + // (this is level ZERO) + // ----------------------------------------------------- + + GDCM_NAME_SPACE::DirListType::iterator it; + + for (it = fileNames.begin(); + it != fileNames.end(); + ++it) + { + if ( GDCM_NAME_SPACE::DirList::IsDirectory(*it) ) + { + if (verbose) + std::cout << "[" << *it << "] is a directory" << std::endl; + + //BrukerDataSet br_acqp; + std::string strAcqp; + strAcqp = (*it) + + GDCM_NAME_SPACE::GDCM_FILESEPARATOR + + "acqp"; + + br_acqp.LoadFile(strAcqp); + br_acqp.FillMap(); + + std::string acqp_scan_name; + std::string acqp_method; + std::string acqp_protocol_location; + + BrukerFieldData b_protocol_location=br_acqp.GetFieldData("ACQ_protocol_location"); + acqp_protocol_location = b_protocol_location.GetStringValue()[0]; + cleanString(acqp_protocol_location); + + BrukerFieldData b_scan_name=br_acqp.GetFieldData("ACQ_scan_name"); + acqp_scan_name = b_scan_name.GetStringValue()[0]; + cleanString(acqp_scan_name); + + BrukerFieldData b_method=br_acqp.GetFieldData("ACQ_method"); + acqp_method = b_method.GetStringValue()[0]; + cleanString(acqp_method); + + BrukerFieldData b_list_size = br_acqp.GetFieldData("ACQ_O1_list_size"); + b_list_size.PrintSelf(); //JP + + nbSlices = b_list_size.GetIntValue()[0]; + + strSerieDescr = GDCM_NAME_SPACE::Util::GetName(*it) + + "-" + acqp_protocol_location + + "-" + acqp_scan_name + + "-" + acqp_method.c_str(); + + sprintf(outputDirName, "%s%c%s", OutputDirName.c_str(), + GDCM_NAME_SPACE::GDCM_FILESEPARATOR, + strSerieDescr.c_str() ); + + std::cout << " ================================================================================\n" + << " ========================= [" << GDCM_NAME_SPACE::Util::GetName(*it).c_str() + << acqp_protocol_location.c_str() + << acqp_scan_name.c_str() + << acqp_method.c_str() + << "]\n" + << " ================================================================================" + << std::endl; + + if (verbose) + printf ("outputDirName [%s]\n", outputDirName); + + DealWithNiveau1(*it, outputDirName); + } + } // end of : for (GDCM_NAME_SPACE::DirListType::iterator it +} + + +// ===================================================================== + +void Bruker2Dicom::DealWithNiveau1(std::string level1Directory, std::string currentOutputDirName) { +// +// e.g. : at level 1, in B67d1.Bp1/6 +// +// acqp fid imnd pdata pulseprogram spnam0 spnam1 + + bool res = CreateDirectory(currentOutputDirName); + + if (!res) { + std::cout << "[" << currentOutputDirName << "] Directory creation failure " << std::endl; + exit (0); + } + GDCM_NAME_SPACE::DirList dirList(level1Directory, false, true); // DON'T get recursively the list of files + GDCM_NAME_SPACE::DirListType fileNames; + fileNames = dirList.GetFilenames(); + // ----------------------------------------------------- + // Iterate to ALL the objets(files/directories) found in the input directory + // ----------------------------------------------------- + GDCM_NAME_SPACE::DirListType::iterator it; + + for (it = fileNames.begin(); + it != fileNames.end(); + ++it) + { + if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(*it) ) + { + if (verbose) + std::cout << "--- [" << *it << "] is a file" << std::endl; + } + } + + char outputDirName[(unsigned int) PATH_MAX+2]; + //std::string firstName; + bool canOpen; + for (it = fileNames.begin(); + it != fileNames.end(); + ++it) + { + if ( GDCM_NAME_SPACE::DirList::IsDirectory(*it) ) + { + // will be always "pdata" ... + if (verbose) + std::cout << "--- [" << *it << "] is a directory" << std::endl; + + /* a recuperer : + if (FileLine.startsWith("##$ACQ_size=")) { + if (FileLine.startsWith("##$NI=")) { + if (FileLine.startsWith("##$NR=")) { + if (FileLine.startsWith("##$ACQ_obj_order=")) { + if (FileLine.startsWith("##$ACQ_word_size=")) { + if (FileLine.startsWith("##$BYTORDA=")) { + if (FileLine.startsWith("##$PULPROG=")) { + */ + + sprintf(outputDirName, "%s%c%s", currentOutputDirName.c_str(), + GDCM_NAME_SPACE::GDCM_FILESEPARATOR, + GDCM_NAME_SPACE::Util::GetName(*it).c_str()); + //br1.PrintSelf(); + + std::string strMethod; + //std::string firstName = *(fileNames.begin()); + + strMethod = GDCM_NAME_SPACE::Util::GetPath(*(fileNames.begin())) + + GDCM_NAME_SPACE::GDCM_FILESEPARATOR + + "method"; + // std::cout << "---strMethod (for method)=> [" << strMethod << "]" << std::endl; + canOpen = br_method.LoadFile(strMethod); + if (!canOpen) + { + strMethod = GDCM_NAME_SPACE::Util::GetPath(*(fileNames.begin()))+ + GDCM_NAME_SPACE::GDCM_FILESEPARATOR + + "imnd"; + //std::cout << "---strMethod (for imnd) => [" << strMethod << "]" << std::endl; + canOpen = br_method.LoadFile(strMethod); + if (!canOpen) + { + std::cout << "Hopeless! neither 'method' nor 'imnd' found" << std::endl; + exit(0); /// \TODO throw an exception ! + } + } + if (verbose) + std::cout << "open => [" << strMethod << "] successfully" << std::endl; + br_method.FillMap(); + + /* a recuperer : + ##$PVM_Fov (dimension) + */ + /* + dans method (pour perfusion seulement?) : + ##$PVM_ObjOrderList=( 8 ) + 0 2 4 6 1 3 5 7 + ##$PVM_NSPacks=2 + ##$PVM_SPackArrNSlices=( 2 ) + 7 1 + */ + DealWithNiveau2(*it,outputDirName ); + } + } +} + +// ===================================================================== + +void Bruker2Dicom::DealWithNiveau2(std::string level2Directory, std::string currentOutputDirName) { + +// e.g. : at level 2 in B67d1.Bp1/6/pdata +// +// acqp fid imnd pdata pulseprogram spnam0 spnam1 +// + + bool res = CreateDirectory(currentOutputDirName); + + if (!res) { + std::cout << "[" << currentOutputDirName << "] Directory creation failure " << std::endl; + exit (0); + } + + GDCM_NAME_SPACE::DirList dirList(level2Directory, false, true); // DON'T get recursively the list of files + + GDCM_NAME_SPACE::DirListType fileNames; + fileNames = dirList.GetFilenames(); + + char outputDirName[(unsigned int) PATH_MAX+2]; + + // ----------------------------------------------------- + // Iterate to ALL the objets(files/directories) found in the input directory + // ----------------------------------------------------- + GDCM_NAME_SPACE::DirListType::iterator it; + bool canOpen; + + if (verbose) + for (it = fileNames.begin(); + it != fileNames.end(); + ++it) + { + if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(*it) ) + { + std::cout << "--- --- [" << *it << "] is a file" << std::endl; + } + + } + + for (it = fileNames.begin(); + it != fileNames.end(); + ++it) + { + if ( GDCM_NAME_SPACE::DirList::IsDirectory(*it) ) + { + + if (verbose) + std::cout << "--- --- [" << *it << "] is a directory" << std::endl; + + // sprintf(outputDirName, "%s%c%s", currentOutputDirName.c_str(), + // GDCM_NAME_SPACE::GDCM_FILESEPARATOR, + // GDCM_NAME_SPACE::Util::GetName(*it).c_str() ); + // MUST be 'pdata'! + +// +// (interest of previous method : +// If unaware user changed the pdata name, it goes on working +// + std::string str_isa; + str_isa = (*it) + + GDCM_NAME_SPACE::GDCM_FILESEPARATOR + + "isa"; + + std::string str_isa_func_name; + canOpen = br_isa.LoadFile(str_isa); + if (!canOpen) + { + sprintf(outputDirName, "%s%c%s", currentOutputDirName.c_str(), + GDCM_NAME_SPACE::GDCM_FILESEPARATOR, + GDCM_NAME_SPACE::Util::GetName(*it).c_str() ); + } + else + { + br_isa.FillMap(); + BrukerFieldData b_isa_func_name = br_isa.GetFieldData("ISA_func_name"); + + str_isa_func_name = b_isa_func_name.GetStringValue()[0]; + cleanString(str_isa_func_name); + + sprintf(outputDirName, "%s%c%s-%s", currentOutputDirName.c_str(), + GDCM_NAME_SPACE::GDCM_FILESEPARATOR, + GDCM_NAME_SPACE::Util::GetName(*it).c_str(), + str_isa_func_name.c_str()); + } + DealWithNiveau3(*it, outputDirName); + } + } +} + + +// +// ===================================================================== +// + +void Bruker2Dicom::DealWithNiveau3(std::string level3Directory, std::string currentOutputDirName){ + +// +// e.g. at level 3, in + + // just to be able to go on checking // JP + if ( GDCM_NAME_SPACE::Util::GetName(level3Directory) != "1") + return; + + bool res = CreateDirectory(currentOutputDirName); + + if (!res) + { + std::cout << "[" << currentOutputDirName << "] Directory creation failure " << std::endl; + exit (0); + } + + GDCM_NAME_SPACE::DirList dirList(level3Directory, false, true); // DON'T get recursively the list of files + GDCM_NAME_SPACE::DirListType::iterator it; + GDCM_NAME_SPACE::DirListType fileNames; + fileNames = dirList.GetFilenames(); + + char original2dseqName [(unsigned int) PATH_MAX+2]; + char currentOutputMhdDirName [(unsigned int) PATH_MAX+2]; + + char outputMhdFileName [(unsigned int) PATH_MAX+2]; + char output2dseqSliceFileName[(unsigned int) PATH_MAX+6]; // think about extra '.dcm' + char output2dseqName [(unsigned int) PATH_MAX+6]; + char output2dseqCartoName [(unsigned int) PATH_MAX+6]; + + char copyFile[PATH_MAX + PATH_MAX + 5]; // Should be enough! + bool canOpen; + + //-------------- try d3proc; + char char_d3proc[(unsigned int) PATH_MAX+2]; + + sprintf(char_d3proc,"%s%c%s", level3Directory.c_str(), GDCM_NAME_SPACE::GDCM_FILESEPARATOR,"d3proc" ); + + if (verbose) + std::cout << "--- => [" << char_d3proc << "]" << std::endl; + std::string str_d3proc(char_d3proc); + canOpen = br_d3proc.LoadFile(str_d3proc); + + if (!canOpen) + { + std::cout << "Hopeless! no 'd3proc' found" << std::endl; + exit(0); /// \TODO throw an exception ! + } + + canOpen = br_d3proc.FillMap(); + if (!canOpen) + { + std::cout << "Hopeless! FillMap failed on 'd3proc'" << std::endl; + exit(0); /// \TODO throw an exception ! + } + + //-------------- end try d3proc; + + + // -------------------try reco + + char char_reco[(unsigned int) PATH_MAX+2]; + + sprintf(char_reco,"%s%c%s", level3Directory.c_str(), GDCM_NAME_SPACE::GDCM_FILESEPARATOR,"reco" ); + //str_d3proc = GDCM_NAME_SPACE::Util::GetPath(*(fileNames.begin()))+ + // GDCM_NAME_SPACE::GDCM_FILESEPARATOR + + // "d3proc"; + if (verbose) + std::cout << "--- => [" << char_reco << "]" << std::endl; + std::string str_reco(char_reco); + canOpen = br_reco.LoadFile(str_reco); + + if (!canOpen) // we try in directory ../1 + { + if (verbose) + std::cout << "[" << str_reco << "] not found " << std::endl; + std::string lastDirName = GDCM_NAME_SPACE::Util::GetPath(level3Directory); + //lastDirName = GDCM_NAME_SPACE::Util::GetPath(lastDirName); + sprintf(char_reco,"%s%c1%c%s", lastDirName.c_str(), GDCM_NAME_SPACE::GDCM_FILESEPARATOR,GDCM_NAME_SPACE::GDCM_FILESEPARATOR,"reco" ); + str_reco=char_reco; + canOpen = br_reco.LoadFile(str_reco); + if (!canOpen) + { + std::cout << "Hopeless! cannot find 'reco' in [" << str_reco << "]" << std::endl; + exit(0); /// \TODO throw an exception ! + } + } + + canOpen = br_reco.FillMap(); + if (!canOpen) + { + std::cout << "Hopeless! FillMap failed on [" << str_reco << "]" << std::endl; + exit(0); /// \TODO throw an exception ! + } + //std::cout << "------------------------------------------------------------------------------------------------" << std::cout; + // br_reco.PrintSelf(); + // std::cout << "------------------------------------------------------------------------------------------------" << std::cout; + + // -------------------end try reco + + + BrukerFieldData bX = br_d3proc.GetFieldData("IM_SIX"); + int NX = bX.GetIntValue()[0]; + + std::cout << "IM_SIX " << NX << std::endl; + BrukerFieldData bY=br_d3proc.GetFieldData("IM_SIY"); + int NY = bY.GetIntValue()[0]; + + std::cout << "IM_SIY " << NY << std::endl; + /// \todo : check if there are actually 3 dimensions or only 2 + + BrukerFieldData bZ= br_d3proc.GetFieldData("IM_SIZ"); + int nbFrames = bZ.GetIntValue()[0]; + std::cout << "IM_SIZ " << nbFrames << std::endl; + + // WARNING DATTYPE is, either in {ip_short, ip_int, ip_char, ...}, or in {1, 2, 3, ...} + + BrukerFieldData bDPT = br_d3proc.GetFieldData("DATTYPE"); + + std::string mhdDataPixelType; + int pixelSize; + getImhDataType(bDPT, mhdDataPixelType, pixelSize); + + BrukerFieldData fov = br_method.GetFieldData("PVM_Fov"); + double fovX = fov.GetDoubleValue()[0]; + double fovY = fov.GetDoubleValue()[1]; + if (verbose) + std::cout << "FOV (ds method) " << fovX << " " << fovY << std::endl; + + /// \TODO probabely a more sophisticated accessor will be necessary : + /// (cf : non contiguous slices, overlapping, slice thickness, space between clices, etc) + BrukerFieldData bsliceDistance = br_method.GetFieldData("PVM_SPackArrSliceDistance"); + double sliceDistance = bsliceDistance.GetDoubleValue()[0]; + + if (mhd) + { + sprintf(currentOutputMhdDirName, "%s%c%s", currentOutputDirName.c_str(), + GDCM_NAME_SPACE::GDCM_FILESEPARATOR, "MhdFiles"); + res = CreateDirectory( currentOutputMhdDirName ); + if (!res) { + std::cout << "[" << currentOutputDirName << "] Directory creation failure " << std::endl; + exit (0); + } + + if (verbose) + std::cout << "Directory creation [" << currentOutputDirName << "]" << std::endl; + } // end if mhd + + std::cout << "nbFrames " << nbFrames << std::endl; + std::cout << "nbSlices " << nbSlices << std::endl; + int k; + int nbInstants = nbFrames/nbSlices; + std::cout << "nbInstants (deduced )" << nbInstants << std::endl; + int instantNb; + int sliceNb; + FILE *fp; // for MHD files + + sprintf( original2dseqName, "%s%c%s", level3Directory.c_str(), GDCM_NAME_SPACE::GDCM_FILESEPARATOR, "2dseq"); + +/**/ + // \TODO : tenir compte du bazar precedent + + // load 2dseq in memory + + fp = fopen(original2dseqName, "rb"); + if (!fp) + { + std::cout << "Cannot open [" << original2dseqName << "] for reading" << std::endl; + exit (0); + } + + unsigned char * buffer_2dseq = new unsigned char[NX*NY*pixelSize*nbSlices*nbInstants]; + ///\ TODO : find a safer way to be sure to read everything! + size_t lgr = fread(buffer_2dseq, 1, NX*NY*pixelSize*nbSlices*nbInstants, fp); + + // This one will be important! + // --------------------------- + imageSet = CreateImageSet ( ); + + strSerieUID = GDCM_NAME_SPACE::Util::CreateUniqueUID(); + if (nbInstants==1) // creer un seul fichier .mhd pour toutes les Slices! (images natives) + { + std::cout << "Single instant : do not split" << std::endl; + if (mhd) + { + sprintf(outputMhdFileName, "%s%cMhdData_Toutes_les_Slices.mhd", currentOutputMhdDirName, + GDCM_NAME_SPACE::GDCM_FILESEPARATOR); + fp=fopen(outputMhdFileName, "w"); + if (!fp) + { + std::cout << "Cannot open [" << outputMhdFileName << "] for writting" << std::endl; + exit(0); + } + else + { + fprintf(fp, "ObjectType = Image\n"); + fprintf(fp, "NDims = 3\n" ); + fprintf(fp, "BinaryData = True \n" ); + fprintf(fp, "BinaryDataByteOrderMSB = False\n" ); + fprintf(fp, "DimSize = %d %d %d\n", NX, NY, nbSlices ); + fprintf(fp, "HeaderSize = %d\n", 0); + fprintf(fp, "ElementSpacing = %lf %lf %lf\n",fovX/NY, fovY/NY, sliceDistance ); + fprintf(fp, "Position = 0 0 %d\n", 0 ); + fprintf(fp, "Offset = 0 0 0\n" ); + fprintf(fp, "CenterOfRotation = 0 0 0\n" ); + fprintf(fp, "ElementNumberOfChannels = 1\n" ); + fprintf(fp, "ElementType = %s\n", mhdDataPixelType.c_str() ); + fprintf(fp, "ElementDataFile = %s\n", "../2dseq_toutes_les_Slices" ); + fclose(fp); + } + sprintf(output2dseqSliceFileName, "%s%c2dseq_toutes_les_Slices", + currentOutputDirName.c_str(), GDCM_NAME_SPACE::GDCM_FILESEPARATOR); + fp=fopen(output2dseqSliceFileName, "wb"); + if (!fp) + { + std::cout << "Cannot open [" << output2dseqSliceFileName << "] for writting" << std::endl; + } + else + { + fwrite( buffer_2dseq, NX*NY*pixelSize, nbSlices, fp); + } + fclose(fp); + strSerieUID = GDCM_NAME_SPACE::Util::CreateUniqueUID(); + } // end if mhd + if (dicom) + { + sprintf(output2dseqSliceFileName, "%s%c2dseq_toutes_les_Slices.dcm", + currentOutputDirName.c_str(), GDCM_NAME_SPACE::GDCM_FILESEPARATOR); + + /* ----------- Write Dicom Image ---------------*/ + MakeDicomImage(buffer_2dseq, + NX, + NY, + nbFrames, + pixelSize, + fovX/NY, fovY/NY, sliceDistance, + output2dseqSliceFileName, + strPatientName, + day, + strStudyUID, + strSerieUID, + strStudyDescr, + strSerieDescr, + strStudyTimeDate, + 0,// index frame number + GDCM_NAME_SPACE::UNMODIFIED_PIXELS_IMAGE + ); + } // end if dicom + } // end if nbInstants = 1 + + else // more than ONE instant + { + // Interleaved ! + // it's (slice1,slide2, ...)t1 ; (slice1,slide2, ...)t2 ; ... + + unsigned char * pixelsForCurrentSlice = new unsigned char[NX*NY*pixelSize*nbInstants]; + + k = 0; + for (sliceNb=0; sliceNb Bruker2Dicom::CreateImageSet ( ) +{ + std::vector imageSet; + br_acqp.SetLoopStructure(); + std::vector tempVect = br_acqp.GetLoopStructure() ; + std::map map = br_acqp.GetBrukerHeaderMap(); + bool result = br_acqp.ObjectVaryingProperties.init(map,tempVect); + + br_acqp.SetImageLoopStructure(); + br_acqp.SetBrukerImageList(); + std::vector > brukerImageList = br_acqp.GetBrukerImageList(); + + BrukerImage image(br_acqp,br_reco); + image.Init(br_acqp,br_reco,1); + + for(int i=0;i > imageOrientation; + std::vector imagePosition; + for(int i=0;iInsertEntryString(str.str(),0x0028,0x0011,"US"); // Columns + str.str(""); + str << Y; + file->InsertEntryString(str.str(),0x0028,0x0010,"US"); // Rows + + if (nbFrames != 1) + { + str.str(""); + str << nbFrames; + file->InsertEntryString(str.str(),0x0028,0x0008,"IS"); // Number of Frames + } + + // Set the pixel type + // //8, 16, 32, 64 (for double ?) + str.str(""); + str << pixelSize*8; + file->InsertEntryString(str.str(),0x0028,0x0100,"US"); // Bits Allocated + + file->InsertEntryString(str.str(),0x0028,0x0101,"US"); // Bits Stored + + str.str(""); + str << pixelSize*8-1; + file->InsertEntryString(str.str(),0x0028,0x0102,"US"); // High Bit + + // Set the pixel representation // 0/1 , 0=unsigned + file->InsertEntryString("1",0x0028,0x0103, "US"); // Pixel Representation + + // Set the samples per pixel // 1:Grey level, 3:RGB + file->InsertEntryString("1",0x0028,0x0002, "US"); // Samples per Pixel + +// 0028 0030 DS 2 Pixel Spacing + str.str(""); + str << spacingX << "\\" << spacingY; + file->InsertEntryString(str.str(),0x0028,0x0030, "DS"); // Pixel Spacing + + // 0018 0050 DS 1 Slice Thickness + str.str(""); + str << sliceDistance; + file->InsertEntryString(str.str(),0x0018,0x0050, "DS"); + + // 1.2.840.10008.5.1.4.1.1.4.1 : Enhanced MR Image Storage + // file->InsertEntryString("1.2.840.10008.5.1.4.1.1.4.1" , 0x0002, 0x0002, "UI"); // [Media Storage SOP Class UID] + // file->InsertEntryString("1.2.840.10008.5.1.4.1.1.4.1" , 0x0008, 0x0016, "UI"); // [SOP Class UID] + + +// OK : MR is NOT multiframe, but I want just a quick an dirty solution +// 1.2.840.10008.5.1.4.1.1.4 MR Image Storage + file->InsertEntryString("1.2.840.10008.5.1.4.1.1.4" , 0x0002, 0x0002, "UI"); // [Media Storage SOP Class UID] + file->InsertEntryString("1.2.840.10008.5.1.4.1.1.4" , 0x0008, 0x0016, "UI"); // [SOP Class UID] + + // if (strlen(patientName) != 0) + file->InsertEntryString(patientName.c_str(),0x0010,0x0010, "PN"); // Patient's Name + + file->InsertEntryString(studyUID, 0x0020, 0x000d, "UI"); + file->InsertEntryString(serieUID, 0x0020, 0x000e, "UI"); + +// 0008 0020 DA 1 Study Date +// 0008 0030 TM 1 Study Time + +/// \TODO split into 2 strings! + file->InsertEntryString(strStudyTimeDate.substr(10,11).c_str(),0x0008,0x0020, "DA"); + file->InsertEntryString(strStudyTimeDate.substr(1,8).c_str(),0x0008,0x0030, "TM"); + + file->InsertEntryString(studyDescr,0x0008,0x1030, "LO"); // Study Description + file->InsertEntryString(serieDescr,0x0008,0x103e, "LO"); // Series Description + +//0008|0060 [CS] [Modality] + file->InsertEntryString("MR",0x0008,0x0060, "CS"); + +// 0020 0037 DS 6 Image Orientation (Patient) + char charImageOrientation[256]; + +/* +std::cout << "try charImageOrientation " << + imageSet[imgNum].getRotationMatrixRPS2XYZ()[0][0] << " " << + imageSet[imgNum].getRotationMatrixRPS2XYZ()[0][1] << " " << + imageSet[imgNum].getRotationMatrixRPS2XYZ()[0][2] << " " << + imageSet[imgNum].getRotationMatrixRPS2XYZ()[1][0] << " " << + imageSet[imgNum].getRotationMatrixRPS2XYZ()[1][1] << " " << + imageSet[imgNum].getRotationMatrixRPS2XYZ()[1][2] << std::endl ; +*/ + sprintf(charImageOrientation,"%f\\%f\\%f \\ %f\\%f\\%f", + imageSet[imgNum].getRotationMatrixRPS2XYZ()[0][0], + imageSet[imgNum].getRotationMatrixRPS2XYZ()[0][1], + imageSet[imgNum].getRotationMatrixRPS2XYZ()[0][2], + imageSet[imgNum].getRotationMatrixRPS2XYZ()[1][0], + imageSet[imgNum].getRotationMatrixRPS2XYZ()[1][1], + imageSet[imgNum].getRotationMatrixRPS2XYZ()[1][2] ) ; + + file->InsertEntryString(charImageOrientation,0x0020,0x0037, "DS"); + + +// 0020 0032 DS 3 Image Position (Patient) + + char charImagePosition[256]; + sprintf(charImagePosition,"%f\\%f\\%f", + imageSet[imgNum].getTranslationVectorRPS2XYZ()[0], + imageSet[imgNum].getTranslationVectorRPS2XYZ()[1], + imageSet[imgNum].getTranslationVectorRPS2XYZ()[2]); + + file->InsertEntryString(charImagePosition,0x0020,0x0032, "DS"); //0020 0032 DS 3 Image Position (Patient) + + + +// 0020 0x1041 DS 1 Slice Location +// sprintf(charImagePosition,"%f",float(imgNum)); +// file->InsertEntryString(charImagePosition,0x0020,0x1041, "DS"); +/* + // Set Rescale Intercept + str.str(""); + str << div; + file->InsertEntryString(str.str(),0x0028,0x1052,"DS"); + + // Set Rescale Slope + str.str(""); + str << mini; + file->InsertEntryString(str.str(),0x0028,0x1053,"DS"); +*/ + + GDCM_NAME_SPACE::FileHelper *fileH; + fileH = GDCM_NAME_SPACE::FileHelper::New(file); + fileH->SetContentType(contentType); + + // cast is just to avoid warnings (*no* conversion is performed) + //fileH->SetImageData((uint8_t *)img,int(maxX*maxY)*sizeof(uint16_t)); // troubles when maxX, mayY are *actually* float! + +//std::cout << "-------------------------------- X*Y*nbFrames*pixelSize " << X << " " << Y << " " << nbFrames << " " << pixelSize << std::endl; + + fileH->SetImageData((uint8_t *)tabPixels, X*Y*nbFrames*pixelSize); + fileH->SetWriteModeToRaw(); + fileH->SetWriteTypeToDcmExplVR(); + if( !fileH->Write(dcmImageName)) + std::cout << "Failed for [" << dcmImageName << "]\n" + << " File is unwrittable" << std::endl; + + if (verbose) + file->Print(); + + file->Delete(); + fileH->Delete(); +} + + diff --git a/lib/src1/bruker2dicom.h b/lib/src1/bruker2dicom.h new file mode 100644 index 0000000..71ff5db --- /dev/null +++ b/lib/src1/bruker2dicom.h @@ -0,0 +1,123 @@ +#ifndef BRUKER2DICOM_H +#define BRUKER2DICOM_H + + +#include "gdcmFile.h" +#include "gdcmFileHelper.h" +#include "gdcmCommon.h" +#include "gdcmDebug.h" +#include "gdcmUtil.h" +#include "gdcmDirList.h" + +#include "gdcmArgMgr.h" +#include "brukerSystem.h" +#include "brukerdataset.h" +#include "brukerkspaceobject.h" +#include "brukerimage.h" + +#include +#include + + + +class creaBruker_EXPORT Bruker2Dicom { + +public: + /*! \brief Constructor +*/ + Bruker2Dicom () /* : verbose(0), mhd(0), dicom(0), day(O)*/ {}; +/*! \brief Destructor +*/ + ~Bruker2Dicom (){}; + + void SetInputDirectory (const std::string &i) { InputDirName = i; } + void SetOutputDirectory(const std::string &o) { OutputDirName = o; } + void SetConvertModeToDicom() { dicom = 1; mhd = 0;} + void SetConvertModeToMhd() { dicom = 0; mhd = 1;} + bool Execute(); + + /* + // For debugging pupose only. + //Don't need accessors : Attributes are 'public' + + void SetVerbose(int v) { verbose = v;} + void SetMhd(int m) { mhd = m; } + void SetDicom(int d) { dicom = d; } + */ + +private : + +void MakeDicomImage(unsigned char *tabPixels, + int X, + int Y, + int nbFrames, + int pixelSize, + double spacingX, double spacingY, double sliceDistance, + std::string dcmImageName, + const std::string &patientName, + const char *day, + std::string &studyUID, + std::string &serieUID, + std::string &studyDescr, + std::string &serieDescr, + std::string &strStudyTimeDate, + int imgNum, + GDCM_NAME_SPACE::ImageContentType contentType + ); + +std::vector CreateImageSet ( ); + +void getImhDataType(BrukerFieldData &bDPT, + std::string &mhdDataPixelType, + int &pixelSize); + +void cleanString(std::string &s); + +bool CreateDirectory(std::string dirNameout); + +void DealWithNiveau1(std::string level1Directory, std::string currentOutputDirName); +void DealWithNiveau2(std::string level2Directory, std::string currentOutputDirName); +void DealWithNiveau3(std::string level3Directory, std::string currentOutputDirName); + +void dealWithCarto(GDCM_NAME_SPACE::DirListType &fileNames, int NX, int NY, int nbSlices, + double fovX, double fovY, double sliceDistance, + char *copyFile, std::string ¤tOutputDirName, + char *outputMhdFileName, char *output2dseqCartoName); + +public: + +// these ones are for debugging only +// don't bbfy the accessors. + + int verbose; + const char *day; + +private : + std::string InputDirName; + std::string OutputDirName; + + int mhd; + int dicom; + + int nbSlices; + BrukerDataSet br_subject; + BrukerDataSet br_acqp; + BrukerDataSet br_method; + BrukerDataSet br_d3proc; + BrukerDataSet br_isa; + BrukerDataSet br_reco; + + std::vector imageSet; + +// For DICOM images. + + std::string strStudyUID; + std::string strSerieUID; + std::string strStudyDescr; + std::string strSerieDescr; + std::string strStudyTimeDate; + std::string strPatientName; +}; + + +#endif diff --git a/lib/src1/brukerFieldData.cpp b/lib/src1/brukerFieldData.cpp new file mode 100644 index 0000000..a4fdc05 --- /dev/null +++ b/lib/src1/brukerFieldData.cpp @@ -0,0 +1,32 @@ +#include "brukerFieldData.h" +#include +#include +#include + +void BrukerFieldData::PrintSelf() +{ + int i; + + //std::cout<< "KeyWord = "< +#include +#include "brukerSystem.h" + + /** +\class BrukerFieldData + \brief This class is an atom to generate a BrukerDataSet + */ +class creaBruker_EXPORT BrukerFieldData { +friend class BrukerDataSet; +public: + /*! \brief Constructor +*/ + BrukerFieldData () {}; +/*! \brief Destructor +*/ + ~BrukerFieldData (){}; +/*! \brief Returns the keyword type: int, float, string as a string +*/ + const std::string &GetDataType() { return DataType;} +/*! \fn int GetDimensionNumber() + \brief Returns the dimension of the keyword: + 0-> scalar + 1-> 1D vector + 2-> 2D vector + ... +*/ + int GetDimensionNumber() { return DimensionNumber;} +/*! \fn const std::vector &GetDimensionNumberValue( ) +\brief Returns a vector of size DimensionNumber giving the size of each dimension of the keyword +*/ + const std::vector &GetDimensionNumberValue( ) { return DimensionNumberValue;} +/*! \fn int GetNumberOfElements() +\brief Returns the total number of elements for keyword +*/ + int GetNumberOfElements() { return NumberOfElements;} +/*! +\fn const std::vector &GetStringValue() +\brief Return a string vector of all the element of keyword +*/ + const std::vector &GetStringValue() { return StringValue;} +/*! +\fn const std::vector &GetIntValue () +\brief Return an int vector of all the element of keyword +*/ + const std::vector &GetIntValue () { return IntValue;} +/*! +\fn const std::vector &GetDoubleValue() +\brief Return a double vector of all the element of keyword +*/ + const std::vector &GetDoubleValue() { return DoubleValue;} + + + void PrintSelf(); + +private : +/*! \var DataType +\brief Datatype of the keyword content +*/ + std::string DataType; +/*! \var DimensionNumber +\brief Dimmensionnality of the keyword +*/ + int DimensionNumber; +/*! \var DimensionNumberValue +\brief Vector of int giving the dimension of each dimension of the keyword content +*/ + std::vector DimensionNumberValue; +/*! \var NumberOfElements +\brief Total number of elements contained in keyword +*/ + int NumberOfElements; +/*! \var StringValue +\brief Vector of string containing the elements of keyword if they are string +*/ + std::vector StringValue; +/*! \var IntValue +\brief Vector of string containing the elements of keyword if they are string +*/ + std::vector IntValue; +/*! \var DoubleValue +\brief Vector of string containing the elements of keyword if they are string +*/ + std::vector DoubleValue; +}; +#endif diff --git a/lib/src1/brukerSystem.h b/lib/src1/brukerSystem.h new file mode 100644 index 0000000..7681792 --- /dev/null +++ b/lib/src1/brukerSystem.h @@ -0,0 +1,26 @@ + +#ifndef _BRUKERSYSTEM_H_ +#define _BRUKERSYSTEM_H_ + + +// Windoze related troubles (as usual) + +//----------------------------------------------------------------------------- + +#if defined(_WIN32) + #ifdef creaBruker_EXPORT_SYMBOLS + #define creaBruker_EXPORT __declspec( dllexport ) +#else + #define creaBruker_EXPORT __declspec( dllimport ) + #endif + #define creaBruker_CDECL __cdecl +#else + #define creaBruker_EXPORT + #define creaBruker_CDECL +#endif // defined(_WIN32) + +#ifdef __BORLANDC__ + #include +#endif + +#endif diff --git a/lib/src1/brukerdataset.cpp b/lib/src1/brukerdataset.cpp new file mode 100644 index 0000000..3a6056b --- /dev/null +++ b/lib/src1/brukerdataset.cpp @@ -0,0 +1,742 @@ +// +// C++ Implementation: brukerdataset +// +// Description: +// +// +// Author: , (C) 2008 +// +// Copyright: See COPYING file that comes with this distribution +// +// + + +#define DEBUG 0 + +#include "brukerdataset.h" + +BrukerDataSet::BrukerDataSet(){} + + +BrukerDataSet::~BrukerDataSet(){} + + +bool BrukerDataSet::LoadFile(std::string& fileToRead) +{ + +//std::cout << +//"------------- BrukerDataSet::LoadFile() Open : [" << fileToRead << "]" << std::endl; + std::ifstream FID; + char * buffer; + FID.open(fileToRead.c_str(), std::ios::binary); + if (FID.rdstate()==std::ios::failbit) { + //std::cout << "BrukerDataSet::LoadFile() Cannot open : [" << fileToRead << "]" << std::endl; + return false; + } + + FID.seekg (0, std::ios::end); + int length = FID.tellg(); + FID.seekg (0, std::ios::beg); + + buffer = new char [length]; + FID.read (buffer,length); + FID.close(); + BrukerDataSet::WholeHeader=buffer; + delete [] buffer; + return true; +} + + + +std::string BrukerDataSet::SearchBufferForText(std::string& file, const boost::regex& RegExp) +{ + boost::cmatch what; + if (regex_search(file.c_str(), what, RegExp)) + return what[1]; + return ""; +} + + +/** + * + * @param file + * @param RegExp + * @return bool + */ +bool BrukerDataSet::BoolMatchBufferForText(std::string& file, const boost::regex& RegExp) +{ + boost::cmatch what; + if (regex_match(file.c_str(), what, RegExp)) + return true; + return false; +} + + + +std::string BrukerDataSet::MatchBufferForText(std::string& file,const boost::regex& RegExp) +{ + boost::cmatch what; + if (regex_match(file.c_str(), what, RegExp)) + return what[1]; + return ""; +} + + + +std::string BrukerDataSet::GetKeyword(std::string& file) +{ + return MatchBufferForText( file,KeyWord); +} + + + +int BrukerDataSet::GetDimensionnality(std::string& file) +{ + int iterator=0; + std::string DimensionnalityBuffer=SearchBufferForText(file,Dimensionnality); + if (DimensionnalityBuffer=="") + return iterator; + boost::match_results what; + boost::match_flag_type flags= boost::match_default; + std::string::const_iterator start,end; + start=DimensionnalityBuffer.begin(); + end=DimensionnalityBuffer.end(); + + while (regex_search(start, end, what, UnsignedInteger)) + { + iterator++; + start=what[0].second; + flags |= boost::match_prev_avail; + flags |= boost::match_not_bob; + } + return iterator; +} + + + +int BrukerDataSet::GetIntValueOfDimN(std::string& file, int N) +{ + int iterator=0; + std::string DimensionnalityBuffer=SearchBufferForText(file,Dimensionnality); + if (N < 1 || DimensionnalityBuffer=="") + return 0; + //std::cout << DimensionnalityBuffer << std::endl; + boost::match_results what; + boost::match_flag_type flags= boost::match_default; + std::string::const_iterator start,end; + start=DimensionnalityBuffer.begin(); + end=DimensionnalityBuffer.end(); + + for (int i=1;i<=N;i++) + { + regex_search(start,end, what, UnsignedInteger); + iterator++; + start=what[0].second; + flags |= boost::match_prev_avail; + flags |= boost::match_not_bob; + } + return atoi(std::string(what[1].first,what[1].second).c_str()); +} + + + +std::string BrukerDataSet::GetValuesPart(std::string& file) +{ + std::string Result; + Result=MatchBufferForText(file,BufferNValues); + if (Result !="") + return Result; + return MatchBufferForText(file,Buffer1Value); +} + + +std::string BrukerDataSet::GetContentType(std::string& file) +{ + std::string ValuesPart, Result; + ValuesPart=GetValuesPart(file); + if (BoolMatchBufferForText(ValuesPart,IntSeries)) + return "int"; + if (BoolMatchBufferForText(ValuesPart,FloatSeries)) + return "float"; + return "string"; +} + + + +int BrukerDataSet::GetIntValueN(std::string& file,int N) +{ + std::string ValuesPart=GetValuesPart(file); + int iterator=0; + if (N < 1 || ValuesPart=="") + return -32767; + + boost::match_results what; + boost::match_flag_type flags= boost::match_default; + std::string::const_iterator start,end; + start=ValuesPart.begin(); + end=ValuesPart.end(); + + while (iterator != N) + { + regex_search(start,end, what, SignedInteger); + iterator++; + start=what[0].second; + flags |= boost::match_prev_avail; + flags |= boost::match_not_bob; + } + return (atoi((std::string(what[1].first,what[1].second)).c_str())); +} + + + +double BrukerDataSet::GetDoubleValueN(std::string& file, int N) +{ + std::string ValuesPart=GetValuesPart(file); + int iterator=0; + if (N < 1 || ValuesPart=="") + return 0; + boost::match_results what; + boost::match_flag_type flags= boost::match_default; + std::string::const_iterator start,end; + start=ValuesPart.begin(); + end=ValuesPart.end(); + + while (iterator != N) + { + regex_search(start,end, what, IntOrFloat); + iterator++; + start=what[0].second; + flags |= boost::match_prev_avail; + flags |= boost::match_not_bob; + } + return (atof((std::string(what[1].first,what[1].second)).c_str())); +} + + + +std::string BrukerDataSet::GetTextValueN(std::string& file, int N) +{ + return GetValuesPart(file); +} + + + +int BrukerDataSet::GetKeywordNumberOfElements(std::string& file) +{ + int NumberOfElements=1; + for (int i=1;i<=GetDimensionnality(file);i++) + NumberOfElements*=GetIntValueOfDimN(file, i); + return NumberOfElements; +} + + + +/** + * +@fn bool BrukerDataSet::FillMap() +@brief This method fills the Bruker headermap with everything contained in the acqp file + +The map is made of BrukerFieldData containing the keywords: +Datatype (string, int, double) +DimensionNumber: The number of Dimensions of the keyword-> 0 scalar, 1-> 1D-vector, 2-> 2D-Matrix, 3->3D-Matrix, ... +DimensionNumberValue: Gives the size of each dimension +DoubleValue: return a vector of values if they are of type double +IntValue: return a vector of values if they are of type int +StringValue: return a string if the values where not identified as a serie of numbers +NumberOfElements: Number of elements corresponding to the keyword given + * @return bool + */ +bool BrukerDataSet::FillMap() +{ + + std::string ValuesBuffer, Keyword,TempString, Substring; + int i; + int KeywordNumber=0; + int PositionDebut=WholeHeader.find("##"); + int PositionFin=PositionDebut+2; + int PosRel; + BrukerFieldData data; + if (PositionFin>=WholeHeader.length()) + return false; + + while(PositionDebut!=std::string::npos) + { + PositionFin=WholeHeader.find("##",PositionDebut+2); + if (-1 == PositionFin) break ; + Substring=WholeHeader.substr (PositionDebut,PositionFin-PositionDebut-1); + PosRel=Substring.find("$$",0); + if (-1 != PosRel) Substring=Substring.substr (0,PosRel-1); + + + if (DEBUG) std::cout<<"Substring=[" << Substring << "]" < BrukerDataSet::GetLoopStructure() const +{ + return LoopStructure; +} + +/** + @fn bool BrukerDataSet::SetLoopStructure (const std::vector & theValue ) + * @brief this methods provide a way to inject a userdefined loop structure, be very aware that this method is not foolproof + * @param theValue + * @return bool + */ +bool BrukerDataSet::SetLoopStructure ( const std::vector & theValue ) +{ + LoopStructure = theValue; +} + + +/** + @fn bool BrukerDataSet::SetLoopStructureOld ( ) + * @brief method to set the default Bruker loopstructure (not yet able to deal with EPI, SPIRAL or spectroscopic experiments + * @return bool + @todo implement multicoil version + */ +bool BrukerDataSet::SetLoopStructureOld () +{ + LoopStructure.clear(); +/* +\file brukerdataset.cpp +\fn bool BrukerDataSet::setGenericLoopStructure ( ) +\brief sets the loop structure of a standard Bruker experiment + +NR (Nbre de repetitions) + NILoop (Boucle eventuelle extra (Diffusion par exemple) si NI<>(NSLICES x NECHOES) cette boucle est a� NI/(NSLICES x NECHOES) + (Attention NILoop peut masquer plusieurs boucles imbriquees !!!!!) + ACQ_size[1..M] (Codage suivant les autres dimensions) + NSLICES (Nombre de tranches) + ACQ_phase_factor (Facteur turbo de la sequence) + ACQ_ns_list_size (Nombre d'echos) + ACQ_size[0] (Ligne acq reelle) + +*/ + + + std::string NRStr("NR"); + std::string NIStr("NI"); + std::string ACQ_sizeStr("ACQ_size"); + std::string ACQ_phase_factorStr("ACQ_phase_factor"); + std::string ACQ_ns_listStr("ACQ_ns_list"); + std::string ACQ_ns_list_sizeStr("ACQ_ns_list_size"); + std::string NSLICESStr("NSLICES"); + + int i, temp; + std::vector TempIntVect; + TempIntVect.clear(); + + if (! CheckExistKeyword(NRStr)) return false; + if (! CheckExistKeyword(NIStr)) return false; + if (! CheckExistKeyword(ACQ_sizeStr)) return false; + if (! CheckExistKeyword(ACQ_phase_factorStr))return false; + if (! CheckExistKeyword(ACQ_ns_list_sizeStr))return false; + if (! CheckExistKeyword(NSLICESStr)) return false; + + TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_size" ].IntValue[0]); + TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[(std::string) "ACQ_ns_list_size"].IntValue[0]); + TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[(std::string) "ACQ_phase_factor"].IntValue[0]); + TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[(std::string) "NSLICES"].IntValue[0]); + if (1<=BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_size" ].DimensionNumber ){ + TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_size" ].IntValue[1]/BrukerDataSet::BrukerHeaderMap[(std::string) "ACQ_phase_factor"].IntValue[0]); + if (2<=BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_size" ].DimensionNumber ) + { + for(i=2;i<=BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_size" ].DimensionNumber;i++) + { + TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_size" ].IntValue[i]); + } + } +} +// Ici, boucles additionnelles si elles existent regroupees en une seule +//temp=GetIntValueN(NIStr,1)/(GetIntValueN(NSLICESStr,1)*GetIntValueN(NECHOESStr,1)); + temp=BrukerDataSet::BrukerHeaderMap[ (std::string) "NI" ].IntValue[0]/(BrukerDataSet::BrukerHeaderMap[ (std::string) "NSLICES" ].IntValue[0]*BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_ns_list_size" ].IntValue[0]); + if (1 < temp) + TempIntVect.push_back(temp); +// fin des boucles cachees + + TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[ (std::string) "NR" ].IntValue[0]); + + LoopStructure=TempIntVect; + return true; +} + + +/** + @fn bool BrukerDataSet::SetLoopStructure ( ) + * @brief method to set the default Bruker loopstructure (not yet able to deal with EPI, SPIRAL or spectroscopic experiments + * @return bool + @todo implement multicoil version + */ +bool BrukerDataSet::SetLoopStructure () +{ + if (! SetInnerObjectLoopStructure()) return false; + if (! SetOuterObjectLoopStructure()) return false; + std::vector Inner=GetInnerObjectLoopStructure(); + std::vector Outer=GetOuterObjectLoopStructure(); + std::vector TmpVect; + TmpVect=Inner; + TmpVect.insert(TmpVect.end(),Outer.begin(),Outer.end()); + LoopStructure=TmpVect; + return true; +} + +std::vector< std :: vector < int > > BrukerDataSet::GetBrukerObjectsLineList() const +{ + return BrukerObjectsLineList; +} + + +bool BrukerDataSet::SetBrukerObjectsLineList () +{ + + std::vector Loop =GetLoopStructure(); + int NumberOfLines, i,j; + NumberOfLines=1; + i=1; + + while (i TempVect (Loop.size()-1,0); + std::vector k (Loop.size()-1,0); + std::vector > TempLineList (NumberOfLines,TempVect); + + for (i=0;i= Loop[j]) { + k[j-1]=0; + k[j]++; + } + } + for (j=1;j<=Loop.size()-1;j++) + TempLineList[i][j-1]=k[j-1]; + k[0]++; + } + BrukerObjectsLineList=TempLineList; + return true; +} + + +std::vector< std::vector < int > > BrukerDataSet::GetBrukerImageList() const +{ + return BrukerImageList; +} + + +bool BrukerDataSet::SetBrukerImageList () +{ + if (LoopStructure.size()==0) + SetImageLoopStructure(); + + std::vector Loop =GetImageLoopStructure(); + int NumberOfLines, i,j; + NumberOfLines=1; + i=1; + + while (i TempVect (Loop.size()-1,0); + std::vector k (Loop.size()-1,0); + std::vector > TempLineList (NumberOfLines,TempVect); + + for (i=0;i= Loop[j]) { + k[j-1]=0; + k[j]++; + } + } + for (j=1;j<=Loop.size()-1;j++) + TempLineList[i][j-1]=k[j-1]; + k[0]++; + } + BrukerImageList=TempLineList; + return true; +} + + + +std::map BrukerDataSet::GetBrukerHeaderMap() const +{ + return BrukerHeaderMap; +} + + + + +//std::map BrukerDataSet::GetBrukerHeaderMap() const +//{ +// return BrukerHeaderMap; +//} + + +bool BrukerDataSet::SetInnerObjectLoopStructure() +{ +/* + ACQ_size[1..M] (Codage suivant les autres dimensions) + NSLICES (Nombre de tranches) + ACQ_phase_factor (Facteur turbo de la sequence) + ACQ_ns_list_size (Nombre d'echos) + ACQ_size[0] (Ligne acq reelle) + +*/ + + int i, temp; + std::vector TempIntVect; + TempIntVect.clear(); + + + if (! CheckExistKeyword("ACQ_size")) return false; + if (! CheckExistKeyword("ACQ_phase_factor"))return false; + if (! CheckExistKeyword("ACQ_ns_list_size"))return false; + if (! CheckExistKeyword("NSLICES")) return false; + + +//std::cout<< "BrukerDataSet::BrukerHeaderMap[ (std::string) ACQ_size ].IntValue[0]" < BrukerDataSet::GetInnerObjectLoopStructure() const +{ + return InnerObjectLoopStructure; +} + +std::vector< int > BrukerDataSet::GetOuterObjectLoopStructure() const +{ + return OuterObjectLoopStructure; +} + + +bool BrukerDataSet::SetOuterObjectLoopStructure () +{ + OuterObjectLoopStructure.clear(); + /* + NR (Nbre de repetitions) + NILoop (Boucle eventuelle extra (Diffusion par exemple) si NI<>(NSLICES x NECHOES) cette boucle est a� NI/(NSLICES x NECHOES) + (Attention NILoop peut masquer plusieurs boucles imbriquees !!!!!) + */ + int temp; + std::vector TempIntVect; + TempIntVect.clear(); + if (! CheckExistKeyword("NR")) return false; + if (! CheckExistKeyword("NI")) return false; +// Ici, boucles additionnelles si elles existent regroupees en une seule +//temp=GetIntValueN(NIStr,1)/(GetIntValueN(NSLICESStr,1)*GetIntValueN(NECHOESStr,1)); + temp=BrukerDataSet::BrukerHeaderMap[ (std::string) "NI" ].IntValue[0]/(BrukerDataSet::BrukerHeaderMap[ (std::string) "NSLICES" ].IntValue[0]*BrukerDataSet::BrukerHeaderMap[ (std::string) "ACQ_ns_list_size" ].IntValue[0]); + if (1 < temp) + TempIntVect.push_back(temp); +// fin des boucles cachees + TempIntVect.push_back(BrukerDataSet::BrukerHeaderMap[ (std::string) "NR" ].IntValue[0]); + OuterObjectLoopStructure=TempIntVect; + return true; +} + + +std::vector< int > BrukerDataSet::GetImageLoopStructure() const +{ + return ImageLoopStructure; +} + + +bool BrukerDataSet::SetImageLoopStructure ( ) +{ + ImageLoopStructure.clear(); + std::vector TempIntVect1=GetInnerObjectLoopStructure(); + std::vector TempIntVect2=GetOuterObjectLoopStructure(); + std::vector TempIntVect3(TempIntVect1.size(),1); + std::vector TempIntVect4; + TempIntVect3[1]=TempIntVect1[1]; + TempIntVect3[3]=TempIntVect1[3]; + TempIntVect4=TempIntVect3; + TempIntVect4.insert(TempIntVect4.end(),TempIntVect2.begin(),TempIntVect2.end()); + ImageLoopStructure = TempIntVect4; + return true; +} diff --git a/lib/src1/brukerdataset.h b/lib/src1/brukerdataset.h new file mode 100644 index 0000000..efb50ce --- /dev/null +++ b/lib/src1/brukerdataset.h @@ -0,0 +1,114 @@ +// +// C++ Interface: brukerdataset +// +// Description: +// +// +// Author: , (C) 2008 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef BRUKERDATASET_H +#define BRUKERDATASET_H + +/*! \file brukerdataset.h +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "boost/regex.hpp" + +#include "brukerSystem.h" +#include "brukerFieldData.h" +#include "brukerobjectvaryingproperties.h" + + const boost::regex KeyWord("^##\\$?([^[:cntrl:]]+)=.*"); + const boost::regex UnsignedInteger("([0-9]+)"); + const boost::regex SignedInteger("(\\-?[0-9]+)"); + const boost::regex Float("([\\-\\+eE0-9\\.]+)"); + const boost::regex IntOrFloat("([\\-\\+eE0-9\\.]+)"); + const boost::regex Dimensionnality("=\\( ([^[:cntrl:]]+) \\)"); + const boost::regex BufferNValues("^##\\$?[^[:cntrl:]]+=\\( [^[:cntrl:]]+ \\)[[:space:]]*[[:cntrl:]]*([^[.dollar-sign.]]+).*"); + const boost::regex Buffer1Value("^##\\$?[^[:cntrl:]]+=(.*)"); + const boost::regex IntSeries("([\\-0-9]*[[:space:]]*[[:cntrl:]]*)+"); + const boost::regex FloatSeries("([\\-\\+eE0-9\\.]+[[:space:]]*[[:cntrl:]]*)+"); + + +/*! \class BrukerDataSet +\brief This class purpose is to extract information from a bruker experiment and setup the extracted information for an easy use +*/ + +class creaBruker_EXPORT BrukerDataSet{ +friend class BrukerKspaceObject; + typedef std::map BrukMapType; + //typedef BrukMapType::iterator iterator; + //typedef BrukMapType::const_iterator const_iterator; +public: + BrukerDataSet(); + ~BrukerDataSet(); + bool LoadFile(std::string& FileToRead); + bool FillMap(); + void PrintKey(std::string &); + void PrintSelf(); + bool Getkspace (std::string &); + const BrukerFieldData& GetFieldData(std::string &); + const BrukerFieldData& GetFieldData(const char *); + bool SetLoopStructure ( ); + bool SetLoopStructureOld ( ); + bool SetLoopStructure (const std::vector& theValue); + std::vector GetLoopStructure ( ) const; + bool SetBrukerObjectsLineList( ); + bool SetBrukerImageList ( ); + + std::vector > GetBrukerObjectsLineList() const; + std::vector > GetBrukerImageList() const; + std::map GetBrukerHeaderMap() const; + + bool SetInnerObjectLoopStructure (); + std::vector GetInnerObjectLoopStructure() const; + bool SetOuterObjectLoopStructure (); + std::vector GetOuterObjectLoopStructure() const; + bool SetImageLoopStructure (); + std::vector GetImageLoopStructure() const; + + BrukerObjectVaryingProperties ObjectVaryingProperties; +private: + + std::string GetKeyword (std::string &kw); + std::string SearchBufferForText (std::string &kw, const boost::regex& RegExp); + bool BoolMatchBufferForText (std::string &kw, const boost::regex& RegExp); + std::string MatchBufferForText (std::string &kw, const boost::regex& RegExp); + int GetDimensionnality (std::string &kw); + int GetIntValueOfDimN (std::string &kw, int n); + int GetIntValueN (std::string &kw, int n); + std::string GetContentType (std::string &kw); + std::string GetValuesPart (std::string &kw); + double GetDoubleValueN (std::string &kw, int n); + int GetKeywordNumberOfElements(std::string &kw); + std::string GetTextValueN (std::string &kw, int n); + bool CheckExistKeyword (std::string &kw); + bool CheckExistKeyword (const char *kw); + + //BrukMapType + + std::map BrukerHeaderMap; + std::string WholeHeader; + std::vector WholeKspace; + std::vector LoopStructure; + std::vector InnerObjectLoopStructure; + std::vector OuterObjectLoopStructure; + std::vector ImageLoopStructure; + std::vector > BrukerObjectsLineList; + std::vector > BrukerImageList; + +protected: +}; + +#endif diff --git a/lib/src1/brukerimage.cpp b/lib/src1/brukerimage.cpp new file mode 100644 index 0000000..41285f5 --- /dev/null +++ b/lib/src1/brukerimage.cpp @@ -0,0 +1,639 @@ +// +// C++ Implementation: brukerimage +// +// Description: +// +// +// Author: Denis Grenier, (C) 2009 +// +// Copyright: See COPYING file that comes with this distribution +// +// +/** +@file brukerimage.cpp +*/ +#include "brukerimage.h" + +/** +* This method takes care of the initialization of the main parameters usually needed to deal with an MRI experiment + * @fn bool BrukerImage::Init(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::Init(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) +{ + +// on devrait plutot les nommer 'computeXXX' (setXXX est d'habitude réservé aux accesseurs 'publics') + + setAbsoluteTimePosition (TheOrigAcqp,TheOrigReco,TheValue); + setRelativeTimePosition (TheOrigAcqp,TheOrigReco,TheValue); + setFOVpixels (TheOrigAcqp,TheOrigReco,TheValue); + setFOVcm (TheOrigAcqp,TheOrigReco,TheValue); + setSliceThickness (TheOrigAcqp,TheOrigReco,TheValue); + setTE (TheOrigAcqp,TheOrigReco,TheValue); + setTR (TheOrigAcqp,TheOrigReco,TheValue); + setTI (TheOrigAcqp,TheOrigReco,TheValue); + setFlipAngle (TheOrigAcqp,TheOrigReco,TheValue); + setLoopStamp (TheOrigAcqp,TheOrigReco,TheValue); + setNA (TheOrigAcqp,TheOrigReco,TheValue); + setNR (TheOrigAcqp,TheOrigReco,TheValue); + setNAE (TheOrigAcqp,TheOrigReco,TheValue); + setDS (TheOrigAcqp,TheOrigReco,TheValue); + setACQ_phase_factor (TheOrigAcqp,TheOrigReco,TheValue); + setRotationMatrixRPS2XYZ (TheOrigAcqp,TheOrigReco,TheValue); + setTranslationVectorRPS2XYZ (TheOrigAcqp,TheOrigReco,TheValue); + setWordType (TheOrigAcqp,TheOrigReco,TheValue); + setImageType (TheOrigAcqp,TheOrigReco,TheValue); + setDataEndianness (TheOrigAcqp,TheOrigReco,TheValue); + setImageByteSize (TheOrigAcqp,TheOrigReco,TheValue); + setBeginingOfImageInBytes (TheOrigAcqp,TheOrigReco,TheValue); +} + +/** + * @brief the constructor uses the BrukerDataSet's of the acqp and reco file + * @fn BrukerImage::BrukerImage(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco) + * @param TheOrigAcqp + * @param TheOrigReco + */ +BrukerImage::BrukerImage(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco) +{ +} + +BrukerImage::~BrukerImage() +{ +} + +/** +* @fn int BrukerImage::getAbsoluteTimePosition() const + * @brief AbsoluteTimePosition is an integer number giving the time of the begining of the acquisition of the dataset + * @return AbsoluteTimePosition int + */ +int BrukerImage::getAbsoluteTimePosition() const +{ + return AbsoluteTimePosition; +} + +/** +* @fn bool BrukerImage::setAbsoluteTimePosition (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue ) + * @brief AbsoluteTimePosition is an integer number giving the time of the begining of the acquisition of the dataset + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setAbsoluteTimePosition (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue ) +{ + AbsoluteTimePosition = TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "ACQ_abs_time"].GetIntValue()[0]; + return true; +} + + +/** + * @brief RelativeTimePosition is the estimated time position of the time the k-space center was acquired + * This notion is very relative when dealing with long experiments and a line or object averaging (NA or NAE <> 1) + * @fn double BrukerImage::getRelativeTimePosition() const + * @return double + */ +double BrukerImage::getRelativeTimePosition() const +{ + return RelativeTimePosition; +} + +/** + * @brief RelativeTimePosition is the estimated instant when the k-space center of each image was acquired + + This notion is very relative when dealing with long experiments and a line or object averaging (NA or NAE <> 1) +* @fn bool BrukerImage::setRelativeTimePosition (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue ) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setRelativeTimePosition (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue ) +{ + long lTEMP = TheOrigAcqp.GetBrukerImageList()[TheValue].back(); + RelativeTimePosition = TheOrigAcqp.ObjectVaryingProperties.getPositionTimePerNR(lTEMP); + return true; +} + + +/** + * @brief FOVpixels is a 1x2 integer vector. it's one of the view value we need to pick in the reco headermap + * @fn bool BrukerImage::setFOVpixels(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setFOVpixels(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) +{ + FOVpixels = TheOrigReco.GetBrukerHeaderMap()[(std::string) "RECO_size"].GetIntValue(); + return true; +} + +/** + * @brief FOVpixels is a 1x2 integer vector. it's one of the view value we need to pick in the reco headermap + * @fn std::vector BrukerImage::getFOVpixels() const + * @return std::vector + */ +const std::vector &BrukerImage::getFOVpixels() const +{ + return FOVpixels; +} + + +/** + * @brief FOVcm is also picked in reco headermap + * @fn bool BrukerImage::setFOVcm(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setFOVcm(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) +{ + FOVcm = TheOrigReco.GetBrukerHeaderMap()[(std::string) "RECO_fov"].GetDoubleValue(); + return true; +} + +/** + * @brief FOVcm is also picked in reco headermap + * @fn std::vector BrukerImage::getFOVcm() const + * @return std::vector + */ +const std::vector &BrukerImage::getFOVcm() const +{ + return FOVcm; +} + +/** + * @brief SliceThickness is in milimeter + * @fn bool BrukerImage::setSliceThickness( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setSliceThickness( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue) +{ + SliceThickness = TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "ACQ_slice_thick"].GetDoubleValue()[0]; + return true; +} + +/** + * @brief SliceThickness is in milimeter + * @fn double BrukerImage::getSliceThickness() const + * @return double + */ +double BrukerImage::getSliceThickness() const +{ + return SliceThickness; +} + +/** +* @brief picks the echo time of the image number TheValue + * @fn bool BrukerImage::setTE( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setTE( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue) +{ + TE = TheOrigAcqp.ObjectVaryingProperties.getTE(TheOrigAcqp.GetBrukerImageList()[TheValue][0]); + return true; +} + +/** + * @fn double BrukerImage::getTE() const + * @brief picks the echo time of the image number TheValue + * @return TE + */ +double BrukerImage::getTE() const +{ + return TE; +} + + +/** + * @brief picks the repetition time of the image number TheValue + * @fn bool BrukerImage::setTR( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setTR(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) +{ + TR=TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "ACQ_repetition_time"].GetDoubleValue()[0]; + return true; +} + + /** + * @fn double BrukerImage::getTR() const + * @brief picks the echo time of the image number TheValue + * @return TR + */ +double BrukerImage::getTR() const +{ + return TR; +} + +/** +* @brief picks the invertion time of the image number TheValue + * @fn bool BrukerImage::setTI( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setTI(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) +{ + TI = TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "ACQ_inversion_time"].GetDoubleValue()[0]; + return true; +} + + /** + * @fn double BrukerImage::getTI() const + * @brief picks the invertion time of the image number TheValue + * @return TI + */ +double BrukerImage::getTI() const +{ + return TI; +} + +/** +* @brief picks the flip angle of the image number TheValue + * @fn bool BrukerImage::setFlipAngle( BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco,int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setFlipAngle(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) +{ + FlipAngle = TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "ACQ_flip_angle"].GetIntValue()[0]; + return true; +} + +/** + * @fn double BrukerImage::getFlipAngle() const + * @brief picks the flip angle of the image number TheValue + * @return FlipAngle +*/ +double BrukerImage::getFlipAngle() const +{ + return FlipAngle; +} + + +/** + * @brief LoopStamp is a vector, copy of the values of all the loop for the image number TheValue + + * The purpose of this "loopstamp" is to provide additionnal information if the methods provided by this class are not sufficient to singularize each image + * @fn bool BrukerImage::setLoopStamp(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setLoopStamp(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) +{ + LoopStamp = TheOrigAcqp.GetBrukerImageList()[TheValue]; + return true; +} + +/** + * @brief LoopStamp is a vector, copy of the values of all the loop for the image number TheValue + * The purpose of this "loopstamp" is to provide additionnal information if the methods provided by this class are not sufficient to singularize each image + * @fn std::vector BrukerImage::getLoopStamp() const + * @return LoopStamp + */ +const std::vector &BrukerImage::getLoopStamp() const +{ + return LoopStamp; +} + + +/** + * @brief NA number of accumulation is useful to track image quality + * @fn bool BrukerImage::setNA(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return + */ +bool BrukerImage::setNA(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) +{ + NA=TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "NA"].GetIntValue()[0]; + return true; +} + +/** + * @brief NA number of accumulation is useful to track image quality + * @fn int BrukerImage::getNA() const + * + * @return NA + */ +int BrukerImage::getNA() const +{ + return NA; +} + +/** +@brief NAE number of object exterior accumulation is useful to track image quality and rather used than NA to average movement artefacts + * @fn bool BrukerImage::setNAE(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setNAE(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) +{ + NAE=TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "NAE"].GetIntValue()[0]; + return true; +} + +/** + @brief NAE number of object exterior accumulation is useful to track image quality and rather used than NA to average movement artefacts + * @fn int BrukerImage::getNAE() const + * @return NAE + */ + +int BrukerImage::getNAE() const +{ + return NAE; +} + +/** +@brief DS (dummy scan) is useful to establish a dynamic equilibrium or to know if one was used + * @fn bool BrukerImage::setDS(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ + +bool BrukerImage::setDS(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) +{ + DS=TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "DS"].GetIntValue()[0]; + return true; +} + +/** + @brief DS (dummy scan) is useful to establish a dynamic equilibrium or to know if one was used + @fn int BrukerImage::get() const + @return DS +*/ +int BrukerImage::getDS() const +{ + return DS; +} + +/** +@brief Phase factor is the number of kspace line acquired in a single shot + * @fn bool BrukerImage::setACQ_phase_factor(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setACQ_phase_factor(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) +{ + ACQ_phase_factor=TheOrigAcqp.GetBrukerHeaderMap()[(std::string) "ACQ_phase_factor"].GetIntValue()[0]; + return true; +} + +/** + @brief Phase factor is the number of kspace line acquired in a single shot + @fn int BrukerImage::getACQ_phase_factor() const + @return +*/ +int BrukerImage::getACQ_phase_factor() const +{ + return ACQ_phase_factor; +} + + +/** +@brief The number of repetition NR is used to repeat a full objects acquisition NR times with a given delay +* This method returns at which repetition belongs the image TheValue + * @fn bool BrukerImage::NR(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setNR(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) +{ + NR= TheOrigAcqp.GetBrukerImageList()[TheValue].back(); + return true; +} + + /** + @brief The number of repetition NR is used to repeat a full objects acquisition NR times with a given delay + * This method returns at which repetition belongs the image TheValue + @fn int BrukerImage::getNR() const + @return NR + */ +int BrukerImage::getNR() const +{ + return NR; +} + + + +/** +@brief RotationMatrixRPS2XYZ is a 3x3 rotation matrix giving the orientation of the TheValue image + * @fn bool BrukerImage::setRotationMatrixRPS2XYZ(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setRotationMatrixRPS2XYZ(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) +{ + RotationMatrixRPS2XYZ = TheOrigAcqp.ObjectVaryingProperties.getOrientation(TheOrigAcqp.GetBrukerImageList()[TheValue][2]); + return true; +} + + /** + @brief RotationMatrixRPS2XYZ is a 3x3 rotation matrix giving the orientation of the TheValue image + @fn std::vector > BrukerImage::getRotationMatrixRPS2XYZ() const + @return RotationMatrixRPS2XYZ + */ +const std::vector > &BrukerImage::getRotationMatrixRPS2XYZ() const +{ + return RotationMatrixRPS2XYZ; +} + + + +/** +@brief TranslationVectorRPS2XYZ is a 1x3 vector of the TheValue image position to the magnet center (in mm) + * @fn bool BrukerImage::setTranslationVectorRPS2XYZ(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setTranslationVectorRPS2XYZ(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) +{ + TranslationVectorRPS2XYZ.clear(); + TranslationVectorRPS2XYZ.push_back(TheOrigAcqp.ObjectVaryingProperties.getPositionR(TheOrigAcqp.GetBrukerImageList()[TheValue][2])); + TranslationVectorRPS2XYZ.push_back(TheOrigAcqp.ObjectVaryingProperties.getPositionP(TheOrigAcqp.GetBrukerImageList()[TheValue][2])); + TranslationVectorRPS2XYZ.push_back(TheOrigAcqp.ObjectVaryingProperties.getPositionS(TheOrigAcqp.GetBrukerImageList()[TheValue][2])); + return true; +} + +/** + @brief TranslationVectorRPS2XYZ is a 1x3 vector of the TheValue image position to the magnet center (in mm) + @fn std::vector BrukerImage::getTranslationVectorRPS2XYZ() const + @return TranslationVectorRPS2XYZ +*/ +const std::vector &BrukerImage::getTranslationVectorRPS2XYZ() const +{ + return TranslationVectorRPS2XYZ; +} + +/** +@brief WordType returns the type of data to read int32_t, int16_t, uint8_t or float32_t + * @fn bool BrukerImage::setWordType(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setWordType(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) +{ + WordType=TheOrigReco.GetBrukerHeaderMap()[(std::string) "RECO_wordtype"].GetStringValue()[0]; + return true; +} + + /** + @brief WordType returns the type of data to read int32_t, int16_t, uint8_t or float32_t + @fn std::string BrukerImage::getWordType() const + @return int32_t, int16_t, uint8_t or float32_t or UNKNOWN + */ +std::string BrukerImage::getWordType() const +{ + if(WordType == ((std::string) "_32BIT_SGN_INT")) return ((std::string)"int32_t"); + if(WordType == ((std::string) "_16BIT_SGN_INT")) return ((std::string)"int16_t"); + if(WordType == ((std::string) "_8BIT_UNSGN_INT")) return ((std::string)"uint8_t"); + if(WordType == ((std::string) "_32BIT_FLOAT")) return ((std::string)"float32_t"); + return ((std::string)"UNKNOWN"); +} + +/** +@brief ImageType returns the type of image : values real for amplitude, real imaginary or phase images and complex for complex images + * @fn bool BrukerImage::setImageType(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setImageType(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) +{ + ImageType=TheOrigReco.GetBrukerHeaderMap()[(std::string) "RECO_image_type"].GetStringValue()[0]; + return true; +} + + /** + @brief ImageType returns the type of image : values real for amplitude, real imaginary or phase images and complex for complex images + @fn std::string BrukerImage::getImageType() const + @return complex or real + */ +std::string BrukerImage::getImageType() const +{ + if(ImageType == ((std::string) "COMPLEXE_IMAGE")) return ((std::string)"complex"); + return ((std::string)"real"); +} + + +/** +@brief DataEndianness gives information on how to swap or no the binary data to read + * @fn bool BrukerImage::setDataEndianness(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setDataEndianness(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) +{ + DataEndianness=TheOrigReco.GetBrukerHeaderMap()[(std::string) "RECO_byte_order"].GetStringValue()[0]; + return true; +} + + /** + @brief DataEndianness gives information on how to swap or no the binary data to read + @fn std::string BrukerImage::getDataEndianness() const + @return DataEndianness + */ +const std::string &BrukerImage::getDataEndianness() const +{ + return DataEndianness; +} + +/** +@brief Information on the image size in byte, useful for offsets calculation + * @fn bool BrukerImage::setImageByteSize(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setImageByteSize(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) +{ + int Dimension, WordSize; + if (getImageType()==((std::string)"complex")) Dimension=2; + else if (getImageType()==((std::string)"real")) Dimension=1; + else return false; + + if (getWordType()==((std::string)"int32_t")||getWordType()==((std::string)"float32_t")) WordSize=4; + else if (getWordType()==((std::string)"int16_t")) WordSize=2; + else if (getWordType()==((std::string)"uint8_t")) WordSize=1; + else /*if (getWordType()==((std::string)"UNKNOWN"))*/ return false; + + ImageByteSize = Dimension*WordSize*getFOVpixels()[0]*getFOVpixels()[1]; + return true; +} + + /** + @brief Information on the image size in byte, useful for offsets calculation + @fn size_t BrukerImage::getImageByteSize() const + @return ImageByteSize + */ +size_t BrukerImage::getImageByteSize() const +{ + return ImageByteSize; +} + + +/** + @brief BeginingOfImageInBytes is the offset of the image number TheValue to the begining of 2dseq file + @fn size_t BrukerImage::getBeginingOfImageInBytes() const + @return BeginingOfImageInBytes +*/ + + +size_t BrukerImage::getBeginingOfImageInBytes() const +{ + return BeginingOfImageInBytes; +} + + +/** +@brief BeginingOfImageInBytes is the offset of the image number TheValue to the begining of 2dseq file + * @fn bool BrukerImage::setBeginingOfImageInBytes(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) + * @param TheOrigAcqp + * @param TheOrigReco + * @param TheValue + * @return bool + */ +bool BrukerImage::setBeginingOfImageInBytes (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue) +{ + BeginingOfImageInBytes = TheValue*getImageByteSize(); +} diff --git a/lib/src1/brukerimage.h b/lib/src1/brukerimage.h new file mode 100644 index 0000000..22e61ee --- /dev/null +++ b/lib/src1/brukerimage.h @@ -0,0 +1,110 @@ +// +// C++ Interface: brukerimage +// +// Description: +// +// +// Author: Denis Grenier, (C) 2009 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef BRUKERIMAGE_H +#define BRUKERIMAGE_H + +#include "brukerdataset.h" +#include "brukerSystem.h" +/** +This class centralizes the informations "needed" to exploit a bruker image file 2dseq + + @author Denis Grenier + @file brukerimage.h +*/ +class creaBruker_EXPORT BrukerImage{ +public: + BrukerImage(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco); + ~BrukerImage(); + + bool Init(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + + int getAbsoluteTimePosition() const; + double getRelativeTimePosition() const; + const std::vector &getFOVpixels() const; + const std::vector &getFOVcm() const; + double getSliceThickness() const; + double getTE() const; + double getTR() const; + double getTI() const; + double getFlipAngle() const; + int getNA() const; + int getNR() const; + int getDS() const; + int getNAE() const; + int getACQ_phase_factor() const; + std::string getWordType() const; + std::string getImageType() const; + const std::string &getDataEndianness() const; + size_t getImageByteSize() const; + size_t getBeginingOfImageInBytes() const; + + const std::vector &getLoopStamp() const; + + const std::vector > &getRotationMatrixRPS2XYZ() const; + const std::vector &getTranslationVectorRPS2XYZ() const; + + +protected: + +private: + +// on devrait plutot les nommer 'computeXXX' (setXXX est d'habitude reserve aux accesseurs 'publics') + + bool setAbsoluteTimePosition (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setRelativeTimePosition (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setFOVpixels (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setFOVcm (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setSliceThickness (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setTE (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setTR (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setTI (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setFlipAngle (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setLoopStamp (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setNA (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setNR (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setNAE (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setDS (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setACQ_phase_factor (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setRotationMatrixRPS2XYZ (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setTranslationVectorRPS2XYZ(BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setWordType (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setImageType (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setDataEndianness (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setImageByteSize (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + bool setBeginingOfImageInBytes (BrukerDataSet &TheOrigAcqp, BrukerDataSet &TheOrigReco, int TheValue); + + std::vector FOVpixels; + std::vector FOVcm; + std::vector LoopStamp; + double SliceThickness; + double TE; + double TR; + double TI; + double FlipAngle; + double RelativeTimePosition; + int NA; + int NR; + int NAE; + int DS; + int ACQ_phase_factor; + std::vector > RotationMatrixRPS2XYZ; + std::vector TranslationVectorRPS2XYZ; + int AbsoluteTimePosition; + std::string WordType; + std::string ImageType; + std::string DataEndianness; + size_t ImageByteSize; + size_t BeginingOfImageInBytes; + +}; + +#endif diff --git a/lib/src1/brukerimageset.cpp b/lib/src1/brukerimageset.cpp new file mode 100644 index 0000000..3e808b1 --- /dev/null +++ b/lib/src1/brukerimageset.cpp @@ -0,0 +1 @@ +#include "brukerimageset.h" diff --git a/lib/src1/brukerimageset.h b/lib/src1/brukerimageset.h new file mode 100644 index 0000000..6c4e77a --- /dev/null +++ b/lib/src1/brukerimageset.h @@ -0,0 +1,28 @@ +// +#ifndef BRUKERIMAGESET_H +#define BRUKERIMAGESET_H + +/* +#include "brukerSystem.h" +#include "brukerimage.h" +#include + +typedef bool (*BOOL_FUNCTION_PFILE_PFILE_POINTER)(File *, File *); +typedef std::map CoherentBrukerImageSetMap; + +class BRUKER_EXPORT BrukerImageSet : public std::vector { +public: + BrukerImageSet(); + ~BrukerImageSet(); + + + /// to allow user to give is own comparison function + void SetUserLessThanFunction( BOOL_FUNCTION_PFILE_PFILE_POINTER userFunc ) + { UserLessThanFunction = userFunc; } + + CoherentBrukerImageSetMap SplitOnOrientation(); + CoherentBrukerImageSetMap SplitOnPosition(); + +}; +*/ +#endif diff --git a/lib/src1/brukerkspaceobject.cpp b/lib/src1/brukerkspaceobject.cpp new file mode 100644 index 0000000..cd7883c --- /dev/null +++ b/lib/src1/brukerkspaceobject.cpp @@ -0,0 +1,137 @@ +// +// C++ Implementation: brukerobject +// +// Description: +// +// +// Author: , (C) 2008 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "brukerkspaceobject.h" + + + +bool BrukerKspaceObject::FillWithObject(BrukerDataSet DataSet, int ObjectNumber) +{ + + std::string TempString; + std::vector< int > TempVectInt; + std::vector TempVectDouble; + + TempString="ACQ_abs_time"; + if (DataSet.CheckExistKeyword(TempString)) { + setAbsoluteTimePosition ( DataSet.BrukerHeaderMap[TempString].GetIntValue()[0] ); + } + else return false; + + TempString="ACQ_phase_factor"; + if (DataSet.CheckExistKeyword(TempString)) { + setACQ_phase_factor(DataSet.BrukerHeaderMap[TempString].GetIntValue()[0]); + } + else return false; + + TempString="ACQ_dim"; + if (DataSet.CheckExistKeyword(TempString)) { + setDimension(DataSet.BrukerHeaderMap[TempString].GetIntValue()[0]); + } + else return false; + + TempString="ACQ_size"; + if (DataSet.CheckExistKeyword(TempString)){ + for (int i=0;i, (C) 2008 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef BRUKERKSPACEOBJECT_H +#define BRUKERKSPACEOBJECT_H + +#include +#include "brukerSystem.h" +#include "brukerdataset.h" + + +class creaBruker_EXPORT BrukerKspaceObject{ +public: + BrukerKspaceObject(BrukerDataSet DataSet); + ~BrukerKspaceObject(); + + + + void setAbsoluteTimePosition ( long theValue ) + { + AbsoluteTimePosition = theValue; + } + + + + long getAbsoluteTimePosition() const + { + return AbsoluteTimePosition; + } + + void setACQ_phase_factor ( int theValue ) + { + ACQ_phase_factor = theValue; + } + + + int getACQ_phase_factor() const + { + return ACQ_phase_factor; + } + + void setDimension ( int theValue ) + { + Dimension = theValue; + } + + int getDimension() const + { + return Dimension; + } + + void setFlipAngle ( double theValue ) + { + FlipAngle = theValue; + } + + double getFlipAngle() const + { + return FlipAngle; + } + + void setImaginaryPart ( const std::vector< double >& theValue ) + { + ImaginaryPart = theValue; + } + + std::vector< double > getImaginaryPart() const + { + return ImaginaryPart; + } + + void setNA ( int theValue ) + { + NA = theValue; + } + + int getNA() const + { + return NA; + } + + void setNR ( int theValue ) + { + NR = theValue; + } + + int getNR() const + { + return NR; + } + + void setNumberOfSlices ( int theValue ) + { + NumberOfSlices = theValue; + } + + +int getNumberOfSlices() const +{ + return NumberOfSlices; +} + +void setObjectNumber ( int theValue ) +{ + ObjectNumber = theValue; +} + + +int getObjectNumber() const +{ + return ObjectNumber; +} + +void setRealPart ( const std::vector< double >& theValue ) +{ + RealPart = theValue; +} + + +std::vector< double > getRealPart() const +{ + return RealPart; +} + +void setRG ( double theValue ) +{ + RG = theValue; +} + + +double getRG() const +{ + return RG; +} + +void setRotationMatrixRPS2XYZ ( const std::vector< std :: vector < double > >& theValue ) +{ + RotationMatrixRPS2XYZ = theValue; +} + + +std::vector< std :: vector < double > > getRotationMatrixRPS2XYZ() const +{ + return RotationMatrixRPS2XYZ; +} + +void setSliceNumber ( int theValue ) +{ + SliceNumber = theValue; +} + + +int getSliceNumber() const +{ + return SliceNumber; +} + +void setSliceThickness ( double theValue ) +{ + SliceThickness = theValue; +} + + +double getSliceThickness() const +{ + return SliceThickness; +} + +void setTE ( double theValue ) +{ + TE = theValue; +} + + +double getTE() const +{ + return TE; +} + + +void setTI ( double theValue ) +{ + TI = theValue; +} + + +double getTI() const +{ + return TI; +} + +void setTR ( double theValue ) +{ + TR = theValue; +} + + +double getTR() const +{ + return TR; +} + +void setTranslationVectorRPS2XYZ ( const std::vector< double >& theValue ) +{ + TranslationVectorRPS2XYZ = theValue; +} + + +std::vector< double > getTranslationVectorRPS2XYZ() const +{ + return TranslationVectorRPS2XYZ; +} + +void setDimensionSizes ( const std::vector< int >& theValue ) +{ + DimensionSizes = theValue; +} + + +std::vector< int > getDimensionSizes() const +{ + return DimensionSizes; +} + +void setFOV ( const std::vector< double >& theValue ) +{ + FOV = theValue; +} + + +std::vector< double > getFOV() const +{ + return FOV; +} + + +bool FillWithObject(BrukerDataSet DataSet, int ObjectNumber); + + +void setNI ( int theValue ) +{ + NI = theValue; +} + + +int getNI() const +{ + return NI; +} + +void setNAE ( int theValue ) +{ + NAE = theValue; +} + + +int getNAE() const +{ + return NAE; +} + +void setDS ( int theValue ) +{ + DS = theValue; +} + + +int getDS() const +{ + return DS; +} + +void setACQ_ns_list ( const std::vector< int >& theValue ) +{ + ACQ_ns_list = theValue; +} + + +std::vector< int > getACQ_ns_list() const +{ + return ACQ_ns_list; +} + +void setACQ_obj_order ( const std::vector< int >& theValue ) +{ + ACQ_obj_order = theValue; +} + + +std::vector< int > getACQ_obj_order() const +{ + return ACQ_obj_order; +} + +void setACQ_echo_time ( const std::vector< int >& theValue ) +{ + ACQ_echo_time = theValue; +} + +std::vector< int > getACQ_echo_time() const +{ + return ACQ_echo_time; +} + + + +private: + int ObjectNumber; + int Dimension; + std::vector DimensionSizes; + std::vector ACQ_ns_list; + std::vector ACQ_obj_order; + std::vector ACQ_echo_time; + double TE; + double TR; + double TI; + double FlipAngle; + double RG; + int NA; + int ACQ_phase_factor; + std::vector > RotationMatrixRPS2XYZ; + std::vector TranslationVectorRPS2XYZ; + long AbsoluteTimePosition; + int NR; + int NI; + int NAE; + int DS; + int NumberOfSlices; + int SliceNumber; + std::vector FOV; + double SliceThickness; + std::vector RealPart; + std::vector ImaginaryPart; +}; + +#endif diff --git a/lib/src1/brukerobjectvaryingproperties.cpp b/lib/src1/brukerobjectvaryingproperties.cpp new file mode 100644 index 0000000..64aefd8 --- /dev/null +++ b/lib/src1/brukerobjectvaryingproperties.cpp @@ -0,0 +1,210 @@ +// +// C++ Implementation: brukerobjectvaryingproperties +// +// Description: +// +// +// Author: denis grenier , (C) 2009 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "brukerobjectvaryingproperties.h" + + + +BrukerObjectVaryingProperties::BrukerObjectVaryingProperties() +{ +} + + +BrukerObjectVaryingProperties::~BrukerObjectVaryingProperties() +{ +} + + + +void BrukerObjectVaryingProperties::setPositionS(std::map & BrukerHM){ + std::vector PosiS =BrukerHM[(std::string) "ACQ_slice_offset"].GetDoubleValue(); + PositionS =PosiS; +}; + +void BrukerObjectVaryingProperties::setPositionR(std::map & BrukerHM){ + PositionR =BrukerHM[(std::string) "ACQ_read_offset"].GetDoubleValue() ; +}; + +void BrukerObjectVaryingProperties::setPositionP(std::map & BrukerHM){ + PositionP =BrukerHM[(std::string) "ACQ_phase1_offset"].GetDoubleValue(); +}; + +void BrukerObjectVaryingProperties::setTE(std::map & BrukerHM){ + TE = BrukerHM[(std::string) "ACQ_echo_time"].GetDoubleValue(); +}; + +double BrukerObjectVaryingProperties::getTE(int theValue) const{ + if (theValue < TE.size() && theValue >=0) {return TE[theValue];} + else throw 0; +} + +/*void BrukerObjectVaryingProperties::setTE(const std::vector< double >& theValue) +{ + TE = theValue; +}*/ + +double BrukerObjectVaryingProperties::getPositionP(int theValue) const{ + if (theValue < PositionP.size() && theValue >=0) return PositionP[theValue]; + else throw 0; +} + +/*void BrukerObjectVaryingProperties::setPositionP(const std::vector< double >& theValue) +{ + PositionP = theValue; +}*/ + +double BrukerObjectVaryingProperties::getPositionR(int theValue) const{ + if (theValue < PositionR.size() && theValue >=0) return PositionR[theValue]; + else throw 0; +} + +/*void BrukerObjectVaryingProperties::setPositionR(const std::vector< double >& theValue) +{ + PositionP = theValue; +}*/ + +double BrukerObjectVaryingProperties::getPositionS(int theValue) const{ + if (theValue < PositionS.size() && theValue >=0) return PositionS[theValue]; + else throw 0; +} + +/*void BrukerObjectVaryingProperties::setPositionS(const std::vector< double >& theValue) +{ + PositionP = theValue; +}*/ + +int BrukerObjectVaryingProperties::getAcquisitionOrder(int theValue) const{ + if (theValue =0) return AcquisitionOrder[theValue]; + else throw 0; +} + +/*void BrukerObjectVaryingProperties::setAcquisitionOrder(const std::vector< int >& theValue1, const std::vector< int >& theValue2) +{ + AcquisitionOrder.clear(); + if (theValue1.size() != theValue2[3]*theValue2[1]) throw 0; + if (theValue2.size() < 4 ) throw 0; + for (int i =0 ;i & BrukerHM, std::vector & LoopStruct){ + std::vector AcqOrder; + if (BrukerHM[(std::string) "ACQ_obj_order"].GetIntValue().size() != LoopStruct[3]*LoopStruct[1]) throw 0; + if (LoopStruct.size() < 4 ) throw 0; + for (int i =0 ;i > BrukerObjectVaryingProperties::getOrientation(int theValue) const{ + if (theValue =0)return Orientation[theValue]; + else throw 0; +} + +/*void BrukerObjectVaryingProperties::setOrientation( std :: vector < double > & theValue1,const std::vector< int >& theValue2) +{ + if (theValue1.size() != theValue2[3]*9) throw 0; + if (theValue2.size() < 4 ) throw 0; + int counter=0; + for(int i=0;i & BrukerHM, std::vector & LoopStruct){ + if (BrukerHM[(std::string) "ACQ_grad_matrix"].GetDoubleValue().size() != LoopStruct[3]*9) throw 0; + if (LoopStruct.size() < 4 ) throw 0; + + std::vector Temp1D(3,0.0); + std::vector > Temp2D; + std::vector > > Temp3D; + int i, j ,k; + + for(i=0;i<3;i++) + Temp2D.push_back(Temp1D); + for (i=0;i=0) return PositionTimePerNR[theValue]; + else throw 0; +} + +void BrukerObjectVaryingProperties::setPositionTimePerNR(std::map & BrukerHM, std::vector & LoopStruct){ + double FloatPositionTimePerNR=BrukerHM[(std::string) "ACQ_repetition_time"].GetDoubleValue()[0]; + int i=0; + int NA=BrukerHM[(std::string) "NA"].GetIntValue()[0]; + int NAE=BrukerHM[(std::string) "NAE"].GetIntValue()[0]; + double temp; + +/* + les loop de 0 a  3 ne sont pas conceres par le temps car ils creent presque systematiquement +un melange temporel des donnees, c'est pour cela que je ne calcule q'un temps moyen a  partir de celles -ci +*/ + for (i=4; i<(LoopStruct.size()-1);i++) + { + FloatPositionTimePerNR=FloatPositionTimePerNR*LoopStruct[i]; + } + FloatPositionTimePerNR=FloatPositionTimePerNR*NA*NAE/2000.0; + if (BrukerHM[(std::string) "ACQ_temporal_delay"].GetDoubleValue().size()==1) + { + temp=BrukerHM[(std::string)"ACQ_temporal_delay"].GetDoubleValue()[0]/1000.0; + for (i=1; i<=LoopStruct.back();i++) + { + PositionTimePerNR.push_back(FloatPositionTimePerNR+ (2*FloatPositionTimePerNR+temp)*(i-1)); + } + } + + if (BrukerHM[(std::string) "ACQ_temporal_delay"].GetDoubleValue().size()!=1&& BrukerHM[(std::string) "ACQ_temporal_delay"].GetDoubleValue().size()!=(LoopStruct.back()-1)) + { + throw 0; + } + if (BrukerHM[(std::string) "ACQ_temporal_delay"].GetDoubleValue().size()!=1&& BrukerHM[(std::string) "ACQ_temporal_delay"].GetDoubleValue().size()==(LoopStruct.back()-1)) + { + PositionTimePerNR[0] = FloatPositionTimePerNR; + for (int i=1; i<=LoopStruct.back();i++) + { + PositionTimePerNR[i] = PositionTimePerNR[i-1]+ (2*FloatPositionTimePerNR+BrukerHM[(std::string) "ACQ_temporal_delay"].GetDoubleValue()[i-1]/1000.0); + } + } +} + + +/*! + \fn BrukerObjectVaryingProperties::init(std::map BrukerHM,std::vector LoopStruct) + */ +bool BrukerObjectVaryingProperties::init(std::map & BrukerHM, std::vector & LoopStruct) +{ + setAcquisitionOrder( BrukerHM, LoopStruct); + setOrientation(BrukerHM, LoopStruct); + setPositionP(BrukerHM); + setPositionR(BrukerHM); + setPositionS(BrukerHM); + setPositionTimePerNR(BrukerHM, LoopStruct); + setTE(BrukerHM); +} + diff --git a/lib/src1/brukerobjectvaryingproperties.h b/lib/src1/brukerobjectvaryingproperties.h new file mode 100644 index 0000000..9158a68 --- /dev/null +++ b/lib/src1/brukerobjectvaryingproperties.h @@ -0,0 +1,64 @@ +// +// C++ Interface: brukerobjectvaryingproperties +// +// Description: +// +// +// Author: denis grenier , (C) 2009 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef BRUKEROBJECTVARYINGPROPERTIES_H +#define BRUKEROBJECTVARYINGPROPERTIES_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "boost/regex.hpp" +#include "brukerFieldData.h" +#include "brukerSystem.h" + +/** + @author denis grenier +*/ +class creaBruker_EXPORT BrukerObjectVaryingProperties{ +public: + BrukerObjectVaryingProperties(); + ~BrukerObjectVaryingProperties(); + + double getTE (int theValue) const; + double getPositionP (int theValue) const; + double getPositionR (int theValue) const; + double getPositionS (int theValue) const; + double getPositionTimePerNR(int theValue) const; + int getAcquisitionOrder (int theValue) const; + + std::vector > getOrientation(int theValue) const; + + bool init(std::map &BrukerHM, std::vector &LoopStruct); + +private: + + void setPositionTimePerNR (std::map &BrukerHM, std::vector &LoopStruct); + void setOrientation (std::map &BrukerHM, std::vector &LoopStruct); + void setAcquisitionOrder (std::map &BrukerHM, std::vector &LoopStruct); + void setPositionS (std::map &BrukerHM); + void setPositionR (std::map &BrukerHM); + void setPositionP (std::map &BrukerHM); + void setTE (std::map &BrukerHM); + std::vector TE; + std::vector PositionR; + std::vector PositionP; + std::vector PositionS; + std::vector PositionTimePerNR; + std::vector AcquisitionOrder; + std::vector > > Orientation; +}; + +#endif diff --git a/lib/template_lib/CMakeLists.txt b/lib/template_lib/CMakeLists.txt new file mode 100644 index 0000000..ce03df3 --- /dev/null +++ b/lib/template_lib/CMakeLists.txt @@ -0,0 +1,59 @@ +#---------------------------------------------------------------------------- +# SET THE NAME OF YOUR LIBRARY +SET ( LIBRARY_NAME MyLib ) +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# CREATES A USER OPTION IN CMAKE +OPTION ( BUILD_${LIBRARY_NAME} "Build ${LIBRARY_NAME} library ?" ON) +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +IF ( BUILD_${LIBRARY_NAME} ) +#---------------------------------------------------------------------------- + + #---------------------------------------------------------------------------- + # BUILD LIBRARY + #---------------------------------------------------------------------------- + + #---------------------------------------------------------------------------- + # LIBRARY HEADERS (TO BE INSTALLED) + # EITHER LIST ALL .h IN CURRENT DIR USING NEXT LINE: + FILE(GLOB ${LIBRARY_NAME}_HEADERS "*.h") + # OR MANUALLY LIST YOUR HEADERS WITH NEXT COMMAND + # SET ( ${LIBRARY_NAME}_HEADERS + # + # ) + #---------------------------------------------------------------------------- + + #---------------------------------------------------------------------------- + # LIBRARY SOURCES (TO BE COMPILED) + # EITHER LIST ALL .cxx, *.cpp, *.cc IN CURRENT DIR USING NEXT LINE: + FILE(GLOB ${LIBRARY_NAME}_SOURCES *.cxx *.cpp *.cc) + # OR MANUALLY LIST YOUR FILES WITH NEXT COMMAND (WITHOUT EXTENSION) + # SET ( ${LIBRARY_NAME}_SOURCES + # + # ) + #---------------------------------------------------------------------------- + + #---------------------------------------------------------------------------- + # LIBRARY DEPENDENCIES (LIBRARIES TO LINK WITH) + SET ( ${LIBRARY_NAME}_LINK_LIBRARIES + ${crea_LIBRARIES} + # ${WXWIDGETS_LIBRARIES} + # ${VTK_LIBRARIES} + # ${ITK_LIBRARIES} + # ${GDCM_LIBRARIES} + # ${BOOST_LIBRARIES} + ) + #---------------------------------------------------------------------------- + + + #---------------------------------------------------------------------------- + # MACRO WHICH DOES ALL THE JOB : BUILD AND INSTALL + CREA_ADD_LIBRARY( ${LIBRARY_NAME} ) + #---------------------------------------------------------------------------- + + + #--------------------------------------------------------------------------- +ENDIF ( BUILD_${LIBRARY_NAME} )