void mitk::PointSetReader::GenerateData() { // Switch the current locale to "C" LocaleSwitch localeSwitch("C"); m_Success = false; if (m_FileName == "") { itkWarningMacro(<< "Sorry, filename has not been set!"); return; }
void mitk::ItkImageFileReader::GenerateData() { mitk::LocaleSwitch localeSwitch("C"); mitk::Image::Pointer image = this->GetOutput(); const unsigned int MINDIM = 2; const unsigned int MAXDIM = 4; MITK_INFO("mitkItkImageFileReader") << "loading " << m_FileName << " via itk::ImageIOFactory... " << std::endl; // Check to see if we can read the file given the name or prefix if ( m_FileName == "" ) { mitkThrow() << "Empty filename in mitk::ItkImageFileReader "; return ; } itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO( m_FileName.c_str(), itk::ImageIOFactory::ReadMode ); if ( imageIO.IsNull() ) { //itkWarningMacro( << "File Type not supported!" ); mitkThrow() << "Could not create itk::ImageIOBase object for filename " << m_FileName; return ; } // Got to allocate space for the image. Determine the characteristics of // the image. imageIO->SetFileName( m_FileName.c_str() ); imageIO->ReadImageInformation(); unsigned int ndim = imageIO->GetNumberOfDimensions(); if ( ndim < MINDIM || ndim > MAXDIM ) { itkWarningMacro( << "Sorry, only dimensions 2, 3 and 4 are supported. The given file has " << ndim << " dimensions! Reading as 4D." ); ndim = MAXDIM; }
void mitk::DiffusionImageNrrdWriterService::Write() { mitk::Image::ConstPointer input = dynamic_cast<const mitk::Image *>(this->GetInput()); VectorImageType::Pointer itkImg; mitk::CastToItkImage(input,itkImg); if (input.IsNull()) { MITK_ERROR <<"Sorry, input to DiffusionImageNrrdWriterService is NULL!"; return; } if ( this->GetOutputLocation().empty() ) { MITK_ERROR << "Sorry, filename has not been set!"; return ; } mitk::LocaleSwitch localeSwitch("C"); char keybuffer[512]; char valbuffer[512]; //itk::MetaDataDictionary dic = input->GetImage()->GetMetaDataDictionary(); vnl_matrix_fixed<double,3,3> measurementFrame = mitk::DiffusionPropertyHelper::GetMeasurementFrame(input); if (measurementFrame(0,0) || measurementFrame(0,1) || measurementFrame(0,2) || measurementFrame(1,0) || measurementFrame(1,1) || measurementFrame(1,2) || measurementFrame(2,0) || measurementFrame(2,1) || measurementFrame(2,2)) { sprintf( valbuffer, " (%lf,%lf,%lf) (%lf,%lf,%lf) (%lf,%lf,%lf)", measurementFrame(0,0), measurementFrame(0,1), measurementFrame(0,2), measurementFrame(1,0), measurementFrame(1,1), measurementFrame(1,2), measurementFrame(2,0), measurementFrame(2,1), measurementFrame(2,2)); itk::EncapsulateMetaData<std::string>(itkImg->GetMetaDataDictionary(),std::string("measurement frame"),std::string(valbuffer)); } sprintf( valbuffer, "DWMRI"); itk::EncapsulateMetaData<std::string>(itkImg->GetMetaDataDictionary(),std::string("modality"),std::string(valbuffer)); if(mitk::DiffusionPropertyHelper::GetGradientContainer(input)->Size()) { sprintf( valbuffer, "%1f", mitk::DiffusionPropertyHelper::GetReferenceBValue(input) ); itk::EncapsulateMetaData<std::string>(itkImg->GetMetaDataDictionary(),std::string("DWMRI_b-value"),std::string(valbuffer)); } for(unsigned int i=0; i<mitk::DiffusionPropertyHelper::GetGradientContainer(input)->Size(); i++) { sprintf( keybuffer, "DWMRI_gradient_%04d", i ); /*if(itk::ExposeMetaData<std::string>(input->GetMetaDataDictionary(), std::string(keybuffer),tmp)) continue;*/ sprintf( valbuffer, "%1f %1f %1f", mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(0), mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(1), mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(2)); itk::EncapsulateMetaData<std::string>(itkImg->GetMetaDataDictionary(),std::string(keybuffer),std::string(valbuffer)); } typedef itk::VectorImage<short,3> ImageType; std::string ext = this->GetMimeType()->GetExtension(this->GetOutputLocation()); ext = itksys::SystemTools::LowerCase(ext); // default extension is .dwi if( ext == "") { ext = ".nrrd"; this->SetOutputLocation(this->GetOutputLocation() + ext); } if (ext == ".hdwi" || ext == ".nrrd" || ext == ".dwi") { MITK_INFO << "Extension " << ext; itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); //io->SetNrrdVectorType( nrrdKindList ); io->SetFileType( itk::ImageIOBase::Binary ); io->UseCompressionOn(); typedef itk::ImageFileWriter<ImageType> WriterType; WriterType::Pointer nrrdWriter = WriterType::New(); nrrdWriter->UseInputMetaDataDictionaryOn(); nrrdWriter->SetInput( itkImg ); nrrdWriter->SetImageIO(io); nrrdWriter->SetFileName(this->GetOutputLocation()); nrrdWriter->UseCompressionOn(); nrrdWriter->SetImageIO(io); try { nrrdWriter->Update(); } catch (itk::ExceptionObject e) { std::cout << e << std::endl; throw; } } }
std::vector<itk::SmartPointer<mitk::BaseData>> mitk::PointSetReaderService::Read() { // Switch the current locale to "C" LocaleSwitch localeSwitch("C"); std::vector<itk::SmartPointer<mitk::BaseData>> result; InputStream stream(this); TiXmlDocument doc; stream >> doc; if (!doc.Error()) { TiXmlHandle docHandle(&doc); // unsigned int pointSetCounter(0); for (TiXmlElement *currentPointSetElement = docHandle.FirstChildElement("point_set_file").FirstChildElement("point_set").ToElement(); currentPointSetElement != NULL; currentPointSetElement = currentPointSetElement->NextSiblingElement()) { mitk::PointSet::Pointer newPointSet = mitk::PointSet::New(); // time geometry assembled for addition after all points // else the SetPoint method would already transform the points that we provide it mitk::ProportionalTimeGeometry::Pointer timeGeometry = mitk::ProportionalTimeGeometry::New(); if (currentPointSetElement->FirstChildElement("time_series") != NULL) { for (TiXmlElement *currentTimeSeries = currentPointSetElement->FirstChildElement("time_series")->ToElement(); currentTimeSeries != NULL; currentTimeSeries = currentTimeSeries->NextSiblingElement()) { unsigned int currentTimeStep(0); TiXmlElement *currentTimeSeriesID = currentTimeSeries->FirstChildElement("time_series_id"); currentTimeStep = atoi(currentTimeSeriesID->GetText()); timeGeometry->Expand(currentTimeStep + 1); // expand (default to identity) in any case TiXmlElement *geometryElem = currentTimeSeries->FirstChildElement("Geometry3D"); if (geometryElem) { Geometry3D::Pointer geometry = Geometry3DToXML::FromXML(geometryElem); if (geometry.IsNotNull()) { timeGeometry->SetTimeStepGeometry(geometry, currentTimeStep); } else { MITK_ERROR << "Could not deserialize Geometry3D element."; } } else { MITK_WARN << "Fallback to legacy behavior: defining PointSet geometry as identity"; } newPointSet = this->ReadPoints(newPointSet, currentTimeSeries, currentTimeStep); } } else { newPointSet = this->ReadPoints(newPointSet, currentPointSetElement, 0); } newPointSet->SetTimeGeometry(timeGeometry); result.push_back(newPointSet.GetPointer()); } } else { mitkThrow() << "Parsing error at line " << doc.ErrorRow() << ", col " << doc.ErrorCol() << ": " << doc.ErrorDesc(); } return result; }
std::vector<BaseData::Pointer> DICOMSegmentationIO::Read() { mitk::LocaleSwitch localeSwitch("C"); LabelSetImage::Pointer labelSetImage; std::vector<BaseData::Pointer> result; const std::string path = this->GetLocalFileName(); MITK_INFO << "loading " << path << std::endl; if (path.empty()) mitkThrow() << "Empty filename in mitk::ItkImageIO "; try { // Get the dcm data set from file path DcmFileFormat dcmFileFormat; OFCondition status = dcmFileFormat.loadFile(path.c_str()); if (status.bad()) mitkThrow() << "Can't read the input file!"; DcmDataset *dataSet = dcmFileFormat.getDataset(); if (dataSet == nullptr) mitkThrow() << "Can't read data from input file!"; // Read the DICOM SEG images (segItkImages) and DICOM tags (metaInfo) dcmqi::ImageSEGConverter *converter = new dcmqi::ImageSEGConverter(); pair<map<unsigned, ImageType::Pointer>, string> dcmqiOutput = converter->dcmSegmentation2itkimage(dataSet); map<unsigned, ImageType::Pointer> segItkImages = dcmqiOutput.first; // For each itk image add a layer to the LabelSetImage output for (auto &element : segItkImages) { // Get the labeled image and cast it to mitkImage typedef itk::CastImageFilter<itkInternalImageType, itkInputImageType> castItkImageFilterType; castItkImageFilterType::Pointer castFilter = castItkImageFilterType::New(); castFilter->SetInput(element.second); castFilter->Update(); Image::Pointer layerImage; CastToMitkImage(castFilter->GetOutput(), layerImage); // Get pixel value of the label itkInternalImageType::ValueType segValue = 1; typedef itk::ImageRegionIterator<const itkInternalImageType> IteratorType; // Iterate over the image to find the pixel value of the label IteratorType iter(element.second, element.second->GetLargestPossibleRegion()); iter.GoToBegin(); while (!iter.IsAtEnd()) { itkInputImageType::PixelType value = iter.Get(); if (value != 0) { segValue = value; break; } ++iter; } dcmqi::JSONSegmentationMetaInformationHandler metaInfo(dcmqiOutput.second.c_str()); metaInfo.read(); MITK_INFO << "Input " << metaInfo.getJSONOutputAsString(); // TODO: Read all DICOM Tags // Get the label information from segment attributes vector<map<unsigned, dcmqi::SegmentAttributes *>>::const_iterator segmentIter = metaInfo.segmentsAttributesMappingList.begin(); map<unsigned, dcmqi::SegmentAttributes *> segmentMap = (*segmentIter); map<unsigned, dcmqi::SegmentAttributes *>::const_iterator segmentMapIter = (*segmentIter).begin(); dcmqi::SegmentAttributes *segmentAttr = (*segmentMapIter).second; OFString labelName; if (segmentAttr->getSegmentedPropertyTypeCodeSequence() != nullptr) segmentAttr->getSegmentedPropertyTypeCodeSequence()->getCodeMeaning(labelName); else { labelName = std::to_string(segmentAttr->getLabelID()).c_str(); if (labelName.empty()) labelName = "Unnamed"; } float tmp[3] = {0.0, 0.0, 0.0}; if (segmentAttr->getRecommendedDisplayRGBValue() != nullptr) { tmp[0] = segmentAttr->getRecommendedDisplayRGBValue()[0] / 255.0; tmp[1] = segmentAttr->getRecommendedDisplayRGBValue()[1] / 255.0; tmp[2] = segmentAttr->getRecommendedDisplayRGBValue()[2] / 255.0; } // If labelSetImage do not exists (first image) if (labelSetImage.IsNull()) { // Initialize the labelSetImage with the read image labelSetImage = LabelSetImage::New(); labelSetImage->InitializeByLabeledImage(layerImage); // Already a label was generated, so set the information to this Label *activeLabel = labelSetImage->GetActiveLabel(labelSetImage->GetActiveLayer()); activeLabel->SetName(labelName.c_str()); activeLabel->SetColor(Color(tmp)); activeLabel->SetValue(segValue); } else { // Add a new layer to the labelSetImage. Background label is set automatically labelSetImage->AddLayer(layerImage); // Add new label Label *newLabel = new Label; newLabel->SetName(labelName.c_str()); newLabel->SetColor(Color(tmp)); newLabel->SetValue(segValue); labelSetImage->GetLabelSet(labelSetImage->GetActiveLayer())->AddLabel(newLabel); } ++segmentIter; } // Clean up if (converter != nullptr) delete converter; } catch (const std::exception &e) { MITK_ERROR << "An error occurred while reading the DICOM Seg file: " << e.what(); return result; } // Set active layer to th first layer of the labelset image if (labelSetImage->GetNumberOfLayers() > 1 && labelSetImage->GetActiveLayer() != 0) labelSetImage->SetActiveLayer(0); result.push_back(labelSetImage.GetPointer()); return result; }
void DICOMSegmentationIO::Write() { ValidateOutputLocation(); mitk::LocaleSwitch localeSwitch("C"); LocalFile localFile(this); const std::string path = localFile.GetFileName(); auto input = dynamic_cast<const LabelSetImage *>(this->GetInput()); if (input == nullptr) mitkThrow() << "Cannot write non-image data"; // Get DICOM information from referenced image vector<DcmDataset *> dcmDatasets; DcmFileFormat *readFileFormat = new DcmFileFormat(); try { // TODO: Generate dcmdataset witk DICOM tags from property list; ATM the source are the filepaths from the // property list mitk::StringLookupTableProperty::Pointer filesProp = dynamic_cast<mitk::StringLookupTableProperty *>(input->GetProperty("files").GetPointer()); if (filesProp.IsNull()) { mitkThrow() << "No property with dicom file path."; return; } StringLookupTable filesLut = filesProp->GetValue(); const StringLookupTable::LookupTableType &lookUpTableMap = filesLut.GetLookupTable(); for (auto it : lookUpTableMap) { const char *fileName = (it.second).c_str(); if (readFileFormat->loadFile(fileName, EXS_Unknown).good()) dcmDatasets.push_back(readFileFormat->getAndRemoveDataset()); } } catch (const std::exception &e) { MITK_ERROR << "An error occurred while getting the dicom informations: " << e.what() << endl; return; } // Iterate over all layers. For each a dcm file will be generated for (unsigned int layer = 0; layer < input->GetNumberOfLayers(); ++layer) { vector<itkInternalImageType::Pointer> segmentations; try { // Cast mitk layer image to itk ImageToItk<itkInputImageType>::Pointer imageToItkFilter = ImageToItk<itkInputImageType>::New(); // BUG: It must be the layer image, but there are some errors with it (dcmqi: generate the dcmSeg "No frame data // available") --> input->GetLayerImage(layer) imageToItkFilter->SetInput(input); imageToItkFilter->Update(); // Cast from original itk type to dcmqi input itk image type typedef itk::CastImageFilter<itkInputImageType, itkInternalImageType> castItkImageFilterType; castItkImageFilterType::Pointer castFilter = castItkImageFilterType::New(); castFilter->SetInput(imageToItkFilter->GetOutput()); castFilter->Update(); itkInternalImageType::Pointer itkLabelImage = castFilter->GetOutput(); itkLabelImage->DisconnectPipeline(); // Iterate over all labels. For each a segmentation image will be created const LabelSet *labelSet = input->GetLabelSet(layer); for (auto itLabel = labelSet->IteratorConstBegin(); itLabel != labelSet->IteratorConstEnd(); ++itLabel) { // Thresold over the image with the given label value itk::ThresholdImageFilter<itkInternalImageType>::Pointer thresholdFilter = itk::ThresholdImageFilter<itkInternalImageType>::New(); thresholdFilter->SetInput(itkLabelImage); thresholdFilter->ThresholdOutside(itLabel->first, itLabel->first); thresholdFilter->SetOutsideValue(0); thresholdFilter->Update(); itkInternalImageType::Pointer segmentImage = thresholdFilter->GetOutput(); segmentImage->DisconnectPipeline(); segmentations.push_back(segmentImage); } } catch (const itk::ExceptionObject &e) { MITK_ERROR << e.GetDescription() << endl; return; } // Create segmentation meta information const std::string &tmpMetaInfoFile = this->CreateMetaDataJsonFile(layer); MITK_INFO << "Writing image: " << path << std::endl; try { // Convert itk segmentation images to dicom image dcmqi::ImageSEGConverter *converter = new dcmqi::ImageSEGConverter(); DcmDataset *result = converter->itkimage2dcmSegmentation(dcmDatasets, segmentations, tmpMetaInfoFile); // Write dicom file DcmFileFormat dcmFileFormat(result); std::string filePath = path.substr(0, path.find_last_of(".")); // If there is more than one layer, we have to write more than 1 dicom file if (input->GetNumberOfLayers() != 1) filePath = filePath + std::to_string(layer) + ".dcm"; else filePath = filePath + ".dcm"; dcmFileFormat.saveFile(filePath.c_str(), EXS_LittleEndianExplicit); // Clean up if (converter != nullptr) delete converter; if (result != nullptr) delete result; } catch (const std::exception &e) { MITK_ERROR << "An error occurred during writing the DICOM Seg: " << e.what() << endl; return; } } // Write a dcm file for the next layer // End of image writing; clean up if (readFileFormat) delete readFileFormat; for (auto obj : dcmDatasets) delete obj; dcmDatasets.clear(); }
void mitk::ParRecFileReader::GenerateOutputInformation() { mitk::Image::Pointer output = this->GetOutput(); if ((output->IsInitialized()) && (this->GetMTime() <= m_ReadHeaderTime.GetMTime())) return; itkDebugMacro(<<"Reading PAR file for GenerateOutputInformation()" << m_FileName); // Check to see if we can read the file given the name or prefix // if ( m_FileName == "" && m_FilePrefix == "" ) { throw itk::ImageFileReaderException(__FILE__, __LINE__, "One of FileName or FilePrefix must be non-empty"); } m_RecFileName = ""; if( m_FileName != "") { int extPos=m_FileName.find_last_of("."); if(extPos>=-1) { const char *ext=m_FileName.c_str()+extPos+1; if(stricmp(ext,"par")==0) m_RecFileName = m_FileName.substr(0,extPos); else m_RecFileName = m_FileName; } else m_RecFileName = m_FileName; m_RecFileName.append(".rec"); bool headerRead = false; bool signedCharType = true; unsigned int dimension=0; unsigned int dimensions[4]={0,0,1,1}; float sliceThickness=0.0; float sliceGap=0.0; float sliceSpacing=0.0; mitk::Vector3D thickness; thickness.Fill(1.0); mitk::Vector3D gap; gap.Fill(0.0); mitk::Vector3D spacing; FILE *f; f=fopen(m_FileName.c_str(), "r"); if(f!=nullptr) { while(!feof(f)) { char s[300], *p; char* ignored = fgets(s,200,f); ++ignored; if(strstr(s,"Max. number of cardiac phases")) { p=strchr(s,':')+1; dimensions[3]=atoi(p); if(dimensions[3]>1) dimension=4; } else if(strstr(s,"Max. number of slices/locations")) { p=strchr(s,':')+1; dimensions[2]=atoi(p); if(dimension==0) { if(dimensions[2]>1) dimension=3; else dimension=2; } } else if(strstr(s,"Image pixel size")) { p=strchr(s,':')+1; int bpe=atoi(p); if(bpe!=8) signedCharType = false; } else if(strstr(s,"Recon resolution")) { p=s+strcspn(s,"0123456789"); sscanf(p,"%u %u", dimensions, dimensions+1); } else if(strstr(s,"FOV (ap,fh,rl) [mm]")) { p=s+strcspn(s,"0123456789"); mitk::LocaleSwitch localeSwitch("C"); sscanf(p,"%lf %lf %lf", &thickness[0], &thickness[1], &thickness[2]); } else if(strstr(s,"Slice thickness [mm]")) { p=s+strcspn(s,"0123456789"); mitk::LocaleSwitch localeSwitch("C"); sscanf(p,"%f", &sliceThickness); } else if(strstr(s,"Slice gap [mm]")) { p=s+strcspn(s,"-0123456789"); mitk::LocaleSwitch localeSwitch("C"); sscanf(p,"%f", &sliceGap); } } fclose(f); //C:\home\ivo\data\coronaries\ucsf-wholeheart-2.par sliceSpacing = sliceThickness+sliceGap; if((dimension>0) && (dimensions[0]>0) && (dimensions[1]>0) && (sliceThickness>0) && (sliceSpacing>0)) { headerRead = true; if(fabs(thickness[0]/dimensions[2]-sliceSpacing)<0.0001) thickness[0]=thickness[1]; else if(fabs(thickness[1]/dimensions[2]-sliceSpacing)<0.0001) thickness[1]=thickness[0]; thickness[2]=sliceSpacing; thickness[0]/=dimensions[0]; thickness[1]/=dimensions[1]; spacing=thickness+gap; } } if( headerRead == false) { itk::ImageFileReaderException e(__FILE__, __LINE__); std::ostringstream msg; msg << " Could not read file " << m_FileName.c_str(); e.SetDescription(msg.str().c_str()); throw e; return; } // define types mitk::PixelType SCType = mitk::MakeScalarPixelType<signed char>(); mitk::PixelType SSType = mitk::MakeScalarPixelType<signed short>(); if( signedCharType ) output->Initialize(SCType, dimension, dimensions); else output->Initialize(SSType, dimension, dimensions); output->GetSlicedGeometry()->SetSpacing(spacing); //output->GetSlicedGeometry()->SetPlaneGeometry(mitk::Image::BuildStandardPlanePlaneGeometry(output->GetSlicedGeometry(), dimensions).GetPointer(), 0); output->GetSlicedGeometry()->SetEvenlySpaced(); } m_ReadHeaderTime.Modified(); }
std::vector<itk::SmartPointer<BaseData> > BaseDICOMReaderService::Read() { std::vector<BaseData::Pointer> result; //special handling of Philips 3D US DICOM. //Copied from DICOMSeriesReaderService std::string fileName = this->GetLocalFileName(); if (DicomSeriesReader::IsPhilips3DDicom(fileName)) { MITK_INFO << "it is a Philips3D US Dicom file" << std::endl; mitk::LocaleSwitch localeSwitch("C"); std::locale previousCppLocale(std::cin.getloc()); std::locale l("C"); std::cin.imbue(l); DataNode::Pointer node = DataNode::New(); mitk::DicomSeriesReader::StringContainer stringvec; stringvec.push_back(fileName); if (DicomSeriesReader::LoadDicomSeries(stringvec, *node)) { BaseData::Pointer data = node->GetData(); StringProperty::Pointer nameProp = StringProperty::New(itksys::SystemTools::GetFilenameName(fileName)); data->GetPropertyList()->SetProperty("name", nameProp); result.push_back(data); } std::cin.imbue(previousCppLocale); return result; } //Normal DICOM handling (It wasn't a Philips 3D US) mitk::StringList relevantFiles = this->GetRelevantFiles(); mitk::DICOMFileReader::Pointer reader = this->GetReader(relevantFiles); reader->SetAdditionalTagsOfInterest(mitk::GetCurrentDICOMTagsOfInterest()); reader->SetTagLookupTableToPropertyFunctor(mitk::GetDICOMPropertyForDICOMValuesFunctor); reader->SetInputFiles(relevantFiles); reader->AnalyzeInputFiles(); reader->LoadImages(); for (unsigned int i = 0; i < reader->GetNumberOfOutputs(); ++i) { const mitk::DICOMImageBlockDescriptor& desc = reader->GetOutput(i); mitk::BaseData::Pointer data = desc.GetMitkImage().GetPointer(); std::string nodeName = "Unnamed_DICOM"; std::string studyDescription = desc.GetPropertyAsString("studyDescription"); std::string seriesDescription = desc.GetPropertyAsString("seriesDescription"); if (!studyDescription.empty()) { nodeName = studyDescription; } if (!seriesDescription.empty()) { if (!studyDescription.empty()) { nodeName += "/"; } nodeName += seriesDescription; } StringProperty::Pointer nameProp = StringProperty::New(nodeName); data->SetProperty("name", nameProp); result.push_back(data); } return result; }
std::vector<BaseData::Pointer> ItkImageIO::Read() { std::vector<BaseData::Pointer> result; mitk::LocaleSwitch localeSwitch("C"); Image::Pointer image = Image::New(); const unsigned int MINDIM = 2; const unsigned int MAXDIM = 4; const std::string path = this->GetLocalFileName(); MITK_INFO << "loading " << path << " via itk::ImageIOFactory... " << std::endl; // Check to see if we can read the file given the name or prefix if (path.empty()) { mitkThrow() << "Empty filename in mitk::ItkImageIO "; } // Got to allocate space for the image. Determine the characteristics of // the image. m_ImageIO->SetFileName(path); m_ImageIO->ReadImageInformation(); unsigned int ndim = m_ImageIO->GetNumberOfDimensions(); if (ndim < MINDIM || ndim > MAXDIM) { MITK_WARN << "Sorry, only dimensions 2, 3 and 4 are supported. The given file has " << ndim << " dimensions! Reading as 4D."; ndim = MAXDIM; } itk::ImageIORegion ioRegion(ndim); itk::ImageIORegion::SizeType ioSize = ioRegion.GetSize(); itk::ImageIORegion::IndexType ioStart = ioRegion.GetIndex(); unsigned int dimensions[MAXDIM]; dimensions[0] = 0; dimensions[1] = 0; dimensions[2] = 0; dimensions[3] = 0; ScalarType spacing[MAXDIM]; spacing[0] = 1.0f; spacing[1] = 1.0f; spacing[2] = 1.0f; spacing[3] = 1.0f; Point3D origin; origin.Fill(0); unsigned int i; for (i = 0; i < ndim; ++i) { ioStart[i] = 0; ioSize[i] = m_ImageIO->GetDimensions(i); if (i < MAXDIM) { dimensions[i] = m_ImageIO->GetDimensions(i); spacing[i] = m_ImageIO->GetSpacing(i); if (spacing[i] <= 0) spacing[i] = 1.0f; } if (i < 3) { origin[i] = m_ImageIO->GetOrigin(i); } } ioRegion.SetSize(ioSize); ioRegion.SetIndex(ioStart); MITK_INFO << "ioRegion: " << ioRegion << std::endl; m_ImageIO->SetIORegion(ioRegion); void *buffer = new unsigned char[m_ImageIO->GetImageSizeInBytes()]; m_ImageIO->Read(buffer); image->Initialize(MakePixelType(m_ImageIO), ndim, dimensions); image->SetImportChannel(buffer, 0, Image::ManageMemory); const itk::MetaDataDictionary &dictionary = m_ImageIO->GetMetaDataDictionary(); // access direction of itk::Image and include spacing mitk::Matrix3D matrix; matrix.SetIdentity(); unsigned int j, itkDimMax3 = (ndim >= 3 ? 3 : ndim); for (i = 0; i < itkDimMax3; ++i) for (j = 0; j < itkDimMax3; ++j) matrix[i][j] = m_ImageIO->GetDirection(j)[i]; // re-initialize PlaneGeometry with origin and direction PlaneGeometry *planeGeometry = image->GetSlicedGeometry(0)->GetPlaneGeometry(0); planeGeometry->SetOrigin(origin); planeGeometry->GetIndexToWorldTransform()->SetMatrix(matrix); // re-initialize SlicedGeometry3D SlicedGeometry3D *slicedGeometry = image->GetSlicedGeometry(0); slicedGeometry->InitializeEvenlySpaced(planeGeometry, image->GetDimension(2)); slicedGeometry->SetSpacing(spacing); MITK_INFO << slicedGeometry->GetCornerPoint(false, false, false); MITK_INFO << slicedGeometry->GetCornerPoint(true, true, true); // re-initialize TimeGeometry TimeGeometry::Pointer timeGeometry; if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TYPE) || dictionary.HasKey(PROPERTY_KEY_TIMEGEOMETRY_TYPE)) { // also check for the name because of backwards compatibility. Past code version stored with the name and not with // the key itk::MetaDataObject<std::string>::ConstPointer timeGeometryTypeData = nullptr; if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TYPE)) { timeGeometryTypeData = dynamic_cast<const itk::MetaDataObject<std::string> *>(dictionary.Get(PROPERTY_NAME_TIMEGEOMETRY_TYPE)); } else { timeGeometryTypeData = dynamic_cast<const itk::MetaDataObject<std::string> *>(dictionary.Get(PROPERTY_KEY_TIMEGEOMETRY_TYPE)); } if (timeGeometryTypeData->GetMetaDataObjectValue() == ArbitraryTimeGeometry::GetStaticNameOfClass()) { MITK_INFO << "used time geometry: " << ArbitraryTimeGeometry::GetStaticNameOfClass() << std::endl; typedef std::vector<TimePointType> TimePointVector; TimePointVector timePoints; if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS)) { timePoints = ConvertMetaDataObjectToTimePointList(dictionary.Get(PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS)); } else if (dictionary.HasKey(PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS)) { timePoints = ConvertMetaDataObjectToTimePointList(dictionary.Get(PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS)); } if (timePoints.size() - 1 != image->GetDimension(3)) { MITK_ERROR << "Stored timepoints (" << timePoints.size() - 1 << ") and size of image time dimension (" << image->GetDimension(3) << ") do not match. Switch to ProportionalTimeGeometry fallback" << std::endl; } else { ArbitraryTimeGeometry::Pointer arbitraryTimeGeometry = ArbitraryTimeGeometry::New(); TimePointVector::const_iterator pos = timePoints.begin(); TimePointVector::const_iterator prePos = pos++; for (; pos != timePoints.end(); ++prePos, ++pos) { arbitraryTimeGeometry->AppendTimeStepClone(slicedGeometry, *pos, *prePos); } timeGeometry = arbitraryTimeGeometry; } } } if (timeGeometry.IsNull()) { // Fallback. If no other valid time geometry has been created, create a ProportionalTimeGeometry MITK_INFO << "used time geometry: " << ProportionalTimeGeometry::GetStaticNameOfClass() << std::endl; ProportionalTimeGeometry::Pointer propTimeGeometry = ProportionalTimeGeometry::New(); propTimeGeometry->Initialize(slicedGeometry, image->GetDimension(3)); timeGeometry = propTimeGeometry; } image->SetTimeGeometry(timeGeometry); buffer = NULL; MITK_INFO << "number of image components: " << image->GetPixelType().GetNumberOfComponents() << std::endl; for (itk::MetaDataDictionary::ConstIterator iter = dictionary.Begin(), iterEnd = dictionary.End(); iter != iterEnd; ++iter) { if (iter->second->GetMetaDataObjectTypeInfo() == typeid(std::string)) { const std::string &key = iter->first; std::string assumedPropertyName = key; std::replace(assumedPropertyName.begin(), assumedPropertyName.end(), '_', '.'); std::string mimeTypeName = GetMimeType()->GetName(); // Check if there is already a info for the key and our mime type. IPropertyPersistence::InfoResultType infoList = mitk::CoreServices::GetPropertyPersistence()->GetInfoByKey(key); auto predicate = [mimeTypeName](const PropertyPersistenceInfo::ConstPointer &x) { return x.IsNotNull() && x->GetMimeTypeName() == mimeTypeName; }; auto finding = std::find_if(infoList.begin(), infoList.end(), predicate); if (finding == infoList.end()) { auto predicateWild = [](const PropertyPersistenceInfo::ConstPointer &x) { return x.IsNotNull() && x->GetMimeTypeName() == PropertyPersistenceInfo::ANY_MIMETYPE_NAME(); }; finding = std::find_if(infoList.begin(), infoList.end(), predicateWild); } PropertyPersistenceInfo::ConstPointer info; if (finding != infoList.end()) { assumedPropertyName = (*finding)->GetName(); info = *finding; } else { // we have not found anything suitable so we generate our own info PropertyPersistenceInfo::Pointer newInfo = PropertyPersistenceInfo::New(); newInfo->SetNameAndKey(assumedPropertyName, key); newInfo->SetMimeTypeName(PropertyPersistenceInfo::ANY_MIMETYPE_NAME()); info = newInfo; } std::string value = dynamic_cast<itk::MetaDataObject<std::string> *>(iter->second.GetPointer())->GetMetaDataObjectValue(); mitk::BaseProperty::Pointer loadedProp = info->GetDeserializationFunction()(value); image->SetProperty(assumedPropertyName.c_str(), loadedProp); // Read properties should be persisted unless they are default properties // which are written anyway bool isDefaultKey(false); for (const auto &defaultKey : m_DefaultMetaDataKeys) { if (defaultKey.length() <= assumedPropertyName.length()) { // does the start match the default key if (assumedPropertyName.substr(0, defaultKey.length()).find(defaultKey) != std::string::npos) { isDefaultKey = true; break; } } } if (!isDefaultKey) { mitk::CoreServices::GetPropertyPersistence()->AddInfo(info); } } } MITK_INFO << "...finished!" << std::endl; result.push_back(image.GetPointer()); return result; }
std::string mitk::CustomTagParser::GetOffsetString(std::string samplingType, std::string offset, std::string measurements) { mitk::LocaleSwitch localeSwitch("C"); std::stringstream results; std::string normalizationIndicatingOffset = "-300"; double offsetDouble = 0.0; int measurementsInt = 0; bool validOffset = false; bool validMeasurements = false; if ("" != offset) { validOffset = true; offsetDouble = std::stod(offset); } if ("" != measurements) { validMeasurements = true; measurementsInt = std::stoi(measurements); } std::vector<double> offsetVector; if (validOffset && validMeasurements) { for (int step = 0; step < measurementsInt -1; ++step) { double currentOffset = -offsetDouble + 2 * step * offsetDouble / (measurementsInt - 2.0); offsetVector.push_back(currentOffset); } } else { MITK_WARN << "Invalid offset or measurements, offset calculation will only work for list sampling type."; } if (samplingType == "1" || samplingType == "Regular") { if (validOffset && validMeasurements) { results << normalizationIndicatingOffset << " "; for (const auto& entry : offsetVector) { results << entry << " "; } } } else if (samplingType == "2" || samplingType == "Alternating") { if (validOffset && validMeasurements) { results << normalizationIndicatingOffset << " "; for (auto& entry : offsetVector) { entry = std::abs(entry); } std::sort(offsetVector.begin(), offsetVector.end(), std::greater<>()); for (unsigned int index = 0; index < offsetVector.size(); ++index) { offsetVector[index] = std::pow(-1, index) * offsetVector[index]; } for (auto& entry : offsetVector) { results << entry << " "; } } } else if (samplingType == "3" || samplingType == "List") { std::string listPath = m_DicomDataPath + "/LIST.txt"; std::ifstream list(listPath.c_str()); if (list.good()) { std::string currentOffset; while (std::getline(list, currentOffset)) { results << currentOffset << " "; } } else { MITK_ERROR << "Could not load list at " << listPath; } } else if (samplingType == "4" || samplingType == "SingleOffset") { if (validOffset && validMeasurements) { results << normalizationIndicatingOffset << " "; for (int step = 0; step < measurementsInt - 1; ++step) { results << offsetDouble << " "; } } } else { MITK_WARN << "Encountered unknown sampling type."; } std::string resultString = results.str(); // replace multiple spaces by a single space std::string::iterator newEnditerator = std::unique(resultString.begin(), resultString.end(), [=](char lhs, char rhs) { return (lhs == rhs) && (lhs == ' '); } ); resultString.erase(newEnditerator, resultString.end()); if ((resultString.length() > 0) && (resultString.at(resultString.length() - 1) == ' ')) { resultString.erase(resultString.end() - 1, resultString.end()); } if ((resultString.length() > 0) && (resultString.at(0) == ' ')) { resultString.erase(resultString.begin(), ++(resultString.begin())); } return resultString; }
void mitk::TeemDiffusionTensor3DReconstructionImageFilter<D,T> ::Update() { itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer randgen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New(); randgen->SetSeed(); // save input image to nrrd file in temp-folder char filename[512]; int random_integer = randgen->GetIntegerVariate(); sprintf( filename, "dwi_%d.nhdr",random_integer); try { mitk::IOUtil::Save(m_Input, filename); } catch (itk::ExceptionObject e) { std::cout << e << std::endl; } file_replace(filename,"vector","list"); // build up correct command from input params char command[4096]; sprintf( command, "tend estim -i %s -B kvp -o tensors_%d.nhdr -knownB0 true", filename, random_integer); //m_DiffusionImages; if(m_EstimateErrorImage) { sprintf( command, "%s -ee error_image_%d.nhdr", command, random_integer); } if(m_Sigma != -19191919) { sprintf( command, "%s -sigma %f", command, m_Sigma); } switch(m_EstimationMethod) { case TeemTensorEstimationMethodsLLS: sprintf( command, "%s -est lls", command); break; case TeemTensorEstimationMethodsMLE: sprintf( command, "%s -est mle", command); break; case TeemTensorEstimationMethodsNLS: sprintf( command, "%s -est nls", command); break; case TeemTensorEstimationMethodsWLS: sprintf( command, "%s -est wls", command); break; } sprintf( command, "%s -wlsi %d", command, m_NumIterations); if(m_ConfidenceThreshold != -19191919.0) { sprintf( command, "%s -t %f", command, m_ConfidenceThreshold); } sprintf( command, "%s -soft %f", command, m_ConfidenceFuzzyness); sprintf( command, "%s -mv %f", command, m_MinPlausibleValue); // call tend estim command std::cout << "Calling <" << command << ">" << std::endl; int success = system(command); if(!success) { MITK_ERROR << "system command could not be called!"; } remove(filename); sprintf( filename, "dwi_%d.raw", random_integer); remove(filename); // change kind from tensor to vector sprintf( filename, "tensors_%d.nhdr", random_integer); file_replace(filename,"3D-masked-symmetric-matrix","vector"); mitk::LocaleSwitch localeSwitch("C"); // read result as mitk::Image and provide it in m_Output typedef itk::ImageFileReader<VectorImageType> FileReaderType; typename FileReaderType::Pointer reader = FileReaderType::New(); reader->SetFileName(filename); reader->Update(); typename VectorImageType::Pointer vecImage = reader->GetOutput(); remove(filename); sprintf( filename, "tensors_%d.raw", random_integer); remove(filename); typename ItkTensorImageType::Pointer itkTensorImage = ItkTensorImageType::New(); itkTensorImage->SetSpacing( vecImage->GetSpacing() ); // Set the image spacing itkTensorImage->SetOrigin( vecImage->GetOrigin() ); // Set the image origin itkTensorImage->SetDirection( vecImage->GetDirection() ); // Set the image direction itkTensorImage->SetLargestPossibleRegion( vecImage->GetLargestPossibleRegion() ); itkTensorImage->SetBufferedRegion( vecImage->GetLargestPossibleRegion() ); itkTensorImage->SetRequestedRegion( vecImage->GetLargestPossibleRegion() ); itkTensorImage->Allocate(); itk::ImageRegionIterator<VectorImageType> it(vecImage, vecImage->GetLargestPossibleRegion()); itk::ImageRegionIterator<ItkTensorImageType> it2(itkTensorImage, itkTensorImage->GetLargestPossibleRegion()); it2 = it2.Begin(); //#pragma omp parallel private (it) { for(it=it.Begin();!it.IsAtEnd(); ++it, ++it2) { //#pragma omp single nowait { VectorType vec = it.Get(); TensorType tensor; for(int i=1;i<7;i++) tensor[i-1] = vec[i] * vec[0]; it2.Set( tensor ); } } // end for } // end ompparallel m_OutputItk = mitk::TensorImage::New(); m_OutputItk->InitializeByItk(itkTensorImage.GetPointer()); m_OutputItk->SetVolume( itkTensorImage->GetBufferPointer() ); // in case: read resulting error-image and provide it in m_ErrorImage if(m_EstimateErrorImage) { // open error image here } }
std::vector<itk::SmartPointer<mitk::BaseData>> mitk::GeometryDataReaderService::Read() { // Switch the current locale to "C" LocaleSwitch localeSwitch("C"); std::vector<itk::SmartPointer<BaseData>> result; InputStream stream(this); TiXmlDocument doc; stream >> doc; if (!doc.Error()) { TiXmlHandle docHandle(&doc); for (TiXmlElement *geomDataElement = docHandle.FirstChildElement("GeometryData").ToElement(); geomDataElement != nullptr; geomDataElement = geomDataElement->NextSiblingElement()) { for (TiXmlElement *currentElement = geomDataElement->FirstChildElement(); currentElement != nullptr; currentElement = currentElement->NextSiblingElement()) { // different geometries could have been serialized from a GeometryData // object: std::string tagName = currentElement->Value(); if (tagName == "Geometry3D") { Geometry3D::Pointer restoredGeometry = Geometry3DToXML::FromXML(currentElement); if (restoredGeometry.IsNotNull()) { GeometryData::Pointer newGeometryData = GeometryData::New(); newGeometryData->SetGeometry(restoredGeometry); result.push_back(newGeometryData.GetPointer()); } else { MITK_ERROR << "Invalid <Geometry3D> tag encountered. Skipping."; } } else if (tagName == "ProportionalTimeGeometry") { ProportionalTimeGeometry::Pointer restoredTimeGeometry = ProportionalTimeGeometryToXML::FromXML(currentElement); if (restoredTimeGeometry.IsNotNull()) { GeometryData::Pointer newGeometryData = GeometryData::New(); newGeometryData->SetTimeGeometry(restoredTimeGeometry); result.push_back(newGeometryData.GetPointer()); } else { MITK_ERROR << "Invalid <ProportionalTimeGeometry> tag encountered. Skipping."; } } } // for child of <GeometryData> } // for <GeometryData> } else { mitkThrow() << "Parsing error at line " << doc.ErrorRow() << ", col " << doc.ErrorCol() << ": " << doc.ErrorDesc(); } if (result.empty()) { mitkThrow() << "Did not read a single GeometryData object from input."; } return result; }
TiXmlElement* mitk::TransferFunctionPropertySerializer::Serialize() { if (const TransferFunctionProperty* prop = dynamic_cast<const TransferFunctionProperty*>(mitk::BasePropertySerializer::m_Property.GetPointer())) { LocaleSwitch localeSwitch("C"); TransferFunction* transferfunction = prop->GetValue(); if (!transferfunction) return nullptr; auto element = new TiXmlElement("TransferFunction"); // serialize scalar opacity function auto scalarOpacityPointlist = new TiXmlElement( "ScalarOpacity" ); TransferFunction::ControlPoints scalarOpacityPoints = transferfunction->GetScalarOpacityPoints(); for ( auto iter = scalarOpacityPoints.begin(); iter != scalarOpacityPoints.end(); ++iter ) { auto pointel = new TiXmlElement("point"); pointel->SetAttribute("x", boost::lexical_cast<std::string>(iter->first)); pointel->SetAttribute("y", boost::lexical_cast<std::string>(iter->second)); scalarOpacityPointlist->LinkEndChild( pointel ); } element->LinkEndChild( scalarOpacityPointlist ); // serialize gradient opacity function auto gradientOpacityPointlist = new TiXmlElement( "GradientOpacity" ); TransferFunction::ControlPoints gradientOpacityPoints = transferfunction->GetGradientOpacityPoints(); for ( auto iter = gradientOpacityPoints.begin(); iter != gradientOpacityPoints.end(); ++iter ) { auto pointel = new TiXmlElement("point"); pointel->SetAttribute("x", boost::lexical_cast<std::string>(iter->first)); pointel->SetAttribute("y", boost::lexical_cast<std::string>(iter->second)); gradientOpacityPointlist->LinkEndChild( pointel ); } element->LinkEndChild( gradientOpacityPointlist ); // serialize color function vtkColorTransferFunction* ctf = transferfunction->GetColorTransferFunction(); if (ctf == nullptr) return nullptr; auto pointlist = new TiXmlElement("Color"); for (int i = 0; i < ctf->GetSize(); i++ ) { double myVal[6]; ctf->GetNodeValue(i, myVal); auto pointel = new TiXmlElement("point"); pointel->SetAttribute("x", boost::lexical_cast<std::string>(myVal[0])); pointel->SetAttribute("r", boost::lexical_cast<std::string>(myVal[1])); pointel->SetAttribute("g", boost::lexical_cast<std::string>(myVal[2])); pointel->SetAttribute("b", boost::lexical_cast<std::string>(myVal[3])); pointel->SetAttribute("midpoint", boost::lexical_cast<std::string>(myVal[4])); pointel->SetAttribute("sharpness", boost::lexical_cast<std::string>(myVal[5])); pointlist->LinkEndChild( pointel ); } element->LinkEndChild( pointlist ); return element; } else return nullptr; }
BaseProperty::Pointer mitk::TransferFunctionPropertySerializer::Deserialize(TiXmlElement* element) { if (!element) return nullptr; mitk::LocaleSwitch localeSwitch("C"); TransferFunction::Pointer tf = TransferFunction::New(); // deserialize scalar opacity function TiXmlElement* scalarOpacityPointlist = element->FirstChildElement("ScalarOpacity"); if (scalarOpacityPointlist == nullptr) { return nullptr; } tf->ClearScalarOpacityPoints(); try { for( TiXmlElement* pointElement = scalarOpacityPointlist->FirstChildElement("point"); pointElement != nullptr; pointElement = pointElement->NextSiblingElement("point")) { std::string x; std::string y; if (pointElement->QueryStringAttribute("x", &x) != TIXML_SUCCESS) return nullptr; if (pointElement->QueryStringAttribute("y", &y) != TIXML_SUCCESS) return nullptr; tf->AddScalarOpacityPoint(boost::lexical_cast<double>(x), boost::lexical_cast<double>(y)); } TiXmlElement* gradientOpacityPointlist = element->FirstChildElement("GradientOpacity"); if (gradientOpacityPointlist == nullptr) { return nullptr; } tf->ClearGradientOpacityPoints(); for( TiXmlElement* pointElement = gradientOpacityPointlist->FirstChildElement("point"); pointElement != nullptr; pointElement = pointElement->NextSiblingElement("point")) { std::string x; std::string y; if (pointElement->QueryStringAttribute("x", &x) != TIXML_SUCCESS) return nullptr; if (pointElement->QueryStringAttribute("y", &y) != TIXML_SUCCESS) return nullptr; tf->AddGradientOpacityPoint(boost::lexical_cast<double>(x), boost::lexical_cast<double>(y)); } TiXmlElement* rgbPointlist = element->FirstChildElement("Color"); if (rgbPointlist == nullptr) { return nullptr; } vtkColorTransferFunction* ctf = tf->GetColorTransferFunction(); if (ctf == nullptr) { return nullptr; } ctf->RemoveAllPoints(); for( TiXmlElement* pointElement = rgbPointlist->FirstChildElement("point"); pointElement != nullptr; pointElement = pointElement->NextSiblingElement("point")) { std::string x; std::string r,g,b, midpoint, sharpness; if (pointElement->QueryStringAttribute("x", &x) != TIXML_SUCCESS) return nullptr; if (pointElement->QueryStringAttribute("r", &r) != TIXML_SUCCESS) return nullptr; if (pointElement->QueryStringAttribute("g", &g) != TIXML_SUCCESS) return nullptr; if (pointElement->QueryStringAttribute("b", &b) != TIXML_SUCCESS) return nullptr; if (pointElement->QueryStringAttribute("midpoint", &midpoint) != TIXML_SUCCESS) return nullptr; if (pointElement->QueryStringAttribute("sharpness", &sharpness) != TIXML_SUCCESS) return nullptr; ctf->AddRGBPoint(boost::lexical_cast<double>(x), boost::lexical_cast<double>(r), boost::lexical_cast<double>(g), boost::lexical_cast<double>(b), boost::lexical_cast<double>(midpoint), boost::lexical_cast<double>(sharpness)); } } catch ( boost::bad_lexical_cast& e ) { MITK_ERROR << "Could not parse string as number: " << e.what(); return nullptr; } return TransferFunctionProperty::New(tf).GetPointer(); }
void ItkImageIO::Write() { const mitk::Image* image = dynamic_cast<const mitk::Image*>(this->GetInput()); if (image == NULL) { mitkThrow() << "Cannot write non-image data"; } struct LocaleSwitch { LocaleSwitch(const std::string& newLocale) : m_OldLocale(std::setlocale(LC_ALL, NULL)) , m_NewLocale(newLocale) { if (m_OldLocale == NULL) { m_OldLocale = ""; } else if (m_NewLocale != m_OldLocale) { // set the locale if (std::setlocale(LC_ALL, m_NewLocale.c_str()) == NULL) { MITK_INFO << "Could not set locale " << m_NewLocale; m_OldLocale = NULL; } } } ~LocaleSwitch() { if (m_OldLocale != NULL && std::setlocale(LC_ALL, m_OldLocale) == NULL) { MITK_INFO << "Could not reset locale " << m_OldLocale; } } private: const char* m_OldLocale; const std::string m_NewLocale; }; // Switch the current locale to "C" LocaleSwitch localeSwitch("C"); // Clone the image geometry, because we might have to change it // for writing purposes BaseGeometry::Pointer geometry = image->GetGeometry()->Clone(); // Check if geometry information will be lost if (image->GetDimension() == 2 && !geometry->Is2DConvertable()) { MITK_WARN << "Saving a 2D image with 3D geometry information. Geometry information will be lost! You might consider using Convert2Dto3DImageFilter before saving."; // set matrix to identity mitk::AffineTransform3D::Pointer affTrans = mitk::AffineTransform3D::New(); affTrans->SetIdentity(); mitk::Vector3D spacing = geometry->GetSpacing(); mitk::Point3D origin = geometry->GetOrigin(); geometry->SetIndexToWorldTransform(affTrans); geometry->SetSpacing(spacing); geometry->SetOrigin(origin); } LocalFile localFile(this); const std::string path = localFile.GetFileName(); MITK_INFO << "Writing image: " << path << std::endl; try { // Implementation of writer using itkImageIO directly. This skips the use // of templated itkImageFileWriter, which saves the multiplexing on MITK side. const unsigned int dimension = image->GetDimension(); const unsigned int* const dimensions = image->GetDimensions(); const mitk::PixelType pixelType = image->GetPixelType(); const mitk::Vector3D mitkSpacing = geometry->GetSpacing(); const mitk::Point3D mitkOrigin = geometry->GetOrigin(); // Due to templating in itk, we are forced to save a 4D spacing and 4D Origin, // though they are not supported in MITK itk::Vector<double, 4u> spacing4D; spacing4D[0] = mitkSpacing[0]; spacing4D[1] = mitkSpacing[1]; spacing4D[2] = mitkSpacing[2]; spacing4D[3] = 1; // There is no support for a 4D spacing. However, we should have a valid value here itk::Vector<double, 4u> origin4D; origin4D[0] = mitkOrigin[0]; origin4D[1] = mitkOrigin[1]; origin4D[2] = mitkOrigin[2]; origin4D[3] = 0; // There is no support for a 4D origin. However, we should have a valid value here // Set the necessary information for imageIO m_ImageIO->SetNumberOfDimensions(dimension); m_ImageIO->SetPixelType(pixelType.GetPixelType()); m_ImageIO->SetComponentType(pixelType.GetComponentType() < PixelComponentUserType ? static_cast<itk::ImageIOBase::IOComponentType>(pixelType.GetComponentType()) : itk::ImageIOBase::UNKNOWNCOMPONENTTYPE); m_ImageIO->SetNumberOfComponents( pixelType.GetNumberOfComponents() ); itk::ImageIORegion ioRegion( dimension ); for(unsigned int i = 0; i < dimension; i++) { m_ImageIO->SetDimensions(i, dimensions[i]); m_ImageIO->SetSpacing(i, spacing4D[i]); m_ImageIO->SetOrigin(i, origin4D[i]); mitk::Vector3D mitkDirection; mitkDirection.SetVnlVector(geometry->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(i)); itk::Vector<double, 4u> direction4D; direction4D[0] = mitkDirection[0]; direction4D[1] = mitkDirection[1]; direction4D[2] = mitkDirection[2]; // MITK only supports a 3x3 direction matrix. Due to templating in itk, however, we must // save a 4x4 matrix for 4D images. in this case, add an homogneous component to the matrix. if (i == 3) { direction4D[3] = 1; // homogenous component } else { direction4D[3] = 0; } vnl_vector<double> axisDirection(dimension); for(unsigned int j = 0; j < dimension; j++) { axisDirection[j] = direction4D[j] / spacing4D[i]; } m_ImageIO->SetDirection(i, axisDirection); ioRegion.SetSize(i, image->GetLargestPossibleRegion().GetSize(i)); ioRegion.SetIndex(i, image->GetLargestPossibleRegion().GetIndex(i)); } //use compression if available m_ImageIO->UseCompressionOn(); m_ImageIO->SetIORegion(ioRegion); m_ImageIO->SetFileName(path); // ***** Remove const_cast after bug 17952 is fixed **** ImageReadAccessor imageAccess(const_cast<mitk::Image*>(image)); m_ImageIO->Write(imageAccess.GetData()); } catch (const std::exception& e) { mitkThrow() << e.what(); } }
// do the work void mitk::GEDicomDiffusionImageHeaderReader::Update() { // check if there are filenames if(m_DicomFilenames.size()) { mitk::LocaleSwitch localeSwitch("C"); // adapted from namic-sandbox // DicomToNrrdConverter.cxx VolumeReaderType::DictionaryArrayRawPointer inputDict = m_VolumeReader->GetMetaDataDictionaryArray(); ReadPublicTags(); float x0, y0, z0; float x1, y1, z1; std::string tag; tag.clear(); itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0020|0032", tag ); sscanf( tag.c_str(), "%f\\%f\\%f", &x0, &y0, &z0 ); std::cout << "Slice 0: " << tag << std::endl; tag.clear(); // assume volume interleaving, i.e. the second dicom file stores // the second slice in the same volume as the first dicom file itk::ExposeMetaData<std::string> ( *(*inputDict)[1], "0020|0032", tag ); sscanf( tag.c_str(), "%f\\%f\\%f", &x1, &y1, &z1 ); std::cout << "Slice 1: " << tag << std::endl; x1 -= x0; y1 -= y0; z1 -= z0; x0 = x1*this->m_Output->xSlice + y1*this->m_Output->ySlice + z1*this->m_Output->zSlice; if (x0 < 0) { m_SliceOrderIS = false; } ReadPublicTags2(); int nSliceInVolume; int nVolume; nSliceInVolume = m_sliceLocations.size(); nVolume = m_nSlice/nSliceInVolume; // assume volume interleaving std::cout << "Number of Slices: " << m_nSlice << std::endl; std::cout << "Number of Volume: " << nVolume << std::endl; std::cout << "Number of Slices in each volume: " << nSliceInVolume << std::endl; for (int k = 0; k < m_nSlice; k += nSliceInVolume) { tag.clear(); bool exist = itk::ExposeMetaData<std::string> ( *(*inputDict)[k], "0043|1039", tag); float b = atof( tag.c_str() ); this->m_Output->bValue = b; vnl_vector_fixed<double, 3> vect3d; if (!exist || b == 0) { vect3d.fill( 0 ); this->m_Output->DiffusionVector = vect3d; continue; } vect3d.fill( 0 ); tag.clear(); itk::ExposeMetaData<std::string> ( *(*inputDict)[k], "0019|10bb", tag); vect3d[0] = atof( tag.c_str() ); tag.clear(); itk::ExposeMetaData<std::string> ( *(*inputDict)[k], "0019|10bc", tag); vect3d[1] = atof( tag.c_str() ); tag.clear(); itk::ExposeMetaData<std::string> ( *(*inputDict)[k], "0019|10bd", tag); vect3d[2] = atof( tag.c_str() ); vect3d.normalize(); this->m_Output->DiffusionVector = vect3d; } TransformGradients(); } }
void mitk::DicomDiffusionImageHeaderReader::ReadPublicTags() { mitk::LocaleSwitch localeSwitch("C"); VolumeReaderType::DictionaryArrayRawPointer inputDict = m_VolumeReader->GetMetaDataDictionaryArray(); // load in all public tags m_nSlice = inputDict->size(); std::string tag; tag.clear(); itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0008|103e", tag ); this->m_Output->seriesDescription = tag.c_str(); tag.clear(); itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0020|0011", tag ); this->m_Output->seriesNumber = atoi(tag.c_str()); tag.clear(); itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0010|0010", tag ); this->m_Output->patientName = tag.c_str(); tag.clear(); itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0028|0010", tag ); this->m_Output->nRows = atoi( tag.c_str() ); tag.clear(); itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0028|0011", tag ); this->m_Output->nCols = atoi( tag.c_str() ); tag.clear(); itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0028|0030", tag ); sscanf( tag.c_str(), "%f\\%f", &this->m_Output->xRes, &this->m_Output->yRes ); tag.clear(); itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0020|0032", tag ); sscanf( tag.c_str(), "%f\\%f\\%f", &this->m_Output->xOrigin, &this->m_Output->yOrigin, &this->m_Output->zOrigin ); tag.clear(); itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0018|0050", tag ); this->m_Output->sliceThickness = atof( tag.c_str() ); tag.clear(); itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0018|0088", tag ); this->m_Output->sliceSpacing = atof( tag.c_str() ); // figure out how many slices are there in a volume, each unique // SliceLocation represent one slice for (int k = 0; k < m_nSlice; k++) { tag.clear(); itk::ExposeMetaData<std::string> ( *(*inputDict)[k], "0020|1041", tag); float sliceLocation = atof( tag.c_str() ); InsertUnique( m_sliceLocations, sliceLocation ); } // check ImageOrientationPatient and figure out slice direction in // L-P-I (right-handed) system. // In Dicom, the coordinate frame is L-P by default. Look at // http://medical.nema.org/dicom/2007/07_03pu.pdf , page 301 tag.clear(); itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0020|0037", tag ); float xRow, yRow, zRow, xCol, yCol, zCol, xSlice, ySlice, zSlice /*, orthoSliceSpacing*/; sscanf( tag.c_str(), "%f\\%f\\%f\\%f\\%f\\%f", &xRow, &yRow, &zRow, &xCol, &yCol, &zCol ); // In Dicom, the measurement frame is L-P by default. Look at // http://medical.nema.org/dicom/2007/07_03pu.pdf , page 301, in // order to make this compatible with Slicer's RAS frame, we // multiply the direction cosines by the negatives of the resolution // (resolution is required by nrrd format). Direction cosine is not // affacted since the resulting frame is still a right-handed frame. xRow = -xRow; yRow = -yRow; xCol = -xCol; yCol = -yCol; // Cross product, this gives I-axis direction xSlice = (yRow*zCol-zRow*yCol)*this->m_Output->sliceSpacing; ySlice = (zRow*xCol-xRow*zCol)*this->m_Output->sliceSpacing; zSlice = (xRow*yCol-yRow*xCol)*this->m_Output->sliceSpacing; xRow *= this->m_Output->xRes; yRow *= this->m_Output->xRes; zRow *= this->m_Output->xRes; xCol *= this->m_Output->yRes; yCol *= this->m_Output->yRes; zCol *= this->m_Output->yRes; this->m_Output->xRow = xRow; this->m_Output->yRow = yRow; this->m_Output->zRow = zRow; this->m_Output->xCol = xCol; this->m_Output->yCol = yCol; this->m_Output->zCol = zCol; this->m_Output->xSlice = xSlice; this->m_Output->ySlice = ySlice; this->m_Output->zSlice = zSlice; }
std::vector<itk::SmartPointer<BaseData> > NrrdTensorImageReader::Read() { std::vector<itk::SmartPointer<mitk::BaseData> > result; std::string location = GetInputLocation(); if ( location == "") { throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, the filename is empty!"); } else { try { mitk::LocaleSwitch localeSwitch("C"); try { std::string fname3 = mitk::IOUtil::GetTempPath()+"/temp_dti.nii.gz"; int c = 0; while( itksys::SystemTools::FileExists(fname3) ) { fname3 = mitk::IOUtil::GetTempPath()+"/temp_dti_" + boost::lexical_cast<std::string>(c) + ".nii.gz"; ++c; } itksys::SystemTools::CopyAFile(location.c_str(), fname3.c_str()); typedef itk::VectorImage<float,3> ImageType; itk::NiftiImageIO::Pointer io = itk::NiftiImageIO::New(); typedef itk::ImageFileReader<ImageType> FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetImageIO(io); reader->SetFileName(fname3); reader->Update(); ImageType::Pointer img = reader->GetOutput(); TensorImage::ItkTensorImageType::Pointer vecImg = TensorImage::ItkTensorImageType::New(); vecImg->SetSpacing( img->GetSpacing() ); // Set the image spacing vecImg->SetOrigin( img->GetOrigin() ); // Set the image origin vecImg->SetDirection( img->GetDirection() ); // Set the image direction vecImg->SetRegions( img->GetLargestPossibleRegion()); vecImg->Allocate(); itk::ImageRegionIterator<TensorImage::ItkTensorImageType> ot (vecImg, vecImg->GetLargestPossibleRegion() ); ot.GoToBegin(); itk::ImageRegionIterator<ImageType> it (img, img->GetLargestPossibleRegion() ); it.GoToBegin(); typedef ImageType::PixelType VarPixType; typedef TensorImage::PixelType FixPixType; int numComponents = img->GetNumberOfComponentsPerPixel(); if (numComponents==6) { MITK_INFO << "Trying to load dti as 6-comp nifti ..."; while (!it.IsAtEnd()) { VarPixType vec = it.Get(); FixPixType fixVec(vec.GetDataPointer()); TensorImage::PixelType tensor; tensor.SetElement(0, vec.GetElement(0)); tensor.SetElement(1, vec.GetElement(1)); tensor.SetElement(2, vec.GetElement(2)); tensor.SetElement(3, vec.GetElement(3)); tensor.SetElement(4, vec.GetElement(4)); tensor.SetElement(5, vec.GetElement(5)); fixVec = tensor; ot.Set(fixVec); ++ot; ++it; } } else if(numComponents==9) { MITK_INFO << "Trying to load dti as 9-comp nifti ..."; while (!it.IsAtEnd()) { VarPixType vec = it.Get(); TensorImage::PixelType tensor; tensor.SetElement(0, vec.GetElement(0)); tensor.SetElement(1, vec.GetElement(1)); tensor.SetElement(2, vec.GetElement(2)); tensor.SetElement(3, vec.GetElement(4)); tensor.SetElement(4, vec.GetElement(5)); tensor.SetElement(5, vec.GetElement(8)); FixPixType fixVec(tensor); ot.Set(fixVec); ++ot; ++it; } } else if (numComponents==1) { MITK_INFO << "Trying to load dti as 4D nifti ..."; typedef itk::Image<float,4> ImageType; typedef itk::ImageFileReader<ImageType> FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetImageIO(io); reader->SetFileName(fname3); reader->Update(); ImageType::Pointer img = reader->GetOutput(); itk::Size<4> size = img->GetLargestPossibleRegion().GetSize(); while (!ot.IsAtEnd()) { TensorImage::PixelType tensor; ImageType::IndexType idx; idx[0] = ot.GetIndex()[0]; idx[1] = ot.GetIndex()[1]; idx[2] = ot.GetIndex()[2]; if (size[3]==6) { for (unsigned int te=0; te<size[3]; te++) { idx[3] = te; tensor.SetElement(te, img->GetPixel(idx)); } } else if (size[3]==9) { idx[3] = 0; tensor.SetElement(0, img->GetPixel(idx)); idx[3] = 1; tensor.SetElement(1, img->GetPixel(idx)); idx[3] = 2; tensor.SetElement(2, img->GetPixel(idx)); idx[3] = 4; tensor.SetElement(3, img->GetPixel(idx)); idx[3] = 5; tensor.SetElement(4, img->GetPixel(idx)); idx[3] = 8; tensor.SetElement(5, img->GetPixel(idx)); } else throw itk::ImageFileReaderException(__FILE__, __LINE__, "Unknown number of components for DTI file. Should be 6 or 9!"); FixPixType fixVec(tensor); ot.Set(fixVec); ++ot; } } OutputType::Pointer resultImage = OutputType::New(); resultImage->InitializeByItk( vecImg.GetPointer() ); resultImage->SetVolume( vecImg->GetBufferPointer() ); result.push_back( resultImage.GetPointer() ); } catch(...) { MITK_INFO << "Trying to load dti as nrrd ..."; typedef itk::VectorImage<float,3> ImageType; itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); typedef itk::ImageFileReader<ImageType> FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetImageIO(io); reader->SetFileName(location); reader->Update(); ImageType::Pointer img = reader->GetOutput(); TensorImage::ItkTensorImageType::Pointer vecImg = TensorImage::ItkTensorImageType::New(); vecImg->SetSpacing( img->GetSpacing() ); // Set the image spacing vecImg->SetOrigin( img->GetOrigin() ); // Set the image origin vecImg->SetDirection( img->GetDirection() ); // Set the image direction vecImg->SetRegions( img->GetLargestPossibleRegion()); vecImg->Allocate(); itk::ImageRegionIterator<TensorImage::ItkTensorImageType> ot (vecImg, vecImg->GetLargestPossibleRegion() ); ot.GoToBegin(); itk::ImageRegionIterator<ImageType> it (img, img->GetLargestPossibleRegion() ); it.GoToBegin(); typedef ImageType::PixelType VarPixType; typedef TensorImage::PixelType FixPixType; int numComponents = img->GetNumberOfComponentsPerPixel(); itk::MetaDataDictionary imgMetaDictionary = img->GetMetaDataDictionary(); std::vector<std::string> imgMetaKeys = imgMetaDictionary.GetKeys(); std::vector<std::string>::const_iterator itKey = imgMetaKeys.begin(); std::string metaString; bool readFrame = false; double xx, xy, xz, yx, yy, yz, zx, zy, zz; MeasurementFrameType measFrame; measFrame.SetIdentity(); MeasurementFrameType measFrameTransp; measFrameTransp.SetIdentity(); for (; itKey != imgMetaKeys.end(); itKey ++) { itk::ExposeMetaData<std::string> (imgMetaDictionary, *itKey, metaString); if (itKey->find("measurement frame") != std::string::npos) { sscanf(metaString.c_str(), " ( %lf , %lf , %lf ) ( %lf , %lf , %lf ) ( %lf , %lf , %lf ) \n", &xx, &xy, &xz, &yx, &yy, &yz, &zx, &zy, &zz); if (xx>10e-10 || xy>10e-10 || xz>10e-10 || yx>10e-10 || yy>10e-10 || yz>10e-10 || zx>10e-10 || zy>10e-10 || zz>10e-10 ) { readFrame = true; measFrame(0,0) = xx; measFrame(0,1) = xy; measFrame(0,2) = xz; measFrame(1,0) = yx; measFrame(1,1) = yy; measFrame(1,2) = yz; measFrame(2,0) = zx; measFrame(2,1) = zy; measFrame(2,2) = zz; measFrameTransp = measFrame.GetTranspose(); } } } if (numComponents==6) { while (!it.IsAtEnd()) { // T'=RTR' VarPixType vec = it.Get(); FixPixType fixVec(vec.GetDataPointer()); if(readFrame) { TensorImage::PixelType tensor; tensor.SetElement(0, vec.GetElement(0)); tensor.SetElement(1, vec.GetElement(1)); tensor.SetElement(2, vec.GetElement(2)); tensor.SetElement(3, vec.GetElement(3)); tensor.SetElement(4, vec.GetElement(4)); tensor.SetElement(5, vec.GetElement(5)); tensor = ConvertMatrixTypeToFixedArrayType(tensor.PreMultiply(measFrame)); tensor = ConvertMatrixTypeToFixedArrayType(tensor.PostMultiply(measFrameTransp)); fixVec = tensor; } ot.Set(fixVec); ++ot; ++it; } } else if(numComponents==9) { while (!it.IsAtEnd()) { VarPixType vec = it.Get(); TensorImage::PixelType tensor; tensor.SetElement(0, vec.GetElement(0)); tensor.SetElement(1, vec.GetElement(1)); tensor.SetElement(2, vec.GetElement(2)); tensor.SetElement(3, vec.GetElement(4)); tensor.SetElement(4, vec.GetElement(5)); tensor.SetElement(5, vec.GetElement(8)); if(readFrame) { tensor = ConvertMatrixTypeToFixedArrayType(tensor.PreMultiply(measFrame)); tensor = ConvertMatrixTypeToFixedArrayType(tensor.PostMultiply(measFrameTransp)); } FixPixType fixVec(tensor); ot.Set(fixVec); ++ot; ++it; } } else if (numComponents==1) { typedef itk::Image<float,4> ImageType; itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); typedef itk::ImageFileReader<ImageType> FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetImageIO(io); reader->SetFileName(location); reader->Update(); ImageType::Pointer img = reader->GetOutput(); itk::Size<4> size = img->GetLargestPossibleRegion().GetSize(); while (!ot.IsAtEnd()) { TensorImage::PixelType tensor; ImageType::IndexType idx; idx[0] = ot.GetIndex()[0]; idx[1] = ot.GetIndex()[1]; idx[2] = ot.GetIndex()[2]; if (size[3]==6) { for (unsigned int te=0; te<size[3]; te++) { idx[3] = te; tensor.SetElement(te, img->GetPixel(idx)); } } else if (size[3]==9) { idx[3] = 0; tensor.SetElement(0, img->GetPixel(idx)); idx[3] = 1; tensor.SetElement(1, img->GetPixel(idx)); idx[3] = 2; tensor.SetElement(2, img->GetPixel(idx)); idx[3] = 4; tensor.SetElement(3, img->GetPixel(idx)); idx[3] = 5; tensor.SetElement(4, img->GetPixel(idx)); idx[3] = 8; tensor.SetElement(5, img->GetPixel(idx)); } else throw itk::ImageFileReaderException(__FILE__, __LINE__, "Unknown number of komponents for DTI file. Should be 6 or 9!"); if(readFrame) { tensor = ConvertMatrixTypeToFixedArrayType(tensor.PreMultiply(measFrame)); tensor = ConvertMatrixTypeToFixedArrayType(tensor.PostMultiply(measFrameTransp)); } FixPixType fixVec(tensor); ot.Set(fixVec); ++ot; } } else { throw itk::ImageFileReaderException(__FILE__, __LINE__, "Image has wrong number of pixel components!"); } OutputType::Pointer resultImage = OutputType::New(); resultImage->InitializeByItk( vecImg.GetPointer() ); resultImage->SetVolume( vecImg->GetBufferPointer() ); result.push_back( resultImage.GetPointer() ); } } catch(std::exception& e) { throw itk::ImageFileReaderException(__FILE__, __LINE__, e.what()); } catch(...) { throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, an error occurred while reading the requested DTI file!"); } } return result; }
/** * Convert files from one ending to the other */ int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("", "i", mitkCommandLineParser::String, "Input image", "input raw dwi", us::Any(), false, false, false, mitkCommandLineParser::Input); parser.addArgument("", "o", mitkCommandLineParser::String, "Output image", "output image", us::Any(), false, false, false, mitkCommandLineParser::Output); parser.addArgument("b0_threshold", "", mitkCommandLineParser::Int, "b0 threshold", "baseline image intensity threshold", 0); parser.addArgument("correct_negative_eigenv", "", mitkCommandLineParser::Bool, "Correct negative eigenvalues", "correct negative eigenvalues", us::Any(false)); parser.setCategory("Signal Modelling"); parser.setTitle("Tensor Reconstruction"); parser.setDescription(""); parser.setContributor("MIC"); std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; std::string inFileName = us::any_cast<std::string>(parsedArgs["i"]); std::string outfilename = us::any_cast<std::string>(parsedArgs["o"]); if (!itksys::SystemTools::GetFilenamePath(outfilename).empty()) outfilename = itksys::SystemTools::GetFilenamePath(outfilename)+"/"+itksys::SystemTools::GetFilenameWithoutExtension(outfilename); else outfilename = itksys::SystemTools::GetFilenameWithoutExtension(outfilename); outfilename += ".dti"; int threshold = 0; if (parsedArgs.count("b0_threshold")) threshold = us::any_cast<int>(parsedArgs["b0_threshold"]); bool correct_negative_eigenv = false; if (parsedArgs.count("correct_negative_eigenv")) correct_negative_eigenv = us::any_cast<bool>(parsedArgs["correct_negative_eigenv"]); try { mitk::Image::Pointer dwi = mitk::IOUtil::Load<mitk::Image>(inFileName); mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); if (correct_negative_eigenv) { typedef itk::TensorReconstructionWithEigenvalueCorrectionFilter< short, float > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi)); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer); filter->SetB0Threshold(threshold); filter->Update(); // Save tensor image itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); io->SetFileType( itk::ImageIOBase::Binary ); io->UseCompressionOn(); mitk::LocaleSwitch localeSwitch("C"); itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< float >, 3 > >::Pointer writer = itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< float >, 3 > >::New(); writer->SetInput(filter->GetOutput()); writer->SetFileName(outfilename); writer->SetImageIO(io); writer->UseCompressionOn(); writer->Update(); } else { typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, float > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer ); filter->SetBValue( mitk::DiffusionPropertyHelper::GetReferenceBValue( dwi )); filter->SetThreshold(threshold); filter->Update(); // Save tensor image itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); io->SetFileType( itk::ImageIOBase::Binary ); io->UseCompressionOn(); mitk::LocaleSwitch localeSwitch("C"); itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< float >, 3 > >::Pointer writer = itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< float >, 3 > >::New(); writer->SetInput(filter->GetOutput()); writer->SetFileName(outfilename); writer->SetImageIO(io); writer->UseCompressionOn(); writer->Update(); } } catch ( itk::ExceptionObject &err) { std::cout << "Exception: " << err; } catch ( std::exception err) { std::cout << "Exception: " << err.what(); } catch ( ... ) { std::cout << "Exception!"; } return EXIT_SUCCESS; }
void ItkImageIO::Write() { const mitk::Image *image = dynamic_cast<const mitk::Image *>(this->GetInput()); if (image == NULL) { mitkThrow() << "Cannot write non-image data"; } // Switch the current locale to "C" LocaleSwitch localeSwitch("C"); // Clone the image geometry, because we might have to change it // for writing purposes BaseGeometry::Pointer geometry = image->GetGeometry()->Clone(); // Check if geometry information will be lost if (image->GetDimension() == 2 && !geometry->Is2DConvertable()) { MITK_WARN << "Saving a 2D image with 3D geometry information. Geometry information will be lost! You might " "consider using Convert2Dto3DImageFilter before saving."; // set matrix to identity mitk::AffineTransform3D::Pointer affTrans = mitk::AffineTransform3D::New(); affTrans->SetIdentity(); mitk::Vector3D spacing = geometry->GetSpacing(); mitk::Point3D origin = geometry->GetOrigin(); geometry->SetIndexToWorldTransform(affTrans); geometry->SetSpacing(spacing); geometry->SetOrigin(origin); } LocalFile localFile(this); const std::string path = localFile.GetFileName(); MITK_INFO << "Writing image: " << path << std::endl; try { // Implementation of writer using itkImageIO directly. This skips the use // of templated itkImageFileWriter, which saves the multiplexing on MITK side. const unsigned int dimension = image->GetDimension(); const unsigned int *const dimensions = image->GetDimensions(); const mitk::PixelType pixelType = image->GetPixelType(); const mitk::Vector3D mitkSpacing = geometry->GetSpacing(); const mitk::Point3D mitkOrigin = geometry->GetOrigin(); // Due to templating in itk, we are forced to save a 4D spacing and 4D Origin, // though they are not supported in MITK itk::Vector<double, 4u> spacing4D; spacing4D[0] = mitkSpacing[0]; spacing4D[1] = mitkSpacing[1]; spacing4D[2] = mitkSpacing[2]; spacing4D[3] = 1; // There is no support for a 4D spacing. However, we should have a valid value here itk::Vector<double, 4u> origin4D; origin4D[0] = mitkOrigin[0]; origin4D[1] = mitkOrigin[1]; origin4D[2] = mitkOrigin[2]; origin4D[3] = 0; // There is no support for a 4D origin. However, we should have a valid value here // Set the necessary information for imageIO m_ImageIO->SetNumberOfDimensions(dimension); m_ImageIO->SetPixelType(pixelType.GetPixelType()); m_ImageIO->SetComponentType(pixelType.GetComponentType() < PixelComponentUserType ? static_cast<itk::ImageIOBase::IOComponentType>(pixelType.GetComponentType()) : itk::ImageIOBase::UNKNOWNCOMPONENTTYPE); m_ImageIO->SetNumberOfComponents(pixelType.GetNumberOfComponents()); itk::ImageIORegion ioRegion(dimension); for (unsigned int i = 0; i < dimension; i++) { m_ImageIO->SetDimensions(i, dimensions[i]); m_ImageIO->SetSpacing(i, spacing4D[i]); m_ImageIO->SetOrigin(i, origin4D[i]); mitk::Vector3D mitkDirection; mitkDirection.SetVnlVector(geometry->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(i)); itk::Vector<double, 4u> direction4D; direction4D[0] = mitkDirection[0]; direction4D[1] = mitkDirection[1]; direction4D[2] = mitkDirection[2]; // MITK only supports a 3x3 direction matrix. Due to templating in itk, however, we must // save a 4x4 matrix for 4D images. in this case, add an homogneous component to the matrix. if (i == 3) { direction4D[3] = 1; // homogenous component } else { direction4D[3] = 0; } vnl_vector<double> axisDirection(dimension); for (unsigned int j = 0; j < dimension; j++) { axisDirection[j] = direction4D[j] / spacing4D[i]; } m_ImageIO->SetDirection(i, axisDirection); ioRegion.SetSize(i, image->GetLargestPossibleRegion().GetSize(i)); ioRegion.SetIndex(i, image->GetLargestPossibleRegion().GetIndex(i)); } // use compression if available m_ImageIO->UseCompressionOn(); m_ImageIO->SetIORegion(ioRegion); m_ImageIO->SetFileName(path); // Handle time geometry const ArbitraryTimeGeometry *arbitraryTG = dynamic_cast<const ArbitraryTimeGeometry *>(image->GetTimeGeometry()); if (arbitraryTG) { itk::EncapsulateMetaData<std::string>(m_ImageIO->GetMetaDataDictionary(), PROPERTY_KEY_TIMEGEOMETRY_TYPE, ArbitraryTimeGeometry::GetStaticNameOfClass()); std::stringstream stream; stream << arbitraryTG->GetTimeBounds(0)[0]; for (TimeStepType pos = 0; pos < arbitraryTG->CountTimeSteps(); ++pos) { stream << " " << arbitraryTG->GetTimeBounds(pos)[1]; } std::string data = stream.str(); itk::EncapsulateMetaData<std::string>( m_ImageIO->GetMetaDataDictionary(), PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS, data); } // Handle properties mitk::PropertyList::Pointer imagePropertyList = image->GetPropertyList(); for (const auto &property : *imagePropertyList->GetMap()) { IPropertyPersistence::InfoResultType infoList = mitk::CoreServices::GetPropertyPersistence()->GetInfo(property.first, GetMimeType()->GetName(), true); if (infoList.empty()) { continue; } std::string value = infoList.front()->GetSerializationFunction()(property.second); if (value == mitk::BaseProperty::VALUE_CANNOT_BE_CONVERTED_TO_STRING) { continue; } std::string key = infoList.front()->GetKey(); itk::EncapsulateMetaData<std::string>(m_ImageIO->GetMetaDataDictionary(), key, value); } ImageReadAccessor imageAccess(image); m_ImageIO->Write(imageAccess.GetData()); } catch (const std::exception &e) { mitkThrow() << e.what(); } }
mitk::PropertyList::Pointer mitk::CustomTagParser::ParseDicomPropertyString(std::string dicomPropertyString) { auto results = mitk::PropertyList::New(); if ("" == dicomPropertyString) { //MITK_ERROR << "Could not parse empty custom dicom string"; return results; } std::map<std::string, std::string> privateParameters; // convert hex to ascii // the Siemens private tag contains the information like this // "43\52\23\34" we jump over each \ and convert the number int len = dicomPropertyString.length(); std::string asciiString; for (int i = 0; i < len; i += 3) { std::string byte = dicomPropertyString.substr(i, 2); auto chr = (char)(int)strtol(byte.c_str(), nullptr, 16); asciiString.push_back(chr); } // extract parameter list std::size_t beginning = asciiString.find("### ASCCONV BEGIN ###") + 21; std::size_t ending = asciiString.find("### ASCCONV END ###"); std::string parameterListString = asciiString.substr(beginning, ending - beginning); boost::replace_all(parameterListString, "\r\n", "\n"); boost::char_separator<char> newlineSeparator("\n"); boost::tokenizer<boost::char_separator<char>> parameters(parameterListString, newlineSeparator); for (const auto ¶meter : parameters) { std::vector<std::string> parts; boost::split(parts, parameter, boost::is_any_of("=")); if (parts.size() == 2) { parts[0].erase(std::remove(parts[0].begin(), parts[0].end(), ' '), parts[0].end()); parts[1].erase(parts[1].begin(), parts[1].begin() + 1); // first character is a space privateParameters[parts[0]] = parts[1]; } } std::string revisionString = ""; try { revisionString = ExtractRevision(privateParameters["tSequenceFileName"]); } catch (const std::exception &e) { MITK_ERROR << "Cannot deduce revision information. Reason: "<< e.what(); return results; } results->SetProperty(m_RevisionPropertyName, mitk::StringProperty::New(revisionString)); std::string jsonString = GetRevisionAppropriateJSONString(revisionString); boost::property_tree::ptree root; std::istringstream jsonStream(jsonString); try { boost::property_tree::read_json(jsonStream, root); } catch (const boost::property_tree::json_parser_error &e) { mitkThrow() << "Could not parse json file. Error was:\n" << e.what(); } for (auto it : root) { if (it.second.empty()) { std::string propertyName = m_CESTPropertyPrefix + it.second.data(); if (m_JSONRevisionPropertyName == propertyName) { results->SetProperty(propertyName, mitk::StringProperty::New(it.first)); } else { results->SetProperty(propertyName, mitk::StringProperty::New(privateParameters[it.first])); } } else { MITK_ERROR << "Currently no support for nested dicom tag descriptors in json file."; } } std::string offset = ""; std::string measurements = ""; results->GetStringProperty("CEST.Offset", offset); results->GetStringProperty("CEST.measurements", measurements); if ("" == measurements) { std::string stringRepetitions = ""; std::string stringAverages = ""; results->GetStringProperty("CEST.repetitions", stringRepetitions); results->GetStringProperty("CEST.averages", stringAverages); std::stringstream measurementStream; try { measurementStream << std::stoi(stringRepetitions) + std::stoi(stringAverages); measurements = measurementStream.str(); MITK_INFO << "Could not find measurements, assuming repetitions + averages. Which is: " << measurements; } catch (const std::invalid_argument &ia) { MITK_ERROR << "Could not find measurements, fallback assumption of repetitions + averages could not be determined either: " << ia.what(); } } std::string preparationType = ""; std::string recoveryMode = ""; std::string spoilingType = ""; results->GetStringProperty(CEST_PROPERTY_NAME_PREPERATIONTYPE().c_str(), preparationType); results->GetStringProperty(CEST_PROPERTY_NAME_RECOVERYMODE().c_str(), recoveryMode); results->GetStringProperty(CEST_PROPERTY_NAME_SPOILINGTYPE().c_str(), spoilingType); if (this->IsT1Sequence(preparationType, recoveryMode, spoilingType, revisionString)) { MITK_INFO << "Parsed as T1 image"; mitk::LocaleSwitch localeSwitch("C"); std::stringstream trecStream; std::string trecPath = m_DicomDataPath + "/TREC.txt"; std::ifstream list(trecPath.c_str()); if (list.good()) { std::string currentTime; while (std::getline(list, currentTime)) { trecStream << currentTime << " "; } } else { MITK_WARN << "Assumed T1, but could not load TREC at " << trecPath; } results->SetStringProperty(CEST_PROPERTY_NAME_TREC().c_str(), trecStream.str().c_str()); } else { MITK_INFO << "Parsed as CEST or WASABI image"; std::string sampling = ""; bool hasSamplingInformation = results->GetStringProperty("CEST.SamplingType", sampling); if (hasSamplingInformation) { std::string offsets = GetOffsetString(sampling, offset, measurements); results->SetStringProperty(m_OffsetsPropertyName.c_str(), offsets.c_str()); } else { MITK_WARN << "Could not determine sampling type."; } } //persist all properties mitk::IPropertyPersistence *persSrv = GetPersistenceService(); if (persSrv) { auto propertyMap = results->GetMap(); for (auto const &prop : *propertyMap) { PropertyPersistenceInfo::Pointer info = PropertyPersistenceInfo::New(); std::string key = prop.first; std::replace(key.begin(), key.end(), '.', '_'); info->SetNameAndKey(prop.first, key); persSrv->AddInfo(info); } } return results; }