diff --git a/Modules/PhotoacousticsLib/MitkPAPhantomGenerator/PAPhantomGenerator.cpp b/Modules/PhotoacousticsLib/MitkPAPhantomGenerator/PAPhantomGenerator.cpp index decd6880be..89c0eba779 100644 --- a/Modules/PhotoacousticsLib/MitkPAPhantomGenerator/PAPhantomGenerator.cpp +++ b/Modules/PhotoacousticsLib/MitkPAPhantomGenerator/PAPhantomGenerator.cpp @@ -1,216 +1,221 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include using namespace mitk::pa; TissueGeneratorParameters::Pointer CreatePhantom_08_03_18_Parameters() { auto returnParameters = TissueGeneratorParameters::New(); returnParameters->SetAirThicknessInMillimeters(12); returnParameters->SetMinBackgroundAbsorption(0.1); returnParameters->SetMaxBackgroundAbsorption(0.1); returnParameters->SetBackgroundAnisotropy(0.9); returnParameters->SetBackgroundScattering(15); returnParameters->SetCalculateNewVesselPositionCallback(&VesselMeanderStrategy::CalculateNewPositionInStraightLine); returnParameters->SetDoPartialVolume(false); returnParameters->SetMinNumberOfVessels(5); returnParameters->SetMaxNumberOfVessels(5); returnParameters->SetMinVesselAbsorption(10); returnParameters->SetMaxVesselAbsorption(10); returnParameters->SetMinVesselAnisotropy(0.9); returnParameters->SetMaxVesselAnisotropy(0.9); returnParameters->SetMinVesselBending(0.1); returnParameters->SetMaxVesselBending(0.3); returnParameters->SetMinVesselRadiusInMillimeters(0.5); returnParameters->SetMaxVesselRadiusInMillimeters(4); returnParameters->SetMinVesselScattering(15); returnParameters->SetMaxVesselScattering(15); returnParameters->SetMinVesselZOrigin(2.2); returnParameters->SetMaxVesselZOrigin(4); returnParameters->SetVesselBifurcationFrequency(5000); returnParameters->SetRandomizePhysicalProperties(false); returnParameters->SetSkinThicknessInMillimeters(0); returnParameters->SetUseRngSeed(false); + //returnParameters->SetVoxelSpacingInCentimeters(0.015); + //returnParameters->SetXDim(280); + //returnParameters->SetYDim(400); + //returnParameters->SetZDim(360); returnParameters->SetVoxelSpacingInCentimeters(0.0075); returnParameters->SetXDim(560); - returnParameters->SetYDim(800); + returnParameters->SetYDim(400); returnParameters->SetZDim(720); return returnParameters; } struct InputParameters { std::string saveFolderPath; std::string identifyer; std::string exePath; std::string probePath; bool verbose; }; InputParameters parseInput(int argc, char* argv[]) { MITK_INFO << "Paring arguments..."; mitkCommandLineParser parser; // set general information parser.setCategory("MITK-Photoacoustics"); parser.setTitle("Mitk Tissue Batch Generator"); parser.setDescription("Creates in silico tissue in batch processing and automatically calculates fluence values for the central slice of the volume."); parser.setContributor("Computer Assisted Medical Interventions, DKFZ"); // how should arguments be prefixed parser.setArgumentPrefix("--", "-"); // add each argument, unless specified otherwise each argument is optional // see mitkCommandLineParser::addArgument for more information parser.beginGroup("Required parameters"); parser.addArgument( "savePath", "s", mitkCommandLineParser::InputDirectory, "Input save folder (directory)", "input save folder", us::Any(), false); parser.addArgument( "mitkMcxyz", "m", mitkCommandLineParser::OutputFile, "MitkMcxyz binary (file)", "path to the MitkMcxyz binary", us::Any(), false); parser.endGroup(); parser.beginGroup("Optional parameters"); parser.addArgument( "probe", "p", mitkCommandLineParser::OutputFile, "xml probe file (file)", "file to the definition of the used probe (*.xml)", us::Any()); parser.addArgument( "verbose", "v", mitkCommandLineParser::Bool, "Verbose Output", "Whether to produce verbose, or rather debug output"); parser.addArgument( "identifyer", "i", mitkCommandLineParser::String, "Generator identifyer (string)", "A unique identifyer for the calculation instance"); InputParameters input; std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size() == 0) exit(-1); if (parsedArgs.count("verbose")) { MITK_INFO << "verbose"; input.verbose = us::any_cast(parsedArgs["verbose"]); } else { input.verbose = false; } if (parsedArgs.count("savePath")) { MITK_INFO << "savePath"; input.saveFolderPath = us::any_cast(parsedArgs["savePath"]); } if (parsedArgs.count("mitkMcxyz")) { MITK_INFO << "mitkMcxyz"; input.exePath = us::any_cast(parsedArgs["mitkMcxyz"]); } if (parsedArgs.count("probe")) { MITK_INFO << "probe"; input.probePath = us::any_cast(parsedArgs["probe"]); } if (parsedArgs.count("identifyer")) { MITK_INFO << "identifyer"; input.identifyer = us::any_cast(parsedArgs["identifyer"]); } else { MITK_INFO << "generating identifyer"; auto uid = mitk::UIDGenerator("", 8); input.identifyer = uid.GetUID(); } MITK_INFO << "Paring arguments...[Done]"; return input; } int main(int argc, char * argv[]) { auto input = parseInput(argc, argv); - double absorptions[10] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19}; + double absorptions[4] = { 2, 4, 7, 10 }; unsigned int iterationNumber = 0; - for(;iterationNumber<10; iterationNumber++) + for (; iterationNumber < 4; iterationNumber++) { - - auto parameters = CreatePhantom_08_03_18_Parameters(); - parameters->SetMinVesselAbsorption(absorptions[iterationNumber]); - parameters->SetMaxVesselAbsorption(absorptions[iterationNumber]); - MITK_INFO(input.verbose) << "Generating tissue.."; - auto resultTissue = PhantomTissueGenerator::GeneratePhantomData(parameters); - MITK_INFO(input.verbose) << "Generating tissue..[Done]"; - - auto inputfolder = std::string(input.saveFolderPath + "input/"); - auto outputfolder = std::string(input.saveFolderPath + "output/"); - if (!itksys::SystemTools::FileIsDirectory(inputfolder)) - { - itksys::SystemTools::MakeDirectory(inputfolder); - } - if (!itksys::SystemTools::FileIsDirectory(outputfolder)) - { - itksys::SystemTools::MakeDirectory(outputfolder); - } - - std::string savePath = input.saveFolderPath + "input/Phantom_" + input.identifyer + - "_" + std::to_string(iterationNumber) + ".nrrd"; - mitk::IOUtil::Save(resultTissue->ConvertToMitkImage(), savePath); - std::string outputPath = input.saveFolderPath + "output/Phantom_" + input.identifyer + - "_" + std::to_string(iterationNumber) + "/"; - - if (!itksys::SystemTools::FileIsDirectory(outputPath)) - { - itksys::SystemTools::MakeDirectory(outputPath); - } - - outputPath = outputPath + "Fluence_Phantom_" + input.identifyer + "_" + std::to_string(iterationNumber); - - MITK_INFO(input.verbose) << "Simulating fluence.."; - - int result = -4; - if(!input.probePath.empty()) - result = std::system(std::string(input.exePath + " -i " + savePath + " -o " + - (outputPath + ".nrrd") + - " -yo " + "0" + " -p " + input.probePath + - " -n 50000").c_str()); - else - result = std::system(std::string(input.exePath + " -i " + savePath + " -o " + - (outputPath + ".nrrd") + - " -yo " + "0" + " -n 50000").c_str()); - - MITK_INFO << result; - MITK_INFO(input.verbose) << "Simulating fluence..[Done]"; + auto parameters = CreatePhantom_08_03_18_Parameters(); + parameters->SetMinVesselAbsorption(absorptions[iterationNumber]); + parameters->SetMaxVesselAbsorption(absorptions[iterationNumber]); + MITK_INFO(input.verbose) << "Generating tissue.."; + auto resultTissue = PhantomTissueGenerator::GeneratePhantomData(parameters); + MITK_INFO(input.verbose) << "Generating tissue..[Done]"; + + auto inputfolder = std::string(input.saveFolderPath + "input/"); + auto outputfolder = std::string(input.saveFolderPath + "output/"); + if (!itksys::SystemTools::FileIsDirectory(inputfolder)) + { + itksys::SystemTools::MakeDirectory(inputfolder); + } + if (!itksys::SystemTools::FileIsDirectory(outputfolder)) + { + itksys::SystemTools::MakeDirectory(outputfolder); + } + + std::string savePath = input.saveFolderPath + "input/Phantom_" + input.identifyer + + "_" + std::to_string(iterationNumber) + ".nrrd"; + mitk::IOUtil::Save(resultTissue->ConvertToMitkImage(), savePath); + std::string outputPath = input.saveFolderPath + "output/Phantom_" + input.identifyer + + "_" + std::to_string(iterationNumber) + "/"; + + resultTissue = nullptr; + + if (!itksys::SystemTools::FileIsDirectory(outputPath)) + { + itksys::SystemTools::MakeDirectory(outputPath); + } + + outputPath = outputPath + "Fluence_Phantom_" + input.identifyer + "_" + std::to_string(iterationNumber); + + MITK_INFO(input.verbose) << "Simulating fluence.."; + + int result = -4; + + result = std::system(std::string(input.exePath + " -i " + savePath + " -o " + + (outputPath + "_low_res.nrrd") + + " -yo " + "0" + " -p " + input.probePath + + " -n 10000000").c_str()); + + result = std::system(std::string(input.exePath + " -i " + savePath + " -o " + + (outputPath + "_mid_res.nrrd") + + " -yo " + "0" + " -p " + input.probePath + + " -n 200000000").c_str()); + + MITK_INFO << result; + MITK_INFO(input.verbose) << "Simulating fluence..[Done]"; } - } diff --git a/Modules/PhotoacousticsLib/include/mitkPAVolume.h b/Modules/PhotoacousticsLib/include/mitkPAVolume.h index 9a6f9c9b59..e6f60707a6 100644 --- a/Modules/PhotoacousticsLib/include/mitkPAVolume.h +++ b/Modules/PhotoacousticsLib/include/mitkPAVolume.h @@ -1,149 +1,149 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKPHOTOACOUSTIC3dVOLUME_H #define MITKPHOTOACOUSTIC3dVOLUME_H #include "MitkPhotoacousticsLibExports.h" //Includes for smart pointer usage #include #include namespace mitk { namespace pa { /** * @brief The Volume class is designed to encapsulate volumetric information and to provide convenience methods * for data access and image conversions. */ class MITKPHOTOACOUSTICSLIB_EXPORT Volume : public itk::LightObject { public: mitkClassMacroItkParent(Volume, itk::LightObject); /** *@brief returns smartpointer reference to a new instance of this objects. * The given data array will be freed upon calling this constructor. *@param data *@param xDim *@param yDim *@param zDim *@return smartpointer reference to a new instance of this object */ static Volume::Pointer New(double* data, unsigned int xDim, unsigned int yDim, unsigned int zDim, double spacing); static Volume::Pointer New(mitk::Image::Pointer image); /** * @brief GetData. Returns data at wanted position. For performance reasons, this method will not check, * if the specified position it within the array. Please use the GetXDim(), GetYDim() and GetZDim() methods * to check for yourself if necessary. * * @param x * @param y * @param z * @return the data contained within the data array held by this Volume at * positon x|y|z. */ double GetData(unsigned int x, unsigned int y, unsigned int z); /** * Returns a const reference to the data encapsuled by this class. */ double* GetData() const; /** * @brief SetData * @param data * @param x * @param y * @param z */ void SetData(double data, unsigned int x, unsigned int y, unsigned int z); /** * @brief GetXDim * @return size of x dimension of this Volume */ unsigned int GetXDim(); /** * @brief GetYDim * @return size of y dimension of this Volume */ unsigned int GetYDim(); /** * @brief GetZDim * @return size of z dimension of this Volume */ unsigned int GetZDim(); /** *@brief returns the Volume instance as an mitk image */ Image::Pointer AsMitkImage(); /** * @brief DeepCopy * @return a deep copy of this Volume. the old volume remains intact and memory is NOT shared * between the objects. */ Volume::Pointer DeepCopy(); /** *@brief convenience method to enable consistent access to the dat array *@return a 1d index from 3d pixel coordinates */ - int GetIndex(unsigned int x, unsigned int y, unsigned int z); + long long GetIndex(unsigned int x, unsigned int y, unsigned int z); double GetSpacing(); void SetSpacing(double spacing); protected: /** * @brief Initialize initializes this volume with the given pointer to the data array. * It is assumed, that the array is of dimension xDim|yDim|zDim. * The Photoacoustic3DVolume will handle memory management of the array and delete it on * constructor call. * * @param data a pointer to the data array * @param xDim x dimension of the data * @param yDim y dimension of the data * @param zDim z dimension of the data */ Volume(double* data, unsigned int xDim, unsigned int yDim, unsigned int zDim, double spacing); Volume(mitk::Image::Pointer image); virtual ~Volume(); const int NUMBER_OF_SPATIAL_DIMENSIONS = 3; Image::Pointer m_InternalMitkImage; // this data is kept to enable fast access unsigned int m_XDim; unsigned int m_YDim; unsigned int m_ZDim; double* m_FastAccessDataPointer; }; } } #endif // MITKPHOTOACOUSTIC3dVOLUME_H diff --git a/Modules/PhotoacousticsLib/src/Domain/Volume/mitkPAInSilicoTissueVolume.cpp b/Modules/PhotoacousticsLib/src/Domain/Volume/mitkPAInSilicoTissueVolume.cpp index 301a5e91f1..cc7b081434 100644 --- a/Modules/PhotoacousticsLib/src/Domain/Volume/mitkPAInSilicoTissueVolume.cpp +++ b/Modules/PhotoacousticsLib/src/Domain/Volume/mitkPAInSilicoTissueVolume.cpp @@ -1,388 +1,387 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include mitk::pa::InSilicoTissueVolume::InSilicoTissueVolume(TissueGeneratorParameters::Pointer parameters, std::mt19937* rng) { { unsigned int xDim = parameters->GetXDim(); unsigned int yDim = parameters->GetYDim(); unsigned int zDim = parameters->GetZDim(); - m_TDim = 4; + m_TDim = 3; unsigned int size = xDim * yDim * zDim; double* absorptionArray = new double[size]; double* scatteringArray = new double[size]; double* anisotropyArray = new double[size]; - double* segmentationArray = new double[size]; + //double* segmentationArray = new double[size]; m_InitialBackgroundAbsorption = (parameters->GetMinBackgroundAbsorption() + parameters->GetMaxBackgroundAbsorption()) / 2; m_Rng = rng; for (unsigned int index = 0; index < size; index++) { absorptionArray[index] = m_InitialBackgroundAbsorption; scatteringArray[index] = parameters->GetBackgroundScattering(); anisotropyArray[index] = parameters->GetBackgroundAnisotropy(); - segmentationArray[index] = SegmentationType::BACKGROUND; + //segmentationArray[index] = SegmentationType::BACKGROUND; } m_AbsorptionVolume = Volume::New(absorptionArray, xDim, yDim, zDim, parameters->GetVoxelSpacingInCentimeters()); m_ScatteringVolume = Volume::New(scatteringArray, xDim, yDim, zDim, parameters->GetVoxelSpacingInCentimeters()); m_AnisotropyVolume = Volume::New(anisotropyArray, xDim, yDim, zDim, parameters->GetVoxelSpacingInCentimeters()); - m_SegmentationVolume = Volume::New(segmentationArray, xDim, yDim, zDim, parameters->GetVoxelSpacingInCentimeters()); + //m_SegmentationVolume = Volume::New(segmentationArray, xDim, yDim, zDim, parameters->GetVoxelSpacingInCentimeters()); } m_TissueParameters = parameters; m_PropertyList = mitk::PropertyList::New(); UpdatePropertyList(); } void mitk::pa::InSilicoTissueVolume::UpdatePropertyList() { //Set properties AddIntProperty("mcflag", m_TissueParameters->GetMCflag()); AddIntProperty("launchflag", m_TissueParameters->GetMCLaunchflag()); AddIntProperty("boundaryflag", m_TissueParameters->GetMCBoundaryflag()); AddDoubleProperty("launchPointX", m_TissueParameters->GetMCLaunchPointX()); AddDoubleProperty("launchPointY", m_TissueParameters->GetMCLaunchPointY()); AddDoubleProperty("launchPointZ", m_TissueParameters->GetMCLaunchPointZ()); AddDoubleProperty("focusPointX", m_TissueParameters->GetMCFocusPointX()); AddDoubleProperty("focusPointY", m_TissueParameters->GetMCFocusPointY()); AddDoubleProperty("focusPointZ", m_TissueParameters->GetMCFocusPointZ()); AddDoubleProperty("trajectoryVectorX", m_TissueParameters->GetMCTrajectoryVectorX()); AddDoubleProperty("trajectoryVectorY", m_TissueParameters->GetMCTrajectoryVectorY()); AddDoubleProperty("trajectoryVectorZ", m_TissueParameters->GetMCTrajectoryVectorZ()); AddDoubleProperty("radius", m_TissueParameters->GetMCRadius()); AddDoubleProperty("waist", m_TissueParameters->GetMCWaist()); AddDoubleProperty("partialVolume", m_TissueParameters->GetDoPartialVolume()); AddDoubleProperty("standardTissueAbsorptionMin", m_TissueParameters->GetMinBackgroundAbsorption()); AddDoubleProperty("standardTissueAbsorptionMax", m_TissueParameters->GetMaxBackgroundAbsorption()); AddDoubleProperty("standardTissueScattering", m_TissueParameters->GetBackgroundScattering()); AddDoubleProperty("standardTissueAnisotropy", m_TissueParameters->GetBackgroundAnisotropy()); AddDoubleProperty("airThickness", m_TissueParameters->GetAirThicknessInMillimeters()); AddDoubleProperty("skinThickness", m_TissueParameters->GetSkinThicknessInMillimeters()); } mitk::pa::InSilicoTissueVolume::InSilicoTissueVolume( Volume::Pointer absorptionVolume, Volume::Pointer scatteringVolume, Volume::Pointer anisotropyVolume, Volume::Pointer segmentationVolume, TissueGeneratorParameters::Pointer tissueParameters, mitk::PropertyList::Pointer propertyList) { m_AbsorptionVolume = absorptionVolume; m_ScatteringVolume = scatteringVolume; m_AnisotropyVolume = anisotropyVolume; - m_SegmentationVolume = segmentationVolume; + //m_SegmentationVolume = segmentationVolume; m_TissueParameters = tissueParameters; m_PropertyList = propertyList; if (m_SegmentationVolume.IsNotNull()) m_TDim = 4; else m_TDim = 3; } double mitk::pa::InSilicoTissueVolume::GetSpacing() { return m_AbsorptionVolume->GetSpacing(); } void mitk::pa::InSilicoTissueVolume::SetSpacing(double spacing) { m_AbsorptionVolume->SetSpacing(spacing); m_ScatteringVolume->SetSpacing(spacing); m_AnisotropyVolume->SetSpacing(spacing); - m_SegmentationVolume->SetSpacing(spacing); + //m_SegmentationVolume->SetSpacing(spacing); } void mitk::pa::InSilicoTissueVolume::AddDoubleProperty(std::string label, double value) { m_PropertyList->SetDoubleProperty(label.c_str(), value); mitk::CoreServices::GetPropertyPersistence()->AddInfo(mitk::PropertyPersistenceInfo::New(label)); } void mitk::pa::InSilicoTissueVolume::AddIntProperty(std::string label, int value) { m_PropertyList->SetIntProperty(label.c_str(), value); mitk::CoreServices::GetPropertyPersistence()->AddInfo(mitk::PropertyPersistenceInfo::New(label)); } mitk::Image::Pointer mitk::pa::InSilicoTissueVolume::ConvertToMitkImage() { mitk::Image::Pointer resultImage = mitk::Image::New(); mitk::PixelType TPixel = mitk::MakeScalarPixelType(); unsigned int* dimensionsOfImage = new unsigned int[4]; // Copy dimensions dimensionsOfImage[0] = m_TissueParameters->GetYDim(); dimensionsOfImage[1] = m_TissueParameters->GetXDim(); dimensionsOfImage[2] = m_TissueParameters->GetZDim(); dimensionsOfImage[3] = m_TDim; resultImage->Initialize(TPixel, 4, dimensionsOfImage, 1); mitk::Vector3D spacing; spacing.Fill(m_TissueParameters->GetVoxelSpacingInCentimeters()); resultImage->SetSpacing(spacing); resultImage->SetImportVolume(m_AbsorptionVolume->GetData(), 0, 0, mitk::Image::CopyMemory); resultImage->SetImportVolume(m_ScatteringVolume->GetData(), 1, 0, mitk::Image::CopyMemory); resultImage->SetImportVolume(m_AnisotropyVolume->GetData(), 2, 0, mitk::Image::CopyMemory); - resultImage->SetImportVolume(m_SegmentationVolume->GetData(), 3, 0, mitk::Image::CopyMemory); + //resultImage->SetImportVolume(m_SegmentationVolume->GetData(), 3, 0, mitk::Image::CopyMemory); resultImage->SetPropertyList(m_PropertyList); return resultImage; } mitk::pa::InSilicoTissueVolume::Pointer mitk::pa::InSilicoTissueVolume::New( Volume::Pointer absorptionVolume, Volume::Pointer scatteringVolume, Volume::Pointer anisotropyVolume, Volume::Pointer segmentationVolume, TissueGeneratorParameters::Pointer tissueParameters, mitk::PropertyList::Pointer propertyList) { InSilicoTissueVolume::Pointer smartPtr = new InSilicoTissueVolume( absorptionVolume, scatteringVolume, anisotropyVolume, segmentationVolume, tissueParameters, propertyList); smartPtr->UnRegister(); return smartPtr; } mitk::pa::InSilicoTissueVolume::~InSilicoTissueVolume() { m_AbsorptionVolume = nullptr; m_ScatteringVolume = nullptr; m_AnisotropyVolume = nullptr; m_SegmentationVolume = nullptr; m_TissueParameters = nullptr; m_PropertyList = nullptr; } void mitk::pa::InSilicoTissueVolume::SetVolumeValues(int x, int y, int z, double absorption, double scattering, double anisotropy) { if (IsInsideVolume(x, y, z)) { m_AbsorptionVolume->SetData(absorption, x, y, z); m_ScatteringVolume->SetData(scattering, x, y, z); m_AnisotropyVolume->SetData(anisotropy, x, y, z); } } void mitk::pa::InSilicoTissueVolume::SetVolumeValues(int x, int y, int z, double absorption, double scattering, double anisotropy, SegmentationType segmentType) { if (IsInsideVolume(x, y, z)) { m_AbsorptionVolume->SetData(absorption, x, y, z); m_ScatteringVolume->SetData(scattering, x, y, z); m_AnisotropyVolume->SetData(anisotropy, x, y, z); - m_SegmentationVolume->SetData(segmentType, x, y, z); + //m_SegmentationVolume->SetData(segmentType, x, y, z); } } bool mitk::pa::InSilicoTissueVolume::IsInsideVolume(int x, int y, int z) { return x >= 0 && x < m_TissueParameters->GetXDim() && y >= 0 && y < m_TissueParameters->GetYDim() && z >= 0 && z < m_TissueParameters->GetZDim(); } mitk::pa::Volume::Pointer mitk::pa::InSilicoTissueVolume::GetAbsorptionVolume() { return m_AbsorptionVolume; } mitk::pa::Volume::Pointer mitk::pa::InSilicoTissueVolume::GetSegmentationVolume() { return m_SegmentationVolume; } void mitk::pa::InSilicoTissueVolume::FinalizeVolume() { AddSkinAndAirLayers(); // If specified, randomize all tissue parameters if (m_TissueParameters->GetRandomizePhysicalProperties()) { RandomizeTissueCoefficients(m_TissueParameters->GetUseRngSeed(), m_TissueParameters->GetRngSeed(), m_TissueParameters->GetRandomizePhysicalPropertiesPercentage()); } unsigned int xDim = m_TissueParameters->GetXDim(); unsigned int yDim = m_TissueParameters->GetYDim(); unsigned int zDim = m_TissueParameters->GetZDim(); std::uniform_real_distribution randomBackgroundAbsorptionDistribution( - m_TissueParameters->GetMinBackgroundAbsorption(), m_TissueParameters->GetMaxBackgroundAbsorption()); - + m_TissueParameters->GetMinBackgroundAbsorption(), m_TissueParameters->GetMaxBackgroundAbsorption()); for (unsigned int z = 0; z < zDim; z++) { - for (unsigned int y = 0; y < yDim; y++) + for (unsigned int y = 0; y < yDim; y++) + { + for (unsigned int x = 0; x < xDim; x++) { - for (unsigned int x = 0; x < xDim; x++) - { - if(fabs(m_AbsorptionVolume->GetData(x, y, z)-m_InitialBackgroundAbsorption) < mitk::eps) - { - m_AbsorptionVolume->SetData(randomBackgroundAbsorptionDistribution(*m_Rng), x, y, z); - } - } + if (fabs(m_AbsorptionVolume->GetData(x, y, z) - m_InitialBackgroundAbsorption) < mitk::eps) + { + m_AbsorptionVolume->SetData(randomBackgroundAbsorptionDistribution(*m_Rng), x, y, z); + } } + } } } void mitk::pa::InSilicoTissueVolume::AddSkinAndAirLayers() { //Calculate the index location according to thickness in cm double airvoxel = (m_TissueParameters->GetAirThicknessInMillimeters() / m_TissueParameters->GetVoxelSpacingInCentimeters()) / 10; double skinvoxel = airvoxel + (m_TissueParameters->GetSkinThicknessInMillimeters() / m_TissueParameters->GetVoxelSpacingInCentimeters()) / 10; for (int y = 0; y < m_TissueParameters->GetYDim(); y++) { for (int x = 0; x < m_TissueParameters->GetXDim(); x++) { // Add air from index 0 to airvoxel if (m_TissueParameters->GetAirThicknessInMillimeters() > mitk::eps) { FillZLayer(x, y, 0, airvoxel, m_TissueParameters->GetAirAbsorption(), m_TissueParameters->GetAirScattering(), m_TissueParameters->GetAirAnisotropy(), SegmentationType::AIR); } //Add skin from index airvoxel to skinvoxel if (m_TissueParameters->GetSkinThicknessInMillimeters() > mitk::eps) { FillZLayer(x, y, airvoxel, skinvoxel, m_TissueParameters->GetSkinAbsorption(), m_TissueParameters->GetSkinScattering(), m_TissueParameters->GetSkinAnisotropy(), SegmentationType::SKIN); } } } } void mitk::pa::InSilicoTissueVolume::FillZLayer(int x, int y, double startIdx, double endIdx, double absorption, double scattering, double anisotropy, SegmentationType segmentationType) { for (int z = startIdx; z < endIdx; z++) { if (IsInsideVolume(x, y, z)) { if (endIdx - z < 1) { //Simulate partial volume effects m_AbsorptionVolume->SetData((1 - (endIdx - z)) * m_AbsorptionVolume->GetData(x, y, z) + (endIdx - z) * absorption, x, y, z); m_ScatteringVolume->SetData((1 - (endIdx - z)) * m_ScatteringVolume->GetData(x, y, z) + (endIdx - z) * scattering, x, y, z); m_AnisotropyVolume->SetData((1 - (endIdx - z)) * m_AnisotropyVolume->GetData(x, y, z) + (endIdx - z) * anisotropy, x, y, z); if (endIdx - z > 0.5) { //Only put the segmentation label if more than half of the partial volume is the wanted tissue type - m_SegmentationVolume->SetData(segmentationType, x, y, z); + //m_SegmentationVolume->SetData(segmentationType, x, y, z); } } else { m_AbsorptionVolume->SetData(absorption, x, y, z); m_ScatteringVolume->SetData(scattering, x, y, z); m_AnisotropyVolume->SetData(anisotropy, x, y, z); - m_SegmentationVolume->SetData(segmentationType, x, y, z); + //m_SegmentationVolume->SetData(segmentationType, x, y, z); } } } } void mitk::pa::InSilicoTissueVolume::RandomizeTissueCoefficients(long rngSeed, bool useRngSeed, double percentage) { std::mt19937 rng; std::random_device randomDevice; if (useRngSeed) { rng.seed(rngSeed); } else { if (randomDevice.entropy() > 0.1) { rng.seed(randomDevice()); } else { rng.seed(std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count()); } } std::normal_distribution<> percentageDistribution(1, percentage / 100); for (int y = 0; y < m_TissueParameters->GetYDim(); y++) { for (int x = 0; x < m_TissueParameters->GetXDim(); x++) { for (int z = 0; z < m_TissueParameters->GetZDim(); z++) { m_AbsorptionVolume->SetData(m_AbsorptionVolume->GetData(x, y, z) * percentageDistribution(rng), x, y, z); m_ScatteringVolume->SetData(m_ScatteringVolume->GetData(x, y, z) * percentageDistribution(rng), x, y, z); } } } } mitk::pa::Volume::Pointer mitk::pa::InSilicoTissueVolume::GetScatteringVolume() { return m_ScatteringVolume; } mitk::pa::Volume::Pointer mitk::pa::InSilicoTissueVolume::GetAnisotropyVolume() { return m_AnisotropyVolume; } void mitk::pa::InSilicoTissueVolume::SetAbsorptionVolume(Volume::Pointer volume) { m_AbsorptionVolume = volume; } void mitk::pa::InSilicoTissueVolume::SetScatteringVolume(Volume::Pointer volume) { m_ScatteringVolume = volume; } void mitk::pa::InSilicoTissueVolume::SetAnisotropyVolume(Volume::Pointer volume) { m_AnisotropyVolume = volume; } void mitk::pa::InSilicoTissueVolume::SetSegmentationVolume(Volume::Pointer volume) { - m_SegmentationVolume = volume; + //m_SegmentationVolume = volume; } diff --git a/Modules/PhotoacousticsLib/src/Domain/Volume/mitkPAVolume.cpp b/Modules/PhotoacousticsLib/src/Domain/Volume/mitkPAVolume.cpp index 992a9ce378..bad7cfa29d 100644 --- a/Modules/PhotoacousticsLib/src/Domain/Volume/mitkPAVolume.cpp +++ b/Modules/PhotoacousticsLib/src/Domain/Volume/mitkPAVolume.cpp @@ -1,153 +1,153 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPAVolume.h" #include #include #include mitk::pa::Volume::Volume(double* data, unsigned int xDim, unsigned int yDim, unsigned int zDim, double spacing) { MITK_INFO << "Initialized by data*"; if (data == nullptr) mitkThrow() << "You may not initialize a mitk::Volume with a nullptr"; m_InternalMitkImage = mitk::Image::New(); unsigned int* dimensions = new unsigned int[NUMBER_OF_SPATIAL_DIMENSIONS]; dimensions[0] = yDim; dimensions[1] = xDim; dimensions[2] = zDim; m_XDim = xDim; m_YDim = yDim; m_ZDim = zDim; mitk::PixelType pixelType = mitk::MakeScalarPixelType(); m_InternalMitkImage->Initialize(pixelType, NUMBER_OF_SPATIAL_DIMENSIONS, dimensions); m_InternalMitkImage->SetImportVolume(data, Image::ImportMemoryManagementType::CopyMemory); SetSpacing(spacing); m_FastAccessDataPointer = GetData(); delete data; } mitk::pa::Volume::Volume(mitk::Image::Pointer image) { MITK_INFO << "Initialized by mitk::Image"; if (image.IsNull()) mitkThrow() << "You may not initialize a mitk::Volume with a null reference to an mitk image"; unsigned int* dimensions = image->GetDimensions(); m_YDim = dimensions[0]; m_XDim = dimensions[1]; m_ZDim = dimensions[2]; m_InternalMitkImage = image; m_FastAccessDataPointer = GetData(); } double mitk::pa::Volume::GetSpacing() { return m_InternalMitkImage->GetGeometry()->GetSpacing()[0]; } void mitk::pa::Volume::SetSpacing(double spacing) { const mitk::ScalarType spacingArray[]{ spacing, spacing, spacing }; m_InternalMitkImage->SetSpacing(spacingArray); } mitk::pa::Volume::~Volume() { m_InternalMitkImage = nullptr; } mitk::pa::Volume::Pointer mitk::pa::Volume::New(double* data, unsigned int xDim, unsigned int yDim, unsigned int zDim, double spacing) { mitk::pa::Volume::Pointer smartPtr = new mitk::pa::Volume(data, xDim, yDim, zDim, spacing); smartPtr->UnRegister(); return smartPtr; } mitk::pa::Volume::Pointer mitk::pa::Volume::New(mitk::Image::Pointer image) { mitk::pa::Volume::Pointer smartPtr = new mitk::pa::Volume(image); smartPtr->UnRegister(); return smartPtr; } mitk::Image::Pointer mitk::pa::Volume::AsMitkImage() { return m_InternalMitkImage; } mitk::pa::Volume::Pointer mitk::pa::Volume::DeepCopy() { long length = GetXDim()*GetYDim()*GetZDim(); double* data = new double[length]; memcpy(data, GetData(), length * sizeof(double)); return mitk::pa::Volume::New(data, GetXDim(), GetYDim(), GetZDim(), GetSpacing()); } double mitk::pa::Volume::GetData(unsigned int x, unsigned int y, unsigned int z) { return m_FastAccessDataPointer[GetIndex(x, y, z)]; } void mitk::pa::Volume::SetData(double data, unsigned int x, unsigned int y, unsigned int z) { m_FastAccessDataPointer[GetIndex(x, y, z)] = data; } unsigned int mitk::pa::Volume::GetXDim() { return m_XDim; } unsigned int mitk::pa::Volume::GetYDim() { return m_YDim; } unsigned int mitk::pa::Volume::GetZDim() { return m_ZDim; } double* mitk::pa::Volume::GetData() const { mitk::ImageWriteAccessor imgRead(m_InternalMitkImage, m_InternalMitkImage->GetVolumeData()); return (double*)imgRead.GetData(); } -int mitk::pa::Volume::GetIndex(unsigned int x, unsigned int y, unsigned int z) +long long mitk::pa::Volume::GetIndex(unsigned int x, unsigned int y, unsigned int z) { #ifdef _DEBUG if (x < 0 || x >(GetXDim() - 1) || y < 0 || y >(GetYDim() - 1) || z < 0 || z >(GetZDim() - 1)) { MITK_ERROR << "Index out of bounds at " << x << "|" << y << "|" << z; mitkThrow() << "Index out of bounds exception!"; } #endif - return z * m_XDim * m_YDim + x * m_YDim + y; + return ((long long)z) * m_XDim * m_YDim + ((long long)x) * m_YDim + ((long long)y); } diff --git a/Modules/PhotoacousticsLib/src/Generator/mitkPAPhantomTissueGenerator.cpp b/Modules/PhotoacousticsLib/src/Generator/mitkPAPhantomTissueGenerator.cpp index 5b264c08ae..167e30b0bb 100644 --- a/Modules/PhotoacousticsLib/src/Generator/mitkPAPhantomTissueGenerator.cpp +++ b/Modules/PhotoacousticsLib/src/Generator/mitkPAPhantomTissueGenerator.cpp @@ -1,158 +1,157 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPAPhantomTissueGenerator.h" #include "mitkPAVector.h" #include "mitkPAVolumeManipulator.h" mitk::pa::InSilicoTissueVolume::Pointer mitk::pa::PhantomTissueGenerator::GeneratePhantomData( TissueGeneratorParameters::Pointer parameters) { MITK_DEBUG << "Initializing Empty Volume"; const double RESAMPLING_FACTOR = 2; if (parameters->GetDoPartialVolume()) { parameters->SetXDim(parameters->GetXDim() * RESAMPLING_FACTOR); parameters->SetYDim(parameters->GetYDim() * RESAMPLING_FACTOR); parameters->SetZDim(parameters->GetZDim() * RESAMPLING_FACTOR); parameters->SetVesselBifurcationFrequency(parameters->GetVesselBifurcationFrequency() * RESAMPLING_FACTOR); parameters->SetVoxelSpacingInCentimeters(parameters->GetVoxelSpacingInCentimeters() / RESAMPLING_FACTOR); } parameters->SetVesselBifurcationFrequency(10000); std::mt19937 randomNumberGenerator; std::random_device randomDevice; if (parameters->GetUseRngSeed()) { randomNumberGenerator.seed(parameters->GetRngSeed()); } else { if (randomDevice.entropy() > 0.1) { randomNumberGenerator.seed(randomDevice()); } else { randomNumberGenerator.seed(std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count()); } } auto generatedVolume = mitk::pa::InSilicoTissueVolume::New(parameters, &randomNumberGenerator); const unsigned int NUMER_OF_VESSELS = 5; const double START_DEPTH_IN_CM = 2.10; const double START_X_IN_CM = 0.76; - const double RADIUS_IN_MM = 0.6125; + const double RADIUS_IN_MM = 0.5; const double INCREMENT_XZ_IN_CM = 0.50; double ABSORPTION_PER_CM = parameters->GetMinVesselAbsorption(); generatedVolume->AddIntProperty("numberOfVessels", NUMER_OF_VESSELS); generatedVolume->AddIntProperty("bifurcationFrequency", parameters->GetVesselBifurcationFrequency()); for (unsigned int vesselNumber = 0; vesselNumber < NUMER_OF_VESSELS; vesselNumber++) { Vector::Pointer initialPosition = Vector::New(); Vector::Pointer initialDirection = Vector::New(); double initialRadius = RADIUS_IN_MM / parameters->GetVoxelSpacingInCentimeters() / 10; std::stringstream radiusString; radiusString << "vessel_" << vesselNumber + 1 << "_radius"; generatedVolume->AddDoubleProperty(radiusString.str(), initialRadius); double absorptionCoefficient = ABSORPTION_PER_CM; std::stringstream absorptionString; absorptionString << "vessel_" << vesselNumber + 1 << "_absorption"; generatedVolume->AddDoubleProperty(absorptionString.str(), absorptionCoefficient); double bendingFactor = 0; std::stringstream bendingString; bendingString << "vessel_" << vesselNumber + 1 << "_bendingFactor"; generatedVolume->AddDoubleProperty(bendingString.str(), bendingFactor); double vesselScattering = 15; std::stringstream scatteringString; scatteringString << "vessel_" << vesselNumber + 1 << "_scattering"; generatedVolume->AddDoubleProperty(scatteringString.str(), vesselScattering); double vesselAnisotropy = 0.9; std::stringstream anisotropyString; anisotropyString << "vessel_" << vesselNumber + 1 << "_anisotropy"; generatedVolume->AddDoubleProperty(anisotropyString.str(), vesselAnisotropy); /*The vessel tree shall start at one of the 4 sides of the volume. * The vessels will always be completely contained in the volume * when starting to meander. * They will meander in a direction perpendicular to the * plane they started from (within the limits of the * DIRECTION_VECTOR_INITIAL_VARIANCE) */ double zposition = (START_DEPTH_IN_CM + (vesselNumber*INCREMENT_XZ_IN_CM)) / parameters->GetVoxelSpacingInCentimeters(); double xposition = (START_X_IN_CM + (vesselNumber*INCREMENT_XZ_IN_CM)) / parameters->GetVoxelSpacingInCentimeters(); - initialPosition->Randomize(xposition, xposition, 0, 0, zposition, zposition, &randomNumberGenerator); initialDirection->Randomize(0, 0, 1, 1, 0, 0, &randomNumberGenerator); initialDirection->Normalize(); MITK_INFO << initialPosition->GetElement(0) << " | " << initialPosition->GetElement(1) << " | " << initialPosition->GetElement(2); MITK_INFO << initialDirection->GetElement(0) << " | " << initialDirection->GetElement(1) << " | " << initialDirection->GetElement(2); VesselProperties::Pointer vesselParams = VesselProperties::New(); vesselParams->SetDirectionVector(initialDirection); vesselParams->SetPositionVector(initialPosition); vesselParams->SetRadiusInVoxel(initialRadius); vesselParams->SetAbsorptionCoefficient(absorptionCoefficient); vesselParams->SetScatteringCoefficient(vesselScattering); vesselParams->SetAnisotopyCoefficient(vesselAnisotropy); vesselParams->SetBifurcationFrequency(parameters->GetVesselBifurcationFrequency()); vesselParams->SetDoPartialVolume(parameters->GetDoPartialVolume()); VesselTree::Pointer vesselTree = VesselTree::New(vesselParams); while (!vesselTree->IsFinished()) { vesselTree->Step(generatedVolume, parameters->GetCalculateNewVesselPositionCallback(), bendingFactor, &randomNumberGenerator); } } if (parameters->GetDoPartialVolume()) { VolumeManipulator::RescaleImage(generatedVolume, (1.0 / RESAMPLING_FACTOR)); parameters->SetXDim(parameters->GetXDim() / RESAMPLING_FACTOR); parameters->SetYDim(parameters->GetYDim() / RESAMPLING_FACTOR); parameters->SetZDim(parameters->GetZDim() / RESAMPLING_FACTOR); parameters->SetVesselBifurcationFrequency(parameters->GetVesselBifurcationFrequency() / RESAMPLING_FACTOR); parameters->SetVoxelSpacingInCentimeters(parameters->GetVoxelSpacingInCentimeters() * RESAMPLING_FACTOR); } generatedVolume->FinalizeVolume(); return generatedVolume; } mitk::pa::PhantomTissueGenerator::PhantomTissueGenerator() { } mitk::pa::PhantomTissueGenerator::~PhantomTissueGenerator() { } diff --git a/Modules/PhotoacousticsLib/test/files.cmake b/Modules/PhotoacousticsLib/test/files.cmake index ae1e015083..0796a506a5 100644 --- a/Modules/PhotoacousticsLib/test/files.cmake +++ b/Modules/PhotoacousticsLib/test/files.cmake @@ -1,40 +1,41 @@ set(MODULE_TESTS # IMPORTANT: If you plan to deactivate / comment out a test please write a bug number to the commented out line of code. # # Example: #mitkMyTest #this test is commented out because of bug 12345 # # It is important that the bug is open and that the test will be activated again before the bug is closed. This assures that # no test is forgotten after it was commented out. If there is no bug for your current problem, please add a new one and # mark it as critical. ################## ON THE FENCE TESTS ################################################# # none ################## DISABLED TESTS ##################################################### ################# RUNNING TESTS ####################################################### mitkSlicedVolumeGeneratorTest.cpp mitkPhotoacousticTissueGeneratorTest.cpp mitkPhotoacousticVectorTest.cpp mitkPhotoacoustic3dVolumeTest.cpp mitkPhotoacousticVolumeTest.cpp mitkPhotoacousticVesselTest.cpp mitkPhotoacousticVesselTreeTest.cpp mitkPhotoacousticVesselMeanderStrategyTest.cpp mitkMcxyzXmlTest.cpp mitkPhotoacousticComposedVolumeTest.cpp mitkPhotoacousticNoiseGeneratorTest.cpp mitkPhotoacousticIOTest.cpp mitkMCThreadHandlerTest.cpp mitkSimulationBatchGeneratorTest.cpp mitkPropertyCalculatorTest.cpp + mitkPhotoacousticImageSavingTest.cpp ) set(RESOURCE_FILES pointsource.xml circlesource.xml rectanglesource.xml twopointsources.xml allsources.xml ) diff --git a/Modules/PhotoacousticsLib/test/mitkPhotoacousticImageSavingTest.cpp b/Modules/PhotoacousticsLib/test/mitkPhotoacousticImageSavingTest.cpp new file mode 100644 index 0000000000..eb74325e89 --- /dev/null +++ b/Modules/PhotoacousticsLib/test/mitkPhotoacousticImageSavingTest.cpp @@ -0,0 +1,61 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include + +#include +#include + +class mitkPhotoacousticImageSavingTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkPhotoacousticImageSavingTestSuite); + MITK_TEST(testSaveImagePlainMitk); + CPPUNIT_TEST_SUITE_END(); + +private: + +public: + + void setUp() + { + } + + void testSaveImagePlainMitk() + { + unsigned int x = pow(2, 30); + unsigned long size = x; + + float* data = new float[size]; + for (unsigned long i = 0; i < size; i++) + data[i] = 0; + + mitk::Image::Pointer image = mitk::Image::New(); + mitk::PixelType TPixel = mitk::MakeScalarPixelType(); + unsigned int* dimensionsOfImage = new unsigned int[1]; + dimensionsOfImage[0] = x; + image->Initialize(TPixel, 1, dimensionsOfImage, 1); + image->SetImportVolume(data, 0, 0, mitk::Image::CopyMemory); + + mitk::IOUtil::Save(image, "C:/Users/groehl/Desktop/test.nrrd"); + } + + void tearDown() + { + } +}; + +MITK_TEST_SUITE_REGISTRATION(mitkPhotoacousticImageSaving) diff --git a/Plugins/org.mitk.gui.qt.photoacoustics.simulation/src/internal/PASimulator.cpp b/Plugins/org.mitk.gui.qt.photoacoustics.simulation/src/internal/PASimulator.cpp index c35200cc00..20109b4428 100644 --- a/Plugins/org.mitk.gui.qt.photoacoustics.simulation/src/internal/PASimulator.cpp +++ b/Plugins/org.mitk.gui.qt.photoacoustics.simulation/src/internal/PASimulator.cpp @@ -1,255 +1,256 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "PASimulator.h" // Qt #include #include #include // mitk #include #include #include #include #include const std::string PASimulator::VIEW_ID = "org.mitk.views.pasimulator"; void PASimulator::SetFocus() { m_Controls.pushButtonShowRandomTissue->setFocus(); } void PASimulator::CreateQtPartControl(QWidget *parent) { m_Controls.setupUi(parent); connect(m_Controls.pushButtonShowRandomTissue, SIGNAL(clicked()), this, SLOT(DoImageProcessing())); connect(m_Controls.pushButtonOpenPath, SIGNAL(clicked()), this, SLOT(OpenFolder())); connect(m_Controls.pushButtonOpenBinary, SIGNAL(clicked()), this, SLOT(OpenBinary())); connect(m_Controls.checkBoxGenerateBatch, SIGNAL(clicked()), this, SLOT(UpdateVisibilityOfBatchCreation())); connect(m_Controls.pushButtonAjustWavelength, SIGNAL(clicked()), this, SLOT(UpdateParametersAccordingToWavelength())); connect(m_Controls.checkBoxRngSeed, SIGNAL(clicked()), this, SLOT(ClickedCheckboxFixedSeed())); connect(m_Controls.checkBoxRandomizeParameters, SIGNAL(clicked()), this, SLOT(ClickedRandomizePhysicalParameters())); auto home = std::getenv("HOME"); std::string home_env = ""; if (home != nullptr) { home_env = std::string(home); } else { home = std::getenv("HOMEPATH"); if (home != nullptr) { home_env = std::string(home); } } m_Controls.label_NrrdFilePath->setText(home_env.c_str()); m_PhotoacousticPropertyCalculator = mitk::pa::PropertyCalculator::New(); UpdateVisibilityOfBatchCreation(); ClickedRandomizePhysicalParameters(); ClickedCheckboxFixedSeed(); } void PASimulator::ClickedRandomizePhysicalParameters() { m_Controls.spinboxRandomizeParameters->setEnabled(m_Controls.checkBoxRandomizeParameters->isChecked()); } void PASimulator::ClickedCheckboxFixedSeed() { m_Controls.spinBoxRngSeed->setEnabled(m_Controls.checkBoxRngSeed->isChecked()); } void PASimulator::UpdateParametersAccordingToWavelength() { int wavelength = m_Controls.spinboxWavelength->value(); double bloodOxygenation = m_Controls.spinboxBloodOxygenSaturation->value() / 100; auto result = m_PhotoacousticPropertyCalculator->CalculatePropertyForSpecificWavelength( mitk::pa::PropertyCalculator::TissueType::BLOOD, wavelength, bloodOxygenation); m_Controls.spinboxMaxAbsorption->setValue(result.mua); m_Controls.spinboxMinAbsorption->setValue(result.mua); m_Controls.spinboxBloodVesselScatteringMinimum->setValue(result.mus); m_Controls.spinboxBloodVesselScatteringMaximum->setValue(result.mus); m_Controls.spinboxBloodVesselAnisotropyMinimum->setValue(result.g); m_Controls.spinboxBloodVesselAnisotropyMaximum->setValue(result.g); result = m_PhotoacousticPropertyCalculator->CalculatePropertyForSpecificWavelength( mitk::pa::PropertyCalculator::TissueType::EPIDERMIS, wavelength, bloodOxygenation); m_Controls.spinboxSkinAbsorption->setValue(result.mua); m_Controls.spinboxSkinScattering->setValue(result.mus); m_Controls.spinboxSkinAnisotropy->setValue(result.g); result = m_PhotoacousticPropertyCalculator->CalculatePropertyForSpecificWavelength( mitk::pa::PropertyCalculator::TissueType::STANDARD_TISSUE, wavelength, bloodOxygenation); m_Controls.spinboxBackgroundAbsorption->setValue(result.mua); m_Controls.spinboxBackgroundScattering->setValue(result.mus); m_Controls.spinboxBackgroundAnisotropy->setValue(result.g); } void PASimulator::UpdateVisibilityOfBatchCreation() { m_Controls.widgetBatchFile->setVisible(m_Controls.checkBoxGenerateBatch->isChecked()); } mitk::pa::TissueGeneratorParameters::Pointer PASimulator::GetParametersFromUIInput() { auto parameters = mitk::pa::TissueGeneratorParameters::New(); // Getting settings from UI // General settings parameters->SetXDim(m_Controls.spinboxXDim->value()); parameters->SetYDim(m_Controls.spinboxYDim->value()); parameters->SetZDim(m_Controls.spinboxZDim->value()); parameters->SetDoPartialVolume(m_Controls.checkBoxPartialVolume->isChecked()); parameters->SetRandomizePhysicalProperties(m_Controls.checkBoxRandomizeParameters->isChecked()); parameters->SetRandomizePhysicalPropertiesPercentage(m_Controls.spinboxRandomizeParameters->value()); parameters->SetVoxelSpacingInCentimeters(m_Controls.spinboxSpacing->value()); parameters->SetUseRngSeed(m_Controls.checkBoxRngSeed->isChecked()); parameters->SetRngSeed(m_Controls.spinBoxRngSeed->value()); // Monte Carlo simulation parameters parameters->SetMCflag(m_Controls.spinboxMcFlag->value()); parameters->SetMCLaunchflag(m_Controls.spinboxLaunchFlag->value()); parameters->SetMCBoundaryflag(m_Controls.spinboxboundaryFlag->value()); parameters->SetMCLaunchPointX(m_Controls.spinboxLaunchpointX->value()); parameters->SetMCLaunchPointY(m_Controls.spinboxLaunchpointY->value()); parameters->SetMCLaunchPointZ(m_Controls.spinboxLaunchpointZ->value()); parameters->SetMCFocusPointX(m_Controls.spinboxFocuspointX->value()); parameters->SetMCFocusPointY(m_Controls.spinboxFocuspointY->value()); parameters->SetMCFocusPointZ(m_Controls.spinboxFocuspointZ->value()); parameters->SetMCTrajectoryVectorX(m_Controls.spinboxTrajectoryVectorX->value()); parameters->SetMCTrajectoryVectorY(m_Controls.spinboxTrajectoryVectorY->value()); parameters->SetMCTrajectoryVectorZ(m_Controls.spinboxTrajectoryVectorZ->value()); parameters->SetMCRadius(m_Controls.spinboxRadius->value()); parameters->SetMCWaist(m_Controls.spinboxWaist->value()); // Vessel settings parameters->SetMaxVesselAbsorption(m_Controls.spinboxMaxAbsorption->value()); parameters->SetMinVesselAbsorption(m_Controls.spinboxMinAbsorption->value()); parameters->SetMaxVesselBending(m_Controls.spinboxMaxBending->value()); parameters->SetMinVesselBending(m_Controls.spinboxMinBending->value()); parameters->SetMaxVesselRadiusInMillimeters(m_Controls.spinboxMaxDiameter->value()); parameters->SetMinVesselRadiusInMillimeters(m_Controls.spinboxMinDiameter->value()); parameters->SetMaxNumberOfVessels(m_Controls.spinboxMaxVessels->value()); parameters->SetMinNumberOfVessels(m_Controls.spinboxMinVessels->value()); parameters->SetMinVesselScattering(m_Controls.spinboxBloodVesselScatteringMinimum->value()); parameters->SetMaxVesselScattering(m_Controls.spinboxBloodVesselScatteringMaximum->value()); parameters->SetMinVesselAnisotropy(m_Controls.spinboxBloodVesselAnisotropyMinimum->value()); parameters->SetMaxVesselAnisotropy(m_Controls.spinboxBloodVesselAnisotropyMaximum->value()); parameters->SetVesselBifurcationFrequency(m_Controls.spinboxBifurcationFrequency->value()); parameters->SetMinVesselZOrigin(m_Controls.spinboxMinSpawnDepth->value()); parameters->SetMaxVesselZOrigin(m_Controls.spinboxMaxSpawnDepth->value()); // Background tissue settings - parameters->SetBackgroundAbsorption(m_Controls.spinboxBackgroundAbsorption->value()); + parameters->SetMinBackgroundAbsorption(m_Controls.spinboxBackgroundAbsorption->value()); + parameters->SetMaxBackgroundAbsorption(m_Controls.spinboxBackgroundAbsorption->value()); parameters->SetBackgroundScattering(m_Controls.spinboxBackgroundScattering->value()); parameters->SetBackgroundAnisotropy(m_Controls.spinboxBackgroundAnisotropy->value()); // Air settings parameters->SetAirThicknessInMillimeters(m_Controls.spinboxAirThickness->value()); //Skin tissue settings parameters->SetSkinThicknessInMillimeters(m_Controls.spinboxSkinThickness->value()); parameters->SetSkinAbsorption(m_Controls.spinboxSkinAbsorption->value()); parameters->SetSkinScattering(m_Controls.spinboxSkinScattering->value()); parameters->SetSkinAnisotropy(m_Controls.spinboxSkinAnisotropy->value()); parameters->SetCalculateNewVesselPositionCallback(&mitk::pa::VesselMeanderStrategy::CalculateRandomlyDivergingPosition); return parameters; } void PASimulator::DoImageProcessing() { int numberOfVolumes = 1; if (m_Controls.checkBoxGenerateBatch->isChecked()) { if (m_Controls.labelBinarypath->text().isNull() || m_Controls.labelBinarypath->text().isEmpty()) { QMessageBox::warning(nullptr, QString("Warning"), QString("You need to specify the binary first!")); return; } numberOfVolumes = m_Controls.spinboxNumberVolumes->value(); if (numberOfVolumes < 1) { QMessageBox::warning(nullptr, QString("Warning"), QString("You need to create at least one volume!")); return; } } auto tissueParameters = GetParametersFromUIInput(); for (int volumeIndex = 0; volumeIndex < numberOfVolumes; volumeIndex++) { mitk::pa::InSilicoTissueVolume::Pointer volume = mitk::pa::InSilicoTissueGenerator::GenerateInSilicoData(tissueParameters); mitk::Image::Pointer tissueVolume = volume->ConvertToMitkImage(); if (m_Controls.checkBoxGenerateBatch->isChecked()) { std::string nrrdFilePath = m_Controls.label_NrrdFilePath->text().toStdString(); std::string tissueName = m_Controls.lineEditTissueName->text().toStdString(); std::string binaryPath = m_Controls.labelBinarypath->text().toStdString(); long numberOfPhotons = m_Controls.spinboxNumberPhotons->value() * 1000L; auto batchParameters = mitk::pa::SimulationBatchGeneratorParameters::New(); batchParameters->SetBinaryPath(binaryPath); batchParameters->SetNrrdFilePath(nrrdFilePath); batchParameters->SetNumberOfPhotons(numberOfPhotons); batchParameters->SetTissueName(tissueName); batchParameters->SetVolumeIndex(volumeIndex); batchParameters->SetYOffsetLowerThresholdInCentimeters(m_Controls.spinboxFromValue->value()); batchParameters->SetYOffsetUpperThresholdInCentimeters(m_Controls.spinboxToValue->value()); batchParameters->SetYOffsetStepInCentimeters(m_Controls.spinboxStepValue->value()); mitk::pa::SimulationBatchGenerator::WriteBatchFileAndSaveTissueVolume(batchParameters, tissueVolume); } else { mitk::DataNode::Pointer dataNode = mitk::DataNode::New(); dataNode->SetData(tissueVolume); dataNode->SetName(m_Controls.lineEditTissueName->text().toStdString()); this->GetDataStorage()->Add(dataNode); mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage()); } } } void PASimulator::OpenFolder() { m_Controls.label_NrrdFilePath->setText(QFileDialog::getExistingDirectory().append("/")); } void PASimulator::OpenBinary() { m_Controls.labelBinarypath->setText(QFileDialog::getOpenFileName()); }