[ITK-users] [ITK] SimpleITK Serieswriter and DicomTags
Matias
matimontg at gmail.com
Wed Apr 5 09:22:09 EDT 2017
Awesome, thanks!
El mié., 5 de abr. de 2017 a la(s) 09:57, Lowekamp, Bradley (NIH/NLM/LHC)
[C] [via ITK - Users] <ml-node+s7n38072h1 at n7.nabble.com> escribió:
> Hello Matias,
>
> Ziv's patch was merged into SimpleITK’s master branch yesterday. The CDash
> builds[1] compiled the update and created binaries which are linked in the
> golden boxes. I believe you want CSharp for window 64[2].
>
> Enjoy!
> Brad
>
> [1] https://open.cdash.org/index.php?project=SimpleITK
> [2] https://open.cdash.org/viewFiles.php?buildid=4839224
>
> On Apr 2, 2017, at 9:58 AM, Yaniv, Ziv Rafael (NIH/NLM/LHC) [C] <[hidden
> email] <http:///user/SendEmail.jtp?type=node&node=38072&i=0>> wrote:
>
> Hi Matias,
>
> We should get it into the main SimpleITK repository shortly (after testing
> etc..). For now please follow Dženan’s recommendation (clone my forked
> repository, checkout the dicomWrite branch and build SimpleITK from that
> branch).
>
> regards
> Ziv
>
>
> *From: *Dženan Zukić <[hidden email]
> <http:///user/SendEmail.jtp?type=node&node=38072&i=1>>
> *Date: *Saturday, April 1, 2017 at 9:37 AM
> *To: *Matias <[hidden email]
> <http:///user/SendEmail.jtp?type=node&node=38072&i=2>>
> *Cc: *Insight-users <[hidden email]
> <http:///user/SendEmail.jtp?type=node&node=38072&i=3>>
>
>
> *Subject: *Re: [ITK-users] [ITK] SimpleITK Serieswriter and DicomTags
>
> Hi Matias,
>
> you should use branch dicomWrite from Ziv's fork
> <https://github.com/zivy/SimpleITK/tree/dicomWrite>.
>
> Regards,
> Dženan
>
>
> On Sat, Apr 1, 2017 at 2:48 AM, Matias <[hidden email]
> <http:///user/SendEmail.jtp?type=node&node=38072&i=4>> wrote:
>
> Thanks Yaniv. So how do I get this branch? I simply download the latest
> version of SimpleITK?
> El vie., 31 de mar. de 2017 a la(s) 19:18, Yaniv, Ziv Rafael (NIH/NLM/LHC)
> [C] [via ITK - Users] <[hidden email]
> <http://user/SendEmail.jtp?type=node&node=38064&i=0>> escribió:
>
> Hello Matias,
>
> Please take a look at the following github pull request (
> https://github.com/SimpleITK/SimpleITK/pull/134), this branch should
> provide the functionality you are looking for. See the Python example
> script included in the commit for the usage of the DICOM series writing.
>
> hope this helps
> Ziv
>
>
> *From: *Matias <[hidden email]
> <http://user/SendEmail.jtp?type=node&node=38063&i=0>>
>
> *Date: *Thursday, March 30, 2017 at 12:14 PM
> *To: *"[hidden email] <http://user/SendEmail.jtp?type=node&node=38063&i=1>"
> <[hidden email] <http://user/SendEmail.jtp?type=node&node=38063&i=2>>
>
> *Subject: *Re: [ITK-users] [ITK] SimpleITK Serieswriter and DicomTags
>
> Yes, this is what I would need to migrate to C#:
> It basically reads a dicom directory and performs rotation on the volume,
> then writes the resulting images back to a directory, copying the tags from
> the original images.
>
> #include "itkImage.h"
> #include "itkGDCMImageIO.h"
> #include "itkGDCMSeriesFileNames.h"
> #include "itkImageSeriesReader.h"
> #include "itkResampleImageFilter.h"
> #include "itkEuler3DTransform.hxx"
> #include "gdcmUIDGenerator.h"
>
> #include "itkImageFileWriter.h"
> #include "itkImageSeriesWriter.h"
> #include "itkNumericSeriesFileNames.h"
> #include "itkTranslationTransform.h"
> #include "string.h";
> #include <itkSliceIterator.h>
>
> #include <iostream>
> #include <string>
> #include <fstream>
>
>
>
> static void CopyDictionary(itk::MetaDataDictionary &fromDict,
> itk::MetaDataDictionary &toDict);
>
> int main(int argc, char* argv[])
> {
> if (argc < 8)
> {
> std::cerr << "Uso: " << std::endl;
> std::cerr << argv[0] << " Directorio_A_Rotar DirectorioResultante Gamma
> Beta Alfa CentroRotacionX CentroRotacionY CentroRotacionZ"
> << std::endl;
> return EXIT_FAILURE;
> }
>
> typedef signed short PixelType;
> const unsigned int Dimension = 3;
> const unsigned int Dimension_Serie = 2;
> typedef itk::Image< PixelType, Dimension > ImageType;
> typedef itk::Image<PixelType, Dimension_Serie> ImageType_Serie;
>
> typedef itk::ImageSeriesReader< ImageType > ReaderType;
> ReaderType::Pointer reader = ReaderType::New();
>
> typedef itk::GDCMImageIO ImageIOType;
> ImageIOType::Pointer gdcmIO = ImageIOType::New();
> reader->SetImageIO(gdcmIO);
>
> typedef itk::GDCMSeriesFileNames NamesGeneratorType;
> NamesGeneratorType::Pointer nameGenerator = NamesGeneratorType::New();
> nameGenerator->SetUseSeriesDetails(true);
> nameGenerator->AddSeriesRestriction("0008|0021");
> nameGenerator->SetDirectory(argv[1]);
>
> try
> {
> std::cout << std::endl << "The directory: " << std::endl;
> std::cout << std::endl << argv[1] << std::endl << std::endl;
> std::cout << "Contains the following DICOM Series: ";
> std::cout << std::endl << std::endl;
>
> typedef std::vector< std::string > SeriesIdContainer;
> const SeriesIdContainer & seriesUID = nameGenerator->GetSeriesUIDs();
> SeriesIdContainer::const_iterator seriesItr = seriesUID.begin();
> SeriesIdContainer::const_iterator seriesEnd = seriesUID.end();
> while (seriesItr != seriesEnd)
> {
> std::cout << seriesItr->c_str() << std::endl;
> ++seriesItr;
> }
>
> std::string seriesIdentifier;
>
> seriesIdentifier = seriesUID.begin()->c_str();
>
>
> std::cout << std::endl << std::endl;
> std::cout << "Now reading series: " << std::endl << std::endl;
> std::cout << seriesIdentifier << std::endl;
> std::cout << std::endl << std::endl;
>
> typedef std::vector< std::string > FileNamesContainer;
> FileNamesContainer fileNames;
> fileNames = nameGenerator->GetFileNames(seriesIdentifier);
>
> reader->SetFileNames(fileNames);
>
> try
> {
> reader->Update();
> }
> catch (itk::ExceptionObject &ex)
> {
> std::cout << ex << std::endl;
> return EXIT_FAILURE;
> }
>
> const ImageType * inputImage = reader->GetOutput();
> /*int numerodedicoms = inputImage->GetLargestPossibleRegion().GetSize()[2];
> int dicomcentral = numerodedicoms / 2;
> std::cout << "Dimenion " << dicomcentral << std::endl;*/
> //itk::EncapsulateMetaData<std::string>(dictionary,
> "0020|0032","-208\\-236\\66");
>
> typedef itk::ResampleImageFilter<ImageType, ImageType> FilterType;
> FilterType::Pointer FiltroResample = FilterType::New();
> FiltroResample->SetInput(reader->GetOutput());
>
> typedef itk::LinearInterpolateImageFunction<ImageType, double >
> InterpolatorType;
> InterpolatorType::Pointer interpolator = InterpolatorType::New();
> FiltroResample->SetInterpolator(interpolator);
> FiltroResample->SetOutputDirection(inputImage->GetDirection());
> FiltroResample->SetOutputOrigin(inputImage->GetOrigin());
>
> ImageType::SizeType inputSize =
> inputImage->GetLargestPossibleRegion().GetSize();
> FiltroResample->SetSize(inputSize);
>
> const ImageType::SpacingType& inputSpacing = inputImage->GetSpacing();
> FiltroResample->SetOutputSpacing(inputSpacing);
>
> FiltroResample->SetDefaultPixelValue(-1000); //Cambiar por un parametro
>
> typedef itk::Euler3DTransform< double > TransformType; //Transform
> TransformType::Pointer transform = TransformType::New();
> double alfa, beta, gamma, centro_rotacion_X, centro_rotacion_Y,
> centro_rotacion_Z;
> gamma = atof(argv[3]);
> beta= atof(argv[4]);
> alfa = atof(argv[5]);
> centro_rotacion_X = atof(argv[6]);
> centro_rotacion_Y = atof(argv[7]);
> centro_rotacion_Z = atof(argv[8]);
> transform->SetRotation(gamma, beta, alfa); //Radianes en el siguiente
> orden en ITK: Gamma, Beta, Alfa | Ibarra
> //double centro[3] = { -14.8371, -54.9443, 175.75 }; //XmmPromedio,
> YmmPromedio, Z Central (mm): Leer directorio y tomar la del medio
> double centro[3] = { centro_rotacion_X, centro_rotacion_Y,
> centro_rotacion_Z }; //XmmPromedio, YmmPromedio, Z Central (mm): Leer
> directorio y tomar la del medio
> transform->SetCenter(centro);
> std::cout << "Centro: " << std::endl << std::endl;
> std::cout << transform->GetCenter() << std::endl;
>
> FiltroResample->SetTransform(transform);
> //FiltroResample->SetMetaDataDictionary(dictionary);
> try
> {
> FiltroResample->Update();
> }
> catch (itk::ExceptionObject &ex)
> {
> return EXIT_FAILURE;
> }
>
>
>
> ReaderType::DictionaryRawPointer inputDict =
> (*(reader->GetMetaDataDictionaryArray()))[0];
> ReaderType::DictionaryArrayType outputArray;
> //std::cout << "array: " << std::endl << outputArray[0] << std::endl;
> // To keep the new series in the same study as the original we need
> // to keep the same study UID. But we need new series and frame of
> // reference UID's.
> gdcm::UIDGenerator suid;
> //std::string seriesUID = suid.Generate();
> gdcm::UIDGenerator fuid;
> std::string frameOfReferenceUID = fuid.Generate();
>
> std::string studyUID;
> std::string sopClassUID;
> itk::ExposeMetaData<std::string>(*inputDict, "0020|000d", studyUID);
> itk::ExposeMetaData<std::string>(*inputDict, "0008|0016", sopClassUID);
> gdcmIO->KeepOriginalUIDOn();
>
> using namespace std;
> double myArray_Z[70]; //Cambiar esto por un argumento que especifica la
> cantidad de imagenes.
> double myArray_X[70]; //Cambiar esto por un argumento que especifica la
> cantidad de imagenes.
> double myArray_Y[70]; //Cambiar esto por un argumento que especifica la
> cantidad de imagenes.
>
> ifstream file("file.txt");
> if (file.is_open())
> {
> for (int i = 0; i < 70; ++i) //Recordar cambiar por el argumento que
> especifica cantidad de imagenes
> {
> file >> myArray_Z[i];
> }
> }
> std::cout << "valor primer Z array: " << std::endl << std::endl;
> std::cout << myArray_Z[0] << std::endl;
>
> for (unsigned int f = 0; f < inputSize[2]; f++)
> {
> // Create a new dictionary for this slice
> ReaderType::DictionaryRawPointer dict = new ReaderType::DictionaryType;
>
> // Copy the dictionary from the first slice
> CopyDictionary(*inputDict, *dict);
>
> // Set the UID's for the study, series, SOP and frame of reference
> itk::EncapsulateMetaData<std::string>(*dict, "0020|000d", studyUID);
> //itk::EncapsulateMetaData<std::string>(*dict, "0020|000e", seriesUID);
> itk::EncapsulateMetaData<std::string>(*dict, "0020|0052",
> frameOfReferenceUID);
>
> gdcm::UIDGenerator sopuid;
> std::string sopInstanceUID = sopuid.Generate();
>
> itk::EncapsulateMetaData<std::string>(*dict, "0008|0018", sopInstanceUID);
> itk::EncapsulateMetaData<std::string>(*dict, "0002|0003", sopInstanceUID);
>
> // Change fields that are slice specific
> std::ostringstream value;
> value.str("");
> value << f + 1;
>
> // Image Number
> itk::EncapsulateMetaData<std::string>(*dict, "0020|0013", value.str());
>
> // Series Description - Append new description to current series
> // description
> std::string oldSeriesDesc;
> itk::ExposeMetaData<std::string>(*inputDict, "0008|103e", oldSeriesDesc);
>
> value.str("");
> value << oldSeriesDesc
> << ": Resampled with pixel spacing "
> << inputSpacing[0] << ", "
> << inputSpacing[1] << ", "
> << inputSpacing[2];
> // This is an long string and there is a 64 character limit in the
> // standard
> unsigned lengthDesc = value.str().length();
>
> std::string seriesDesc(value.str(), 0,
> lengthDesc > 64 ? 64
> : lengthDesc);
> itk::EncapsulateMetaData<std::string>(*dict, "0008|103e", seriesDesc);
>
> // Series Number
> value.str("");
> value << 1001;
> itk::EncapsulateMetaData<std::string>(*dict, "0020|0011", value.str());
>
> // Derivation Description - How this image was derived
> value.str("");
> for (int i = 0; i < argc; i++)
> {
> value << argv[i] << " ";
> }
>
> lengthDesc = value.str().length();
> std::string derivationDesc(value.str(), 0,
> lengthDesc > 1024 ? 1024
> : lengthDesc);
> itk::EncapsulateMetaData<std::string>(*dict, "0008|2111", derivationDesc);
>
> // Image Position Patient: This is calculated by computing the
> // physical coordinate of the first pixel in each slice.
> ImageType::PointType position;
> ImageType::IndexType index;
> index[0] = 0;
> index[1] = 0;
> index[2] = myArray_Z[f];
> FiltroResample->GetOutput()->TransformIndexToPhysicalPoint(index,
> position);
>
> //El origen que calculamos en el proyecto no se toca. (Origen = origen -
> average)
>
> //Cambiamos el ImageOrientationPatient SOLAMENTE si el valor original en
> la imagen es: 1\0\0\0\1\0. En el caso que se cambia el signo, se debe
> cambiar el signo del origen
> //value.str("");
> //value << -1 << "\\" << 0 << "\\" << 0 << "\\" << 0 << "\\" << -1 << "\\"
> << 0; //PASAR ESTO POR ARGUMENTO!!!
> //itk::EncapsulateMetaData<std::string>(*dict, "0020|0037", value.str());
>
> value.str("");
> value << -235.1629 << "\\" << -195.0557 << "\\" << myArray_Z[f]; //PASAR
> ESTO POR ARGUMENTO!!! El origen - Centro
> itk::EncapsulateMetaData<std::string>(*dict, "0020|0032", value.str());
>
>
> // Slice Location: For now, we store the z component of the Image
> // Position Patient.
> value.str("");
> value << position[2];
> itk::EncapsulateMetaData<std::string>(*dict, "0020|1041", value.str());
>
> // Slice Thickness: For now, we store the z spacing
> value.str("");
> value << inputSpacing[2];
> itk::EncapsulateMetaData<std::string>(*dict, "0018|0050",
> value.str());
> // Spacing Between Slices
> itk::EncapsulateMetaData<std::string>(*dict, "0018|0088",
> value.str());
>
> // Save the dictionary
> outputArray.push_back(dict);
> }
>
>
> typedef itk::ImageFileWriter< ImageType > WriterType;
> WriterType::Pointer writer = WriterType::New();
>
> typedef itk::ImageSeriesWriter< ImageType, ImageType_Serie >
> SeriesWriterType;
> SeriesWriterType::Pointer seriesWriter = SeriesWriterType::New();
> seriesWriter->SetInput(FiltroResample->GetOutput());
>
> writer->SetFileName(argv[2]);
> writer->SetInput(FiltroResample->GetOutput());
>
> itksys::SystemTools::MakeDirectory("Test"); //PASAR ESTO POR ARGUMENTO!!
> typedef itk::NumericSeriesFileNames OutputNamesGeneratorType;
> OutputNamesGeneratorType::Pointer outputNames =
> OutputNamesGeneratorType::New();
> std::string seriesFormat("Test"); //PASAR ESTO POR ARGUMENTO!!
> seriesFormat = seriesFormat + "/" + "IM%d.dcm";
> outputNames->SetSeriesFormat(seriesFormat.c_str());
> outputNames->SetStartIndex(1);
> outputNames->SetEndIndex(inputSize[2]);
>
> seriesWriter->SetImageIO(gdcmIO);
> seriesWriter->SetFileNames(outputNames->GetFileNames());
> seriesWriter->SetMetaDataDictionaryArray(&outputArray);
>
> std::cout << "Escribiendo la imagen como..." << std::endl << std::endl;
> std::cout << argv[2] << std::endl << std::endl;
>
> try
> {
> writer->Update();
> seriesWriter->Update();
> }
> catch (itk::ExceptionObject &ex)
> {
> std::cout << ex << std::endl;
> return EXIT_FAILURE;
> }
>
>
> }
> catch (itk::ExceptionObject &ex)
> {
> std::cout << ex << std::endl;
> return EXIT_FAILURE;
> }
>
> return EXIT_SUCCESS;
>
> }
>
> void CopyDictionary(itk::MetaDataDictionary &fromDict,
> itk::MetaDataDictionary &toDict)
> {
> typedef itk::MetaDataDictionary DictionaryType;
>
> DictionaryType::ConstIterator itr = fromDict.Begin();
> DictionaryType::ConstIterator end = fromDict.End();
> typedef itk::MetaDataObject< std::string > MetaDataStringType;
>
> while (itr != end)
> {
> itk::MetaDataObjectBase::Pointer entry = itr->second;
>
> MetaDataStringType::Pointer entryvalue =
> dynamic_cast<MetaDataStringType *>(entry.GetPointer());
> if (entryvalue)
> {
> std::string tagkey = itr->first;
> std::string tagvalue = entryvalue->GetMetaDataObjectValue();
> itk::EncapsulateMetaData<std::string>(toDict, tagkey, tagvalue);
> }
> ++itr;
> }
> }
>
>
> El jue., 30 de mar. de 2017 a la(s) 11:25, Lowekamp, Bradley (NIH/NLM/LHC)
> [C] [via ITK - Users] <[hidden email]> escribió:
>
> Hello,
>
> Writing correct DICOM continues to be a struggle with SimpleITK and ITK.
> It is generally recommended to directly use GDCM or DCMTK to write a proper
> DICOM series.
>
> SimpleITK tries to keep things, well, simple and straight forward. But ITK
> ties to do some smart things, which get in the way for certain uses with
> SimpleITK. We are trying to document and develop a nominal set of DICOM
> output operations that work in SimpleITK.
>
> Do you have working C++ code that works for your intended operation? Can
> you share a small section of code which does what you expect it C++?
>
> Thank,
> Brad
>
>
> > On Mar 30, 2017, at 8:49 AM, Matias <[hidden email]
> <http://user/SendEmail.jtp?type=node&node=38052&i=0>> wrote:
> >
> > Hi,
> >
> > I've been dealing with ITK for years in C++ and now I would need to use
> > SimpleITK and C# as far as I can in a new proyect.
> >
> > Is the SimpleITK SeriesWriter working for Dicom Files? Last time I tried
> to
> > use it I had problems with the DicomTags, these would not copy or there
> was
> > no method to copy the tags to the resulting slices.
> >
> > Currently, I read a volume of slices, apply rotation and then I need to
> > write the resulting image as another set of slices AND keeping tag
> > information such as patient name, etc.
> >
> > Thank you,
> >
> > Matias.
> >
> >
> >
> > --
> > View this message in context:
> http://itk-users.7.n7.nabble.com/SimpleITK-Serieswriter-and-DicomTags-tp38050.html
> > Sent from the ITK - Users mailing list archive at Nabble.com
> <http://nabble.com>.
> > _____________________________________
> > Powered by www.kitware.com
> >
> > Visit other Kitware open-source projects at
> > http://www.kitware.com/opensource/opensource.html
> >
> > Kitware offers ITK Training Courses, for more information visit:
> > http://www.kitware.com/products/protraining.php
> >
> > Please keep messages on-topic and check the ITK FAQ at:
> > http://www.itk.org/Wiki/ITK_FAQ
> >
> > Follow this link to subscribe/unsubscribe:
> > http://public.kitware.com/mailman/listinfo/insight-users
> > _______________________________________________
> > Community mailing list
> > [hidden email] <http://user/SendEmail.jtp?type=node&node=38052&i=1>
> > http://public.kitware.com/mailman/listinfo/community
>
>
> _____________________________________
> Powered by www.kitware.com
>
> Visit other Kitware open-source projects at
> http://www.kitware.com/opensource/opensource.html
>
> Kitware offers ITK Training Courses, for more information visit:
> http://www.kitware.com/products/protraining.php
>
> Please keep messages on-topic and check the ITK FAQ at:
> http://www.itk.org/Wiki/ITK_FAQ
>
> Follow this link to subscribe/unsubscribe:
> http://public.kitware.com/mailman/listinfo/insight-users
> ------------------------------
> *If you reply to this email, your message will be added to the discussion
> below:*
>
> http://itk-users.7.n7.nabble.com/SimpleITK-Serieswriter-and-DicomTags-tp38050p38052.html
> To unsubscribe from SimpleITK Serieswriter and DicomTags, click here.
> NAML
> <http://itk-users.7.n7.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml>
>
> --
> Matias
>
> ------------------------------
> View this message in context: Re: [ITK-users] [ITK] SimpleITK
> Serieswriter and DicomTags
> <http://itk-users.7.n7.nabble.com/SimpleITK-Serieswriter-and-DicomTags-tp38050p38056.html>
>
>
> Sent from the ITK - Users mailing list archive
> <http://itk-users.7.n7.nabble.com/> at Nabble.com <http://nabble.com>.
>
>
> _____________________________________
> Powered by www.kitware.com
>
> Visit other Kitware open-source projects at
> http://www.kitware.com/opensource/opensource.html
>
> Kitware offers ITK Training Courses, for more information visit:
> http://www.kitware.com/products/protraining.php
>
> Please keep messages on-topic and check the ITK FAQ at:
> http://www.itk.org/Wiki/ITK_FAQ
>
> Follow this link to subscribe/unsubscribe:
> http://public.kitware.com/mailman/listinfo/insight-users
>
> *If you reply to this email, your message will be added to the discussion
> below:*
>
> http://itk-users.7.n7.nabble.com/SimpleITK-Serieswriter-and-DicomTags-tp38050p38063.html
> To unsubscribe from SimpleITK Serieswriter and DicomTags, click here.
> NAML
> <http://itk-users.7.n7.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml>
>
> --
> Matias
>
> ------------------------------
> View this message in context: Re: [ITK-users] [ITK] SimpleITK
> Serieswriter and DicomTags
> <http://itk-users.7.n7.nabble.com/SimpleITK-Serieswriter-and-DicomTags-tp38050p38064.html>
> Sent from the ITK - Users mailing list archive
> <http://itk-users.7.n7.nabble.com/> at
>
> --
Matias
--
View this message in context: http://itk-users.7.n7.nabble.com/SimpleITK-Serieswriter-and-DicomTags-tp38050p38073.html
Sent from the ITK - Users mailing list archive at Nabble.com.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/insight-users/attachments/20170405/41c9b5ff/attachment-0001.html>
More information about the Insight-users
mailing list