diff --git a/Modules/PhotoacousticsLib/MitkOxygenationTissueBatchGenerator/OxygenationBatchGenerator.cpp b/Modules/PhotoacousticsLib/MitkOxygenationTissueBatchGenerator/OxygenationBatchGenerator.cpp index 3cb80bdf27..a74fa5daea 100644 --- a/Modules/PhotoacousticsLib/MitkOxygenationTissueBatchGenerator/OxygenationBatchGenerator.cpp +++ b/Modules/PhotoacousticsLib/MitkOxygenationTissueBatchGenerator/OxygenationBatchGenerator.cpp @@ -1,258 +1,312 @@ /*=================================================================== 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 #include #include using namespace mitk::pa; -TissueGeneratorParameters::Pointer CreateOxygenationParameters(int wavelength, double oxygenation, long rng) +TissueGeneratorParameters::Pointer CreateOxygenationParameters(int wavelength, double oxygenation, long rng, double radius) { auto propertyCalculator = PropertyCalculator::New(); auto background_properties = propertyCalculator->CalculatePropertyForSpecificWavelength( PropertyCalculator::TissueType::STANDARD_TISSUE, wavelength, oxygenation); auto returnParameters = TissueGeneratorParameters::New(); + returnParameters->SetAirThicknessInMillimeters(12); returnParameters->SetMinBackgroundAbsorption(background_properties.mua); returnParameters->SetMaxBackgroundAbsorption(background_properties.mua); returnParameters->SetBackgroundAnisotropy(background_properties.g); returnParameters->SetBackgroundScattering(background_properties.mus); returnParameters->SetCalculateNewVesselPositionCallback(&VesselMeanderStrategy::CalculateRandomlyDivergingPosition); + returnParameters->SetDoPartialVolume(false); - returnParameters->SetMinNumberOfVessels(2); - returnParameters->SetMaxNumberOfVessels(10); + returnParameters->SetMinNumberOfVessels(1); + returnParameters->SetMaxNumberOfVessels(1); + + auto vessel_properties = propertyCalculator->CalculatePropertyForSpecificWavelength( + PropertyCalculator::TissueType::BLOOD, wavelength, oxygenation); + //---These are calculated for each vessel individually - returnParameters->SetMinVesselAbsorption(0); - returnParameters->SetMaxVesselAbsorption(0); - returnParameters->SetMinVesselAnisotropy(0); - returnParameters->SetMaxVesselAnisotropy(0); - returnParameters->SetMinVesselScattering(0); - returnParameters->SetMaxVesselScattering(0); + returnParameters->SetMinVesselAbsorption(vessel_properties.mua); + returnParameters->SetMaxVesselAbsorption(vessel_properties.mua); + returnParameters->SetMinVesselAnisotropy(vessel_properties.g); + returnParameters->SetMaxVesselAnisotropy(vessel_properties.g); + returnParameters->SetMinVesselScattering(vessel_properties.mus); + returnParameters->SetMaxVesselScattering(vessel_properties.mus); //--- - returnParameters->SetMinVesselBending(0.1); - returnParameters->SetMaxVesselBending(0.3); - returnParameters->SetMinVesselRadiusInMillimeters(0.5); - returnParameters->SetMaxVesselRadiusInMillimeters(4); - returnParameters->SetMinVesselZOrigin(2.2); - returnParameters->SetMaxVesselZOrigin(4); - returnParameters->SetVesselBifurcationFrequency(50); + + returnParameters->SetMinVesselBending(0); + returnParameters->SetMaxVesselBending(0); + returnParameters->SetMinVesselRadiusInMillimeters(radius); + returnParameters->SetMaxVesselRadiusInMillimeters(radius); + returnParameters->SetMinVesselZOrigin(2.5); + returnParameters->SetMaxVesselZOrigin(2.5); + returnParameters->SetVesselBifurcationFrequency(5000); returnParameters->SetRandomizePhysicalProperties(false); returnParameters->SetSkinThicknessInMillimeters(0); returnParameters->SetUseRngSeed(true); returnParameters->SetRngSeed(rng); - returnParameters->SetVoxelSpacingInCentimeters(0.06); - returnParameters->SetXDim(70); - returnParameters->SetYDim(50); - returnParameters->SetZDim(90); - returnParameters->SetRandomizeVesselOpticalParams(true); + returnParameters->SetVoxelSpacingInCentimeters(0.12); + returnParameters->SetXDim(35); + returnParameters->SetYDim(25); + returnParameters->SetZDim(45); + returnParameters->SetRandomizeVesselOpticalParams(false); + returnParameters->SetForceVesselsMoveAlongYDirection(true); returnParameters->SetTargetWavelength(wavelength); 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 Oxygenation 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; } -void simulate(int wavelength, double oxygenation, long rng_seed, int iterationNumber, InputParameters input) +void simulate(int wavelength, double oxygenation, long rng_seed, int iterationNumber, InputParameters input, double radius) { - auto parameters = CreateOxygenationParameters(wavelength, oxygenation, rng_seed); + auto parameters = CreateOxygenationParameters(wavelength, oxygenation, rng_seed, radius); MITK_INFO(input.verbose) << "Generating tissue.."; auto resultTissue = InSilicoTissueGenerator::GenerateInSilicoData(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/BaselineHB_" + input.identifyer + "_" + std::to_string(iterationNumber) + "_oxy" + std::to_string(oxygenation); std::string outputPath = input.saveFolderPath + "output/BaselineHB_" + input.identifyer + "_" + std::to_string(iterationNumber) + "_oxy" + std::to_string(oxygenation); if (!itksys::SystemTools::FileIsDirectory(outputPath)) { itksys::SystemTools::MakeDirectory(outputPath); } if (!itksys::SystemTools::FileIsDirectory(savePath)) { itksys::SystemTools::MakeDirectory(savePath); } savePath = savePath + "/wl" + std::to_string(wavelength) + ".nrrd"; mitk::IOUtil::Save(resultTissue->ConvertToMitkImage(), savePath); outputPath = outputPath + "/wl" + std::to_string(wavelength); MITK_INFO(input.verbose) << "Simulating fluence.."; double yo=0; std::string yo_string = std::to_string(round(yo*100)/100.0); int result = -4; if(!input.probePath.empty()) result = std::system(std::string(input.exePath + " -i " + savePath + " -o " + (outputPath + ".nrrd") + " -yo " + yo_string + " -p " + input.probePath + " -n 10000000").c_str()); else result = std::system(std::string(input.exePath + " -i " + savePath + " -o " + (outputPath + "_oxy" + std::to_string((int) (oxygenation*100)) + "_wl" + std::to_string(wavelength) + ".nrrd") + " -yo " + yo_string + " -n 10000000").c_str()); MITK_INFO << "wl: " << wavelength << ": " << result; MITK_INFO(input.verbose) << "Simulating fluence..[Done]"; } int main(int argc, char * argv[]) { auto input = parseInput(argc, argv); unsigned int iterationNumber = 0; std::mt19937 randomNumberGenerator; std::random_device randomDevice; 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()); } std::uniform_real_distribution randomOxygenation(0, 1); std::uniform_int_distribution randomLong(0, std::numeric_limits::max()); - while (true) - { - long rng_seed = randomLong(randomNumberGenerator); - double oxygenation = randomOxygenation(randomNumberGenerator); + //while (true) + //{ + long rng_seed = 17;//randomLong(randomNumberGenerator); + double oxygenation = 0.9999;//randomOxygenation(randomNumberGenerator); for(int wavelength = 700; wavelength < 960; wavelength+=10) { - simulate(wavelength, oxygenation, rng_seed, iterationNumber, input); + simulate(wavelength, oxygenation, rng_seed, iterationNumber, input, 2); } iterationNumber++; - } + + rng_seed = 17;//randomLong(randomNumberGenerator); + oxygenation = 0.0001;//randomOxygenation(randomNumberGenerator); + + for(int wavelength = 700; wavelength < 960; wavelength+=10) + { + simulate(wavelength, oxygenation, rng_seed, iterationNumber, input, 2); + } + + iterationNumber++; + + rng_seed = 17;//randomLong(randomNumberGenerator); + oxygenation = 0.5;//randomOxygenation(randomNumberGenerator); + + for(int wavelength = 700; wavelength < 960; wavelength+=10) + { + simulate(wavelength, oxygenation, rng_seed, iterationNumber, input, 2); + } + + rng_seed = 17;//randomLong(randomNumberGenerator); + oxygenation = 0.9999;//randomOxygenation(randomNumberGenerator); + + for(int wavelength = 700; wavelength < 960; wavelength+=10) + { + simulate(wavelength, oxygenation, rng_seed, iterationNumber, input, 0.5); + } + + iterationNumber++; + + rng_seed = 17;//randomLong(randomNumberGenerator); + oxygenation = 0.0001;//randomOxygenation(randomNumberGenerator); + + for(int wavelength = 700; wavelength < 960; wavelength+=10) + { + simulate(wavelength, oxygenation, rng_seed, iterationNumber, input, 0.5); + } + + iterationNumber++; + + rng_seed = 17;//randomLong(randomNumberGenerator); + oxygenation = 0.5;//randomOxygenation(randomNumberGenerator); + + for(int wavelength = 700; wavelength < 960; wavelength+=10) + { + simulate(wavelength, oxygenation, rng_seed, iterationNumber, input, 0.5); + } + //} } diff --git a/Modules/PhotoacousticsLib/src/Utils/mitkPAPropertyCalculator.cpp b/Modules/PhotoacousticsLib/src/Utils/mitkPAPropertyCalculator.cpp index 8ff8e0f1f8..aef7e7e24f 100644 --- a/Modules/PhotoacousticsLib/src/Utils/mitkPAPropertyCalculator.cpp +++ b/Modules/PhotoacousticsLib/src/Utils/mitkPAPropertyCalculator.cpp @@ -1,154 +1,154 @@ /*=================================================================== 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 "mitkPAPropertyCalculator.h" // us #include #include #include #include #include mitk::pa::PropertyCalculator::Properties mitk::pa::PropertyCalculator:: CalculatePropertyForSpecificWavelength( TissueType tissueType, int wavelength, double bloodOxygenInFraction) { Properties returnValue; if (!m_Valid) { mitkThrow() << "PhotoacousticPropertyGenerator was not loaded properly."; return returnValue; } double bloodOxygenation = bloodOxygenInFraction; double bloodVolumeFraction; double waterVolumeFraction; double fatVolumeFraction; double melanosomesVolumeFraction; double musp500; double fray; double bmie; double g; switch (tissueType) { case AIR: returnValue.mua = 1e-4; returnValue.mus = 1.0; returnValue.g = 1.0; return returnValue; case BLOOD: bloodVolumeFraction = 1.0; - waterVolumeFraction = 0.95; - fatVolumeFraction = 0.02; + waterVolumeFraction = 0.5;//0.95; + fatVolumeFraction = 0;//0.005;//0.02; melanosomesVolumeFraction = 0; musp500 = 10; fray = 0; bmie = 1; g = 0.9; break; case EPIDERMIS: bloodVolumeFraction = 0; bloodOxygenation = 0; waterVolumeFraction = 0.75; fatVolumeFraction = 0.01; melanosomesVolumeFraction = 0.02; musp500 = 40; fray = 0; bmie = 1; g = 0.9; break; case FAT: bloodVolumeFraction = 0.01; bloodOxygenation = 0.75; waterVolumeFraction = 0.5; fatVolumeFraction = 0.6; melanosomesVolumeFraction = 0; musp500 = 17.47; fray = 0.2; bmie = 0.5; g = 0.9; break; case STANDARD_TISSUE: default: - bloodVolumeFraction = 0.02; - waterVolumeFraction = 0.8; - fatVolumeFraction = 0.05; + bloodVolumeFraction = 0.01; + waterVolumeFraction = 0.65;//0.8; + fatVolumeFraction = 0;//0.1;//0.05; melanosomesVolumeFraction = 0; musp500 = 25; fray = 0.25; bmie = 1; g = 0.9; break; } // We want the reduced scattering coefficient directly. double musp = musp500 * (fray * pow(wavelength / 500.0, -4.0) + ((1 - fray) * pow(wavelength / 500.0, -bmie))); returnValue.mus = musp; - returnValue.mus = 15;//musp; + returnValue.mus = 10;//musp; double mua = bloodVolumeFraction*bloodOxygenation*m_SpectralLibMap[MapType::OXYGENATED][wavelength] + bloodVolumeFraction*(1 - bloodOxygenation)*m_SpectralLibMap[MapType::DEOXYGENATED][wavelength] + waterVolumeFraction*m_SpectralLibMap[MapType::WATER][wavelength] + fatVolumeFraction*m_SpectralLibMap[MapType::FATTY][wavelength] + melanosomesVolumeFraction*m_SpectralLibMap[MapType::MELANIN][wavelength]; returnValue.mua = mua; returnValue.g = g; return returnValue; } mitk::pa::PropertyCalculator::PropertyCalculator() { us::ModuleResource resource = us::GetModuleContext()->GetModule()->GetResource("spectralLIB.dat"); if (resource.IsValid()) { us::ModuleResourceStream resourceStream(resource); std::string line; int wavelength = 300; int counter = 0; while (std::getline(resourceStream, line, '\t')) { int currentLineIdx = counter % 6; if (currentLineIdx == 0) wavelength = std::stoi(line); else { std::istringstream lineStream(line); double tempDouble; lineStream >> tempDouble; m_SpectralLibMap[currentLineIdx][wavelength] = tempDouble; } ++counter; } } else { m_Valid = false; } m_Valid = true; } mitk::pa::PropertyCalculator::~PropertyCalculator() { m_SpectralLibMap.clear(); m_Valid = false; }