diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticTissueGenerator.cpp b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticTissueGenerator.cpp index 2f951d5203..0630bcde21 100644 --- a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticTissueGenerator.cpp +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticTissueGenerator.cpp @@ -1,151 +1,148 @@ /*=================================================================== 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 "mitkPhotoacousticTissueGenerator.h" #include "mitkPhotoacousticSmartVector.h" #include "mitkPhotoacousticFatTissueGenerator.h" mitk::PhotoacousticVolume::Pointer mitk::PhotoacousticTissueGenerator::GenerateInSilicoData(mitk::PhotoacousticTissueGeneratorParameters::Pointer parameters) { MITK_DEBUG << "Initializing Empty Volume"; mitk::PhotoacousticVolume::Pointer generatedVolume = mitk::PhotoacousticVolume::New(); generatedVolume->Initialize(parameters); const double DIRECTION_VECTOR_INITIAL_VARIANCE = 0.2; 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()); } } mitk::PhotoacousticFatTissueGenerator::CreateFatGlobules(generatedVolume, parameters, &randomNumberGenerator); std::uniform_int_distribution randomNumVesselDistribution(parameters->GetMinNumberOfVessels(), parameters->GetMaxNumberOfVessels()); std::uniform_real_distribution randomBendingDistribution(parameters->GetMinVesselBending(), parameters->GetMaxVesselBending()); std::uniform_real_distribution randomAbsorptionDistribution(parameters->GetMinVesselAbsorption(), parameters->GetMaxVesselAbsorption()); std::uniform_real_distribution randomRadiusDistribution(parameters->GetMinVesselRadius(), parameters->GetMaxVesselRadius()); std::uniform_real_distribution randomScatteringDistribution(parameters->GetMinVesselScattering(), parameters->GetMaxVesselScattering()); std::uniform_real_distribution randomAnisotropyDistribution(parameters->GetMinVesselAnisotropy(), parameters->GetMaxVesselAnisotropy()); std::uniform_int_distribution borderTypeDistribution(0, 3); int numberOfBloodVessels = randomNumVesselDistribution(randomNumberGenerator); generatedVolume->AddIntProperty("numberOfVessels", numberOfBloodVessels); generatedVolume->AddIntProperty("bifurcationFrequency", parameters->GetVesselBifurcationFrequency()); MITK_INFO << "Simulating "<< numberOfBloodVessels <<" vessel structures"; for(int vesselNumber = 0; vesselNumber < numberOfBloodVessels; vesselNumber++) { mitk::PhotoacousticSmartVector::Pointer initialPosition = mitk::PhotoacousticSmartVector::New(); mitk::PhotoacousticSmartVector::Pointer initialDirection = mitk::PhotoacousticSmartVector::New(); double initialRadius = randomRadiusDistribution(randomNumberGenerator) / parameters->GetVoxelSpacing() / 10; std::stringstream radiusString; radiusString <<"vessel_"<AddDoubleProperty(radiusString.str(), initialRadius); double absorptionCoefficient = randomAbsorptionDistribution(randomNumberGenerator); std::stringstream absorptionString; absorptionString <<"vessel_"<AddDoubleProperty(absorptionString.str(), absorptionCoefficient); double bendingFactor = randomBendingDistribution(randomNumberGenerator); std::stringstream bendingString; bendingString <<"vessel_"<AddDoubleProperty(bendingString.str(), bendingFactor); double vesselScattering = randomScatteringDistribution(randomNumberGenerator); std::stringstream scatteringString; scatteringString <<"vessel_"<AddDoubleProperty(scatteringString.str(), vesselScattering); double vesselAnisotropy= randomAnisotropyDistribution(randomNumberGenerator); std::stringstream anisotropyString; anisotropyString <<"vessel_"<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) */ int borderType = borderTypeDistribution(randomNumberGenerator); switch(borderType) { case 0: - initialPosition->Randomize(0, 0, initialRadius, parameters->GetYDim()-initialRadius, parameters->GetMinNumberOfVessels()/10/parameters->GetVoxelSpacing(), - parameters->GetMaxNumberOfVessels()/10/parameters->GetVoxelSpacing(), &randomNumberGenerator); + initialPosition->Randomize(0, 0, initialRadius, parameters->GetYDim()-initialRadius, parameters->GetMinVesselZOrigin()/parameters->GetVoxelSpacing(), + parameters->GetMaxVesselZOrigin()/parameters->GetVoxelSpacing(), &randomNumberGenerator); initialDirection->Randomize(1, 2, -DIRECTION_VECTOR_INITIAL_VARIANCE, DIRECTION_VECTOR_INITIAL_VARIANCE, -DIRECTION_VECTOR_INITIAL_VARIANCE, DIRECTION_VECTOR_INITIAL_VARIANCE,&randomNumberGenerator); break; case 1: - initialPosition->Randomize(parameters->GetXDim(), parameters->GetXDim(), initialRadius, parameters->GetYDim() - initialRadius, parameters->GetMinNumberOfVessels()/10/parameters->GetVoxelSpacing(), - parameters->GetMaxNumberOfVessels()/10/parameters->GetVoxelSpacing(), &randomNumberGenerator); + initialPosition->Randomize(parameters->GetXDim(), parameters->GetXDim(), initialRadius, parameters->GetYDim() - initialRadius, parameters->GetMinVesselZOrigin()/10/parameters->GetVoxelSpacing(), + parameters->GetMaxVesselZOrigin()/parameters->GetVoxelSpacing(), &randomNumberGenerator); initialDirection->Randomize(-2, -1, -DIRECTION_VECTOR_INITIAL_VARIANCE, DIRECTION_VECTOR_INITIAL_VARIANCE, -DIRECTION_VECTOR_INITIAL_VARIANCE, DIRECTION_VECTOR_INITIAL_VARIANCE, &randomNumberGenerator); break; case 2: - initialPosition->Randomize(initialRadius, parameters->GetXDim() - initialRadius, 0, 0, parameters->GetMinNumberOfVessels()/10/parameters->GetVoxelSpacing(), - parameters->GetMaxNumberOfVessels()/10/parameters->GetVoxelSpacing(), &randomNumberGenerator); + initialPosition->Randomize(initialRadius, parameters->GetXDim() - initialRadius, 0, 0, parameters->GetMinVesselZOrigin()/parameters->GetVoxelSpacing(), + parameters->GetMaxVesselZOrigin()/parameters->GetVoxelSpacing(), &randomNumberGenerator); initialDirection->Randomize(-DIRECTION_VECTOR_INITIAL_VARIANCE, DIRECTION_VECTOR_INITIAL_VARIANCE, 1, 2, -DIRECTION_VECTOR_INITIAL_VARIANCE, DIRECTION_VECTOR_INITIAL_VARIANCE, &randomNumberGenerator); break; case 3: - initialPosition->Randomize(initialRadius, parameters->GetXDim() - initialRadius, parameters->GetYDim(), parameters->GetYDim(), parameters->GetMinNumberOfVessels()/10/parameters->GetVoxelSpacing(), - parameters->GetMaxNumberOfVessels()/10/parameters->GetVoxelSpacing(), &randomNumberGenerator); + initialPosition->Randomize(initialRadius, parameters->GetXDim() - initialRadius, parameters->GetYDim(), parameters->GetYDim(), parameters->GetMinVesselZOrigin()/parameters->GetVoxelSpacing(), + parameters->GetMaxVesselZOrigin()/parameters->GetVoxelSpacing(), &randomNumberGenerator); initialDirection->Randomize(-DIRECTION_VECTOR_INITIAL_VARIANCE, DIRECTION_VECTOR_INITIAL_VARIANCE, -2, -1, -DIRECTION_VECTOR_INITIAL_VARIANCE, DIRECTION_VECTOR_INITIAL_VARIANCE, &randomNumberGenerator); break; } mitk::PhotoacousticVesselTree::Pointer vesselTree = mitk::PhotoacousticVesselTree::New(); - MITK_INFO << "Initializing vessel structure"; vesselTree->Initialize(initialPosition, initialDirection, initialRadius, absorptionCoefficient, vesselScattering, vesselAnisotropy, parameters->GetVesselBifurcationFrequency(), &randomNumberGenerator); - MITK_INFO << "Simulating vessel structure"; while(!vesselTree->IsFinished()) { - MITK_INFO << "Step"; vesselTree->Step(generatedVolume, parameters->GetCalculateNewVesselPositionCallback(), bendingFactor, &randomNumberGenerator); } } generatedVolume->GaussianBlur3D(); generatedVolume->FinalizeVolume(parameters); return generatedVolume; } diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVessel.cpp b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVessel.cpp index d5ac1021de..879b57962a 100644 --- a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVessel.cpp +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVessel.cpp @@ -1,167 +1,171 @@ /*=================================================================== 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 "mitkPhotoacousticVessel.h" #include #include #include mitk::PhotoacousticVessel::PhotoacousticVessel(): m_RangeDistribution(M_PI/16, M_PI/8), m_SignDistribution(-1, 1) { srand(std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count()); m_Finished = false; m_Position = nullptr; m_Direction = nullptr; m_Radius = -1; m_AbsorptionCoefficient = -1; m_ScatteringCoefficient = -1; m_AnisotropyCoefficient = -1; m_VesselMeanderStrategy = nullptr; m_WalkedDistance = 0; m_State = UNINITIALIZED; } mitk::PhotoacousticVessel::~PhotoacousticVessel() { m_Position = nullptr; m_Direction = nullptr; m_VesselMeanderStrategy = nullptr; m_State = UNINITIALIZED; } void mitk::PhotoacousticVessel::Initialize(mitk::PhotoacousticSmartVector::Pointer initialPosition, mitk::PhotoacousticSmartVector::Pointer initialDirection, double initialRadius, double absorptionCoefficient, double scatteringCoefficient, double anisotophyCoefficient, double bifurcationFrequency, std::mt19937* rng) { m_Radius = initialRadius; m_AbsorptionCoefficient = absorptionCoefficient; m_ScatteringCoefficient = scatteringCoefficient; m_AnisotropyCoefficient = anisotophyCoefficient; m_Finished = false; m_Position = initialPosition; m_Direction = initialDirection; m_VesselMeanderStrategy = mitk::PhotoacousticVesselMeanderStrategy::New(); m_State = INITIALIZED; std::normal_distribution<> factor(1, VESSEL_BIFURCATION_VARIATION_SIGMA); m_BifurcationFrequency = bifurcationFrequency * factor(*rng); - m_RadiusRangeDistribution = std::uniform_real_distribution<>(m_Radius * NEW_RADIUS_MINIMUM_RELATIVE_SIZE, - m_Radius * NEW_RADIUS_MAXIMUM_RELATIVE_SIZE); + m_RadiusRangeDistribution = std::uniform_real_distribution<>(NEW_RADIUS_MINIMUM_RELATIVE_SIZE, + NEW_RADIUS_MAXIMUM_RELATIVE_SIZE); } void mitk::PhotoacousticVessel::ExpandVessel(mitk::PhotoacousticVolume::Pointer volume, CalculateNewVesselPositionCallback calculateNewPosition, double bendingFactor, std::mt19937* rng) { AssertState(INITIALIZED); mitk::PhotoacousticSmartVector::Pointer oldPosition = mitk::PhotoacousticSmartVector::New(); oldPosition->SetValue(m_Position); (m_VesselMeanderStrategy->*calculateNewPosition)(m_Position, m_Direction, bendingFactor, rng); DrawVesselInVolume(oldPosition, volume); } bool mitk::PhotoacousticVessel::CanBifurcate() { return m_BifurcationFrequency < m_WalkedDistance; } int mitk::PhotoacousticVessel::GetSign(std::mt19937 *rng) { if(m_SignDistribution(*rng) < 0) return -1; return 1; } mitk::PhotoacousticVessel::Pointer mitk::PhotoacousticVessel::Bifurcate(std::mt19937* rng) { AssertState(INITIALIZED); mitk::PhotoacousticVessel::Pointer newVessel = mitk::PhotoacousticVessel::New(); mitk::PhotoacousticSmartVector::Pointer newDirection = m_Direction->Clone(); double thetaChange = m_RangeDistribution(*rng) * GetSign(rng); double phiChange = m_RangeDistribution(*rng) * GetSign(rng); newDirection->Rotate(thetaChange, phiChange); m_Direction->Rotate(-thetaChange, -phiChange); - double newRadius = m_RadiusRangeDistribution(*rng); + double newRadius = m_RadiusRangeDistribution(*rng)*m_Radius; + + MITK_INFO << "old radius: " << m_Radius; m_Radius = sqrt(m_Radius*m_Radius - newRadius*newRadius); + MITK_INFO << "new radii: " << m_Radius << " | " << newRadius; + newVessel->Initialize(m_Position->Clone(), newDirection, newRadius, m_AbsorptionCoefficient, m_ScatteringCoefficient, m_AnisotropyCoefficient, m_BifurcationFrequency, rng); m_WalkedDistance = 0; return newVessel; } void mitk::PhotoacousticVessel::DrawVesselInVolume(mitk::PhotoacousticSmartVector::Pointer fromPosition, mitk::PhotoacousticVolume::Pointer volume) { AssertState(INITIALIZED); mitk::PhotoacousticSmartVector::Pointer diffVector = mitk::PhotoacousticSmartVector::New(); diffVector->SetElement(0, fromPosition->GetElement(0)-m_Position->GetElement(0)); diffVector->SetElement(1, fromPosition->GetElement(1)-m_Position->GetElement(1)); diffVector->SetElement(2, fromPosition->GetElement(2)-m_Position->GetElement(2)); //1/SCALING_FACTOR steps along the direction vector are taken and drawn into the image. mitk::PhotoacousticSmartVector::Pointer stepSize = mitk::PhotoacousticSmartVector::New(); stepSize->SetValue(m_Direction); stepSize->Scale(SCALING_FACTOR); while (diffVector->GetNorm() >= SCALING_FACTOR) { m_WalkedDistance += stepSize->GetNorm(); fromPosition->SetElement(0, fromPosition->GetElement(0)+stepSize->GetElement(0)); fromPosition->SetElement(1, fromPosition->GetElement(1)+stepSize->GetElement(1)); fromPosition->SetElement(2, fromPosition->GetElement(2)+stepSize->GetElement(2)); int xPos = fromPosition->GetElement(0); int yPos = fromPosition->GetElement(1); int zPos = fromPosition->GetElement(2); for(int x = xPos - m_Radius; x <= xPos + m_Radius; x++) for(int y = yPos - m_Radius; y <= yPos + m_Radius; y++) for(int z = zPos - m_Radius; z <= zPos + m_Radius; z++) { if( m_Radius*m_Radius >= (x-xPos)*(x-xPos)+(y-yPos)*(y-yPos)+(z-zPos)*(z-zPos)) { volume->SetVolumeValues(x, y, z, m_AbsorptionCoefficient, m_ScatteringCoefficient, m_AnisotropyCoefficient, mitk::PhotoacousticVolume::SegmentationType::VESSEL); } } diffVector->SetElement(0, fromPosition->GetElement(0)-m_Position->GetElement(0)); diffVector->SetElement(1, fromPosition->GetElement(1)-m_Position->GetElement(1)); diffVector->SetElement(2, fromPosition->GetElement(2)-m_Position->GetElement(2)); if(!volume->IsInsideVolume(xPos, yPos, zPos)) { m_Radius = 0; break; } } } bool mitk::PhotoacousticVessel::IsFinished() { return m_Radius < MINIMUM_VESSEL_RADIUS; } diff --git a/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/PASimulator.cpp b/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/PASimulator.cpp index 8b1fd0cd4e..73a1745da6 100644 --- a/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/PASimulator.cpp +++ b/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/PASimulator.cpp @@ -1,317 +1,319 @@ /*=================================================================== 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 #ifdef __linux__ #include #include #else #include #endif #include #include const std::string PASimulator::VIEW_ID = "org.mitk.views.pasimulator"; void PASimulator::SetFocus() { m_Controls.pushButtonShowRandomTissue->setFocus(); } void PASimulator::CreateQtPartControl( QWidget *parent ) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi( parent ); connect(m_Controls.pushButtonShowRandomTissue, SIGNAL(clicked()), this, SLOT(DoImageProcessing()) ); connect(m_Controls.checkBoxGauss, SIGNAL(stateChanged(int)), this, SLOT(ClickedGaussBox())); 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()) ); m_Controls.spinboxSigma->setEnabled(false); m_Controls.labelSigma->setEnabled(false); m_Controls.label_NrrdFilePath->setText((std::string(getenv("HOME"))+"/").c_str()); m_PhotoacousticPropertyCalculator = mitk::PhotoacousticPropertyCalculator::New(); UpdateVisibilityOfBatchCreation(); ClickedRandomizePhysicalParameters(); ClickedCheckboxFixedSeed(); ClickedGaussBox(); } 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; mitk::PhotoacousticPropertyCalculator::Properties result = m_PhotoacousticPropertyCalculator->CalculatePropertyForSpecificWavelength( mitk::PhotoacousticPropertyCalculator::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::PhotoacousticPropertyCalculator::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::PhotoacousticPropertyCalculator::TissueType::FAT, wavelength, bloodOxygenation); m_Controls.spinboxFatAbsorption->setValue(result.mua); m_Controls.spinboxFatScattering->setValue(result.mus); m_Controls.spinboxFatAnisotropy->setValue(result.g); result = m_PhotoacousticPropertyCalculator->CalculatePropertyForSpecificWavelength( mitk::PhotoacousticPropertyCalculator::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()); } void PASimulator::DoImageProcessing() { 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; } } int numberOfVolumes = m_Controls.spinboxNumberVolumes->value(); if(numberOfVolumes<1) { QMessageBox::warning(nullptr, QString("Warning"), QString("You need to create at least one volume!")); return; } mitk::PhotoacousticTissueGeneratorParameters::Pointer parameters = mitk::PhotoacousticTissueGeneratorParameters::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->SetDoVolumeSmoothing(m_Controls.checkBoxGauss->isChecked()); parameters->SetVolumeSmoothingSigma(m_Controls.spinboxSigma->value()); parameters->SetRandomizePhysicalProperties(m_Controls.checkBoxRandomizeParameters->isChecked()); parameters->SetRandomizePhysicalPropertiesPercentage(m_Controls.spinboxRandomizeParameters->value()); parameters->SetVoxelSpacing(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->SetMaxVesselRadius(m_Controls.spinboxMaxDiameter->value()); parameters->SetMinVesselRadius(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->SetBackgroundScattering(m_Controls.spinboxBackgroundScattering->value()); parameters->SetBackgroundAnisotropy(m_Controls.spinboxBackgroundAnisotropy->value()); // Air settings parameters->SetAirThickness(m_Controls.spinboxAirThickness->value()); //Fat tissue settings parameters->SetFatPercentage(m_Controls.spinboxFatPercentage->value()); parameters->SetFatAbsorption(m_Controls.spinboxFatAbsorption->value()); parameters->SetFatScattering(m_Controls.spinboxFatScattering->value()); parameters->SetFatAnisotropy(m_Controls.spinboxFatAnisotropy->value()); //Skin tissue settings parameters->SetSkinThickness(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::PhotoacousticVesselMeanderStrategy::CalculateRandomlyDivergingPosition); for(int volumeIndex = 0; volumeIndex < numberOfVolumes; volumeIndex++) { MITK_DEBUG << "Generating in silico data"; mitk::PhotoacousticVolume::Pointer volume = mitk::PhotoacousticTissueGenerator::GenerateInSilicoData(parameters); MITK_DEBUG << "Generating mitk::Image"; mitk::Image::Pointer tissueVolume = volume->ConvertToMitkImage(); if(m_Controls.checkBoxGenerateBatch->isChecked()) { std::string volumeNumber = ""; if(volumeIndex<10) { volumeNumber = "00" + std::to_string(volumeIndex); } else if(volumeIndex<100) { volumeNumber = "0" + std::to_string(volumeIndex); } else { volumeNumber = std::to_string(volumeIndex); } std::string outputFolderName = m_Controls.label_NrrdFilePath->text().toStdString() + m_Controls.lineEditTissueName->text().toStdString() + volumeNumber; std::string savePath = outputFolderName + ".nrrd"; mitk::IOUtil::Save(tissueVolume, savePath); std::string filename = "executescript"; std::string filenameAllSimulation = "simulate_all"; #ifdef __linux__ mkdir(outputFolderName.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); filename += ".sh"; filenameAllSimulation += ".sh"; #else mkdir(outputFolderName.c_str()); filename += ".bat"; filenameAllSimulation += ".bat"; #endif std::ofstream file(outputFolderName+"/"+filename); outputFolderName = "/home/ubuntu/sim/" + m_Controls.lineEditTissueName->text().toStdString() + volumeNumber; savePath = outputFolderName + ".nrrd"; if(file.is_open()) { for(double d = -1.8; d <=1.9; d+=0.12) { file << m_Controls.labelBinarypath->text().toStdString() << " -p PROBE_DESIGN.xml -i " << savePath << " -o " << outputFolderName << "/" << m_Controls.lineEditTissueName->text().toStdString() << "_yo" << round(d*100) / 100 << ".nrrd" << " -yo " << round(d*100) / 100 << " -n " << (m_Controls.spinboxNumberPhotons->value()*1000L) << "\n"; } file << "mv " << outputFolderName << "/ " << "/home/ubuntu/E130-Projekte/Biophotonics/qPAT/InVitroData/\n"; file.close(); } std::ofstream fileAllSimulation(m_Controls.label_NrrdFilePath->text().toStdString()+"/"+filenameAllSimulation, std::ios_base::app); if(fileAllSimulation.is_open()) { for(double d = -1.8; d <=1.9; d+=0.12) { fileAllSimulation << m_Controls.labelBinarypath->text().toStdString() << " -p PROBE_DESIGN.xml -i " << savePath << " -o " << outputFolderName << "/" << m_Controls.lineEditTissueName->text().toStdString() << "_yo" << round(d*100) / 100 << ".nrrd" << " -yo " << round(d*100) / 100 << " -n " << (m_Controls.spinboxNumberPhotons->value()*1000L) << "\n"; } fileAllSimulation << "mv " << outputFolderName << "/ " << "/home/ubuntu/E130-Projekte/Biophotonics/qPAT/InVitroData/\n"; fileAllSimulation.close(); } } 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()); } } MITK_DEBUG << "Handing stuff to UI Thread now.."; } void PASimulator::ClickedGaussBox() { if(m_Controls.checkBoxGauss->isChecked()) { m_Controls.spinboxSigma->setEnabled(true); m_Controls.labelSigma->setEnabled(true); } else { m_Controls.spinboxSigma->setEnabled(false); m_Controls.labelSigma->setEnabled(false); } } void PASimulator::OpenFolder() { m_Controls.label_NrrdFilePath->setText(QFileDialog::getExistingDirectory().append("/")); } void PASimulator::OpenBinary() { m_Controls.labelBinarypath->setText(QFileDialog::getOpenFileName()); } diff --git a/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/PASimulatorControls.ui b/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/PASimulatorControls.ui index 86f6890ab4..4a7f6608cb 100644 --- a/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/PASimulatorControls.ui +++ b/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/PASimulatorControls.ui @@ -1,4939 +1,5069 @@ PASimulatorControls 0 0 433 655 0 0 - Roboto + Ubuntu Qt::NoContextMenu QmitkTemplate :/org.mitk.gui.qt.photoacousticsimulation/resources/icon.xpm:/org.mitk.gui.qt.photoacousticsimulation/resources/icon.xpm 0 0 415 600 Ubuntu 0 Generator 10 10 391 581 0 0 391 581 0 0 0 0 75 true Volume parameters 0 0 0 25 16777215 25 Tissue name: 0 0 0 25 16777215 25 Size x: 0 0 0 25 16777215 25 50 false Spacing: 0 0 0 25 16777215 25 PhotoacousticTissue 0 0 0 25 16777215 25 1 9999 70 0 0 0 25 16777215 25 y: 0 0 0 25 16777215 25 9999 100 0 0 0 25 16777215 25 z: 0 0 0 25 16777215 25 9999 90 0 0 0 25 16777215 25 voxels Qt::Horizontal 40 20 0 0 0 25 16777215 25 2 0.010000000000000 0.060000000000000 0 0 0 25 16777215 25 cm Qt::Horizontal 40 20 0 0 0 25 16777215 25 Randomize: 0 0 0 25 16777215 25 Partial volume effects: 0 0 0 25 16777215 25 Custom seed: 0 0 0 25 16777215 25 false true 0 0 0 25 16777215 25 false true 0 0 0 25 16777215 25 0 0 0 25 16777215 25 sigma: 0 0 0 25 16777215 25 0 100.000000000000000 0.010000000000000 2.000000000000000 0 0 0 25 16777215 25 % Qt::Horizontal 40 20 0 0 0 25 16777215 25 sigma: 0 0 0 25 16777215 25 10.000000000000000 0.100000000000000 1.000000000000000 0 0 0 25 16777215 25 voxels Qt::Horizontal 40 20 0 0 0 25 16777215 25 999999999 170704057 Qt::Horizontal 40 20 Generate batch file output: false Number of volumes to generate: 1 9999999 1 Qt::Horizontal 40 20 Save generated tissue path: 0 0 50 0 50 16777215 open Path to MitkMcxyz binary: 0 0 50 0 50 16777215 open Number of Photons (x1000): 0 999999999 1 100000 0 0 Generate Tissue Qt::Vertical 20 40 Tissue 10 10 391 581 0 0 391 581 0 0 0 0 0 0 0 25 16777215 25 11 75 false true false Air Parameters 0 0 0 25 16777215 25 50 false Thickness: 0 0 0 10 16777215 10 11 75 true 0 0 0 25 16777215 25 75 false true false Background Parameters 0 0 0 25 16777215 25 Absorption coefficient: 0 0 0 25 16777215 25 Scattering coefficient: 0 0 0 25 16777215 25 Anisotropy facor: 0 0 0 10 16777215 10 11 75 true 0 0 0 25 16777215 25 75 false true false Skin Parameters 0 0 0 25 16777215 25 Thickness: 0 0 0 25 16777215 25 Absorption coefficient: 0 0 0 25 16777215 25 Scattering coefficient: 0 0 0 25 16777215 25 Anisotropy facor: 0 0 0 10 16777215 10 11 75 true 0 0 0 25 16777215 25 75 false true false Fat Parameters 0 0 0 25 16777215 25 Body fat percentage: 0 0 0 25 16777215 25 Absorption coefficient: 0 0 0 25 16777215 25 Scattering coefficient: 0 0 0 25 16777215 25 Anisotropy facor: 0 0 0 25 16777215 25 11 75 true 0 0 0 25 16777215 25 999.990000000000009 0.100000000000000 12.000000000000000 0 0 0 25 16777215 25 mm Qt::Horizontal 40 20 0 0 0 10 16777215 10 11 75 true 0 0 0 25 16777215 25 75 true 0 0 0 25 16777215 25 0.010000000000000 0.100000000000000 0.100000000000000 0 0 0 25 16777215 25 per cm Qt::Horizontal 40 20 0 0 0 25 16777215 25 0.010000000000000 1000.000000000000000 0.500000000000000 15.000000000000000 0 0 0 25 16777215 25 per cm Qt::Horizontal 40 20 0 0 0 25 16777215 25 0.010000000000000 1.000000000000000 0.010000000000000 0.900000000000000 Qt::Horizontal 40 20 0 0 0 10 16777215 10 11 75 true 0 0 0 25 16777215 25 75 true 0 0 0 25 16777215 25 0.100000000000000 0.000000000000000 0 0 0 25 16777215 25 mm Qt::Horizontal 40 20 0 0 0 25 16777215 25 0.010000000000000 0.100000000000000 3.000000000000000 0 0 0 25 16777215 25 per cm Qt::Horizontal 40 20 0 0 0 25 16777215 25 0.010000000000000 1000.000000000000000 0.500000000000000 20.000000000000000 0 0 0 25 16777215 25 per cm Qt::Horizontal 40 20 0 0 0 25 16777215 25 0.010000000000000 1.000000000000000 0.010000000000000 0.900000000000000 Qt::Horizontal 40 20 0 0 0 10 16777215 10 11 75 true 0 0 0 25 16777215 25 75 true 0 0 0 25 16777215 25 0 1.000000000000000 0.000000000000000 0 0 0 25 16777215 25 % Qt::Horizontal 40 20 0 0 0 25 16777215 25 0.010000000000000 0.100000000000000 0.200000000000000 0 0 0 25 16777215 25 per cm Qt::Horizontal 40 20 0 0 0 25 16777215 25 0.010000000000000 1000.000000000000000 0.500000000000000 18.000000000000000 0 0 0 25 16777215 25 per cm Qt::Horizontal 40 20 0 0 0 25 16777215 25 0.010000000000000 1.000000000000000 0.010000000000000 0.900000000000000 Qt::Horizontal 40 20 Qt::Vertical 20 40 Vessels 10 10 391 581 0 0 391 581 0 0 0 0 75 true Vessel Parameters 0 25 16777215 25 The number of bloos vessels to generate Count: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 0 25 16777215 25 The radius of the blood vessels in mm Radius: 0 25 16777215 25 the absorption coefficient refers to the number of absorption events per centimeter. Absorption: 0 25 16777215 25 The reduced scattering coefficient. It refers to the amount of scattering events per centimeter. Scattering: 0 25 16777215 25 The anisotropy factor is the probability of a photon to not change its direction after a scattering event. Anisotropy factor: 0 25 16777215 25 The bifurcation frequency determines how often the vessel should bifurcate. The vessel will bifurcate after meandering a mean of the specified amount of voxels. When given a value of 0, the vessel will never bifurcate. Bifurcation frequency: 0 25 16777215 25 The curvedness it a setting to determine how much the vessel is allowed to bend during creation. A value of 0 refers to no bending at all and a value of 5 is the maximum. Curvedness: + + + + + 0 + 25 + + + + + 16777215 + 25 + + + + The spawn depth defines the depth range in which the vessels enter the volume. + + + Spawn depth: + + + 0 25 16777215 25 The minimum number of blood vessels 0 - 0 + 1 0 25 16777215 25 to 0 25 16777215 25 The maximum number of blood vessels - 0 + 3 0 25 16777215 25 Vessels Qt::Horizontal QSizePolicy::Expanding 60 20 0 25 16777215 25 The minimum radius 2.250000000000000 0 25 16777215 25 to 0 25 16777215 25 The maximum radius 4.050000000000000 0 25 16777215 25 mm Qt::Horizontal QSizePolicy::Expanding 60 20 0 25 16777215 25 The minimum absorption coefficient 0.010000000000000 2.000000000000000 0 25 16777215 25 to 0 25 16777215 25 The maximum absorption coefficient 0.010000000000000 8.000000000000000 0 25 16777215 25 per cm Qt::Horizontal QSizePolicy::Expanding 60 20 0 25 16777215 25 The minimum scattering 2 0.010000000000000 999.000000000000000 1.000000000000000 15.000000000000000 0 25 16777215 25 to 0 25 16777215 25 The minimum scattering 2 0.010000000000000 999.000000000000000 1.000000000000000 15.000000000000000 0 25 16777215 25 per cm Qt::Horizontal QSizePolicy::Expanding 60 20 0 25 16777215 25 The minimum anisotropy factor 2 0.010000000000000 1.000000000000000 0.100000000000000 0.900000000000000 0 25 16777215 25 to 0 25 16777215 25 The maximum anisotropy factor 2 0.010000000000000 1.000000000000000 0.100000000000000 0.900000000000000 Qt::Horizontal QSizePolicy::Expanding 60 20 0 25 16777215 25 The bifurcation frequency determines how often the vessel should bifurcate. The vessel will bifurcate after meandering a mean of the specified amount of voxels. When given a value of 0, the vessel will never bifurcate. 0 1.000000000000000 999999999.000000000000000 5.000000000000000 - 5000.000000000000000 + 20.000000000000000 0 25 16777215 25 voxels Qt::Horizontal QSizePolicy::Expanding 60 20 0 25 16777215 25 The minimal curvedness of the vessel. A value of 0 refers to no bending at all and a value of 5 is the maximum. 5.000000000000000 0.000000000000000 0 25 16777215 25 to 0 25 16777215 25 The maximal curvedness of the vessel. A value of 0 refers to no bending at all and a value of 5 is the maximum. 5.000000000000000 0.010000000000000 0.200000000000000 0 25 16777215 25 A.U. Qt::Horizontal QSizePolicy::Expanding 60 20 + + + + + + + 0 + 25 + + + + + 16777215 + 25 + + + + The minimum spawn depth + + + 0.010000000000000 + + + 2.200000000000000 + + + + + + + + 0 + 25 + + + + + 16777215 + 25 + + + + to + + + + + + + + 0 + 25 + + + + + 16777215 + 25 + + + + the maximum spawn depth + + + 0.010000000000000 + + + 4.200000000000000 + + + + + + + + 0 + 25 + + + + + 16777215 + 25 + + + + cm + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 60 + 20 + + + + + + Qt::Vertical 20 40 Monte Carlo 10 10 391 581 0 0 391 581 0 0 0 0 75 true Monte Carlo Parameters 0 25 16777215 25 50 false General: 0 0 0 25 16777215 25 Mcflag: 0 0 0 25 16777215 25 Launchflag: 0 0 0 25 16777215 25 Boundaryflag: 0 0 0 25 16777215 25 1 4 Qt::Horizontal 40 20 0 0 0 25 16777215 25 0 0 Qt::Horizontal 40 20 0 0 0 25 16777215 25 1 2 Qt::Horizontal 40 20 0 25 16777215 25 50 false Initial launch point: 0 25 16777215 25 x 0 25 16777215 25 4 1000000.000000000000000 0.000000000000000 0 25 16777215 25 y 0 25 16777215 25 4 1000000.000000000000000 0.000000000000000 0 25 16777215 25 z 0 25 16777215 25 4 1000000.000000000000000 0.000000000000000 Qt::Horizontal 40 20 0 25 16777215 25 50 false Focus point: 0 25 16777215 25 x 0 25 16777215 25 4 1000000.000000000000000 0.000000000000000 0 25 16777215 25 y 0 25 16777215 25 4 1000000.000000000000000 0.000000000000000 0 25 16777215 25 z 0 25 16777215 25 4 1000000.000000000000000 0.000000000000000 Qt::Horizontal 40 20 0 25 16777215 25 50 false Trajectory vector: 0 25 16777215 25 x 0 25 16777215 25 4 1000000.000000000000000 0.000000000000000 0 25 16777215 25 y 0 25 16777215 25 4 1000000.000000000000000 0.342000000000000 0 25 16777215 25 z 0 25 16777215 25 4 1000000.000000000000000 0.939700000000000 Qt::Horizontal 40 20 radius: waist: 4 1000.000000000000000 0.500000000000000 Qt::Horizontal 40 20 4 1000.000000000000000 0.010000000000000 Qt::Horizontal 40 20 Qt::Vertical 20 40 Wavelength 10 10 391 581 0 0 391 581 Qt::NoContextMenu 0 0 0 0 75 true Adjust physical properties by wavelength false 16777215 150 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This widget enables the adjustment of the physical properties of the tissue according to a selected wavelength of the light and the oxygen saturation of the blood.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The algorithm and measurements were provided by the publication <span style=" font-weight:600;">Optical properties of biological tissues: a review </span>by Steve L. Jacques.</p></body></html> 0 0 0 25 16777215 25 Wavelength: 0 0 0 25 16777215 25 Vessel oxygen saturation: 0 0 0 25 16777215 25 0 300.000000000000000 1000.000000000000000 650.000000000000000 Qt::Horizontal 40 20 0 0 0 25 16777215 25 0 100.000000000000000 75.000000000000000 0 0 0 25 16777215 25 % Qt::Horizontal 40 20 Adjust tissue properties Qt::Vertical 20 40