diff --git a/Modules/ModuleList.cmake b/Modules/ModuleList.cmake index afa09b7371..f13a8bda04 100644 --- a/Modules/ModuleList.cmake +++ b/Modules/ModuleList.cmake @@ -1,81 +1,82 @@ # The entries in the mitk_modules list must be # ordered according to their dependencies. set(mitk_modules Core CommandLine AppUtil DCMTesting RDF LegacyIO DataTypesExt Annotation LegacyGL AlgorithmsExt MapperExt DICOMReader DICOMReaderServices DICOMTesting SceneSerializationBase PlanarFigure ImageDenoising ImageExtraction LegacyAdaptors SceneSerialization Gizmo GraphAlgorithms Multilabel ImageStatistics ContourModel SurfaceInterpolation Segmentation PlanarFigureSegmentation OpenViewCore QtWidgets QtWidgetsExt C3js QmlItems SegmentationUI DiffusionImaging GPGPU OpenIGTLink IGTBase IGT CameraCalibration RigidRegistration RigidRegistrationUI DeformableRegistration DeformableRegistrationUI OpenCL OpenCVVideoSupport QtOverlays ToFHardware ToFProcessing ToFUI US USUI DicomUI Simulation Remeshing Python QtPython Persistence OpenIGTLinkUI IGTUI VtkShaders DicomRT RTUI IOExt XNAT TubeGraph BiophotonicsHardware Classification TumorInvasionAnalysis MatchPointRegistration + PhotoacousticSimulation MatchPointRegistrationUI BoundingShape ) if(MITK_ENABLE_PIC_READER) list(APPEND mitk_modules IpPicSupportIO) endif() diff --git a/Modules/PhotoacousticSimulation/CMakeLists.txt b/Modules/PhotoacousticSimulation/CMakeLists.txt new file mode 100644 index 0000000000..87021ccfb0 --- /dev/null +++ b/Modules/PhotoacousticSimulation/CMakeLists.txt @@ -0,0 +1,11 @@ +MITK_CREATE_MODULE( PhotoacousticSimulation + INCLUDE_DIRS src/Algorithms src/Utils src/ProbeDesign src/IO src/Thread + DEPENDS MitkAlgorithmsExt tinyxml + PACKAGE_DEPENDS + tinyxml + PUBLIC ITK +) + +add_subdirectory(MCxyz) + +add_subdirectory(Testing) diff --git a/Modules/PhotoacousticSimulation/MCxyz/CMakeLists.txt b/Modules/PhotoacousticSimulation/MCxyz/CMakeLists.txt new file mode 100644 index 0000000000..71e6c6e748 --- /dev/null +++ b/Modules/PhotoacousticSimulation/MCxyz/CMakeLists.txt @@ -0,0 +1,11 @@ +OPTION(BUILD_PhotoacousticSimulationMCxyz "Build MiniApp for Photoacoustic Simulation Module (mcxyz)" ON) + +IF(BUILD_PhotoacousticSimulationMCxyz) + PROJECT( MCxyz ) + mitk_create_executable(MCxyz + DEPENDS MitkCommandLine MitkCore MitkPhotoacousticSimulation + PACKAGE_DEPENDS + CPP_FILES mitkMCxyz.cpp) + + install(TARGETS ${EXECUTABLE_TARGET} RUNTIME DESTINATION bin) + ENDIF() diff --git a/Modules/PhotoacousticSimulation/MCxyz/files.cmake b/Modules/PhotoacousticSimulation/MCxyz/files.cmake new file mode 100644 index 0000000000..91f4bbcb81 --- /dev/null +++ b/Modules/PhotoacousticSimulation/MCxyz/files.cmake @@ -0,0 +1,3 @@ +set(CPP_FILES + mitkMCxyz.cpp +) diff --git a/Modules/PhotoacousticSimulation/MCxyz/mitkMCxyz.cpp b/Modules/PhotoacousticSimulation/MCxyz/mitkMCxyz.cpp new file mode 100755 index 0000000000..d27342d979 --- /dev/null +++ b/Modules/PhotoacousticSimulation/MCxyz/mitkMCxyz.cpp @@ -0,0 +1,1479 @@ +/*=================================================================== + +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. + +===================================================================*/ +// Please retain the following copyright notice +/****************************************************************** + * based on mcxyz.c Oct2014 + * + * mcxyz.c, in ANSI Standard C programing language + * + * created 2010, 2012 by + * Steven L. JACQUES + * Ting LI + * Oregon Health & Science University + * + *******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "mitkCommandLineParser.h" +#include "mitkIOUtil.h" +#include "mitkImageCast.h" +#include +#include +#include +#include +#include + +#include +#include "mitkPhotoacousticLightSource.h" +#include + +#ifdef __linux__ +#include +#include +#else +#include +#endif + +#define ls 1.0E-7 /* Moving photon a little bit off the voxel face */ +#define PI 3.1415926 +#define ALIVE 1 /* if photon not yet terminated */ +#define DEAD 0 /* if photon is to be terminated */ +#define THRESHOLD 0.01 /* used in roulette */ +#define CHANCE 0.1 /* used in roulette */ +#define SQR(x) (x*x) +#define SIGN(x) ((x)>=0 ? 1:-1) +#define ONE_MINUS_COSZERO 1.0E-12 /* If 1-cos(theta) <= ONE_MINUS_COSZERO, fabs(theta) <= 1e-6 rad. */ +/* If 1+cos(theta) <= ONE_MINUS_COSZERO, fabs(PI-theta) <= 1e-6 rad. */ + +/* Struct for storing x,y and z coordinates */ +struct Location +{ + int x, y, z; + double absorb; +}; + +struct Location initLocation(int x, int y, int z, double absorb) +{ + struct Location loc; + loc.x = x; + loc.y = y; + loc.z = z; + loc.absorb = absorb; + return loc; +} + +class DetectorVoxel +{ +public: + Location location; + std::vector* recordedPhotonRoute = new std::vector(); + double* fluenceContribution; + double m_PhotonNormalizationValue; + long m_NumberPhotonsCurrent; + + DetectorVoxel(Location location, long totalNumberOfVoxels, double photonNormalizationValue) + { + this->location = location; + this->fluenceContribution = (double *)malloc(totalNumberOfVoxels*sizeof(double)); + for(int j=0; jGetVolumeData(0)); + normalizationVector = (double *) readAccess3.GetData(); + } + + if (m_inputImage.IsNotNull()) // load stuff from nrrd file + { + simulationTimeFromFile = 0; + + Nx = m_inputImage->GetDimensions()[1]; + Ny = m_inputImage->GetDimensions()[0]; + Nz = m_inputImage->GetDimensions()[2]; + + xSpacing = m_inputImage->GetGeometry(0)->GetSpacing()[0]; + ySpacing = m_inputImage->GetGeometry(0)->GetSpacing()[1]; + zSpacing = m_inputImage->GetGeometry(0)->GetSpacing()[2]; + + mcflag = std::stoi(m_inputImage->GetProperty("mcflag")->GetValueAsString().c_str()); // mcflag, 0 = uniform, 1 = Gaussian, 2 = iso-pt, 4 = monospectral fraunhofer setup + launchflag = std::stoi(m_inputImage->GetProperty("launchflag")->GetValueAsString().c_str());// 0 = let mcxyz calculate trajectory, 1 = manually set launch vector + boundaryflag = std::stoi(m_inputImage->GetProperty("boundaryflag")->GetValueAsString().c_str());// 0 = no boundaries, 1 = escape at boundaries, 2 = escape at surface only + + xs = std::stod(m_inputImage->GetProperty("launchPointX")->GetValueAsString().c_str()); + ys = std::stod(m_inputImage->GetProperty("launchPointY")->GetValueAsString().c_str()) + yOffset; + zs = std::stod(m_inputImage->GetProperty("launchPointZ")->GetValueAsString().c_str()); + + xfocus = std::stod(m_inputImage->GetProperty("focusPointX")->GetValueAsString().c_str()); + yfocus = std::stod(m_inputImage->GetProperty("focusPointY")->GetValueAsString().c_str()); + zfocus = std::stod(m_inputImage->GetProperty("focusPointZ")->GetValueAsString().c_str()); + + ux0 = std::stod(m_inputImage->GetProperty("trajectoryVectorX")->GetValueAsString().c_str()); + uy0 = std::stod(m_inputImage->GetProperty("trajectoryVectorY")->GetValueAsString().c_str()); + uz0 = std::stod(m_inputImage->GetProperty("trajectoryVectorZ")->GetValueAsString().c_str()); + + radius = std::stod(m_inputImage->GetProperty("radius")->GetValueAsString().c_str()); + waist = std::stod(m_inputImage->GetProperty("waist")->GetValueAsString().c_str()); + + totalNumberOfVoxels = Nx*Ny*Nz; + if (verbose) std::cout << totalNumberOfVoxels << " = sizeof totalNumberOfVoxels" << std::endl; + + muaVector = ( double *)malloc(totalNumberOfVoxels*sizeof(double)); /* tissue structure */ + musVector = ( double *)malloc(totalNumberOfVoxels*sizeof(double)); /* tissue structure */ + gVector = ( double *)malloc(totalNumberOfVoxels*sizeof(double)); /* tissue structure */ + + mitk::ImageReadAccessor readAccess0(m_inputImage, m_inputImage->GetVolumeData(0)); + muaVector = (double *) readAccess0.GetData(); + mitk::ImageReadAccessor readAccess1(m_inputImage, m_inputImage->GetVolumeData(1)); + musVector = (double *) readAccess1.GetData(); + mitk::ImageReadAccessor readAccess2(m_inputImage, m_inputImage->GetVolumeData(2)); + gVector = (double *) readAccess2.GetData(); + } + else + { + mitkThrow() << "No longer support loading of binary tissue files."; + } + } +}; + +class ReturnValues +{ + +private: + long i1 = 0, i2 = 31; // used Random Generator + long ma[56]; // used Random Generator /* ma[0] is not used. */ + long mj, mk; + short i, ii; +public: + long long Nphotons; + double* totalFluence; + std::string myname; + DetectorVoxel* detectorVoxel; + + ReturnValues() + { + detectorVoxel = nullptr; + Nphotons = 0; + totalFluence = nullptr; + } + + /* SUBROUTINES */ + + /************************************************************************** + * RandomGen + * A random number generator that generates uniformly + * distributed random numbers between 0 and 1 inclusive. + * The algorithm is based on: + * W.H. Press, S.A. Teukolsky, W.T. Vetterling, and B.P. + * Flannery, "Numerical Recipes in C," Cambridge University + * Press, 2nd edition, (1992). + * and + * D.E. Knuth, "Seminumerical Algorithms," 2nd edition, vol. 2 + * of "The Art of Computer Programming", Addison-Wesley, (1981). + * + * When Type is 0, sets Seed as the seed. Make sure 0 b) + m = a; + else + m = b; + return m; + } + + /*********************************************************** + * min2 + ****/ + double min2(double a, double b) { + double m; + if (a >= b) + m = b; + else + m = a; + return m; + } + /*********************************************************** + * min3 + ****/ + double min3(double a, double b, double c) { + double m; + if (a <= min2(b, c)) + m = a; + else if (b <= min2(a, c)) + m = b; + else + m = c; + return m; + } + + /******************** + * my version of FindVoxelFace for no scattering. + * s = ls + FindVoxelFace2(x,y,z, tempx, tempy, tempz, dx, dy, dz, ux, uy, uz); + ****/ + double FindVoxelFace2(double x1,double y1,double z1, double x2, double y2, double z2,double dx,double dy,double dz, double ux, double uy, double uz) + { + int ix1 = floor(x1/dx); + int iy1 = floor(y1/dy); + int iz1 = floor(z1/dz); + + int ix2,iy2,iz2; + if (ux >= 0) + ix2 = ix1 + 1; + else + ix2 = ix1; + + if (uy >= 0) + iy2 = iy1 + 1; + else + iy2 = iy1; + + if (uz >= 0) + iz2 = iz1 + 1; + else + iz2 = iz1; + + double xs = fabs( (ix2*dx - x1)/ux); + double ys = fabs( (iy2*dy - y1)/uy); + double zs = fabs( (iz2*dz - z1)/uz); + + double s = min3(xs, ys, zs); + + return s; + } + + /*********************************************************** + * FRESNEL REFLECTANCE + * Computes reflectance as photon passes from medium 1 to + * medium 2 with refractive indices n1,n2. Incident + * angle a1 is specified by cosine value ca1 = cos(a1). + * Program returns value of transmitted angle a1 as + * value in *ca2_Ptr = cos(a2). + ****/ + double RFresnel(double n1, /* incident refractive index.*/ + double n2, /* transmit refractive index.*/ + double ca1, /* cosine of the incident */ + /* angle a1, 00. */ + { + double r; + + if(n1==n2) { /** matched boundary. **/ + *ca2_Ptr = ca1; + r = 0.0; + } + else if(ca1>(1.0 - 1.0e-12)) { /** normal incidence. **/ + *ca2_Ptr = ca1; + r = (n2-n1)/(n2+n1); + r *= r; + } + else if(ca1< 1.0e-6) { /** very slanted. **/ + *ca2_Ptr = 0.0; + r = 1.0; + } + else { /** general. **/ + double sa1, sa2; /* sine of incident and transmission angles. */ + double ca2; /* cosine of transmission angle. */ + sa1 = sqrt(1-ca1*ca1); + sa2 = n1*sa1/n2; + if(sa2>=1.0) { + /* double check for total internal reflection. */ + *ca2_Ptr = 0.0; + r = 1.0; + } + else { + double cap, cam; /* cosines of sum ap or diff am of the two */ + /* angles: ap = a1 + a2, am = a1 - a2. */ + double sap, sam; /* sines. */ + *ca2_Ptr = ca2 = sqrt(1-sa2*sa2); + cap = ca1*ca2 - sa1*sa2; /* c+ = cc - ss. */ + cam = ca1*ca2 + sa1*sa2; /* c- = cc + ss. */ + sap = sa1*ca2 + ca1*sa2; /* s+ = sc + cs. */ + sam = sa1*ca2 - ca1*sa2; /* s- = sc - cs. */ + r = 0.5*sam*sam*(cam*cam+cap*cap)/(sap*sap*cam*cam); + /* rearranged for speed. */ + } + } + return(r); + } /******** END SUBROUTINE **********/ + + + + /*********************************************************** + * the boundary is the face of some voxel + * find the the photon's hitting position on the nearest face of the voxel and update the step size. + ****/ + double FindVoxelFace(double x1,double y1,double z1, double x2, double y2, double z2,double dx,double dy,double dz, double ux, double uy, double uz) + { + double x_1 = x1/dx; + double y_1 = y1/dy; + double z_1 = z1/dz; + double x_2 = x2/dx; + double y_2 = y2/dy; + double z_2 = z2/dz; + double fx_1 = floor(x_1) ; + double fy_1 = floor(y_1) ; + double fz_1 = floor(z_1) ; + double fx_2 = floor(x_2) ; + double fy_2 = floor(y_2) ; + double fz_2 = floor(z_2) ; + double x=0, y=0, z=0, x0=0, y0=0, z0=0, s=0; + + if ((fx_1 != fx_2) && (fy_1 != fy_2) && (fz_1 != fz_2) ) { //#10 + fx_2=fx_1+SIGN(fx_2-fx_1);//added + fy_2=fy_1+SIGN(fy_2-fy_1);//added + fz_2=fz_1+SIGN(fz_2-fz_1);//added + + x = (max2(fx_1,fx_2)-x_1)/ux; + y = (max2(fy_1,fy_2)-y_1)/uy; + z = (max2(fz_1,fz_2)-z_1)/uz; + if (x == min3(x,y,z)) { + x0 = max2(fx_1,fx_2); + y0 = (x0-x_1)/ux*uy+y_1; + z0 = (x0-x_1)/ux*uz+z_1; + } + else if (y == min3(x,y,z)) { + y0 = max2(fy_1,fy_2); + x0 = (y0-y_1)/uy*ux+x_1; + z0 = (y0-y_1)/uy*uz+z_1; + } + else { + z0 = max2(fz_1,fz_2); + y0 = (z0-z_1)/uz*uy+y_1; + x0 = (z0-z_1)/uz*ux+x_1; + } + } + else if ( (fx_1 != fx_2) && (fy_1 != fy_2) ) { //#2 + fx_2=fx_1+SIGN(fx_2-fx_1);//added + fy_2=fy_1+SIGN(fy_2-fy_1);//added + x = (max2(fx_1,fx_2)-x_1)/ux; + y = (max2(fy_1,fy_2)-y_1)/uy; + if (x == min2(x,y)) { + x0 = max2(fx_1,fx_2); + y0 = (x0-x_1)/ux*uy+y_1; + z0 = (x0-x_1)/ux*uz+z_1; + } + else { + y0 = max2(fy_1, fy_2); + x0 = (y0-y_1)/uy*ux+x_1; + z0 = (y0-y_1)/uy*uz+z_1; + } + } + else if ( (fy_1 != fy_2) &&(fz_1 != fz_2) ) { //#3 + fy_2=fy_1+SIGN(fy_2-fy_1);//added + fz_2=fz_1+SIGN(fz_2-fz_1);//added + y = (max2(fy_1,fy_2)-y_1)/uy; + z = (max2(fz_1,fz_2)-z_1)/uz; + if (y == min2(y,z)) { + y0 = max2(fy_1,fy_2); + x0 = (y0-y_1)/uy*ux+x_1; + z0 = (y0-y_1)/uy*uz+z_1; + } + else { + z0 = max2(fz_1, fz_2); + x0 = (z0-z_1)/uz*ux+x_1; + y0 = (z0-z_1)/uz*uy+y_1; + } + } + else if ( (fx_1 != fx_2) && (fz_1 != fz_2) ) { //#4 + fx_2=fx_1+SIGN(fx_2-fx_1);//added + fz_2=fz_1+SIGN(fz_2-fz_1);//added + x = (max2(fx_1,fx_2)-x_1)/ux; + z = (max2(fz_1,fz_2)-z_1)/uz; + if (x == min2(x,z)) { + x0 = max2(fx_1,fx_2); + y0 = (x0-x_1)/ux*uy+y_1; + z0 = (x0-x_1)/ux*uz+z_1; + } + else { + z0 = max2(fz_1, fz_2); + x0 = (z0-z_1)/uz*ux+x_1; + y0 = (z0-z_1)/uz*uy+y_1; + } + } + else if (fx_1 != fx_2) { //#5 + fx_2=fx_1+SIGN(fx_2-fx_1);//added + x0 = max2(fx_1,fx_2); + y0 = (x0-x_1)/ux*uy+y_1; + z0 = (x0-x_1)/ux*uz+z_1; + } + else if (fy_1 != fy_2) { //#6 + fy_2=fy_1+SIGN(fy_2-fy_1);//added + y0 = max2(fy_1, fy_2); + x0 = (y0-y_1)/uy*ux+x_1; + z0 = (y0-y_1)/uy*uz+z_1; + } + else { //#7 + z0 = max2(fz_1, fz_2); + fz_2=fz_1+SIGN(fz_2-fz_1);//added + x0 = (z0-z_1)/uz*ux+x_1; + y0 = (z0-z_1)/uz*uy+y_1; + } + //s = ( (x0-fx_1)*dx + (y0-fy_1)*dy + (z0-fz_1)*dz )/3; + //s = sqrt( SQR((x0-x_1)*dx) + SQR((y0-y_1)*dy) + SQR((z0-z_1)*dz) ); + //s = sqrt(SQR(x0-x_1)*SQR(dx) + SQR(y0-y_1)*SQR(dy) + SQR(z0-z_1)*SQR(dz)); + s = sqrt( SQR((x0-x_1)*dx) + SQR((y0-y_1)*dy) + SQR((z0-z_1)*dz)); + return (s); + } +}; + +/* DECLARE FUNCTIONS */ + +void runMonteCarlo(InputValues* inputValues, ReturnValues* returnValue, int thread, mitk::MonteCarloThreadHandler::Pointer threadHandler); + +int detector_x = -1; +int detector_z = -1; +bool interpretAsTime = true; +bool simulatePVFC = false; +int requestedNumberOfPhotons = 100000; +float requestedSimulationTime = 0; // in minutes +int concurentThreadsSupported = -1; +float yOffset = 0; // in mm +bool saveLegacy = false; +std::string normalizationFilename; +std::string inputFilename; +std::string outputFilename; + +mitk::PhotoacousticProbe::Pointer m_PhotoacousticProbe; + +int main(int argc, char * argv[]) { + mitkCommandLineParser parser; + // set general information + parser.setCategory( "MITK-Photoacoustics" ); + parser.setTitle( "Mitk MCxyz" ); + parser.setDescription( "Runs Monte Carlo simulations on inputed tissues." ); + parser.setContributor( "CAI, DKFZ based on code by Jacques and Li" ); + + // 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 I/O parameters"); + parser.addArgument( + "input", "i", mitkCommandLineParser::InputFile, + "Input tissue file", "input tissue file (*.nrrd)", + us::Any(), false ); + parser.addArgument( + "output", "o", mitkCommandLineParser::OutputFile, + "Output fluence file", "where to save the simulated fluence (*.nrrd)", + us::Any(), false ); + parser.endGroup(); + parser.beginGroup("Optional parameters"); + parser.addArgument( + "verbose", "v", mitkCommandLineParser::Bool, + "Verbose Output", "Whether to produce verbose, or rather debug output" ); + parser.addArgument( + "detector-x", "dx", mitkCommandLineParser::Int, + "Detector voxel x position", "Determines the x position of the detector voxel (default: -1 = dont use detector voxel)", -1 ); + parser.addArgument( + "detector-z", "dz", mitkCommandLineParser::Int, + "Detector voxel z position", "Determines the z position of the detector voxel (default: -1 = dont use detector voxel)", -1 ); + parser.addArgument( + "number-of-photons", "n", mitkCommandLineParser::Int, + "Number of photons", "Specifies the number of photons (default: 100000). Simulation stops after that number. Use -t --timer to define a timer instead"); + parser.addArgument( + "timer", "t", mitkCommandLineParser::Float, + "Simulation time in min", "Specifies the amount of time for simutation (default: 0). Simulation stops after that number of minutes. -n --number-of-photons is the override and default behavior and defines the maximum number of photons instead. If no simulation time or number of photons is specified the file time is taken."); + parser.addArgument( + "y-offset", "yo", mitkCommandLineParser::Float, + "Probe Y-Offset in mm", "Specifies an offset of the photoacoustic probe in the y direction depending on the initial probe position (default: 0) in mm."); + parser.addArgument( + "jobs", "j", mitkCommandLineParser::Int, + "Number of jobs", "Specifies the number of jobs for simutation (default: -1 which starts as many jobs as supported)."); + parser.addArgument( + "probe-xml", "p", mitkCommandLineParser::InputFile, + "Xml definition of the probe", "Specifies the absolute path of the location of the xml definition file of the probe design."); + parser.addArgument("normalization-file", "nf", mitkCommandLineParser::InputFile, + "Input normalization file", "The input normalization file is used for normalization of the number of photons in the PVFC calculations."); + parser.endGroup(); + + // parse arguments, this method returns a mapping of long argument names and their values + std::map parsedArgs = parser.parseArguments( argc, argv ); + if ( parsedArgs.size() == 0 ) + return EXIT_FAILURE; + // parse, cast and set required arguments + inputFilename = us::any_cast( parsedArgs[ "input" ] ); + // strip ending + inputFilename = inputFilename.substr(0, inputFilename.find("_H.mci")); + inputFilename = inputFilename.substr(0, inputFilename.find("_T.bin")); + + outputFilename = us::any_cast( parsedArgs[ "output" ] ); + // add .nrrd if not there + std::string suffix = ".nrrd"; + if (outputFilename.compare(outputFilename.size() - suffix.size(), suffix.size(), suffix) != 0) + outputFilename = outputFilename + suffix; + + + + // default values for optional arguments + // parse, cast and set optional arguments if given + if ( parsedArgs.count( "verbose" ) ) + { + verbose = us::any_cast( parsedArgs[ "verbose" ] ); + } + if ( parsedArgs.count( "detector-x" ) ) + { + detector_x = us::any_cast( parsedArgs[ "detector-x" ] ); + } + if ( parsedArgs.count( "detector-z" ) ) + { + detector_z = us::any_cast( parsedArgs[ "detector-z" ] ); + } + if ( parsedArgs.count( "timer" ) ) + { + requestedSimulationTime = us::any_cast( parsedArgs[ "timer" ] ); + if (requestedSimulationTime > 0) interpretAsTime = true; + } + if ( parsedArgs.count( "y-offset" ) ) + { + yOffset = us::any_cast( parsedArgs[ "y-offset" ] ); + } + if ( parsedArgs.count( "number-of-photons" ) ) + { + requestedNumberOfPhotons = us::any_cast( parsedArgs[ "number-of-photons" ] ); + if (requestedNumberOfPhotons > 0) interpretAsTime = false; + } + if ( parsedArgs.count( "jobs" ) ) + { + concurentThreadsSupported = us::any_cast( parsedArgs[ "jobs" ] ); + } + if ( parsedArgs.count( "probe-xml") ) + { + std::string inputXmlProbeDesign = us::any_cast( parsedArgs[ "probe-xml" ] ); + m_PhotoacousticProbe = mitk::PhotoacousticProbe::New(inputXmlProbeDesign, verbose); + if(!m_PhotoacousticProbe->IsValid()) + { + std::cerr << "Xml File was not valid. Simulation failed." << std::endl; + return EXIT_FAILURE; + } + } + if ( parsedArgs.count( "normalization-file" ) ) + { + normalizationFilename = us::any_cast( parsedArgs[ "normalization-file" ] ); + } + + if(concurentThreadsSupported == 0 || concurentThreadsSupported == -1) + { + concurentThreadsSupported = std::thread::hardware_concurrency(); + if(concurentThreadsSupported == 0) + { + std::cout << "Could not determine number of available threads. Launching only one." << std::endl; + concurentThreadsSupported = 1; + } + } + + if(detector_x!=-1 && detector_z!=-1) + { + if(verbose) + std::cout << "Performing PVFC calculation for x=" << detector_x << " and z=" << detector_z << std::endl; + simulatePVFC = true; + } + else + { + if(verbose) + std::cout << "Will not perform PVFC calculation due to x=" << detector_x << " and/or z=" << detector_z << std::endl; + } + + InputValues allInput = InputValues(); + allInput.LoadValues(inputFilename, yOffset, normalizationFilename, simulatePVFC); + + std::vector allValues(concurentThreadsSupported); + std::thread* threads = new std::thread[concurentThreadsSupported]; + + for(long i=0; iSetPackageSize(1000); + + if (verbose) std::cout << "\nStarting simulation ...\n" << std::endl; + + auto simulationStartTime = std::chrono::system_clock::now(); + + for(int i = 0; i(simulationTimeElapsed).count() << "sec " << std::endl; + + /**** SAVE + Convert data to relative fluence rate [cm^-2] and save. + *****/ + + if(!simulatePVFC) + { + if (verbose) std::cout << "Allocating memory for normal simulation result ... "; + double* finalTotalFluence = (double *)malloc(allInput.totalNumberOfVoxels*sizeof(double)); + if (verbose) std::cout << "[OK]" << std::endl; + if (verbose) std::cout << "Cleaning memory for normal simulation result ..."; + for (int i=0; i(); + unsigned int* dimensionsOfImage = new unsigned int[3]; + + // Copy dimensions + dimensionsOfImage[0] = allInput.Ny; + dimensionsOfImage[1] = allInput.Nx; + dimensionsOfImage[2] = allInput.Nz; + + resultImage->Initialize(TPixel, 3, dimensionsOfImage); + + mitk::Vector3D spacing; + spacing[0] = allInput.ySpacing; + spacing[1] = allInput.xSpacing; + spacing[2] = allInput.zSpacing; + resultImage->SetSpacing(spacing); + resultImage->SetImportVolume( finalTotalFluence, 0,0, mitk::Image::CopyMemory ); + + resultImage->GetPropertyList()->SetFloatProperty("y-offset", yOffset); + mitk::CoreServices::GetPropertyPersistence()->AddInfo("y-offset", mitk::PropertyPersistenceInfo::New("y-offset")); + + mitk::IOUtil::SaveImage(resultImage, outputFilename); + + if (verbose) std::cout << "[OK]" << std::endl; + + if (verbose) + { + std::cout << "x spacing = " << tdx << std::endl; + std::cout << "y spacing = " << tdy << std::endl; + std::cout << "z spacing = " << tdz << std::endl; + std::cout << "total number of voxels = " << allInput.totalNumberOfVoxels << std::endl; + std::cout << "number of photons = " << (int) tNphotons << std::endl; + } + } + else // if simulate PVFC + { + if (verbose) std::cout << "Allocating memory for PVFC simulation result ... "; + double* detectorFluence = ((double*) malloc(allInput.totalNumberOfVoxels*sizeof(double))); + if (verbose) std::cout << "[OK]" << std::endl; + if (verbose) std::cout << "Cleaning memory for PVFC simulation result ..."; + for (int i=0; im_NumberPhotonsCurrent; + for (int voxelNumber=0; voxelNumberfluenceContribution[voxelNumber]; + } + } + if (verbose) std::cout << "[OK]" << std::endl; + std::cout << "total number of photons simulated: " + << tNphotons << std::endl; + + // Normalize deposition (A) to yield fluence rate (F). + double temp = tdx*tdy*tdz*tNphotons; + for (int i=0; ilocation.x; + double detectorY = allValues[0].detectorVoxel->location.y; + double detectorZ = allValues[0].detectorVoxel->location.z; + detectorname << detectorX << "," << detectorY<< "," + << detectorZ << "FluenceContribution.nrrd"; + // Save the binary file + std::string outputFileBase = outputFilename.substr(0, outputFilename.find(".nrrd")); + outputFilename = outputFileBase + "_p" + detectorname.str().c_str(); + + mitk::Image::Pointer pvfcImage = mitk::Image::New(); + unsigned int* dimensionsOfPvfcImage = new unsigned int[3]; + + // Copy dimensions + dimensionsOfPvfcImage[0] = allInput.Ny; + dimensionsOfPvfcImage[1] = allInput.Nx; + dimensionsOfPvfcImage[2] = allInput.Nz; + + pvfcImage->Initialize(mitk::MakeScalarPixelType(), 3, dimensionsOfPvfcImage); + + mitk::Vector3D pvfcSpacing; + pvfcSpacing[0] = allInput.ySpacing; + pvfcSpacing[1] = allInput.xSpacing; + pvfcSpacing[2] = allInput.zSpacing; + pvfcImage->SetSpacing(pvfcSpacing); + pvfcImage->SetImportVolume( detectorFluence, 0,0, mitk::Image::CopyMemory ); + + pvfcImage->GetPropertyList()->SetFloatProperty("detector-x", detectorX); + mitk::CoreServices::GetPropertyPersistence()->AddInfo("detector-x", mitk::PropertyPersistenceInfo::New("detector-x")); + pvfcImage->GetPropertyList()->SetFloatProperty("detector-y", detectorY); + mitk::CoreServices::GetPropertyPersistence()->AddInfo("detector-y", mitk::PropertyPersistenceInfo::New("detector-y")); + pvfcImage->GetPropertyList()->SetFloatProperty("detector-z", detectorZ); + mitk::CoreServices::GetPropertyPersistence()->AddInfo("detector-z", mitk::PropertyPersistenceInfo::New("detector-z")); + pvfcImage->GetPropertyList()->SetFloatProperty("normalization-factor", allValues[0].detectorVoxel->m_PhotonNormalizationValue); + mitk::CoreServices::GetPropertyPersistence()->AddInfo("normalization-factor", mitk::PropertyPersistenceInfo::New("normalization-factor")); + pvfcImage->GetPropertyList()->SetFloatProperty("simulated-photons", pvfcPhotons); + mitk::CoreServices::GetPropertyPersistence()->AddInfo("simulated-photons", mitk::PropertyPersistenceInfo::New("simulated-photons")); + + mitk::IOUtil::SaveImage(pvfcImage, outputFilename); + + if (verbose) std::cout << "[OK]" << std::endl; + + if (verbose) + { + std::cout << "x spacing = " << tdx << std::endl; + std::cout << "y spacing = " << tdy << std::endl; + std::cout << "z spacing = " << tdz << std::endl; + std::cout << "total number of voxels = " << allInput.totalNumberOfVoxels << std::endl; + std::cout << "number of photons = " << (int) tNphotons << std::endl; + } + } + + exit(EXIT_SUCCESS); +} /* end of main */ + + +/* CORE FUNCTION */ +void runMonteCarlo(InputValues* inputValues, ReturnValues* returnValue, int thread, mitk::MonteCarloThreadHandler::Pointer threadHandler) +{ + if (verbose) std::cout << "Thread "<totalFluence = (double *)malloc(inputValues->totalNumberOfVoxels*sizeof(double)); /* relative fluence rate [W/cm^2/W.delivered] */ + + if(detector_x!=-1 && detector_z!=-1) + { + if(detector_x<0 || detector_x>inputValues->Nx) + { + std::cout << "Requested detector x position not valid. Needs to be >= 0 and <= " << inputValues->Nx << std::endl; + exit(EXIT_FAILURE); + } + if(detector_z<1 || detector_z>inputValues->Nz) + { + std::cout << "Requested detector z position not valid. Needs to be > 0 and <= " << inputValues->Nz << std::endl; + exit(EXIT_FAILURE); + } + + double photonNormalizationValue = 1 / inputValues->GetNormalizationValue(detector_x,inputValues->Ny/2,detector_z); + returnValue->detectorVoxel = new DetectorVoxel(initLocation(detector_x,inputValues->Ny/2,detector_z,0),inputValues->totalNumberOfVoxels, photonNormalizationValue); + } + + /**** ======================== MAJOR CYCLE ============================ *****/ + + auto duration = std::chrono::system_clock::now().time_since_epoch(); + returnValue->RandomGen(0, (std::chrono::duration_cast(duration).count()+thread)%32000, NULL); /* initiate with seed = 1, or any long integer. */ + for(j=0; jtotalNumberOfVoxels;j++) returnValue->totalFluence[j] = 0; // ensure F[] starts empty. + + /**** RUN Launch N photons, initializing each one before progation. *****/ + + long photonsToSimulate = 0; + + do{ + + photonsToSimulate = threadHandler->GetNextWorkPackage(); + if(returnValue->detectorVoxel != nullptr) + { + photonsToSimulate = photonsToSimulate * returnValue->detectorVoxel->m_PhotonNormalizationValue; + } + + if(verbose) + MITK_INFO << "Photons to simulate: " << photonsToSimulate; + + photonIterator = 0L; + + do { + /**** LAUNCH Initialize photon position and trajectory. *****/ + + photonIterator += 1; /* increment photon count */ + W = 1.0; /* set photon weight to one */ + photon_status = ALIVE; /* Launch an ALIVE photon */ + CNT = 0; + + /**** SET SOURCE* Launch collimated beam at x,y center.****/ + /****************************/ + /* Initial position. */ + + if(m_PhotoacousticProbe.IsNotNull()) + { + double rnd1 = -1; + double rnd2 = -1; + double rnd3 = -1; + double rnd4 = -1; + double rnd5 = -1; + double rnd6 = -1; + double rnd7 = -1; + double rnd8 = -1; + + while ((rnd1 = returnValue->RandomGen(1,0,NULL)) <= 0.0); + while ((rnd2 = returnValue->RandomGen(1,0,NULL)) <= 0.0); + while ((rnd3 = returnValue->RandomGen(1,0,NULL)) <= 0.0); + while ((rnd4 = returnValue->RandomGen(1,0,NULL)) <= 0.0); + while ((rnd5 = returnValue->RandomGen(1,0,NULL)) <= 0.0); + while ((rnd6 = returnValue->RandomGen(1,0,NULL)) <= 0.0); + while ((rnd7 = returnValue->RandomGen(1,0,NULL)) <= 0.0); + while ((rnd8 = returnValue->RandomGen(1,0,NULL)) <= 0.0); + + mitk::PhotoacousticLightSource::PhotonInformation info = m_PhotoacousticProbe->GetNextPhoton(rnd1, rnd2, rnd3, rnd4, rnd5, rnd6, rnd7, rnd8); + x = info.xPosition; + y = yOffset + info.yPosition; + z = info.zPosition; + ux = info.xAngle; + uy = info.yAngle; + uz = info.zAngle; + if(verbose) + std::cout << "Created photon at position (" << x << "|" << y << "|" << z << ") with angles (" << ux << "|" << uy << "|" << uz << ")." << std::endl; + } + else + { + /* trajectory */ + if (inputValues->launchflag == 1) // manually set launch + { + x = inputValues->xs; + y = inputValues->ys; + z = inputValues->zs; + ux = inputValues->ux0; + uy = inputValues->uy0; + uz = inputValues->uz0; + } + else // use mcflag + { + if (inputValues->mcflag == 0) // uniform beam + { + // set launch point and width of beam + while ((rnd = returnValue->RandomGen(1,0,NULL)) <= 0.0); // avoids rnd = 0 + r = inputValues->radius*sqrt(rnd); // radius of beam at launch point + while ((rnd = returnValue->RandomGen(1,0,NULL)) <= 0.0); // avoids rnd = 0 + phi = rnd*2.0*PI; + x = inputValues->xs + r*cos(phi); + y = inputValues->ys + r*sin(phi); + z = inputValues->zs; + // set trajectory toward focus + while ((rnd = returnValue->RandomGen(1,0,NULL)) <= 0.0); // avoids rnd = 0 + r = inputValues->waist*sqrt(rnd); // radius of beam at focus + while ((rnd = returnValue->RandomGen(1,0,NULL)) <= 0.0); // avoids rnd = 0 + phi = rnd*2.0*PI; + + // !!!!!!!!!!!!!!!!!!!!!!! setting input values will braek + + inputValues->xfocus = r*cos(phi); + inputValues->yfocus = r*sin(phi); + temp = sqrt((x - inputValues->xfocus)*(x - inputValues->xfocus) + + (y - inputValues->yfocus)*(y - inputValues->yfocus) + inputValues->zfocus*inputValues->zfocus); + ux = -(x - inputValues->xfocus)/temp; + uy = -(y - inputValues->yfocus)/temp; + uz = sqrt(1 - ux*ux + uy*uy); + } + else if (inputValues->mcflag == 5) // Multispectral DKFZ prototype + { + // set launch point and width of beam + while ((rnd = returnValue->RandomGen(1,0,NULL)) <= 0.0); + + //offset in x direction in cm (random) + x = (rnd*2.5)-1.25; + + while ((rnd = returnValue->RandomGen(1,0,NULL)) <= 0.0); + double b = ((rnd)-0.5); + y = (b >0? yOffset+1.5 : yOffset-1.5); + z = 0.1; + ux = 0; + + while ((rnd = returnValue->RandomGen(1,0,NULL)) <= 0.0); + + //Angle of beam in y direction + uy = sin((rnd*0.42)-0.21 + (b < 0? 1.0 : -1.0) * 0.436); + + while ((rnd = returnValue->RandomGen(1,0,NULL)) <= 0.0); + + // angle of beam in x direction + ux = sin((rnd*0.42)-0.21); + uz = sqrt(1 - ux*ux - uy*uy); + } + else if (inputValues->mcflag == 4) // Monospectral prototype DKFZ + { + // set launch point and width of beam + while ((rnd = returnValue->RandomGen(1,0,NULL)) <= 0.0); + + //offset in x direction in cm (random) + x = (rnd*2.5)-1.25; + + while ((rnd = returnValue->RandomGen(1,0,NULL)) <= 0.0); + double b = ((rnd)-0.5); + y = (b >0? yOffset+0.83 : yOffset-0.83); + z = 0.1; + ux = 0; + + while ((rnd = returnValue->RandomGen(1,0,NULL)) <= 0.0); + + //Angle of beam in y direction + uy = sin((rnd*0.42)-0.21 + (b < 0? 1.0 : -1.0) * 0.375); + + while ((rnd = returnValue->RandomGen(1,0,NULL)) <= 0.0); + + // angle of beam in x direction + ux = sin((rnd*0.42)-0.21); + uz = sqrt(1 - ux*ux - uy*uy); + } + else { // isotropic pt source + costheta = 1.0 - 2.0 * returnValue->RandomGen(1,0,NULL); + sintheta = sqrt(1.0 - costheta*costheta); + psi = 2.0 * PI * returnValue->RandomGen(1,0,NULL); + cospsi = cos(psi); + if (psi < PI) + sinpsi = sqrt(1.0 - cospsi*cospsi); + else + sinpsi = -sqrt(1.0 - cospsi*cospsi); + x = inputValues->xs; + y = inputValues->ys; + z = inputValues->zs; + ux = sintheta*cospsi; + uy = sintheta*sinpsi; + uz = costheta; + } + } // end use mcflag + } + /****************************/ + + /* Get tissue voxel properties of launchpoint. + * If photon beyond outer edge of defined voxels, + * the tissue equals properties of outermost voxels. + * Therefore, set outermost voxels to infinite background value. + */ + ix = (int)(inputValues->Nx/2 + x/inputValues->xSpacing); + iy = (int)(inputValues->Ny/2 + y/inputValues->ySpacing); + iz = (int)(z/inputValues->zSpacing); + if (ix >= inputValues->Nx) ix = inputValues->Nx-1; + if (iy >= inputValues->Ny) iy = inputValues->Ny-1; + if (iz >= inputValues->Nz) iz = inputValues->Nz-1; + if (ix < 0) ix=0; + if (iy < 0) iy=0; + if (iz < 0) iz=0; + /* Get the tissue type of located voxel */ + i = (long)(iz*inputValues->Ny*inputValues->Nx + ix*inputValues->Ny + iy); + + bflag = 1; // initialize as 1 = inside volume, but later check as photon propagates. + + if(returnValue->detectorVoxel != nullptr) + returnValue->detectorVoxel->recordedPhotonRoute->clear(); + + /* HOP_DROP_SPIN_CHECK + Propagate one photon until it dies as determined by ROULETTE. + *******/ + do { + /**** HOP + Take step to new position + s = dimensionless stepsize + x, uy, uz are cosines of current photon trajectory + *****/ + while ((rnd = returnValue->RandomGen(1, 0, NULL)) <= 0.0); /* yields 0 < rnd <= 1 */ + sleft = -log(rnd); /* dimensionless step */ + CNT += 1; + + do{ // while sleft>0 + s = sleft/inputValues->musVector[i]; /* Step size [cm].*/ + tempx = x + s*ux; /* Update positions. [cm] */ + tempy = y + s*uy; + tempz = z + s*uz; + + sv = returnValue->SameVoxel(x,y,z, tempx, tempy, tempz, inputValues->xSpacing,inputValues->ySpacing,inputValues->zSpacing); + if (sv) /* photon in same voxel */ + { + x = tempx; /* Update positions. */ + y = tempy; + z = tempz; + + /**** DROP + Drop photon weight (W) into local bin. + *****/ + + absorb = W*(1 - exp(-inputValues->muaVector[i]*s)); /* photon weight absorbed at this step */ + W -= absorb; /* decrement WEIGHT by amount absorbed */ + // If photon within volume of heterogeneity, deposit energy in F[]. + // Normalize F[] later, when save output. + if (bflag) + { + i = (long)(iz*inputValues->Ny*inputValues->Nx + ix*inputValues->Ny + iy); + returnValue->totalFluence[i]+=absorb; + // only save data if blag==1, i.e., photon inside simulation cube + + //For each detectorvoxel + if(returnValue->detectorVoxel != nullptr) + { + //Add photon position to the recorded photon route + returnValue->detectorVoxel->recordedPhotonRoute->push_back(initLocation(ix, iy, iz, absorb)); + + //If the photon is currently at the detector position + if((returnValue->detectorVoxel->location.x == ix) + && ((returnValue->detectorVoxel->location.y == iy) + || (returnValue->detectorVoxel->location.y-1 == iy)) + && (returnValue->detectorVoxel->location.z == iz)) + { + //For each voxel in the recorded photon route + for(unsigned int routeIndex = 0; routeIndex < returnValue->detectorVoxel->recordedPhotonRoute->size(); routeIndex++) + { + //increment the fluence contribution at that particular position + i = (long)(returnValue->detectorVoxel->recordedPhotonRoute->at(routeIndex).z*inputValues->Ny*inputValues->Nx + + returnValue->detectorVoxel->recordedPhotonRoute->at(routeIndex).x*inputValues->Ny + + returnValue->detectorVoxel->recordedPhotonRoute->at(routeIndex).y); + returnValue->detectorVoxel->fluenceContribution[i] += returnValue->detectorVoxel->recordedPhotonRoute->at(routeIndex).absorb; + } + + //Clear the recorded photon route + returnValue->detectorVoxel->m_NumberPhotonsCurrent++; + returnValue->detectorVoxel->recordedPhotonRoute->clear(); + } + } + } + + /* Update sleft */ + sleft = 0; /* dimensionless step remaining */ + } + else /* photon has crossed voxel boundary */ + { + /* step to voxel face + "littlest step" so just inside new voxel. */ + s = ls + returnValue->FindVoxelFace2(x,y,z, tempx,tempy,tempz, inputValues->xSpacing,inputValues->ySpacing,inputValues->zSpacing, ux,uy,uz); + + /**** DROP + Drop photon weight (W) into local bin. + *****/ + absorb = W*(1-exp(-inputValues->muaVector[i]*s)); /* photon weight absorbed at this step */ + W -= absorb; /* decrement WEIGHT by amount absorbed */ + // If photon within volume of heterogeneity, deposit energy in F[]. + // Normalize F[] later, when save output. + if (bflag) + { + // only save data if bflag==1, i.e., photon inside simulation cube + + //For each detectorvoxel + if(returnValue->detectorVoxel != nullptr) + { + //Add photon position to the recorded photon route + returnValue->detectorVoxel->recordedPhotonRoute->push_back(initLocation(ix, iy, iz, absorb)); + + //If the photon is currently at the detector position + if((returnValue->detectorVoxel->location.x == ix) + && ((returnValue->detectorVoxel->location.y == iy) + || (returnValue->detectorVoxel->location.y-1 == iy)) + && (returnValue->detectorVoxel->location.z == iz)) + { + //For each voxel in the recorded photon route + for(unsigned int routeIndex = 0; routeIndex < returnValue->detectorVoxel->recordedPhotonRoute->size(); routeIndex++) + { + //increment the fluence contribution at that particular position + i = (long)(returnValue->detectorVoxel->recordedPhotonRoute->at(routeIndex).z*inputValues->Ny*inputValues->Nx + + returnValue->detectorVoxel->recordedPhotonRoute->at(routeIndex).x*inputValues->Ny + + returnValue->detectorVoxel->recordedPhotonRoute->at(routeIndex).y); + returnValue->detectorVoxel->fluenceContribution[i] += returnValue->detectorVoxel->recordedPhotonRoute->at(routeIndex).absorb; + } + + //Clear the recorded photon route + returnValue->detectorVoxel->m_NumberPhotonsCurrent++; + returnValue->detectorVoxel->recordedPhotonRoute->clear(); + } + } + + i = (long)(iz*inputValues->Ny*inputValues->Nx + ix*inputValues->Ny + iy); + returnValue->totalFluence[i]+=absorb; + } + + /* Update sleft */ + sleft -= s*inputValues->musVector[i]; /* dimensionless step remaining */ + if (sleft<=ls) sleft = 0; + + /* Update positions. */ + x += s*ux; + y += s*uy; + z += s*uz; + + // pointers to voxel containing optical properties + ix = (int)(inputValues->Nx/2 + x/inputValues->xSpacing); + iy = (int)(inputValues->Ny/2 + y/inputValues->ySpacing); + iz = (int)(z/inputValues->zSpacing); + + bflag = 1; // Boundary flag. Initialize as 1 = inside volume, then check. + if (inputValues->boundaryflag==0) { // Infinite medium. + // Check if photon has wandered outside volume. + // If so, set tissue type to boundary value, but let photon wander. + // Set blag to zero, so DROP does not deposit energy. + if (iz>=inputValues->Nz) {iz=inputValues->Nz-1; bflag = 0;} + if (ix>=inputValues->Nx) {ix=inputValues->Nx-1; bflag = 0;} + if (iy>=inputValues->Ny) {iy=inputValues->Ny-1; bflag = 0;} + if (iz<0) {iz=0; bflag = 0;} + if (ix<0) {ix=0; bflag = 0;} + if (iy<0) {iy=0; bflag = 0;} + } + else if (inputValues->boundaryflag==1) { // Escape at boundaries + if (iz>=inputValues->Nz) {iz=inputValues->Nz-1; photon_status = DEAD; sleft=0;} + if (ix>=inputValues->Nx) {ix=inputValues->Nx-1; photon_status = DEAD; sleft=0;} + if (iy>=inputValues->Ny) {iy=inputValues->Ny-1; photon_status = DEAD; sleft=0;} + if (iz<0) {iz=0; photon_status = DEAD; sleft=0;} + if (ix<0) {ix=0; photon_status = DEAD; sleft=0;} + if (iy<0) {iy=0; photon_status = DEAD; sleft=0;} + } + else if (inputValues->boundaryflag==2) { // Escape at top surface, no x,y bottom z boundaries + if (iz>=inputValues->Nz) {iz=inputValues->Nz-1; bflag = 0;} + if (ix>=inputValues->Nx) {ix=inputValues->Nx-1; bflag = 0;} + if (iy>=inputValues->Ny) {iy=inputValues->Ny-1; bflag = 0;} + if (iz<0) {iz=0; photon_status = DEAD; sleft=0;} + if (ix<0) {ix=0; bflag = 0;} + if (iy<0) {iy=0; bflag = 0;} + } + + // update pointer to tissue type + i = (long)(iz*inputValues->Ny*inputValues->Nx + ix*inputValues->Ny + iy); + } //(sv) /* same voxel */ + + } while(sleft > 0); //do...while + + /**** SPIN + Scatter photon into new trajectory defined by theta and psi. + Theta is specified by cos(theta), which is determined + based on the Henyey-Greenstein scattering function. + Convert theta and psi into cosines ux, uy, uz. + *****/ + /* Sample for costheta */ + while ((rnd = returnValue->RandomGen(1, 0, NULL)) <= 0.0); + if (inputValues->gVector[i] == 0.0) + { + costheta = 2.0 * rnd - 1.0; + } + else + { + double temp = (1.0 - inputValues->gVector[i]*inputValues->gVector[i]) + /(1.0 - inputValues->gVector[i] + 2*inputValues->gVector[i]*rnd); + costheta = (1.0 + inputValues->gVector[i]*inputValues->gVector[i] - temp*temp)/(2.0*inputValues->gVector[i]); + } + sintheta = sqrt(1.0 - costheta*costheta); /* sqrt() is faster than sin(). */ + + /* Sample psi. */ + psi = 2.0*PI*returnValue->RandomGen(1, 0, NULL); + cospsi = cos(psi); + if (psi < PI) + sinpsi = sqrt(1.0 - cospsi*cospsi); /* sqrt() is faster than sin(). */ + else + sinpsi = -sqrt(1.0 - cospsi*cospsi); + + /* New trajectory. */ + if (1 - fabs(uz) <= ONE_MINUS_COSZERO) { /* close to perpendicular. */ + uxx = sintheta * cospsi; + uyy = sintheta * sinpsi; + uzz = costheta * SIGN(uz); /* SIGN() is faster than division. */ + } + else { /* usually use this option */ + temp = sqrt(1.0 - uz * uz); + uxx = sintheta * (ux * uz * cospsi - uy * sinpsi) / temp + ux * costheta; + uyy = sintheta * (uy * uz * cospsi + ux * sinpsi) / temp + uy * costheta; + uzz = -sintheta * cospsi * temp + uz * costheta; + } + + /* Update trajectory */ + ux = uxx; + uy = uyy; + uz = uzz; + + /**** CHECK ROULETTE + If photon weight below THRESHOLD, then terminate photon using Roulette technique. + Photon has CHANCE probability of having its weight increased by factor of 1/CHANCE, + and 1-CHANCE probability of terminating. + *****/ + if (W < THRESHOLD) { + if (returnValue->RandomGen(1, 0, NULL) <= CHANCE) + W /= CHANCE; + else photon_status = DEAD; + } + + } while (photon_status == ALIVE); /* end STEP_CHECK_HOP_SPIN */ + /* if ALIVE, continue propagating */ + /* If photon DEAD, then launch new photon. */ + + } while (photonIterator < photonsToSimulate); /* end RUN */ + + returnValue->Nphotons+=photonsToSimulate; + + } while (photonsToSimulate > 0); + + if (verbose) std::cout << "------------------------------------------------------" << std::endl; + if (verbose) std::cout << "Thread "<< thread <<" is finished." << std::endl; +} diff --git a/Modules/PhotoacousticSimulation/Resources/photoacoustics128x128.png b/Modules/PhotoacousticSimulation/Resources/photoacoustics128x128.png new file mode 100644 index 0000000000..e325debb9e Binary files /dev/null and b/Modules/PhotoacousticSimulation/Resources/photoacoustics128x128.png differ diff --git a/Modules/PhotoacousticSimulation/Resources/spectralLIB.dat b/Modules/PhotoacousticSimulation/Resources/spectralLIB.dat new file mode 100644 index 0000000000..b2e2f59f24 --- /dev/null +++ b/Modules/PhotoacousticSimulation/Resources/spectralLIB.dat @@ -0,0 +1 @@ +300 353 345 0.0067 0.0001 3720 301 346 337 0.0066 0.0001 3680 302 338 328 0.0065 0.0001 3640 303 335 322 0.0064 0.0001 3600 304 332 315 0.0063 0.0001 3560 305 333 310 0.0062 0.0001 3520 306 334 305 0.0061 0.0001 3480 307 335 307 0.00599 0.0001 3450 308 337 309 0.00589 0.0001 3410 309 338 313 0.00579 0.0001 3370 310 339 317 0.00569 0.0001 3340 311 346 325 0.00559 0.0001 3300 312 353 333 0.00549 0.0001 3270 313 361 342 0.00539 0.0001 3230 314 370 350 0.00529 0.0001 3200 315 379 358 0.00519 0.0001 3160 316 388 366 0.00509 0.0001 3130 317 396 374 0.00499 0.0001 3100 318 404 381 0.00489 0.0001 3070 319 413 390 0.00478 0.0001 3030 320 422 399 0.00468 0.0001 3000 321 431 409 0.00458 0.0001 2970 322 440 419 0.00448 0.0001 2940 323 450 429 0.00438 0.0001 2910 324 460 439 0.00428 0.0001 2880 325 471 449 0.00418 0.0001 2850 326 481 458 0.00411 0.0001 2820 327 491 466 0.00403 0.0001 2790 328 502 474 0.00396 0.0001 2760 329 512 480 0.00388 0.0001 2740 330 522 487 0.00381 0.0001 2710 331 531 493 0.00374 0.0001 2680 332 541 499 0.00366 0.0001 2660 333 547 505 0.00359 0.0001 2630 334 554 512 0.00351 0.0001 2600 335 558 523 0.00344 0.0001 2580 336 562 534 0.00337 0.0001 2550 337 566 547 0.00329 0.0001 2530 338 570 559 0.00322 0.0001 2500 339 574 570 0.00314 0.0001 2480 340 578 581 0.00307 0.0001 2450 341 581 588 0.003 0.0001 2430 342 584 594 0.00292 0.0001 2410 343 587 601 0.00285 0.0001 2380 344 590 608 0.00277 0.0001 2360 345 587 615 0.0027 0.0001 2340 346 584 621 0.00263 0.0001 2310 347 581 629 0.00255 0.0001 2290 348 578 636 0.00248 0.0001 2270 349 574 645 0.0024 0.0001 2250 350 571 654 0.00233 0.0001 2230 351 567 663 0.00228 0.0001 2210 352 562 672 0.00224 0.0001 2190 353 559 681 0.00219 0.0001 2160 354 555 690 0.00214 0.0001 2140 355 550 699 0.0021 0.0001 2120 356 544 707 0.00205 0.0001 2100 357 534 712 0.00201 0.0001 2090 358 524 716 0.00196 0.0001 2070 359 516 719 0.00191 0.0001 2050 360 507 723 0.00187 0.0001 2030 361 501 726 0.00182 0.0001 2010 362 494 728 0.00177 0.0001 1990 363 488 731 0.00173 0.0001 1970 364 481 733 0.00168 0.0001 1950 365 477 736 0.00163 0.0001 1940 366 474 738 0.00159 0.0001 1920 367 471 741 0.00154 0.0001 1900 368 469 744 0.00149 0.0001 1880 369 470 747 0.00145 0.0001 1870 370 472 750 0.0014 0.0001 1850 371 481 752 0.00136 0.0001 1830 372 490 755 0.00131 0.0001 1820 373 500 758 0.00126 0.0001 1800 374 509 761 0.00122 0.0001 1790 375 520 764 0.00117 0.0001 1770 376 530 767 0.00115 0.0001 1750 377 542 770 0.00112 0.0001 1740 378 554 773 0.0011 0.0001 1720 379 570 776 0.00108 0.0001 1710 380 587 778 0.00105 0.0001 1690 381 607 778 0.00103 0.0001 1680 382 626 778 0.001 0.0001 1660 383 649 787 0.000981 0.0001 1650 384 672 796 0.000958 0.0001 1640 385 698 810 0.000934 0.0001 1620 386 724 824 0.00091 0.0001 1610 387 758 839 0.000887 0.0001 1590 388 793 854 0.000863 0.0001 1580 389 846 876 0.00084 0.0001 1570 390 898 898 0.000816 0.0001 1550 391 957 931 0.000792 0.0001 1540 392 1020 964 0.000769 0.0001 1530 393 1080 995 0.000745 0.0001 1510 394 1140 1030 0.000722 0.0001 1500 395 1190 1050 0.000698 0.0001 1490 396 1240 1080 0.000674 0.0001 1480 397 1290 1110 0.000651 0.0001 1460 398 1330 1140 0.000627 0.0001 1450 399 1380 1170 0.000604 0.0001 1440 400 1430 1200 0.00058 0.0001 1430 401 1470 1230 0.000572 0.0001 1420 402 1520 1260 0.000564 0.0001 1400 403 1590 1310 0.000556 0.0001 1390 404 1650 1360 0.000548 0.0001 1380 405 1770 1400 0.00054 0.0001 1370 406 1900 1450 0.000532 0.0001 1360 407 2080 1490 0.000524 0.0001 1350 408 2260 1540 0.000516 0.0001 1340 409 2380 1580 0.000508 0.0001 1330 410 2500 1630 0.0005 0.0001 1320 411 2590 1670 0.000492 0.0001 1300 412 2680 1720 0.000484 0.0001 1290 413 2740 1780 0.000476 0.0001 1280 414 2810 1830 0.000468 0.0001 1270 415 2800 1890 0.00046 0.0001 1260 416 2790 1950 0.000452 0.0001 1250 417 2780 2010 0.000444 0.0001 1240 418 2760 2070 0.000436 0.0001 1230 419 2670 2120 0.000428 0.0001 1220 420 2570 2180 0.00042 0.0001 1210 421 2440 2240 0.000412 0.0001 1200 422 2310 2300 0.000404 0.0001 1190 423 2160 2390 0.000396 0.0001 1190 424 2010 2470 0.000388 0.0001 1180 425 1880 2520 0.00038 0.0001 1170 426 1750 2580 0.000376 0.0001 1160 427 1630 2630 0.000372 0.0001 1150 428 1520 2680 0.000368 0.0001 1140 429 1420 2760 0.000364 8.28 1130 430 1320 2830 0.00036 8.216 1120 431 1230 2890 0.000356 8.158 1110 432 1150 2960 0.000352 8.069 1110 433 1020 2960 0.000348 7.927 1100 434 885 2960 0.000344 7.832 1090 435 798 2940 0.00034 7.721 1080 436 711 2930 0.000336 7.652 1070 437 675 2810 0.000332 7.623 1060 438 638 2690 0.000328 7.56 1060 439 594 2450 0.000324 7.474 1050 440 549 2210 0.00032 7.383 1040 441 523 2080 0.000316 7.244 1030 442 497 1950 0.000312 7.104 1020 443 466 1730 0.000308 7 1020 444 436 1510 0.000304 6.899 1010 445 422 1390 0.0003 6.811 1000 446 409 1270 0.000296 6.729 994 447 384 1100 0.000292 6.659 986 448 359 928 0.000288 6.571 979 449 348 741 0.000284 6.464 972 450 336 553 0.00028 6.375 965 451 326 444 0.000279 6.291 957 452 315 335 0.000277 6.21 950 453 301 265 0.000276 6.135 943 454 287 194 0.000275 6.049 937 455 276 179 0.000273 5.95 930 456 265 164 0.000272 5.837 923 457 260 152 0.000271 5.751 916 458 254 139 0.000269 5.663 910 459 246 132 0.000268 5.593 903 460 238 125 0.000267 5.523 897 461 230 119 0.000265 5.413 890 462 221 112 0.000264 5.288 884 463 217 108 0.000263 5.144 877 464 213 103 0.000262 4.985 871 465 206 100 0.00026 4.846 865 466 199 97.1 0.000259 4.72 859 467 193 94.2 0.000258 4.594 853 468 187 91.2 0.000256 4.513 846 469 182 88.8 0.000255 4.434 840 470 178 86.5 0.000254 4.327 835 471 174 84.2 0.000252 4.208 829 472 169 82 0.000251 4.084 823 473 165 81.3 0.00025 3.961 817 474 161 80.6 0.000248 3.843 811 475 158 79.9 0.000247 3.732 806 476 154 79.2 0.000247 3.635 800 477 151 78.9 0.000247 3.534 794 478 148 78.5 0.000247 3.452 789 479 146 78.2 0.000247 3.386 783 480 143 77.9 0.000248 3.315 778 481 140 78.8 0.000248 3.261 773 482 138 79.7 0.000248 3.192 767 483 136 80.6 0.000248 3.109 762 484 135 81.5 0.000248 3.013 757 485 133 82.3 0.000248 2.919 752 486 132 83.2 0.000248 2.832 747 487 131 84.2 0.000248 2.75 741 488 129 85.1 0.000249 2.676 736 489 128 87.2 0.000249 2.597 731 490 127 89.3 0.000249 2.515 726 491 125 91.4 0.000249 2.437 722 492 124 93.5 0.000249 2.368 717 493 122 95.7 0.000249 2.298 712 494 120 97.8 0.000249 2.25 707 495 119 99.9 0.000249 2.193 702 496 117 102 0.00025 2.124 698 497 115 104 0.00025 2.06 693 498 114 107 0.00025 1.998 688 499 113 109 0.00025 1.942 684 500 112 112 0.00025 1.906 679 501 111 114 0.000253 1.875 675 502 110 117 0.000256 1.828 670 503 110 120 0.000258 1.776 666 504 109 122 0.000261 1.724 661 505 108 125 0.000264 1.683 657 506 107 127 0.000267 1.648 653 507 107 130 0.00027 1.62 648 508 107 133 0.000272 1.576 644 509 107 135 0.000275 1.534 640 510 107 138 0.000278 1.501 636 511 108 141 0.000281 1.475 632 512 108 144 0.000284 1.457 628 513 109 147 0.000286 1.432 624 514 109 150 0.000289 1.403 619 515 111 154 0.000292 1.368 615 516 112 157 0.000295 1.33 612 517 116 160 0.000298 1.298 608 518 121 163 0.0003 1.27 604 519 125 166 0.000303 1.246 600 520 130 169 0.000306 1.231 596 521 136 173 0.000309 1.211 592 522 142 176 0.000312 1.189 588 523 149 180 0.000314 1.165 585 524 157 184 0.000317 1.145 581 525 165 188 0.00032 1.132 577 526 174 192 0.000325 1.113 574 527 183 197 0.00033 1.091 570 528 193 201 0.000336 1.064 566 529 203 205 0.000341 1.042 563 530 214 209 0.000346 1.031 559 531 224 213 0.000351 1.017 556 532 235 217 0.000356 1.002 552 533 243 221 0.000362 0.991 549 534 251 225 0.000367 0.984 546 535 259 229 0.000372 0.978 542 536 266 233 0.000377 0.97 539 537 272 237 0.000382 0.951 535 538 277 241 0.000388 0.929 532 539 281 245 0.000393 0.913 529 540 285 249 0.000398 0.896 526 541 285 254 0.000403 0.88 522 542 285 258 0.000408 0.864 519 543 282 262 0.000414 0.849 516 544 279 266 0.000419 0.84 513 545 273 270 0.000424 0.833 510 546 267 275 0.000429 0.828 507 547 258 278 0.000434 0.822 504 548 250 281 0.00044 0.805 500 549 240 284 0.000445 0.785 497 550 230 286 0.00045 0.773 494 551 221 288 0.000464 0.763 491 552 212 290 0.000477 0.76 489 553 205 291 0.000491 0.757 486 554 197 292 0.000504 0.746 483 555 191 292 0.000518 0.733 480 556 185 292 0.000532 0.724 477 557 182 291 0.000545 0.718 474 558 179 290 0.000559 0.71 471 559 177 289 0.000572 0.704 468 560 175 288 0.000586 0.698 466 561 175 284 0.0006 0.69 463 562 175 280 0.000613 0.682 460 563 178 275 0.000627 0.673 457 564 182 271 0.00064 0.662 455 565 189 266 0.000654 0.653 452 566 195 261 0.000668 0.647 449 567 205 256 0.000681 0.641 447 568 215 251 0.000695 0.636 444 569 227 246 0.000708 0.63 442 570 238 241 0.000722 0.629 439 571 251 237 0.000736 0.633 436 572 263 232 0.000749 0.639 434 573 274 228 0.000763 0.632 431 574 285 223 0.000776 0.613 429 575 291 219 0.00079 0.589 426 576 297 215 0.00085 0.573 424 577 295 210 0.000911 0.562 422 578 293 206 0.000971 0.563 419 579 281 202 0.00103 0.566 417 580 268 198 0.00109 0.566 414 581 250 195 0.00115 0.564 412 582 232 191 0.00121 0.562 410 583 209 187 0.00127 0.562 407 584 185 184 0.00133 0.557 405 585 164 180 0.00139 0.548 403 586 142 176 0.00145 0.541 400 587 124 171 0.00151 0.53 398 588 106 166 0.00158 0.52 396 589 91.5 159 0.00164 0.512 394 590 77.1 152 0.0017 0.502 391 591 66.6 144 0.00176 0.493 389 592 56.1 136 0.00182 0.488 387 593 48.6 129 0.00188 0.485 385 594 41.1 121 0.00194 0.486 383 595 35.8 113 0.002 0.487 381 596 30.4 106 0.00206 0.479 378 597 27.3 98.7 0.00212 0.472 376 598 24.1 91.3 0.00218 0.467 374 599 20.6 85 0.00224 0.462 372 600 17.1 78.6 0.0023 0.466 370 601 15.7 75.8 0.00232 0.471 368 602 14.3 72.9 0.00234 0.479 366 603 12.8 70.1 0.00236 0.487 364 604 11.4 67.3 0.00238 0.487 362 605 10.5 64.5 0.0024 0.484 360 606 9.58 61.7 0.00242 0.48 358 607 9.2 58.9 0.00244 0.475 356 608 8.82 56.1 0.00246 0.47 354 609 8.44 53.3 0.00248 0.469 352 610 8.06 50.6 0.0025 0.464 350 611 7.69 48.3 0.00252 0.458 348 612 7.31 46 0.00254 0.454 346 613 6.93 43.8 0.00256 0.442 345 614 6.55 41.6 0.00258 0.427 343 615 6.25 40.4 0.0026 0.422 341 616 5.94 39.3 0.00262 0.423 339 617 5.72 38.2 0.00264 0.43 337 618 5.49 37.1 0.00266 0.437 335 619 5.27 36 0.00268 0.435 334 620 5.04 34.9 0.0027 0.43 332 621 4.82 34 0.00272 0.425 330 622 4.59 33.2 0.00274 0.433 328 623 4.37 32.4 0.00276 0.44 327 624 4.14 31.6 0.00278 0.438 325 625 3.97 30.9 0.0028 0.432 323 626 3.79 30.1 0.00282 0.426 321 627 3.66 29.4 0.00283 0.424 320 628 3.53 28.7 0.00285 0.426 318 629 3.4 28.2 0.00286 0.428 316 630 3.27 27.6 0.00288 0.428 315 631 3.14 27 0.0029 0.429 313 632 3.01 26.4 0.00291 0.437 311 633 2.87 25.9 0.00293 0.444 310 634 2.74 25.3 0.00294 0.44 308 635 2.65 25 0.00296 0.431 306 636 2.56 24.6 0.00298 0.42 305 637 2.51 24.3 0.00299 0.422 303 638 2.47 24 0.00301 0.433 302 639 2.42 23.6 0.00302 0.446 300 640 2.37 23.3 0.00304 0.452 299 641 2.32 22.9 0.00306 0.45 297 642 2.27 22.6 0.00307 0.449 295 643 2.22 22.2 0.00309 0.453 294 644 2.17 21.9 0.0031 0.46 292 645 2.13 21.6 0.00312 0.465 291 646 2.09 21.2 0.00314 0.464 289 647 2.06 20.9 0.00315 0.464 288 648 2.03 20.7 0.00317 0.464 286 649 2 20.4 0.00318 0.465 285 650 1.97 20.1 0.0032 0.471 283 651 1.94 19.8 0.00324 0.472 282 652 1.91 19.5 0.00328 0.467 281 653 1.88 19.2 0.00331 0.464 279 654 1.85 18.9 0.00335 0.457 278 655 1.82 18.6 0.00339 0.448 276 656 1.79 18.4 0.00343 0.438 275 657 1.77 18.1 0.00347 0.428 274 658 1.74 17.8 0.0035 0.424 272 659 1.73 17.5 0.00354 0.422 271 660 1.71 17.3 0.00358 0.418 269 661 1.7 17 0.00362 0.414 268 662 1.68 16.8 0.00366 0.413 267 663 1.67 16.6 0.00369 0.414 265 664 1.65 16.4 0.00373 0.419 264 665 1.64 16.1 0.00377 0.428 263 666 1.62 15.9 0.00381 0.439 261 667 1.61 15.7 0.00385 0.447 260 668 1.6 15.4 0.00388 0.452 259 669 1.59 15.2 0.00392 0.453 258 670 1.57 15 0.00396 0.45 256 671 1.56 14.7 0.004 0.452 255 672 1.55 14.5 0.00404 0.457 254 673 1.54 14.3 0.00407 0.462 252 674 1.53 14.1 0.00411 0.463 251 675 1.52 13.9 0.00415 0.457 250 676 1.51 13.7 0.00422 0.446 249 677 1.5 13.5 0.0043 0.433 248 678 1.5 13.3 0.00437 0.422 246 679 1.49 13.1 0.00445 0.413 245 680 1.49 12.9 0.00452 0.406 244 681 1.48 12.7 0.00459 0.398 243 682 1.48 12.5 0.00467 0.387 242 683 1.47 12.3 0.00474 0.375 240 684 1.47 12.1 0.00482 0.37 239 685 1.47 11.9 0.00489 0.369 238 686 1.46 11.7 0.00496 0.366 237 687 1.47 11.5 0.00504 0.361 236 688 1.47 11.3 0.00511 0.354 235 689 1.47 11.2 0.00519 0.348 233 690 1.48 11 0.00526 0.342 232 691 1.48 10.9 0.00533 0.338 231 692 1.49 10.7 0.00541 0.335 230 693 1.49 10.6 0.00548 0.331 229 694 1.5 10.4 0.00556 0.328 228 695 1.5 10.3 0.00563 0.324 227 696 1.51 10.2 0.0057 0.321 226 697 1.52 10 0.00578 0.324 225 698 1.53 9.89 0.00585 0.327 224 699 1.54 9.75 0.00593 0.325 223 700 1.55 9.61 0.006 0.323 221 701 1.56 9.47 0.0064 0.32 220 702 1.57 9.32 0.00679 0.319 219 703 1.59 9.18 0.00719 0.322 218 704 1.6 9.04 0.00758 0.326 217 705 1.61 8.9 0.00798 0.323 216 706 1.62 8.75 0.00838 0.318 215 707 1.64 8.62 0.00877 0.313 214 708 1.65 8.48 0.00917 0.31 213 709 1.67 8.36 0.00956 0.311 212 710 1.68 8.25 0.00996 0.315 211 711 1.7 8.13 0.0104 0.32 210 712 1.71 8.02 0.0108 0.321 209 713 1.73 7.9 0.0111 0.32 208 714 1.74 7.79 0.0115 0.321 207 715 1.76 7.67 0.0119 0.326 206 716 1.78 7.56 0.0123 0.334 205 717 1.8 7.44 0.0127 0.343 204 718 1.82 7.33 0.0131 0.351 204 719 1.84 7.21 0.0135 0.358 203 720 1.86 7.1 0.0139 0.367 202 721 1.88 6.99 0.0143 0.376 201 722 1.91 6.88 0.0147 0.383 200 723 1.93 6.77 0.0151 0.39 199 724 1.95 6.66 0.0155 0.401 198 725 1.97 6.55 0.0159 0.415 197 726 1.99 6.45 0.0163 0.43 196 727 2.02 6.31 0.0167 0.447 195 728 2.04 6.17 0.0171 0.463 194 729 2.06 6.04 0.0175 0.48 193 730 2.09 5.9 0.0179 0.499 193 731 2.11 5.9 0.0183 0.516 192 732 2.14 5.9 0.0187 0.535 191 733 2.16 5.9 0.0191 0.552 190 734 2.18 5.9 0.0195 0.564 189 735 2.21 5.9 0.0199 0.576 188 736 2.24 5.9 0.0203 0.589 187 737 2.28 5.9 0.0207 0.6 187 738 2.32 5.89 0.0212 0.616 186 739 2.35 5.93 0.0216 0.636 185 740 2.39 5.98 0.022 0.654 184 741 2.42 6.1 0.0224 0.68 183 742 2.46 6.22 0.0228 0.707 182 743 2.5 6.34 0.0232 0.735 182 744 2.53 6.47 0.0236 0.768 181 745 2.57 6.62 0.024 0.801 180 746 2.61 6.78 0.0244 0.837 179 747 2.65 6.96 0.0248 0.874 178 748 2.69 7.14 0.0252 0.908 178 749 2.73 7.33 0.0256 0.941 177 750 2.77 7.52 0.026 0.972 176 751 2.81 7.82 0.0259 1.001 175 752 2.86 8.11 0.0258 1.03 174 753 2.9 8.19 0.0258 1.059 174 754 2.94 8.26 0.0257 1.089 173 755 2.97 8.31 0.0256 1.12 172 756 3.01 8.36 0.0255 1.155 171 757 3.04 8.36 0.0254 1.19 171 758 3.07 8.36 0.0254 1.227 170 759 3.11 8.32 0.0253 1.258 169 760 3.14 8.29 0.0252 1.278 168 761 3.17 8.18 0.0251 1.289 168 762 3.2 8.08 0.025 1.29 167 763 3.23 7.95 0.025 1.273 166 764 3.27 7.82 0.0249 1.249 166 765 3.3 7.68 0.0248 1.206 165 766 3.33 7.55 0.0247 1.153 164 767 3.37 7.42 0.0246 1.089 163 768 3.41 7.29 0.0246 1.021 163 769 3.44 7.16 0.0245 0.948 162 770 3.48 7.02 0.0244 0.871 161 771 3.52 6.89 0.0243 0.793 161 772 3.55 6.76 0.0242 0.719 160 773 3.59 6.63 0.0242 0.653 159 774 3.63 6.5 0.0241 0.596 159 775 3.66 6.36 0.024 0.553 158 776 3.69 6.23 0.0238 0.515 157 777 3.72 6.1 0.0237 0.481 156 778 3.75 5.97 0.0235 0.451 156 779 3.77 5.86 0.0234 0.426 155 780 3.8 5.76 0.0232 0.409 154 781 3.83 5.65 0.023 0.391 154 782 3.86 5.55 0.0229 0.378 153 783 3.89 5.44 0.0227 0.366 153 784 3.91 5.34 0.0226 0.36 152 785 3.94 5.23 0.0224 0.357 151 786 3.96 5.13 0.0222 0.355 151 787 3.98 5.03 0.0221 0.353 150 788 4.01 4.94 0.0219 0.349 149 789 4.03 4.85 0.0218 0.346 149 790 4.05 4.77 0.0216 0.346 148 791 4.07 4.69 0.0214 0.347 147 792 4.09 4.6 0.0213 0.347 147 793 4.11 4.52 0.0211 0.347 146 794 4.13 4.44 0.021 0.352 146 795 4.17 4.37 0.0208 0.359 145 796 4.21 4.3 0.0206 0.369 144 797 4.27 4.24 0.0205 0.379 144 798 4.32 4.19 0.0203 0.387 143 799 4.35 4.13 0.0202 0.393 143 800 4.37 4.08 0.02 0.403 142 801 4.4 4.03 0.02 0.413 141 802 4.43 3.98 0.02 0.424 141 803 4.46 3.97 0.02 0.434 140 804 4.48 3.95 0.0199 0.442 140 805 4.5 3.93 0.0199 0.454 139 806 4.52 3.91 0.0199 0.467 138 807 4.55 3.89 0.0199 0.482 138 808 4.58 3.87 0.0199 0.497 137 809 4.61 3.86 0.0199 0.511 137 810 4.63 3.84 0.0199 0.527 136 811 4.65 3.83 0.0203 0.547 136 812 4.67 3.81 0.0207 0.567 135 813 4.69 3.8 0.0211 0.583 135 814 4.71 3.78 0.0215 0.594 134 815 4.73 3.77 0.0219 0.603 133 816 4.75 3.76 0.0223 0.615 133 817 4.79 3.74 0.0227 0.633 132 818 4.83 3.73 0.0231 0.654 132 819 4.87 3.72 0.0235 0.674 131 820 4.91 3.71 0.0239 0.691 131 821 4.94 3.71 0.0247 0.708 130 822 4.98 3.71 0.0255 0.724 130 823 5.02 3.71 0.0264 0.74 129 824 5.06 3.71 0.0272 0.758 129 825 5.09 3.71 0.028 0.775 128 826 5.12 3.71 0.0282 0.786 128 827 5.14 3.71 0.0284 0.796 127 828 5.17 3.71 0.0286 0.799 127 829 5.19 3.71 0.0289 0.802 126 830 5.22 3.71 0.0291 0.803 126 831 5.24 3.71 0.0296 0.803 125 832 5.26 3.71 0.0302 0.801 125 833 5.29 3.71 0.0308 0.794 124 834 5.31 3.71 0.0313 0.785 124 835 5.34 3.71 0.0319 0.775 123 836 5.36 3.71 0.0325 0.764 123 837 5.39 3.71 0.033 0.757 122 838 5.42 3.71 0.0336 0.751 122 839 5.44 3.71 0.0341 0.739 121 840 5.47 3.71 0.0347 0.726 121 841 5.5 3.71 0.0355 0.715 120 842 5.53 3.71 0.0364 0.703 120 843 5.56 3.71 0.0372 0.692 119 844 5.58 3.71 0.038 0.685 119 845 5.6 3.7 0.0389 0.678 118 846 5.62 3.7 0.0397 0.669 118 847 5.63 3.7 0.0405 0.661 117 848 5.64 3.7 0.0413 0.651 117 849 5.65 3.7 0.0422 0.643 116 850 5.67 3.7 0.043 0.637 116 851 5.68 3.7 0.0434 0.633 116 852 5.69 3.7 0.0438 0.632 115 853 5.7 3.7 0.0441 0.631 115 854 5.71 3.7 0.0445 0.633 114 855 5.73 3.7 0.0449 0.639 114 856 5.74 3.7 0.0453 0.647 113 857 5.77 3.7 0.0456 0.656 113 858 5.8 3.71 0.046 0.662 112 859 5.82 3.71 0.0464 0.666 112 860 5.85 3.72 0.0468 0.674 112 861 5.87 3.72 0.0473 0.68 111 862 5.9 3.73 0.0478 0.69 111 863 5.92 3.73 0.0483 0.705 110 864 5.95 3.74 0.0489 0.724 110 865 5.97 3.74 0.0494 0.751 109 866 5.99 3.75 0.0499 0.786 109 867 6 3.75 0.0504 0.822 109 868 6.01 3.76 0.051 0.86 108 869 6.03 3.77 0.0515 0.899 108 870 6.04 3.78 0.052 0.938 107 871 6.05 3.79 0.0528 0.979 107 872 6.07 3.8 0.0536 1.022 107 873 6.08 3.81 0.0544 1.074 106 874 6.09 3.82 0.0552 1.133 106 875 6.11 3.83 0.056 1.198 105 876 6.12 3.85 0.056 1.264 105 877 6.13 3.86 0.056 1.345 105 878 6.15 3.87 0.056 1.43 104 879 6.16 3.88 0.056 1.527 104 880 6.18 3.89 0.056 1.636 103 881 6.19 3.9 0.0564 1.752 103 882 6.21 3.91 0.0569 1.867 103 883 6.22 3.92 0.0573 1.992 102 884 6.24 3.93 0.0578 2.121 102 885 6.25 3.94 0.0582 2.262 101 886 6.27 3.94 0.0587 2.414 101 887 6.28 3.95 0.0591 2.581 101 888 6.29 3.96 0.0595 2.754 100 889 6.3 3.97 0.06 2.932 99.9 890 6.31 3.98 0.0604 3.116 99.6 891 6.32 3.99 0.0612 3.305 99.2 892 6.33 4 0.0619 3.491 98.8 893 6.34 4.01 0.0627 3.674 98.4 894 6.35 4.02 0.0635 3.833 98.1 895 6.36 4.03 0.0642 3.983 97.7 896 6.37 4.04 0.065 4.121 97.4 897 6.38 4.05 0.0657 4.256 97 898 6.39 4.06 0.0665 4.384 96.6 899 6.4 4.07 0.0672 4.506 96.3 900 6.42 4.08 0.068 4.633 95.9 901 6.43 4.09 0.0685 4.766 95.6 902 6.44 4.1 0.069 4.915 95.2 903 6.45 4.1 0.0695 5.078 94.9 904 6.46 4.11 0.07 5.267 94.5 905 6.47 4.12 0.0705 5.472 94.2 906 6.48 4.12 0.0709 5.721 93.8 907 6.48 4.13 0.0714 5.994 93.5 908 6.49 4.13 0.0719 6.316 93.1 909 6.49 4.14 0.0724 6.663 92.8 910 6.5 4.15 0.0729 7.046 92.5 911 6.51 4.15 0.0765 7.438 92.1 912 6.51 4.16 0.0802 7.837 91.8 913 6.52 4.16 0.0838 8.234 91.4 914 6.53 4.17 0.0875 8.621 91.1 915 6.53 4.17 0.0911 8.994 90.8 916 6.54 4.17 0.0947 9.354 90.5 917 6.54 4.17 0.0984 9.683 90.1 918 6.55 4.16 0.102 10 89.8 919 6.55 4.16 0.106 10.32 89.5 920 6.55 4.16 0.109 10.65 89.2 921 6.56 4.16 0.116 10.99 88.8 922 6.56 4.16 0.123 11.33 88.5 923 6.57 4.16 0.13 11.67 88.2 924 6.57 4.16 0.137 12 87.9 925 6.57 4.15 0.144 12.31 87.6 926 6.57 4.14 0.15 12.6 87.2 927 6.56 4.12 0.156 12.82 86.9 928 6.56 4.11 0.161 12.99 86.6 929 6.55 4.1 0.167 13.07 86.3 930 6.54 4.09 0.173 13.1 86 931 6.54 4.06 0.182 12.99 85.7 932 6.53 4.03 0.192 12.83 85.4 933 6.52 3.99 0.201 12.53 85.1 934 6.52 3.95 0.211 12.18 84.8 935 6.51 3.91 0.22 11.75 84.5 936 6.51 3.87 0.23 11.26 84.2 937 6.51 3.83 0.239 10.7 83.9 938 6.51 3.79 0.248 10.08 83.6 939 6.5 3.75 0.258 9.433 83.3 940 6.5 3.71 0.267 8.754 83 941 6.5 3.67 0.28 8.088 82.7 942 6.5 3.63 0.292 7.446 82.4 943 6.49 3.59 0.304 6.822 82.1 944 6.49 3.54 0.316 6.25 81.8 945 6.49 3.48 0.329 5.704 81.5 946 6.48 3.43 0.341 5.234 81.3 947 6.47 3.38 0.353 4.802 81 948 6.46 3.33 0.365 4.445 80.7 949 6.46 3.28 0.378 4.109 80.4 950 6.45 3.22 0.39 3.799 80.1 951 6.44 3.17 0.393 3.519 79.8 952 6.43 3.12 0.396 3.274 79.6 953 6.42 3.09 0.399 3.046 79.3 954 6.41 3.05 0.402 2.852 79 955 6.4 3.01 0.405 2.666 78.7 956 6.39 2.97 0.408 2.504 78.5 957 6.38 2.93 0.411 2.358 78.2 958 6.37 2.89 0.414 2.242 77.9 959 6.36 2.85 0.417 2.133 77.6 960 6.35 2.81 0.42 2.047 77.4 961 6.34 2.78 0.423 1.975 77.1 962 6.33 2.74 0.426 1.917 76.8 963 6.32 2.69 0.429 1.86 76.6 964 6.31 2.65 0.432 1.808 76.3 965 6.3 2.59 0.435 1.753 76 966 6.28 2.53 0.438 1.693 75.8 967 6.27 2.48 0.441 1.639 75.5 968 6.25 2.42 0.444 1.589 75.3 969 6.24 2.36 0.447 1.554 75 970 6.22 2.3 0.45 1.528 74.7 971 6.21 2.26 0.45 1.51 74.5 972 6.19 2.22 0.45 1.491 74.2 973 6.18 2.19 0.45 1.463 74 974 6.16 2.15 0.45 1.431 73.7 975 6.14 2.12 0.45 1.413 73.5 976 6.13 2.08 0.446 1.408 73.2 977 6.1 2.05 0.442 1.414 73 978 6.08 2.01 0.438 1.421 72.7 979 6.06 1.97 0.434 1.423 72.5 980 6.04 1.93 0.43 1.417 72.2 981 6.02 1.88 0.428 1.407 72 982 6 1.84 0.426 1.406 71.7 983 5.98 1.8 0.424 1.42 71.5 984 5.95 1.76 0.422 1.441 71.3 985 5.93 1.72 0.42 1.481 71 986 5.9 1.68 0.418 1.524 70.8 987 5.87 1.64 0.416 1.564 70.5 988 5.84 1.6 0.414 1.607 70.3 989 5.81 1.56 0.412 1.652 70.1 990 5.78 1.52 0.41 1.716 69.8 991 5.75 1.48 0.405 1.793 69.6 992 5.72 1.43 0.4 1.891 69.4 993 5.69 1.39 0.395 1.994 69.1 994 5.66 1.35 0.39 2.087 68.9 995 5.63 1.31 0.385 2.178 68.7 996 5.6 1.27 0.38 2.272 68.4 997 5.57 1.23 0.375 2.366 68.2 998 5.54 1.19 0.37 2.464 68 999 5.51 1.15 0.365 2.56 67.8 1000 5.48 1.11 0.36 2.654 67.5 diff --git a/Modules/PhotoacousticSimulation/Testing/CMakeLists.txt b/Modules/PhotoacousticSimulation/Testing/CMakeLists.txt new file mode 100644 index 0000000000..153cd81e2e --- /dev/null +++ b/Modules/PhotoacousticSimulation/Testing/CMakeLists.txt @@ -0,0 +1 @@ +MITK_CREATE_MODULE_TESTS() diff --git a/Modules/PhotoacousticSimulation/Testing/Resources/allsources.xml b/Modules/PhotoacousticSimulation/Testing/Resources/allsources.xml new file mode 100644 index 0000000000..36a213c5f9 --- /dev/null +++ b/Modules/PhotoacousticSimulation/Testing/Resources/allsources.xml @@ -0,0 +1,70 @@ + + + + 1 + + POINT + 0.3 + 0.2 + 0.1 + + + + -0.1 + 0.1 + UNIFORM + + + -0.2 + 0.2 + UNIFORM + + + + + 1 + + RECTANGLE + 0.4 + 0.5 + 0.6 + 0.7 + 0.8 + 0.9 + + + + -0.3 + 0.3 + GAUSSIAN + + + -0.4 + 0.4 + GAUSSIAN + + + + + 1 + + CIRCLE + 0.4 + 0.5 + 0.6 + 0.5 + + + + -0.3 + 0.3 + GAUSSIAN + + + -0.4 + 0.4 + GAUSSIAN + + + + diff --git a/Modules/PhotoacousticSimulation/Testing/Resources/circlesource.xml b/Modules/PhotoacousticSimulation/Testing/Resources/circlesource.xml new file mode 100644 index 0000000000..14ef65dd58 --- /dev/null +++ b/Modules/PhotoacousticSimulation/Testing/Resources/circlesource.xml @@ -0,0 +1,25 @@ + + + + 1 + + CIRCLE + 0.3 + 0.2 + 0.1 + 2 + + + + -0.1 + 0.1 + GAUSSIAN + + + -0.2 + 0.2 + UNIFORM + + + + diff --git a/Modules/PhotoacousticSimulation/Testing/Resources/pointsource.xml b/Modules/PhotoacousticSimulation/Testing/Resources/pointsource.xml new file mode 100644 index 0000000000..0ab73fdb8d --- /dev/null +++ b/Modules/PhotoacousticSimulation/Testing/Resources/pointsource.xml @@ -0,0 +1,24 @@ + + + + 1 + + POINT + 0.3 + 0.2 + 0.1 + + + + -0.1 + 0.1 + UNIFORM + + + -0.2 + 0.2 + UNIFORM + + + + diff --git a/Modules/PhotoacousticSimulation/Testing/Resources/rectanglesource.xml b/Modules/PhotoacousticSimulation/Testing/Resources/rectanglesource.xml new file mode 100644 index 0000000000..7c9a4f2f9e --- /dev/null +++ b/Modules/PhotoacousticSimulation/Testing/Resources/rectanglesource.xml @@ -0,0 +1,27 @@ + + + + 1 + + RECTANGLE + 0.3 + 0.2 + 0.1 + 1 + 2 + 3 + + + + -0.1 + 0.1 + UNIFORM + + + -0.2 + 0.2 + UNIFORM + + + + diff --git a/Modules/PhotoacousticSimulation/Testing/Resources/twopointsources.xml b/Modules/PhotoacousticSimulation/Testing/Resources/twopointsources.xml new file mode 100644 index 0000000000..5054ee51c8 --- /dev/null +++ b/Modules/PhotoacousticSimulation/Testing/Resources/twopointsources.xml @@ -0,0 +1,45 @@ + + + + 1 + + POINT + 0.3 + 0.2 + 0.1 + + + + -0.1 + 0.1 + UNIFORM + + + -0.2 + 0.2 + UNIFORM + + + + + 1 + + POINT + 0.4 + 0.5 + 0.6 + + + + -0.3 + 0.3 + GAUSSIAN + + + -0.4 + 0.4 + GAUSSIAN + + + + diff --git a/Modules/PhotoacousticSimulation/Testing/files.cmake b/Modules/PhotoacousticSimulation/Testing/files.cmake new file mode 100644 index 0000000000..615e5513a6 --- /dev/null +++ b/Modules/PhotoacousticSimulation/Testing/files.cmake @@ -0,0 +1,33 @@ +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 ##################################################### + # none + + ################# RUNNING TESTS ####################################################### + mitkPhotoacousticTissueGeneratorTest.cpp + mitkPhotoacousticVectorTest.cpp + mitkPhotoacousticVolumeTest.cpp + mitkPhotoacousticVesselTest.cpp + mitkPhotoacousticVesselTreeTest.cpp + mitkPhotoacousticVesselMeanderStrategyTest.cpp + mitkMcxyzXmlTest.cpp +) + +set(RESOURCE_FILES +pointsource.xml +circlesource.xml +rectanglesource.xml +twopointsources.xml +allsources.xml +) diff --git a/Modules/PhotoacousticSimulation/Testing/mitkMcxyzXmlTest.cpp b/Modules/PhotoacousticSimulation/Testing/mitkMcxyzXmlTest.cpp new file mode 100644 index 0000000000..1acedf6e57 --- /dev/null +++ b/Modules/PhotoacousticSimulation/Testing/mitkMcxyzXmlTest.cpp @@ -0,0 +1,243 @@ +/*=================================================================== + +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 + +// us +#include +#include +#include +#include +#include + +#include +#include + +class mitkMcxyzXmlTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkMcxyzXmlTestSuite); + MITK_TEST(TestCreatePointSourceProbe); + MITK_TEST(TestCreateCircleSourceProbe); + MITK_TEST(TestCreateRectangleSourceProbe); + MITK_TEST(TestCreateTwoPointSourcesProbe); + MITK_TEST(TestCreateAllSourcesProbe); + MITK_TEST(TestValuesAreInBoundsUniformRectangle); + MITK_TEST(TestValuesAreInBoundsGaussianRectangle); + CPPUNIT_TEST_SUITE_END(); + +private: + + mitk::PhotoacousticLightSource::Pointer m_LightSource; + mitk::PhotoacousticProbe::Pointer m_Probe; + std::string m_XmlProbePointSource; + std::string m_XmlProbeCircleSource; + std::string m_XmlProbeRectangleSource; + std::string m_XmlProbeTwoPointSources; + std::string m_XmlProbeAllSources; + +public: + + void setUp() + { + m_LightSource = mitk::PhotoacousticLightSource::New(); + LoadXmlFile("pointsource.xml", &m_XmlProbePointSource); + LoadXmlFile("circlesource.xml", &m_XmlProbeCircleSource); + LoadXmlFile("rectanglesource.xml", &m_XmlProbeRectangleSource); + LoadXmlFile("twopointsources.xml", &m_XmlProbeTwoPointSources); + LoadXmlFile("allsources.xml", &m_XmlProbeAllSources); + } + + void LoadXmlFile(std::string filename, std::string* lines) + { + us::ModuleResource pointSourceXml = us::GetModuleContext()->GetModule()->GetResource(filename); + std::string line; + if(pointSourceXml.IsValid() && pointSourceXml.IsFile()) + { + us::ModuleResourceStream stream(pointSourceXml); + stream.std::istream::imbue(std::locale("en_GB.UTF-8")); + while(std::getline(stream, line)) + { + *lines = *lines + line + " "; + } + } + else + { + MITK_ERROR << "Xml file was not valid"; + } + } + + void TestCreatePointSourceProbe() + { + m_Probe = mitk::PhotoacousticProbe::New(m_XmlProbePointSource.c_str(), true); + CPPUNIT_ASSERT(true == m_Probe->IsValid()); + } + + void TestCreateCircleSourceProbe() + { + m_Probe = mitk::PhotoacousticProbe::New(m_XmlProbeCircleSource.c_str(), true); + CPPUNIT_ASSERT(true == m_Probe->IsValid()); + } + + void TestCreateRectangleSourceProbe() + { + m_Probe = mitk::PhotoacousticProbe::New(m_XmlProbeRectangleSource.c_str(), true); + CPPUNIT_ASSERT(true == m_Probe->IsValid()); + } + + void TestCreateTwoPointSourcesProbe() + { + m_Probe = mitk::PhotoacousticProbe::New(m_XmlProbeTwoPointSources.c_str(), true); + CPPUNIT_ASSERT(true == m_Probe->IsValid()); + } + + void TestCreateAllSourcesProbe() + { + m_Probe = mitk::PhotoacousticProbe::New(m_XmlProbeAllSources.c_str(), true); + CPPUNIT_ASSERT(true == m_Probe->IsValid()); + } + + void TestValuesAreInBoundsUniformRectangle() + { + int MAXIMUM = 2; + int MINIMUM = -2; + + int ANGLE_MAXIMUM = 1; + int ANGLE_MINIMUM = -1; + + m_LightSource->SetAngleXMode(mitk::PhotoacousticLightSource::DistributionMode::UNIFORM); + m_LightSource->SetAngleYMode(mitk::PhotoacousticLightSource::DistributionMode::UNIFORM); + + m_LightSource->SetAngleXMaximum(ANGLE_MAXIMUM); + m_LightSource->SetAngleXMinimum(ANGLE_MINIMUM); + + m_LightSource->SetAngleYMaximum(ANGLE_MAXIMUM); + m_LightSource->SetAngleYMinimum(ANGLE_MINIMUM); + + m_LightSource->SetSpawnLocationX(MINIMUM); + m_LightSource->SetSpawnLocationXLength(2*MAXIMUM); + + m_LightSource->SetSpawnLocationY(MINIMUM); + m_LightSource->SetSpawnLocationYLength(2*MAXIMUM); + + m_LightSource->SetSpawnLocationZ(MINIMUM); + m_LightSource->SetSpawnLocationZLength(2*MAXIMUM); + + m_LightSource->SetSpawnLocationRadius(MAXIMUM); + + m_LightSource->SetVerbose(false); + + m_LightSource->SetSpawnType(mitk::PhotoacousticLightSource::SpawnType::RECTANGLE); + + std::mt19937 rng; + rng.seed(std::chrono::duration_cast(std::chrono::high_resolution_clock:: + now().time_since_epoch()).count()); + std::uniform_real_distribution<> realDist(0, 1); + + for(int i=0, length=10000; iGetNextPhoton(realDist(rng), realDist(rng), realDist(rng), realDist(rng), + realDist(rng), realDist(rng), realDist(rng)); + + CPPUNIT_ASSERT(result.xAngle>=ANGLE_MINIMUM); + CPPUNIT_ASSERT(result.xAngle<=ANGLE_MAXIMUM); + CPPUNIT_ASSERT(result.yAngle>=ANGLE_MINIMUM); + CPPUNIT_ASSERT(result.yAngle<=ANGLE_MAXIMUM); + CPPUNIT_ASSERT(result.zAngle>=0); + CPPUNIT_ASSERT(result.zAngle<=ANGLE_MAXIMUM); + CPPUNIT_ASSERT(result.xPosition>=MINIMUM); + CPPUNIT_ASSERT(result.xPosition<=MAXIMUM); + CPPUNIT_ASSERT(result.yPosition>=MINIMUM); + CPPUNIT_ASSERT(result.yPosition<=MAXIMUM); + CPPUNIT_ASSERT(result.zPosition>=MINIMUM); + CPPUNIT_ASSERT(result.zPosition<=MAXIMUM); + } + } + + void TestValuesAreInBoundsGaussianRectangle() + { + int MAXIMUM = 2; + int MINIMUM = -2; + + int ANGLE_MAXIMUM = 1; + int ANGLE_MINIMUM = -1; + + m_LightSource->SetAngleXMode(mitk::PhotoacousticLightSource::DistributionMode::GAUSSIAN); + m_LightSource->SetAngleYMode(mitk::PhotoacousticLightSource::DistributionMode::GAUSSIAN); + + m_LightSource->SetAngleXMaximum(ANGLE_MAXIMUM); + m_LightSource->SetAngleXMinimum(ANGLE_MINIMUM); + + m_LightSource->SetAngleYMaximum(ANGLE_MAXIMUM); + m_LightSource->SetAngleYMinimum(ANGLE_MINIMUM); + + m_LightSource->SetSpawnLocationX(MINIMUM); + m_LightSource->SetSpawnLocationXLength(2*MAXIMUM); + + m_LightSource->SetSpawnLocationY(MINIMUM); + m_LightSource->SetSpawnLocationYLength(2*MAXIMUM); + + m_LightSource->SetSpawnLocationZ(MINIMUM); + m_LightSource->SetSpawnLocationZLength(2*MAXIMUM); + + m_LightSource->SetSpawnLocationRadius(MAXIMUM); + + m_LightSource->SetVerbose(false); + + m_LightSource->SetSpawnType(mitk::PhotoacousticLightSource::SpawnType::RECTANGLE); + + std::mt19937 rng; + rng.seed(std::chrono::duration_cast(std::chrono::high_resolution_clock:: + now().time_since_epoch()).count()); + std::uniform_real_distribution<> realDist(0, 1); + + for(int i=0, length=10000; iGetNextPhoton(realDist(rng), realDist(rng), realDist(rng), realDist(rng), + realDist(rng), realDist(rng), realDist(rng)); + + CPPUNIT_ASSERT(result.xAngle>=ANGLE_MINIMUM); + CPPUNIT_ASSERT(result.xAngle<=ANGLE_MAXIMUM); + CPPUNIT_ASSERT(result.yAngle>=ANGLE_MINIMUM); + CPPUNIT_ASSERT(result.yAngle<=ANGLE_MAXIMUM); + CPPUNIT_ASSERT(result.zAngle>=0); + CPPUNIT_ASSERT(result.zAngle<=ANGLE_MAXIMUM); + CPPUNIT_ASSERT(result.xPosition>=MINIMUM); + CPPUNIT_ASSERT(result.xPosition<=MAXIMUM); + CPPUNIT_ASSERT(result.yPosition>=MINIMUM); + CPPUNIT_ASSERT(result.yPosition<=MAXIMUM); + CPPUNIT_ASSERT(result.zPosition>=MINIMUM); + CPPUNIT_ASSERT(result.zPosition<=MAXIMUM); + } + } + + void tearDown() + { + m_XmlProbePointSource = ""; + m_XmlProbeCircleSource = ""; + m_XmlProbeRectangleSource = ""; + m_XmlProbeTwoPointSources = ""; + m_XmlProbeAllSources = ""; + m_Probe = nullptr; + } + +}; + +MITK_TEST_SUITE_REGISTRATION(mitkMcxyzXml) diff --git a/Modules/PhotoacousticSimulation/Testing/mitkPhotoacousticTissueGeneratorTest.cpp b/Modules/PhotoacousticSimulation/Testing/mitkPhotoacousticTissueGeneratorTest.cpp new file mode 100644 index 0000000000..74d2fc7e36 --- /dev/null +++ b/Modules/PhotoacousticSimulation/Testing/mitkPhotoacousticTissueGeneratorTest.cpp @@ -0,0 +1,49 @@ +/*=================================================================== + +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 "mitkPhotoacousticVolume.h" +#include "mitkPhotoacousticTissueGenerator.h" + +class mitkPhotoacousticTissueGeneratorTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkPhotoacousticTissueGeneratorTestSuite); + + CPPUNIT_TEST_SUITE_END(); + +private: + +public: + + void setUp() + { + + } + + + + void tearDown() + { + + } + +}; + +MITK_TEST_SUITE_REGISTRATION(mitkPhotoacousticTissueGenerator) diff --git a/Modules/PhotoacousticSimulation/Testing/mitkPhotoacousticVectorTest.cpp b/Modules/PhotoacousticSimulation/Testing/mitkPhotoacousticVectorTest.cpp new file mode 100644 index 0000000000..687d67eea6 --- /dev/null +++ b/Modules/PhotoacousticSimulation/Testing/mitkPhotoacousticVectorTest.cpp @@ -0,0 +1,277 @@ +/*=================================================================== + +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 "mitkPhotoacousticSmartVector.h" + +class mitkPhotoacousticVectorTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkPhotoacousticVectorTestSuite); + + MITK_TEST(TestNormalizeVector); + MITK_TEST(TestRotateVectorZeroDegrees); + MITK_TEST(TestRotatedVectorPositiveDegrees); + MITK_TEST(TestRotateVectorZeroDegrees); + MITK_TEST(TestScaleVector); + MITK_TEST(TestCloneVector); + + CPPUNIT_TEST_SUITE_END(); + +private: + + mitk::PhotoacousticSmartVector::Pointer m_TestVector; + mitk::PhotoacousticSmartVector::Pointer m_TestReturnVector; + + const double DIF_VAL = 0.001; + const double TWO_PI = 6.283185; + +public: + + void setUp() + { + m_TestVector = mitk::PhotoacousticSmartVector::New(); + m_TestReturnVector = mitk::PhotoacousticSmartVector::New(); + } + + void TestNormalizeVector() + { + std::stringstream output; + int a = 2; + int b = 3; + int c = 4; + + m_TestVector->SetElement(0,a); + m_TestVector->SetElement(1,b); + m_TestVector->SetElement(2,c); + + + output << "The vectorlength should be"; + output << sqrt(a*a+b*b+c*c); + CPPUNIT_ASSERT_EQUAL_MESSAGE( output.str(), sqrt(a*a+b*b+c*c), m_TestVector->GetNorm()); + output.flush(); + + m_TestVector->Normalize(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("The vectorlength should be 1.", true, m_TestVector->GetNorm()-1 < DIF_VAL); + } + + void TestRotateVectorZeroDegrees() + { + int a = 1; + int b = 2; + int c = 3; + + double length; + + m_TestVector->SetElement(0,a); + m_TestVector->SetElement(1,b); + m_TestVector->SetElement(2,c); + + length = m_TestVector->GetNorm(); + + m_TestVector->Rotate(0,0); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("The vector length should be equal", length, m_TestVector->GetNorm()); + + CPPUNIT_ASSERT_MESSAGE("The vector value at index0 should be 1.0", m_TestVector->GetElement(0) - 1 < DIF_VAL); + CPPUNIT_ASSERT_MESSAGE("The vector value at index1 should be 2.0", m_TestVector->GetElement(1) - 2 < DIF_VAL); + CPPUNIT_ASSERT_MESSAGE("The vector value at index2 should be 3.0", m_TestVector->GetElement(2) - 3 < DIF_VAL); + + } + + void TestRotatedVectorPositiveDegrees() + { + MITK_INFO << atan2(0, 0); + + for(int r = 0; r<10; r++) + { + for(double phi = 0.1; phi < 3; phi+=0.1) + { + for(double theta = 0.1; theta < 3; theta+=0.1) + { + + double rotateTheta = 0.1; + double rotatePhi = 0.1; + + m_TestVector->SetElement(0, r * sin(theta) * cos(phi)); + m_TestVector->SetElement(1, r * sin(theta) * sin(phi)); + m_TestVector->SetElement(2, r * cos(theta)); + + m_TestVector->Rotate(rotateTheta, rotatePhi); + + double newTheta = fmod(theta + rotateTheta, TWO_PI); + double newPhi = fmod(phi + rotatePhi, TWO_PI); + + double expectedX = r * sin(newTheta) * cos(newPhi); + double expectedY = r * sin(newTheta) * sin(newPhi); + double expectedZ = r * cos(newTheta); + + CPPUNIT_ASSERT_MESSAGE("The vector value at index0 should be " + std::to_string(expectedX) + " but was " + std::to_string(m_TestVector->GetElement(0)) + + " at r=" + std::to_string(r) + " phi=" + std::to_string(phi) + " theta=" + std::to_string(theta), + m_TestVector->GetElement(0) - expectedX < DIF_VAL); + CPPUNIT_ASSERT_MESSAGE("The vector value at index1 should be " + std::to_string(expectedY) + " but was " + std::to_string(m_TestVector->GetElement(0)) + + " at r=" + std::to_string(r) + " phi=" + std::to_string(phi) + " theta=" + std::to_string(theta), + m_TestVector->GetElement(1) - expectedY < DIF_VAL); + CPPUNIT_ASSERT_MESSAGE("The vector value at index2 should be " + std::to_string(expectedZ) + " but was " + std::to_string(m_TestVector->GetElement(0)) + + " at r=" + std::to_string(r) + " phi=" + std::to_string(phi) + " theta=" + std::to_string(theta), + m_TestVector->GetElement(2) - expectedZ < DIF_VAL); + } + } + } + + } + + void TestRotatedVectorNegativeDegrees() + { + + for(int r = 0; r<10; r++) + { + for(double phi = -0.1; phi > -3; phi-=0.1) + { + for(double theta = -0.1; theta > -3; theta-=0.1) + { + + double rotateTheta = -0.1; + double rotatePhi = -0.1; + + m_TestVector->SetElement(0, r * sin(theta) * cos(phi)); + m_TestVector->SetElement(1, r * sin(theta) * sin(phi)); + m_TestVector->SetElement(2, r * cos(theta)); + + m_TestVector->Rotate(rotateTheta, rotatePhi); + + double newTheta = fmod(theta + rotateTheta, TWO_PI); + double newPhi = fmod(phi + rotatePhi, TWO_PI); + + double expectedX = r * sin(newTheta) * cos(newPhi); + double expectedY = r * sin(newTheta) * sin(newPhi); + double expectedZ = r * cos(newTheta); + + CPPUNIT_ASSERT_MESSAGE("The vector value at index0 should be " + std::to_string(expectedX) + " but was " + std::to_string(m_TestVector->GetElement(0)) + + " at r=" + std::to_string(r) + " phi=" + std::to_string(phi) + " theta=" + std::to_string(theta), + m_TestVector->GetElement(0) - expectedX < DIF_VAL); + CPPUNIT_ASSERT_MESSAGE("The vector value at index1 should be " + std::to_string(expectedY) + " but was " + std::to_string(m_TestVector->GetElement(0)) + + " at r=" + std::to_string(r) + " phi=" + std::to_string(phi) + " theta=" + std::to_string(theta), + m_TestVector->GetElement(1) - expectedY < DIF_VAL); + CPPUNIT_ASSERT_MESSAGE("The vector value at index2 should be " + std::to_string(expectedZ) + " but was " + std::to_string(m_TestVector->GetElement(0)) + + " at r=" + std::to_string(r) + " phi=" + std::to_string(phi) + " theta=" + std::to_string(theta), + m_TestVector->GetElement(2) - expectedZ < DIF_VAL); + } + } + } + + } + + void TestScaleVector() + { + double a = 1.0; + double b = 2.0; + double c = 3.0; + + double length; + + for (double testFactor = -2.0; testFactor<=2.0; testFactor+=0.3) + { + + double potElement0Fctr; + double potElement1Fctr; + double potElement2Fctr; + double testLength; + + std::stringstream output; + + m_TestVector->SetElement(0,a); + m_TestVector->SetElement(1,b); + m_TestVector->SetElement(2,c); + + length = m_TestVector->GetNorm(); + + potElement0Fctr = (m_TestVector->GetElement(0)*testFactor)*(m_TestVector->GetElement(0)*testFactor); + potElement1Fctr = (m_TestVector->GetElement(1)*testFactor)*(m_TestVector->GetElement(1)*testFactor); + potElement2Fctr = (m_TestVector->GetElement(2)*testFactor)*(m_TestVector->GetElement(2)*testFactor); + + testLength = sqrt(potElement0Fctr + potElement1Fctr + potElement2Fctr); + + m_TestVector->Scale(testFactor); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("The vector length should not be equal", + sqrt(potElement0Fctr + potElement1Fctr + potElement2Fctr), m_TestVector->GetNorm()); + + output << "The vector value at index0 should be"; + output << a*testFactor; + CPPUNIT_ASSERT_EQUAL_MESSAGE( output.str(), a*testFactor, m_TestVector->GetElement(0)); + output.flush(); + + output << "The vector value at index1 should be"; + output << b*testFactor; + CPPUNIT_ASSERT_EQUAL_MESSAGE( output.str(), b*testFactor, m_TestVector->GetElement(1)); + output.flush(); + + output << "The vector value at index2 should be"; + output << c*testFactor; + CPPUNIT_ASSERT_EQUAL_MESSAGE( output.str(), c*testFactor, m_TestVector->GetElement(2)); + output.flush(); + } + + } + + void TestCloneVector() + { + int a = 1; + int b = 2; + int c = 3; + + m_TestVector->SetElement(0,a); + m_TestVector->SetElement(1,b); + m_TestVector->SetElement(2,c); + + m_TestReturnVector = m_TestVector->Clone(); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "The vector length should be equal",(m_TestVector->GetNorm()),m_TestReturnVector->GetNorm()); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "The vector value at index0 should be equal", m_TestVector->GetElement(0), m_TestReturnVector->GetElement(0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "The vector value at index1 should be equal", m_TestVector->GetElement(1), m_TestReturnVector->GetElement(1)); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "The vector value at index2 should be equal", m_TestVector->GetElement(2), m_TestReturnVector->GetElement(2)); + + m_TestReturnVector->Rotate(M_PI/4,M_PI/4); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "The vector value at index0 should be not equal", true, m_TestVector->GetElement(0)!= m_TestReturnVector->GetElement(0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "The vector value at index0 should be not equal", true, m_TestVector->GetElement(1)!= m_TestReturnVector->GetElement(1)); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "The vector value at index0 should be not equal", true, m_TestVector->GetElement(2)!= m_TestReturnVector->GetElement(2)); + + for(double testFactor = -2.0; testFactor<=2.0; testFactor+=0.3) + { + + m_TestReturnVector->Scale(testFactor); + + CPPUNIT_ASSERT_EQUAL_MESSAGE( "The vector value at index0 should be not equal", true, m_TestVector->GetElement(0)!= m_TestReturnVector->GetElement(0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "The vector value at index0 should be not equal", true, m_TestVector->GetElement(1)!= m_TestReturnVector->GetElement(1)); + CPPUNIT_ASSERT_EQUAL_MESSAGE( "The vector value at index0 should be not equal", true, m_TestVector->GetElement(2)!= m_TestReturnVector->GetElement(2)); + } + } + + void tearDown() + { + m_TestVector = nullptr; + m_TestReturnVector = nullptr; + } + +}; + +MITK_TEST_SUITE_REGISTRATION(mitkPhotoacousticVector) diff --git a/Modules/PhotoacousticSimulation/Testing/mitkPhotoacousticVesselMeanderStrategyTest.cpp b/Modules/PhotoacousticSimulation/Testing/mitkPhotoacousticVesselMeanderStrategyTest.cpp new file mode 100644 index 0000000000..8a3b620167 --- /dev/null +++ b/Modules/PhotoacousticSimulation/Testing/mitkPhotoacousticVesselMeanderStrategyTest.cpp @@ -0,0 +1,121 @@ +/*=================================================================== + +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 "mitkPhotoacousticVolume.h" +#include "mitkPhotoacousticTissueGenerator.h" +#include "mitkPhotoacousticVesselMeanderStrategy.h" + +class mitkPhotoacousticVesselMeanderStrategyTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkPhotoacousticVesselMeanderStrategyTestSuite); + MITK_TEST(TestCalculateNewPositionInStraightLine); + + CPPUNIT_TEST_SUITE_END(); + +private: + mitk::PhotoacousticVesselMeanderStrategy::Pointer m_TestVector; + mitk::PhotoacousticSmartVector::Pointer m_TestPostion; + mitk::PhotoacousticSmartVector::Pointer m_TestDirection; + +public: + + void setUp() + { + + m_TestVector = mitk::PhotoacousticVesselMeanderStrategy::New(); + m_TestPostion = mitk::PhotoacousticSmartVector::New(); + m_TestDirection = mitk::PhotoacousticSmartVector::New(); + + } + + void TestCalculateNewPositionInStraightLine() + { + std::stringstream output; + + int a = 0; + int b = 1; + int c = 2; + int d = 3; + int e = 4; + int f = 5; + + for(int i = -2; i <= 2; i++) + { + if(i == 0) + { + i++; + } + + for(int j = -2; j <= 2; j++ ) + { + if(j == 0) + { + j++; + } + + m_TestPostion -> SetElement(0,a*i); + m_TestPostion -> SetElement(1,b*i); + m_TestPostion -> SetElement(2,c*i); + m_TestDirection -> SetElement(0,d*j); + m_TestDirection -> SetElement(1,e*j); + m_TestDirection -> SetElement(2,f*j); + + m_TestVector->CalculateNewPositionInStraightLine(m_TestPostion,m_TestDirection, 0, nullptr); + + MITK_INFO<<"m_TestPosition Element(0) ="<GetElement(0); + MITK_INFO<<"Data0 ="<<(a*i) + (d*j); + MITK_INFO<<"m_TestPosition Element(1) ="<GetElement(1); + MITK_INFO<<"Data1 ="<<(b*i) + (e*j); + MITK_INFO<<"m_TestPosition Element(2) ="<GetElement(2); + MITK_INFO<<"Data2 ="<<(c*i) + (f*j); + + output << "Element0 from m_TestPosition should be "; + output << a*i + d*j; + CPPUNIT_ASSERT_EQUAL_MESSAGE( output.str(), true, a*i + d*j == m_TestPostion->GetElement(0)); + output.flush(); + + output << "Element1 from m_TestPosition should be "; + output << b*i + e*j; + CPPUNIT_ASSERT_EQUAL_MESSAGE( output.str(), true, b*i + e*j == m_TestPostion->GetElement(1)); + output.flush(); + + output << "Element2 from m_TestPosition should be "; + output << c*i + f*j; + CPPUNIT_ASSERT_EQUAL_MESSAGE( output.str(), true, c*i + f*j == m_TestPostion->GetElement(2)); + output.flush(); + + } + } + + } + + void tearDown() + { + + m_TestVector = nullptr; + m_TestPostion = nullptr; + m_TestDirection = nullptr; + + } + +}; + +MITK_TEST_SUITE_REGISTRATION(mitkPhotoacousticVesselMeanderStrategy) diff --git a/Modules/PhotoacousticSimulation/Testing/mitkPhotoacousticVesselTest.cpp b/Modules/PhotoacousticSimulation/Testing/mitkPhotoacousticVesselTest.cpp new file mode 100644 index 0000000000..ba5e5d9e10 --- /dev/null +++ b/Modules/PhotoacousticSimulation/Testing/mitkPhotoacousticVesselTest.cpp @@ -0,0 +1,76 @@ +/*=================================================================== + +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 "mitkPhotoacousticVolume.h" +#include "mitkPhotoacousticSmartVector.h" +#include "mitkPhotoacousticVessel.h" + +class mitkPhotoacousticVesselTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkPhotoacousticVesselTestSuite); + MITK_TEST(TestInitializedVesselOnlyZero); + + CPPUNIT_TEST_SUITE_END(); + +private: + mitk::PhotoacousticVessel::Pointer m_TestVessel; + mitk::PhotoacousticSmartVector::Pointer m_TestInitialPosition; + mitk::PhotoacousticSmartVector::Pointer m_TestInitialDirection; +public: + + void setUp() + { + m_TestVessel = mitk::PhotoacousticVessel ::New(); + m_TestInitialPosition = mitk::PhotoacousticSmartVector::New(); + m_TestInitialDirection = mitk::PhotoacousticSmartVector::New(); + + } + + void TestInitializedVesselOnlyZero() + { + int a = 1; + int b = 2; + int c = 3; + int d = 4; + int e = 5; + int f = 6; + + m_TestInitialPosition->SetElement(0,a); + m_TestInitialPosition->SetElement(1,b); + m_TestInitialPosition->SetElement(2,c); + + m_TestInitialDirection->SetElement(0,d); + m_TestInitialDirection->SetElement(1,e); + m_TestInitialDirection->SetElement(2,f); + + } + + void tearDown() + { + m_TestVessel = nullptr; + m_TestInitialPosition = nullptr; + m_TestInitialDirection = nullptr; + + } + +}; + +MITK_TEST_SUITE_REGISTRATION(mitkPhotoacousticVessel) diff --git a/Modules/PhotoacousticSimulation/Testing/mitkPhotoacousticVesselTreeTest.cpp b/Modules/PhotoacousticSimulation/Testing/mitkPhotoacousticVesselTreeTest.cpp new file mode 100644 index 0000000000..b7960028e6 --- /dev/null +++ b/Modules/PhotoacousticSimulation/Testing/mitkPhotoacousticVesselTreeTest.cpp @@ -0,0 +1,50 @@ +/*=================================================================== + +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 "mitkPhotoacousticVolume.h" +#include "mitkPhotoacousticTissueGenerator.h" + +class mitkPhotoacousticVesselTreeTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkPhotoacousticVesselTreeTestSuite); + + CPPUNIT_TEST_SUITE_END(); + +private: + //mitk::PhotoacousticTissueGenerator::Pointer m_TissueGenerator; + +public: + + void setUp() + { + //m_TissueGenerator = mitk::PhotoacousticTissueGenerator::New(); + + } + + void tearDown() + { + //m_TissueGenerator = nullptr; + + } + +}; + +MITK_TEST_SUITE_REGISTRATION(mitkPhotoacousticVesselTree) diff --git a/Modules/PhotoacousticSimulation/Testing/mitkPhotoacousticVolumeTest.cpp b/Modules/PhotoacousticSimulation/Testing/mitkPhotoacousticVolumeTest.cpp new file mode 100644 index 0000000000..8328eb195b --- /dev/null +++ b/Modules/PhotoacousticSimulation/Testing/mitkPhotoacousticVolumeTest.cpp @@ -0,0 +1,181 @@ +/*=================================================================== + +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 "mitkPhotoacousticVolume.h" +#include "mitkPhotoacousticTissueGeneratorParameters.h" + +class mitkPhotoacousticVolumeTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkPhotoacousticVolumeTestSuite); + MITK_TEST(TestInitializedTissueContainsOnlyZeros); + MITK_TEST(TestConvertedMitkImageContainsOnlyZerosOrAir); + MITK_TEST(TestTissueVolumeContainsCorrectAbsorptionNumber); + MITK_TEST(TestTissueVolumeContainsCorrectScatteringNumber); + MITK_TEST(TestTissueVolumeContainsCorrectAnisotropyNumber); + + CPPUNIT_TEST_SUITE_END(); + +private: + + mitk::PhotoacousticVolume::Pointer m_PhotoacousticVolume; + mitk::PhotoacousticTissueGeneratorParameters::Pointer m_TissueGeneratorParameters; + +public: + + void setUp() + { + + m_PhotoacousticVolume = mitk::PhotoacousticVolume::New(); + m_TissueGeneratorParameters = mitk::PhotoacousticTissueGeneratorParameters::New(); + + } + + void TestInitializedTissueContainsOnlyZeros() + { + int dims = 30; + m_TissueGeneratorParameters->SetXDim(dims); + m_TissueGeneratorParameters->SetYDim(dims); + m_TissueGeneratorParameters->SetZDim(dims); + m_TissueGeneratorParameters->SetAirThickness(0); + m_TissueGeneratorParameters->SetBackgroundAbsorption(0); + m_PhotoacousticVolume->Initialize(m_TissueGeneratorParameters); + + for(int x = 0; xGetVolumeAbsorptionValue(x, y, z)) < mitk::eps, true); + } + } + } + } + + void TestConvertedMitkImageContainsOnlyZerosOrAir() + { + int dims = 30; + m_TissueGeneratorParameters->SetXDim(dims); + m_TissueGeneratorParameters->SetYDim(dims); + m_TissueGeneratorParameters->SetZDim(dims); + m_PhotoacousticVolume->Initialize(m_TissueGeneratorParameters); + + mitk::Image::Pointer testImage = m_PhotoacousticVolume->ConvertToMitkImage(); + + mitk::ImageReadAccessor imgMemAcc(testImage); + double* imagePointer = (double*)imgMemAcc.GetData(); + + for(int index = 0; indexSetXDim(dims); + m_TissueGeneratorParameters->SetYDim(dims); + m_TissueGeneratorParameters->SetZDim(dims); + m_PhotoacousticVolume->Initialize(m_TissueGeneratorParameters); + + m_PhotoacousticVolume->SetVolumeValues(0, 0, 0, 0, 0, 0); + m_PhotoacousticVolume->SetVolumeValues(0, 0, 1, 1, 0, 0); + m_PhotoacousticVolume->SetVolumeValues(0, 1, 0, 2, 0, 0); + m_PhotoacousticVolume->SetVolumeValues(0, 1, 1, 3, 0, 0); + m_PhotoacousticVolume->SetVolumeValues(1, 0, 0, 4, 0, 0); + m_PhotoacousticVolume->SetVolumeValues(1, 0, 1, 5, 0, 0); + m_PhotoacousticVolume->SetVolumeValues(1, 1, 0, 6, 0, 0); + m_PhotoacousticVolume->SetVolumeValues(1, 1, 1, 7, 0, 0); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 0.0, m_PhotoacousticVolume->GetVolumeAbsorptionValue(0, 0, 0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 1.0, m_PhotoacousticVolume->GetVolumeAbsorptionValue(0, 0, 1)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 2.0, m_PhotoacousticVolume->GetVolumeAbsorptionValue(0, 1, 0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 3.0, m_PhotoacousticVolume->GetVolumeAbsorptionValue(0, 1, 1)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 4.0, m_PhotoacousticVolume->GetVolumeAbsorptionValue(1, 0, 0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 5.0, m_PhotoacousticVolume->GetVolumeAbsorptionValue(1, 0, 1)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 6.0, m_PhotoacousticVolume->GetVolumeAbsorptionValue(1, 1, 0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 7.0, m_PhotoacousticVolume->GetVolumeAbsorptionValue(1, 1, 1)); + } + + void TestTissueVolumeContainsCorrectScatteringNumber() + { + int dims = 2; + m_TissueGeneratorParameters->SetXDim(dims); + m_TissueGeneratorParameters->SetYDim(dims); + m_TissueGeneratorParameters->SetZDim(dims); + m_PhotoacousticVolume->Initialize(m_TissueGeneratorParameters); + + m_PhotoacousticVolume->SetVolumeValues(0, 0, 0, 0, 0, 0); + m_PhotoacousticVolume->SetVolumeValues(0, 0, 1, 0, 1, 0); + m_PhotoacousticVolume->SetVolumeValues(0, 1, 0, 0, 2, 0); + m_PhotoacousticVolume->SetVolumeValues(0, 1, 1, 0, 3, 0); + m_PhotoacousticVolume->SetVolumeValues(1, 0, 0, 0, 4, 0); + m_PhotoacousticVolume->SetVolumeValues(1, 0, 1, 0, 5, 0); + m_PhotoacousticVolume->SetVolumeValues(1, 1, 0, 0, 6, 0); + m_PhotoacousticVolume->SetVolumeValues(1, 1, 1, 0, 7, 0); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 0.0, m_PhotoacousticVolume->GetVolumeScatteringValue(0, 0, 0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 1.0, m_PhotoacousticVolume->GetVolumeScatteringValue(0, 0, 1)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 2.0, m_PhotoacousticVolume->GetVolumeScatteringValue(0, 1, 0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 3.0, m_PhotoacousticVolume->GetVolumeScatteringValue(0, 1, 1)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 4.0, m_PhotoacousticVolume->GetVolumeScatteringValue(1, 0, 0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 5.0, m_PhotoacousticVolume->GetVolumeScatteringValue(1, 0, 1)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 6.0, m_PhotoacousticVolume->GetVolumeScatteringValue(1, 1, 0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 7.0, m_PhotoacousticVolume->GetVolumeScatteringValue(1, 1, 1)); + } + + void TestTissueVolumeContainsCorrectAnisotropyNumber() + { + int dims = 2; + m_TissueGeneratorParameters->SetXDim(dims); + m_TissueGeneratorParameters->SetYDim(dims); + m_TissueGeneratorParameters->SetZDim(dims); + m_PhotoacousticVolume->Initialize(m_TissueGeneratorParameters); + + m_PhotoacousticVolume->SetVolumeValues(0, 0, 0, 0, 0, 0); + m_PhotoacousticVolume->SetVolumeValues(0, 0, 1, 0, 0, 1); + m_PhotoacousticVolume->SetVolumeValues(0, 1, 0, 0, 0, 2); + m_PhotoacousticVolume->SetVolumeValues(0, 1, 1, 0, 0, 3); + m_PhotoacousticVolume->SetVolumeValues(1, 0, 0, 0, 0, 4); + m_PhotoacousticVolume->SetVolumeValues(1, 0, 1, 0, 0, 5); + m_PhotoacousticVolume->SetVolumeValues(1, 1, 0, 0, 0, 6); + m_PhotoacousticVolume->SetVolumeValues(1, 1, 1, 0, 0, 7); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 0.0, m_PhotoacousticVolume->GetVolumeAnisotropyValue(0, 0, 0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 1.0, m_PhotoacousticVolume->GetVolumeAnisotropyValue(0, 0, 1)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 2.0, m_PhotoacousticVolume->GetVolumeAnisotropyValue(0, 1, 0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 3.0, m_PhotoacousticVolume->GetVolumeAnisotropyValue(0, 1, 1)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 4.0, m_PhotoacousticVolume->GetVolumeAnisotropyValue(1, 0, 0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 5.0, m_PhotoacousticVolume->GetVolumeAnisotropyValue(1, 0, 1)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 6.0, m_PhotoacousticVolume->GetVolumeAnisotropyValue(1, 1, 0)); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Should be correct value", 7.0, m_PhotoacousticVolume->GetVolumeAnisotropyValue(1, 1, 1)); + } + + + void tearDown() + { + m_PhotoacousticVolume = nullptr; + } + +}; + +MITK_TEST_SUITE_REGISTRATION(mitkPhotoacousticVolume) diff --git a/Modules/PhotoacousticSimulation/files.cmake b/Modules/PhotoacousticSimulation/files.cmake new file mode 100644 index 0000000000..2153b543ad --- /dev/null +++ b/Modules/PhotoacousticSimulation/files.cmake @@ -0,0 +1,25 @@ +set(CPP_FILES + Utils/mitkPhotoacousticPropertyCalculator.cpp + Utils/mitkPhotoacousticSmartVector.cpp + Utils/mitkPhotoacousticStatefulObject.cpp + Utils/mitkPhotoacousticTissueGeneratorParameters.cpp + Algorithms/mitkPhotoacousticVolume.cpp + Algorithms/mitkPhotoacousticTissueGenerator.cpp + Algorithms/mitkPhotoacousticVesselTree.cpp + Algorithms/mitkPhotoacousticVessel.cpp + Algorithms/mitkPhotoacousticVesselMeanderStrategy.cpp + Algorithms/mitkPhotoacousticNoiseGenerator.cpp + Algorithms/mitkPhotoacoustic3dVolume.cpp + Algorithms/mitkPhotoacousticFatTissueGenerator.cpp + Algorithms/mitkPhotoacousticComposedVolume.cpp + Algorithms/mitkPhotoacousticSlicedVolumeGenerator.cpp + ProbeDesign/mitkPhotoacousticProbe.cpp + ProbeDesign/mitkPhotoacousticLightSource.cpp + IO/mitkPhotoacousticIO.cpp + Thread/mitkMonteCarloThreadHandler.cpp +) + +set(RESOURCE_FILES + photoacoustics128x128.png + spectralLIB.dat +) diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacoustic3dVolume.cpp b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacoustic3dVolume.cpp new file mode 100644 index 0000000000..c24003f240 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacoustic3dVolume.cpp @@ -0,0 +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 "mitkPhotoacoustic3dVolume.h" +#include + +mitk::Photoacoustic3dVolume::Photoacoustic3dVolume(double* data, int xDim, int yDim, int zDim): + m_XDim(xDim), + m_YDim(yDim), + m_ZDim(zDim) +{ + if(data == nullptr) + mitkThrow() << "You may not initialize a mitk::Photoacoustic3dVolume with a nullptr"; + + m_VolumeData = data; + m_State = INITIALIZED; +} + +mitk::Photoacoustic3dVolume::~Photoacoustic3dVolume() +{ + static std::mutex destructorMutex; + + destructorMutex.lock(); + if(m_VolumeData!= nullptr) + { + delete[] m_VolumeData; + m_VolumeData = nullptr; + } + m_State = UNINITIALIZED; + destructorMutex.unlock(); +} +mitk::Photoacoustic3dVolume::Pointer mitk::Photoacoustic3dVolume::DeepCopy() +{ + AssertState(INITIALIZED); + long length = m_XDim*m_YDim*m_ZDim; + double* data = new double[length]; + memcpy(data, m_VolumeData, length*sizeof(double)); + + return mitk::Photoacoustic3dVolume::New(data, m_XDim, m_YDim, m_ZDim); +} + +mitk::Image::Pointer mitk::Photoacoustic3dVolume::ConvertToMitkImage() +{ + AssertState(INITIALIZED); + + mitk::Image::Pointer resultImage = mitk::Image::New(); + + mitk::PixelType TPixel = mitk::MakeScalarPixelType(); + + unsigned int* dimensionsOfImage = new unsigned int[NUMBER_OF_SPATIAL_DIMENSIONS]; + dimensionsOfImage[0] = m_YDim; + dimensionsOfImage[1] = m_XDim; + dimensionsOfImage[2] = m_ZDim; + + MITK_DEBUG << "Initializing image..."; + resultImage->Initialize(TPixel, NUMBER_OF_SPATIAL_DIMENSIONS, dimensionsOfImage, 1); + + resultImage->SetImportVolume(m_VolumeData); + + MITK_DEBUG << "Initializing image...[Done]"; + + return resultImage; +} + +double mitk::Photoacoustic3dVolume::GetData(int x, int y, int z) +{ + AssertState(INITIALIZED); + return m_VolumeData[GetIndex(x, y, z)]; +} + +void mitk::Photoacoustic3dVolume::SetData(double data, int x, int y, int z) +{ + AssertState(INITIALIZED); + m_VolumeData[GetIndex(x, y, z)] = data; +} + +int mitk::Photoacoustic3dVolume::GetXDim() +{ + AssertState(INITIALIZED); + return m_XDim; +} + +int mitk::Photoacoustic3dVolume::GetYDim() +{ + AssertState(INITIALIZED); + return m_YDim; +} + +int mitk::Photoacoustic3dVolume::GetZDim() +{ + AssertState(INITIALIZED); + return m_ZDim; +} + +mitk::Photoacoustic3dVolume::Pointer mitk::Photoacoustic3dVolume::CreateDifferenceImage(mitk::Photoacoustic3dVolume::Pointer other, bool relative) +{ + AssertState(INITIALIZED); + + double* resultArray = (double*) malloc(m_XDim*m_YDim*m_ZDim*sizeof(double)); + + for(int z=0; zGetData(x, y, z); + else + resultArray[GetIndex(x, y, z)] = GetData(x, y, z) - other->GetData(x, y, z); + } + } + } + + return New(resultArray, m_XDim, m_YDim, m_ZDim); +} + +mitk::Photoacoustic3dVolume::Pointer mitk::Photoacoustic3dVolume::ThresholdImage(double threshold) +{ + AssertState(INITIALIZED); + + double* resultArray = (double*) malloc(m_XDim*m_YDim*m_ZDim*sizeof(double)); + + for(int z=0; zthreshold) + resultArray[GetIndex(x, y, z)] = 1; + else + resultArray[GetIndex(x, y, z)] = 0; + } + } + } + + return New(resultArray, m_XDim, m_YDim, m_ZDim); +} + +int mitk::Photoacoustic3dVolume::GetIndex(int x, int y, int z) +{ + return z * m_XDim * m_YDim + x * m_YDim + y; +} diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacoustic3dVolume.h b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacoustic3dVolume.h new file mode 100644 index 0000000000..582a8ba81c --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacoustic3dVolume.h @@ -0,0 +1,138 @@ +/*=================================================================== + +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 "MitkPhotoacousticSimulationExports.h" + +//Includes for smart pointer usage +#include "mitkCommon.h" +#include "itkLightObject.h" +#include "mitkPhotoacousticStatefulObject.h" + +#include + +namespace mitk +{ +/** + * @brief The Photoacoustic3dVolume class is designed to encapsulate volumetric information and to provide convenience methods + * for data access and image conversions. + */ +class MITKPHOTOACOUSTICSIMULATION_EXPORT Photoacoustic3dVolume : public itk::LightObject, public mitk::PhotoacousticStatefulObject +{ +public: + + mitkClassMacroItkParent(mitk::Photoacoustic3dVolume, itk::LightObject) + mitkNewMacro4Param(Self, double*, int, int, int) + + /** + * @brief ConvertToMitkImage + * Creates a new mitk::Image and copies the data array into it. + * + * @return a mitk::Image::Pointer containing a copy (!) of the data of this array. + */ + mitk::Image::Pointer ConvertToMitkImage(); + + /** + * @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 Photoacoustic3dVolume at + * positon x|y|z. + */ + double GetData(int x, int y, int z); + + /** + * @brief SetData + * @param data + * @param x + * @param y + * @param z + */ + void SetData(double data, int x, int y, int z); + + /** + * @brief GetXDim + * @return size of x dimension of this Photoacoustic3dVolume + */ + int GetXDim(); + + /** + * @brief GetYDim + * @return size of y dimension of this Photoacoustic3dVolume + */ + int GetYDim(); + + /** + * @brief GetZDim + * @return size of z dimension of this Photoacoustic3dVolume + */ + int GetZDim(); + + /** + * @brief DeepCopy + * @return a deep copy of this Photoacoustic3dVolume. the old volume remains intact and memory is NOT shared + * between the objects. + */ + mitk::Photoacoustic3dVolume::Pointer DeepCopy(); + + /** + * @brief CreateDifferenceImage creates a difference image of this volume and another. + * @param other + * @param relative if true, the images will be divided, if false they will be subtracted. + * @return a new volume. The data of the original images is not affected. + */ + mitk::Photoacoustic3dVolume::Pointer CreateDifferenceImage(mitk::Photoacoustic3dVolume::Pointer other, + bool relative = false); + + /** + * @brief ThresholdImage applies a binary threshold filter to this image. + * @param threshold + * @return a new binary volume. The data of the current instance will not be affected. + */ + mitk::Photoacoustic3dVolume::Pointer ThresholdImage(double threshold); + +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. + * + * @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 + */ + Photoacoustic3dVolume(double* data, int xDim, int yDim, int zDim); + virtual ~Photoacoustic3dVolume(); + + const int NUMBER_OF_SPATIAL_DIMENSIONS = 3; + + double* m_VolumeData; + int m_XDim; + int m_YDim; + int m_ZDim; + + int GetIndex(int x, int y, int z); +}; +} + +#endif // MITKPHOTOACOUSTIC3dVOLUME_H diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticComposedVolume.cpp b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticComposedVolume.cpp new file mode 100644 index 0000000000..d888441cf5 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticComposedVolume.cpp @@ -0,0 +1,160 @@ +/*=================================================================== + +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 "mitkPhotoacousticComposedVolume.h" +#include "mitkIOUtil.h" +#include "mitkImageReadAccessor.h" +#include + +mitk::PhotoacousticComposedVolume::~PhotoacousticComposedVolume() +{ + m_FluenceValues.clear(); +} + +mitk::PhotoacousticComposedVolume::PhotoacousticComposedVolume() +{ + m_FluenceValues.clear(); +} + +int mitk::PhotoacousticComposedVolume::GetNumberOfFluenceComponents() +{ + return m_FluenceComponents; +} + +int mitk::PhotoacousticComposedVolume::GetYOffsetForFluenceComponent(int fluenceComponent) +{ + return (int)(m_FluenceValues.at(fluenceComponent).yOffset/m_Spacing); +} + +double mitk::PhotoacousticComposedVolume::GetFluenceValue(int fluenceComponent, int x, int y, int z) +{ + return m_FluenceValues.at(fluenceComponent).fluenceValue[z * m_XDim * m_YDim + x * m_YDim + y + GetYOffsetForFluenceComponent(fluenceComponent)]; +} + +void mitk::PhotoacousticComposedVolume::InitializeByNrrd(std::string nrrdFile) +{ + AssertState(UNINITIALIZED); + MITK_INFO << "Initializing PhotoacousticComposedVolume by nrrd..."; + mitk::Image::Pointer inputImage = mitk::IOUtil::LoadImage(nrrdFile); + + m_XDim = inputImage->GetDimensions()[1]; + m_YDim = inputImage->GetDimensions()[0]; + m_ZDim = inputImage->GetDimensions()[2]; + m_TDim = 3; + m_FluenceComponents = 0; + + double xSpacing = inputImage->GetGeometry(0)->GetSpacing()[1]; + double ySpacing = inputImage->GetGeometry(0)->GetSpacing()[0]; + double zSpacing = inputImage->GetGeometry(0)->GetSpacing()[2]; + + if((xSpacing - ySpacing) > mitk::eps || (xSpacing - zSpacing) > mitk::eps || (ySpacing - zSpacing) > mitk::eps ) + { + throw mitk::Exception("Cannot handle unequal spacing."); + } + + m_Spacing = xSpacing; + + m_PropertyList = inputImage->GetPropertyList(); + + bool hasMcFlag = m_PropertyList->GetProperty("mcflag")!=nullptr; + bool hasLaunchflag = m_PropertyList->GetProperty("launchflag")!=nullptr; + bool hasBoundaryFlag = m_PropertyList->GetProperty("boundaryflag")!=nullptr; + bool haslaunchpointX = m_PropertyList->GetProperty("launchPointX")!=nullptr; + bool hasFocusPointY = m_PropertyList->GetProperty("focusPointY")!=nullptr; + bool hasTrajectoryVectorZ = m_PropertyList->GetProperty("trajectoryVectorZ")!=nullptr; + + if(!hasMcFlag || !hasLaunchflag || !hasBoundaryFlag || + !haslaunchpointX || !hasFocusPointY || !hasTrajectoryVectorZ) + { + throw mitk::Exception("At least one property is missing."); + } + + mitk::ImageReadAccessor readAccess0(inputImage, inputImage->GetVolumeData(0)); + m_AbsorptionArray = new double[m_XDim*m_YDim*m_ZDim]; + memcpy(m_AbsorptionArray, readAccess0.GetData(), m_XDim*m_YDim*m_ZDim*sizeof(double)); + + mitk::ImageReadAccessor readAccess1(inputImage, inputImage->GetVolumeData(1)); + m_ScatteringArray = new double[m_XDim*m_YDim*m_ZDim]; + memcpy(m_ScatteringArray, readAccess1.GetData(), m_XDim*m_YDim*m_ZDim*sizeof(double)); + + mitk::ImageReadAccessor readAccess2(inputImage, inputImage->GetVolumeData(2)); + m_AnisotropyArray = new double[m_XDim*m_YDim*m_ZDim]; + memcpy(m_AnisotropyArray, readAccess2.GetData(), m_XDim*m_YDim*m_ZDim*sizeof(double)); + + m_State = INITIALIZED; + MITK_INFO << "Initializing PhotoacousticComposedVolume by nrrd...[Done]"; +} + +void mitk::PhotoacousticComposedVolume::AddSlice(std::string nrrdFile) +{ + AssertState(INITIALIZED); + MITK_DEBUG << "Adding slice..."; + + mitk::Image::Pointer inputImage = mitk::IOUtil::LoadImage(nrrdFile); + mitk::ImageReadAccessor readAccess0(inputImage, inputImage->GetVolumeData(0)); + + int size = m_XDim*m_YDim*m_ZDim; + double* fluenceArray = new double[size]; + memcpy(fluenceArray, readAccess0.GetData(), size*sizeof(double)); + + std::string yOff = inputImage->GetProperty("y-offset")->GetValueAsString(); + MITK_DEBUG << "Reading y Offset: " << yOff; + std::replace( yOff.begin(), yOff.end(), '.', ','); + double yOffset = std::stod(yOff); + MITK_DEBUG << "Converted offset " << yOffset; + + MITK_DEBUG << "Creating FluenceValue"; + FluenceValue fv; + fv.fluenceValue = fluenceArray; + fv.yOffset = yOffset; + fv.size = size; + + for(int i = 0; i < 2; i++) + { + m_FluenceValues.push_back(fv); + m_FluenceComponents++; + m_TDim++; + } + + MITK_DEBUG << "Adding slice...[Done]"; +} + +void mitk::PhotoacousticComposedVolume::Sort() +{ + std::sort(m_FluenceValues.begin(), m_FluenceValues.end(), [](const FluenceValue& struct1, const FluenceValue& struct2) + { + return (struct1.yOffset < struct2.yOffset); + }); +} + +mitk::Image::Pointer mitk::PhotoacousticComposedVolume::ConvertToMitkImage() +{ + AssertState(INITIALIZED); + MITK_DEBUG << "Converting to Mitk Image..."; + + Sort(); + + MITK_DEBUG << "Creating basic mitk image..."; + mitk::Image::Pointer oldImage = mitk::PhotoacousticVolume::ConvertToMitkImage(); + MITK_DEBUG << "Creating basic mitk image...[Done]"; + + for(int component = 3; component < m_TDim; component++) + { + oldImage->SetImportVolume(m_FluenceValues.at(component-3).fluenceValue, component, 0, mitk::Image::CopyMemory); + } + + MITK_DEBUG << "Converting to Mitk Image...[Done]"; + return oldImage; +} diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticComposedVolume.h b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticComposedVolume.h new file mode 100644 index 0000000000..88cf2a2815 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticComposedVolume.h @@ -0,0 +1,167 @@ +/*=================================================================== + +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 MITKPHOTOACOUSTICCOMPOSEDVOLUME_H +#define MITKPHOTOACOUSTICCOMPOSEDVOLUME_H + +#include + +#include +#include +#include + +//Includes for smart pointer usage +#include "mitkCommon.h" +#include "itkLightObject.h" + +namespace mitk +{ +/** + * @brief The PhotoacousticComposedVolume class provides the means to systematically collect nrrd files that correspond to + * different simulation slices of the same PhotoacousticVolume. + * + * An instance of this class is needed for the PhotoacousticSlicedVolumeGenerator + */ +class MITKPHOTOACOUSTICSIMULATION_EXPORT PhotoacousticComposedVolume : public mitk::PhotoacousticVolume +{ +public: + mitkClassMacro(mitk::PhotoacousticComposedVolume, mitk::PhotoacousticVolume) + itkFactorylessNewMacro(Self) + + /** + * @brief The FluenceValue struct + * A simple class struct to make a pair of a data array and a corresponding yOffset. + */ + struct FluenceValue + { + double* fluenceValue; + double yOffset; + int size; + + FluenceValue() + { + fluenceValue = nullptr; + } + + ~FluenceValue() + { + if(fluenceValue!=nullptr) + delete[] fluenceValue; + + fluenceValue = nullptr; + } + + FluenceValue (const FluenceValue &other) + { + fluenceValue = new double[other.size]; + size = other.size; + yOffset = other.yOffset; + memcpy(fluenceValue, other.fluenceValue, sizeof(double) * size); + } + + const FluenceValue &operator=(const FluenceValue &other) + { + if(this == &other) + return *this; + + if(fluenceValue!=nullptr) + { + delete[] fluenceValue; + fluenceValue = nullptr; + } + + fluenceValue = new double[other.size]; + size = other.size; + yOffset = other.yOffset; + + memcpy(fluenceValue, other.fluenceValue, sizeof(double) * size); + + return *this; + } + }; + + /** + * @brief InitializeByNrrd + * Initializes this Composed Volume with a ground truth nrrd file. + * The given file needs to have equal spacing. + * The given file needs all necessary parameters as meta data in the nrrd header. + * The given file needs to contain absorption, scattering and anisotrophy coefficients + * in the time steps 0, 1, and 2. + * + * @param nrrdFile path to the nrrd file on hard drive + */ + void InitializeByNrrd(std::string nrrdFile); + + /** + * @brief AddSlice + * Adds a MC Simulation nrrd file to this composed volume. + * The given file needs to contain the meta information "y-offset". + * This method ensures that all added slices are in the correct order + * corresponding to their y-offset. + * + * @param nrrdFile path to the nrrd file on hard drive + */ + void AddSlice(std::string nrrdFile); + + /** + * @brief ConvertToMitkImage + * Creates an mitk image out of this composed volume. + * In ths image, all sliced simulation volumes are put into different + * time components. + * If you need a 3D Reconstruction, use the mitk::SlicedVolumeGenerator. + * + * @ref mitkSlicedVolumeGenerator.h + * + * @return a mitk::Image::Pointer containing the data of the composed volume + */ + mitk::Image::Pointer ConvertToMitkImage(); + + /** + * @brief GetNumberOfFluenceComponents + * @return the number of fluence components encapsuled by this ComposedVolume. + */ + int GetNumberOfFluenceComponents(); + + /** + * @brief GetFluenceValue + * @param fluenceComponent + * @param x + * @param y + * @param z + * @return the fluence value for a specific fluence component index at the given 3D location. + */ + double GetFluenceValue(int fluenceComponent, int x, int y, int z); + + /** + * @brief GetYOffsetForFluenceComponent + * @param fluenceComponent + * @return the y-offset value for a given fluence component index. + */ + int GetYOffsetForFluenceComponent(int fluenceComponent); + + void Sort(); + +protected: + PhotoacousticComposedVolume(); + ~PhotoacousticComposedVolume(); + +private: + int m_FluenceComponents; + std::vector m_FluenceValues; +}; +} + +#endif // MITKPHOTOACOUSTICCOMPOSEDVOLUME_H diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticComposedVolume.h.autosave b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticComposedVolume.h.autosave new file mode 100644 index 0000000000..2636ab4b3a --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticComposedVolume.h.autosave @@ -0,0 +1,167 @@ +/*=================================================================== + +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 MITKPHOTOACOUSTICCOMPOSEDVOLUME_H +#define MITKPHOTOACOUSTICCOMPOSEDVOLUME_H + +#include + +#include +#include +#include + +//Includes for smart pointer usage +#include "mitkCommon.h" +#include "itkLightObject.h" + +namespace mitk +{ +/** + * @brief The PhotoacousticComposedVolume class provides the means to systematically collect nrrd files that correspond to + * different simulation slices of the same PhotoacousticVolume. + * + * An instance of this class is needed for the PhotoacousticSlicedVolumeGenerator + */ +class MITKPHOTOACOUSTICSIMULATION_EXPORT PhotoacousticComposedVolume : public mitk::PhotoacousticVolume +{ +public: + mitkClassMacro(mitk::PhotoacousticComposedVolume, mitk::PhotoacousticVolume) + itkFactorylessNewMacro(Self) + + /** + * @brief The FluenceValue struct + * A simple class struct to make a pair of a data array and a corresponding yOffset. + */ + struct FluenceValue + { + double* fluenceValue; + double yOffset; + int size; + + FluenceValue() + { + fluenceValue = nullptr; + } + + ~FluenceValue() + { + if(fluenceValue!=nullptr) + delete[] fluenceValue; + + fluenceValue = nullptr; + } + + FluenceValue (const FluenceValue &other) + { + fluenceValue = new double[other.size]; + size = other.size; + yOffset = other.yOffset; + memcpy(fluenceValue, other.fluenceValue, sizeof(double) * size); + } + + const FluenceValue &operator=(const FluenceValue &other) + { + if(this == &other) + return *this; + + if(fluenceValue!=nullptr) + { + delete[] fluenceValue; + fluenceValue = nullptr; + } + + fluenceValue = new double[other.size]; + size = other.size; + yOffset = other.yOffset; + + memcpy(fluenceValue, other.fluenceValue, sizeof(double) * size); + + return *this; + } + }; + + /** + * @brief InitializeByNrrd + * Initializes this Composed Volume with a ground truth nrrd file. + * The given file needs to have equal spacing. + * The given file needs all necessary parameters as meta data in the nrrd header. + * The given file needs to contain absorption, scattering and anisotrophy coefficients + * in the time steps 0, 1, and 2. + * + * @param nrrdFile path to the nrrd file on hard drive + */ + void InitializeByNrrd(std::string nrrdFile); + + /** + * @brief AddSlice + * Adds a MC Simulation nrrd file to this composed volume. + * The given file needs to contain the meta information "y-offset". + * This method ensures that all added slices are in the correct order + * corresponding to their y-offset. + * + * @param nrrdFile path to the nrrd file on hard drive + */ + void AddSlice(std::string nrrdFile); + + /** + * @brief ConvertToMitkImage + * Creates an mitk image out of this composed volume. + * In ths image, all sliced simulation volumes are put into different + * time components. + * If you need a 3D Reconstruction, use the mitk::SlicedVolumeGenerator. + * + * @ref mitkSlicedVolumeGenerator.h + * + * @return a mitk::Image::Pointer containing the data of the composed volume + */ + mitk::Image::Pointer ConvertToMitkImage(); + + /** + * @brief GetNumberOfFluenceComponents + * @return the number of fluence components encapsuled by this ComposedVolume. + */ + int GetNumberOfFluenceComponents(); + + /** + * @brief GetFluenceValue + * @param fluenceComponent + * @param x + * @param y + * @param z + * @return the fluence value for a specific fluence component index at the given 3D location. + */ + double GetFluenceValue(int fluenceComponent, int x, int y, int z); + + /** + * @brief GetYOffsetForFluenceComponent + * @param fluenceComponent + * @return the y-offset value for a given fluence component index. + */ + int GetYOffsetForFluenceComponent(int fluenceComponent); + + void Sort(); + +protected: + PhotoacousticComposedVolume(); + ~PhotoacousticComposedVolume(); + +private: + int m_FluenceComponents; + std::vector m_FluenceValues; +}; +} + +#endif // MITKPHOTOACOUSTICCOMPOSEDVOLUME_H diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticFatTissueGenerator.cpp b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticFatTissueGenerator.cpp new file mode 100644 index 0000000000..857e93b1cf --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticFatTissueGenerator.cpp @@ -0,0 +1,53 @@ +#include "mitkPhotoacousticFatTissueGenerator.h" +#include +#include +#include + +void mitk::PhotoacousticFatTissueGenerator::CreateFatGlobules(mitk::PhotoacousticVolume::Pointer image, mitk::PhotoacousticTissueGeneratorParameters::Pointer parameters, + std::mt19937* rng) +{ + if (parameters->GetFatPercentage() < mitk::eps) + return; + + const double VOLUME_CONSTANT = 4.0 / 3.0 * 3.14159265359; + const double NORMAL_DISTRIBUTION_SIGMA = 0.2; + const double MINIMUM_FAT_GLOBULES_FACTOR = 0.83; + const double MAXIMUM_FAT_GLOBULES_FACTOR = 1.2; + + int xDim = image->getXDim(); + int yDim = image->getYDim(); + int zDim = image->getZDim(); + + long length = xDim*yDim*zDim; + + double sqrtLength = 2 * sqrt(sqrt(length)); + + std::uniform_int_distribution<> numberOfFatGlobulesDist(MINIMUM_FAT_GLOBULES_FACTOR*sqrtLength, + MAXIMUM_FAT_GLOBULES_FACTOR*sqrtLength); + std::normal_distribution<> normalDistribution(1, NORMAL_DISTRIBUTION_SIGMA); + + int numberOfFatGlobules = numberOfFatGlobulesDist(*rng); + + double radius = pow(length*parameters->GetFatPercentage()/100.0/(numberOfFatGlobules * VOLUME_CONSTANT), (1.0/3.0)); + + std::uniform_int_distribution<> xDist(-radius, xDim+radius); + std::uniform_int_distribution<> yDist(-radius, yDim+radius); + std::uniform_int_distribution<> zDist(1.5*radius, zDim+radius); + + for(int fatGlobuleIdx = 0; fatGlobuleIdxSetVolumeValues(x, y, z, parameters->GetFatAbsorption(), parameters->GetFatScattering(), parameters->GetFatAnisotropy(), mitk::PhotoacousticVolume::SegmentationType::FAT); + } + } + } +} diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticFatTissueGenerator.h b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticFatTissueGenerator.h new file mode 100644 index 0000000000..cbded88a7b --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticFatTissueGenerator.h @@ -0,0 +1,46 @@ +/*=================================================================== + +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 MITKPHOTOACOUSTICFATTISSUEGENERATOR_H +#define MITKPHOTOACOUSTICFATTISSUEGENERATOR_H + +#include "MitkPhotoacousticSimulationExports.h" + +#include "mitkPhotoacousticVolume.h" +#include "mitkPhotoacousticTissueGeneratorParameters.h" + +namespace mitk +{ +class MITKPHOTOACOUSTICSIMULATION_EXPORT PhotoacousticFatTissueGenerator +{ +public: + + /** + * @brief CreateFatGlobules + * @param image + * @param parameters + * @param rng + */ + static void CreateFatGlobules(mitk::PhotoacousticVolume::Pointer image, mitk::PhotoacousticTissueGeneratorParameters::Pointer parameters, + std::mt19937* rng); +private: + PhotoacousticFatTissueGenerator(); + ~PhotoacousticFatTissueGenerator(); + +}; +} + +#endif // MITKPHOTOACOUSTICFATTISSUEGENERATOR_H diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticNoiseGenerator.cpp b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticNoiseGenerator.cpp new file mode 100644 index 0000000000..4daeedcfb7 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticNoiseGenerator.cpp @@ -0,0 +1,43 @@ +#include "mitkPhotoacousticNoiseGenerator.h" +#include +#include +#include + +void mitk::PhotoacousticNoiseGenerator::ApplyNoiseModel(mitk::Photoacoustic3dVolume::Pointer image, double detectorNoise, double speckleNoise) +{ + if(detectorNoise < 0 || speckleNoise < 0) + { + std::string msg = "detectorNoise must be >= 0 and speckleNoise must be >= 0"; + MITK_ERROR << msg; + mitkThrow() << msg; + } + + if(detectorNoise == 0 && speckleNoise == 1) + { + return; + } + + std::mt19937 rng; + std::random_device randomDevice; + if(randomDevice.entropy()>mitk::eps) + { + rng.seed(randomDevice()); + } + else + { + rng.seed(std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count()); + } + std::normal_distribution<> detector(detectorNoise/2, detectorNoise/2); + std::normal_distribution<> speckle(1, speckleNoise); + + //TODO: Determine realistic noise model. + for(int x = 0, xLength=image->GetXDim(); x < xLength; x++) + for(int y = 0, yLength=image->GetYDim(); y < yLength; y++) + for(int z = 0, zLength=image->GetZDim(); z < zLength; z++) + { + double additiveNoise = detector(rng); + if(additiveNoise<=0) + additiveNoise = 0; + image->SetData((image->GetData(x, y, z)+additiveNoise)*speckle(rng), x, y, z); + } +} diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticNoiseGenerator.h b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticNoiseGenerator.h new file mode 100644 index 0000000000..2efd334fc1 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticNoiseGenerator.h @@ -0,0 +1,46 @@ +/*=================================================================== + +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 MITKPHOTOACOUSTICNOISEGENERATOR_H +#define MITKPHOTOACOUSTICNOISEGENERATOR_H + +#include "MitkPhotoacousticSimulationExports.h" + +#include "mitkPhotoacoustic3dVolume.h" + +namespace mitk +{ +class MITKPHOTOACOUSTICSIMULATION_EXPORT PhotoacousticNoiseGenerator final +{ +public: + + /** + * @brief ApplyNoiseModel + * Applies noise to an image. + * @param image the image to apply the noise to + * @param detectorNoise >= 0 + * @param speckleNoise >= 1 + */ + static void ApplyNoiseModel(mitk::Photoacoustic3dVolume::Pointer image, double detectorNoise, double speckleNoise); + +private: + PhotoacousticNoiseGenerator(); + ~PhotoacousticNoiseGenerator(); + +}; +} + +#endif // MITKPHOTOACOUSTICNOISEGENERATOR_H diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticSlicedVolumeGenerator.cpp b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticSlicedVolumeGenerator.cpp new file mode 100644 index 0000000000..a653f5bdad --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticSlicedVolumeGenerator.cpp @@ -0,0 +1,129 @@ +/*=================================================================== + +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 "mitkPhotoacousticSlicedVolumeGenerator.h" +#include +#include + +mitk::PhotoacousticSlicedVolumeGenerator::PhotoacousticSlicedVolumeGenerator() +{ + m_State = UNINITIALIZED; + m_YSlice = -1; + m_Precorrect = false; + m_PrecorrectionVolume = nullptr; +} + +mitk::PhotoacousticSlicedVolumeGenerator::~PhotoacousticSlicedVolumeGenerator() +{ + m_State = UNINITIALIZED; + m_YSlice = -1; + m_Precorrect = false; + m_PrecorrectionVolume = nullptr; +} + +void mitk::PhotoacousticSlicedVolumeGenerator::Initialize(int ySlice, bool precorrect, std::string precorrectionVolumeFilename, bool inverse) +{ + m_State = INITIALIZED; + m_YSlice = ySlice; + m_Precorrect = precorrect; + m_Inverse = inverse; + + if(m_Precorrect) + m_PrecorrectionVolume = mitk::PhotoacousticIO::LoadNrrd(precorrectionVolumeFilename); +} + +mitk::Photoacoustic3dVolume::Pointer mitk::PhotoacousticSlicedVolumeGenerator::GetSlicedFluenceImageFromComposedVolume(mitk::PhotoacousticComposedVolume::Pointer composedVolume) +{ + if(m_State !=INITIALIZED) + throw mitk::Exception("Sliced Volume Generator not initialized yet."); + + int fluenceComponents = composedVolume->GetNumberOfFluenceComponents(); + + int xDim = composedVolume->getXDim(); + int zDim = composedVolume->getZDim(); + + double* imageArray = new double[xDim*zDim*fluenceComponents]; + + for(int fluenceComponentIdx = 0; fluenceComponentIdx< fluenceComponents; fluenceComponentIdx++) + for(int z = 0; z< zDim; z++) + for(int x = 0; x< xDim; x++) + { + int index = z * xDim * fluenceComponents + x * fluenceComponents + fluenceComponentIdx; + imageArray[index] = composedVolume->GetFluenceValue(fluenceComponentIdx, x, m_YSlice, z); + + if(m_Precorrect) + imageArray[index] = imageArray[index] / m_PrecorrectionVolume->GetData(x, m_YSlice, z); + + //TODO: Set this value to INF if imageArray[index] = 0? + if(m_Inverse ) + { + if(imageArray[index]!=0) + { + imageArray[index] = 1 / imageArray[index]; + } + else + { + imageArray[index] = INFINITY; + } + } + } + + return mitk::Photoacoustic3dVolume::New(imageArray, xDim, fluenceComponents, zDim); +} + +mitk::Photoacoustic3dVolume::Pointer mitk::PhotoacousticSlicedVolumeGenerator::GetSlicedSignalImageFromComposedVolume(mitk::PhotoacousticComposedVolume::Pointer composedVolume) +{ + if(m_State !=INITIALIZED) + throw mitk::Exception("Sliced Volume Generator not initialized yet."); + + int fluenceComponents = composedVolume->GetNumberOfFluenceComponents(); + + int xDim = composedVolume->getXDim(); + int zDim = composedVolume->getZDim(); + + double* imageArray = new double[xDim*zDim*fluenceComponents]; + + for(int fluenceComponentIdx = 0; fluenceComponentIdx< fluenceComponents; fluenceComponentIdx++) + for(int z = 0; z< zDim; z++) + for(int x = 0; x< xDim; x++) + { + int y = m_YSlice+composedVolume->GetYOffsetForFluenceComponent(fluenceComponentIdx); + imageArray[z * xDim * fluenceComponents + x * fluenceComponents + fluenceComponentIdx] = composedVolume->GetFluenceValue(fluenceComponentIdx, x, m_YSlice, z) + * composedVolume->GetVolumeAbsorptionValue(x, y, z); + } + + return mitk::Photoacoustic3dVolume::New(imageArray, xDim, fluenceComponents, zDim); +} + +void mitk::PhotoacousticSlicedVolumeGenerator::PrecorrectSignalImage(mitk::Photoacoustic3dVolume::Pointer signalVolume) +{ + if(m_PrecorrectionVolume.IsNull()) + { + MITK_WARN << "precorrection could not be performed, because a precorrection volume was not loaded."; + return; + } + int xDim = signalVolume->GetXDim(); + int zDim = signalVolume->GetZDim(); + int yDim = signalVolume->GetYDim(); + + for(int z = 0; z < zDim; z++) + for(int y = 0; y < yDim; y++) + for(int x = 0; x < xDim; x++) + { + signalVolume->SetData(signalVolume->GetData(x, y, z) / m_PrecorrectionVolume->GetData(x, m_YSlice, z), x, y, z); + } + +} diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticSlicedVolumeGenerator.h b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticSlicedVolumeGenerator.h new file mode 100644 index 0000000000..6f387f7b53 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticSlicedVolumeGenerator.h @@ -0,0 +1,62 @@ +/*=================================================================== + +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 MITKPHOTOACOUSTICSLICEDVOLUMEGENERATOR_H +#define MITKPHOTOACOUSTICSLICEDVOLUMEGENERATOR_H + +#include + +#include +#include +#include + +//Includes for smart pointer usage +#include "mitkCommon.h" +#include "itkLightObject.h" + +namespace mitk +{ +class MITKPHOTOACOUSTICSIMULATION_EXPORT PhotoacousticSlicedVolumeGenerator : public itk::LightObject +{ +public: + mitkClassMacroItkParent(mitk::PhotoacousticSlicedVolumeGenerator, itk::LightObject) + itkFactorylessNewMacro(Self) + + void Initialize(int ySlice, bool precorrect, std::string precorrectionVolumeFilename, bool inverse); + + mitk::Photoacoustic3dVolume::Pointer GetSlicedFluenceImageFromComposedVolume(mitk::PhotoacousticComposedVolume::Pointer composedVolume); + + mitk::Photoacoustic3dVolume::Pointer GetSlicedSignalImageFromComposedVolume(mitk::PhotoacousticComposedVolume::Pointer composedVolume); + + void PrecorrectSignalImage(mitk::Photoacoustic3dVolume::Pointer signalVolume); + +protected: + PhotoacousticSlicedVolumeGenerator(); + virtual ~PhotoacousticSlicedVolumeGenerator(); + + enum State{ + UNINITIALIZED, INITIALIZED + }; + + State m_State; + int m_YSlice; + bool m_Precorrect; + bool m_Inverse; + mitk::Photoacoustic3dVolume::Pointer m_PrecorrectionVolume; +}; +} + +#endif // MITKPHOTOACOUSTICSLICEDVOLUMEGENERATOR_H diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticTissueGenerator.cpp b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticTissueGenerator.cpp new file mode 100644 index 0000000000..0630bcde21 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticTissueGenerator.cpp @@ -0,0 +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->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->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->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->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(); + + vesselTree->Initialize(initialPosition, initialDirection, initialRadius, absorptionCoefficient, vesselScattering, vesselAnisotropy, parameters->GetVesselBifurcationFrequency(), &randomNumberGenerator); + + while(!vesselTree->IsFinished()) + { + vesselTree->Step(generatedVolume, parameters->GetCalculateNewVesselPositionCallback(), bendingFactor, &randomNumberGenerator); + } + + } + + generatedVolume->GaussianBlur3D(); + + generatedVolume->FinalizeVolume(parameters); + + return generatedVolume; +} diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticTissueGenerator.h b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticTissueGenerator.h new file mode 100644 index 0000000000..e594054a47 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticTissueGenerator.h @@ -0,0 +1,55 @@ +/*=================================================================== + +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 mitkPhotoacousticTissueGenerator_h +#define mitkPhotoacousticTissueGenerator_h + +#include +#include +#include +#include + +#include +#include + +#include "mitkPhotoacousticVesselTree.h" +#include "mitkPhotoacousticVolume.h" + +#include "mitkCommon.h" + +namespace mitk +{ + +class MITKPHOTOACOUSTICSIMULATION_EXPORT PhotoacousticTissueGenerator final +{ +public: + + /** + * @brief GenerateInSilicoData This method will return a PhotoacousticVolume created in terms of the given parameters. + * @param parameters + * @return + */ + static mitk::PhotoacousticVolume::Pointer GenerateInSilicoData(mitk::PhotoacousticTissueGeneratorParameters::Pointer parameters); + + +private: + PhotoacousticTissueGenerator(); + virtual ~PhotoacousticTissueGenerator(); + +}; +} + +#endif diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVessel.cpp b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVessel.cpp new file mode 100644 index 0000000000..3adc5b2231 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVessel.cpp @@ -0,0 +1,167 @@ +/*=================================================================== + +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<>(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)*m_Radius; + + m_Radius = sqrt(m_Radius*m_Radius - newRadius*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/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVessel.h b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVessel.h new file mode 100644 index 0000000000..bed86c90bf --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVessel.h @@ -0,0 +1,125 @@ +/*=================================================================== + +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 MITKVESSEL_H +#define MITKVESSEL_H + +#include "mitkVector.h" +#include "mitkPhotoacousticVesselMeanderStrategy.h" +#include "mitkPhotoacousticVolume.h" +#include "mitkPhotoacousticSmartVector.h" +#include "mitkPhotoacousticStatefulObject.h" + +#include + +//Includes for smart pointer usage +#include "mitkCommon.h" +#include "itkLightObject.h" + +namespace mitk { + +class MITKPHOTOACOUSTICSIMULATION_EXPORT PhotoacousticVessel : public itk::LightObject, public mitk::PhotoacousticStatefulObject +{ +public: + mitkClassMacroItkParent(mitk::PhotoacousticVessel, itk::LightObject) + itkFactorylessNewMacro(Self) + + /** + * Callback function definition of a PhotoacousticVesselMeanderStrategy + */ + typedef void (mitk::PhotoacousticVesselMeanderStrategy::*CalculateNewVesselPositionCallback) + (mitk::PhotoacousticSmartVector::Pointer, mitk::PhotoacousticSmartVector::Pointer, double, std::mt19937*); + + /** + * @brief Initialize initializes this PhotoacousticVessel with the given parameters. + * + * @param initialPosition + * @param initialDirection + * @param initialRadius + * @param absorptionCoefficient + * @param scatteringCoefficient + * @param anisotropyCoefficient + * @param bifurcationFrequency + * @param rng + */ + void Initialize(mitk::PhotoacousticSmartVector::Pointer initialPosition, mitk::PhotoacousticSmartVector::Pointer initialDirection, + double initialRadius, double absorptionCoefficient, double scatteringCoefficient, double anisotropyCoefficient, + double bifurcationFrequency, std::mt19937* rng); + + /** + * @brief ExpandVessel makes this PhotoacousticVessel expand one step in its current direction. + * After expanding, the vessel will draw itself into the given PhotoacousticVolume. + * + * @param volume volume for the vessel to draw itself in + * @param calculateNewPosition a callback function of the PhotoacousticVesselMeanderStrategy class. + * It is used to calculate the final position after taking the step. + * @param bendingFactor a metric of how much the PhotoacousticVessel should bend. If set to 0 the vessel will go in a straight line. + */ + void ExpandVessel(mitk::PhotoacousticVolume::Pointer volume, CalculateNewVesselPositionCallback calculateNewPosition, double bendingFactor, std::mt19937* rng); + + /** + * @brief CanBifurcate + * @return true if the PhotoacousticVessel is ready to Bifurcate() + */ + bool CanBifurcate(); + + /** + * @brief Bifurcate bifurcates this vessel into two new ones. Makes sure that the volume of the vessels stays the same. + * + * @return a new vessel split up from the current one. + */ + mitk::PhotoacousticVessel::Pointer Bifurcate(std::mt19937* rng); + + /** + * @brief IsFinished + * @return true if the vessel cannot expand any further + */ + bool IsFinished(); + +protected: + PhotoacousticVessel(); + virtual ~PhotoacousticVessel(); + +private: + + const double MINIMUM_VESSEL_RADIUS = 1; + const double SCALING_FACTOR = 0.33; + const double VESSEL_BIFURCATION_VARIATION_SIGMA = 0.2; + const double NEW_RADIUS_MINIMUM_RELATIVE_SIZE = 0.6; + const double NEW_RADIUS_MAXIMUM_RELATIVE_SIZE = 0.8; + + void DrawVesselInVolume(mitk::PhotoacousticSmartVector::Pointer toPosition, mitk::PhotoacousticVolume::Pointer volume); + mitk::PhotoacousticSmartVector::Pointer m_Position; + mitk::PhotoacousticSmartVector::Pointer m_Direction; + double m_Radius; + double m_AbsorptionCoefficient; + double m_ScatteringCoefficient; + double m_AnisotropyCoefficient; + double m_WalkedDistance; + double m_BifurcationFrequency; + mitk::PhotoacousticVesselMeanderStrategy::Pointer m_VesselMeanderStrategy; + bool m_Finished; + + std::uniform_real_distribution<> m_RangeDistribution; + std::uniform_real_distribution<> m_SignDistribution; + std::uniform_real_distribution<> m_RadiusRangeDistribution; + + int GetSign(std::mt19937* rng); +}; + +} + +#endif // MITKVESSEL_H diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVesselMeanderStrategy.cpp b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVesselMeanderStrategy.cpp new file mode 100644 index 0000000000..f39053f1f8 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVesselMeanderStrategy.cpp @@ -0,0 +1,53 @@ +/*=================================================================== + +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 "mitkPhotoacousticVesselMeanderStrategy.h" + +mitk::PhotoacousticVesselMeanderStrategy::PhotoacousticVesselMeanderStrategy() +{ +} + +mitk::PhotoacousticVesselMeanderStrategy::~PhotoacousticVesselMeanderStrategy() +{ +} + +void mitk::PhotoacousticVesselMeanderStrategy::CalculateNewPositionInStraightLine(mitk::PhotoacousticSmartVector::Pointer position, mitk::PhotoacousticSmartVector::Pointer direction, double /*bendingFactor*/, std::mt19937* rng) +{ + if(direction->GetNorm() <= mitk::eps) + { + direction->Randomize(rng); + } + + position->SetElement(0,position->GetElement(0) + direction->GetElement(0)); + position->SetElement(1,position->GetElement(1) + direction->GetElement(1)); + position->SetElement(2,position->GetElement(2) + direction->GetElement(2)); +} + +void mitk::PhotoacousticVesselMeanderStrategy::CalculateRandomlyDivergingPosition(mitk::PhotoacousticSmartVector::Pointer position, mitk::PhotoacousticSmartVector::Pointer direction, double bendingFactor, std::mt19937* rng) +{ + if(direction->GetNorm() <= mitk::eps) + { + direction->Randomize(rng); + } + + direction->RandomizeByPercentage(RANDOMIZATION_PERCENTAGE, bendingFactor, rng); + + position->SetElement(0,position->GetElement(0) + direction->GetElement(0)); + position->SetElement(1,position->GetElement(1) + direction->GetElement(1)); + position->SetElement(2,position->GetElement(2) + direction->GetElement(2)); +} + + diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVesselMeanderStrategy.h b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVesselMeanderStrategy.h new file mode 100644 index 0000000000..2cefe90572 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVesselMeanderStrategy.h @@ -0,0 +1,64 @@ +/*=================================================================== + +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 MITKVESSELMEANDERSTRATEGY_H +#define MITKVESSELMEANDERSTRATEGY_H + +#include "mitkVector.h" +#include "mitkPhotoacousticSmartVector.h" + +#include + +//Includes for smart pointer usage +#include "mitkCommon.h" +#include "itkLightObject.h" + +namespace mitk { + +class MITKPHOTOACOUSTICSIMULATION_EXPORT PhotoacousticVesselMeanderStrategy : public itk::LightObject +{ +public: + mitkClassMacroItkParent(mitk::PhotoacousticVesselMeanderStrategy, itk::LightObject) + itkFactorylessNewMacro(Self) + + /** + * @brief CalculateNewPositionInStraightLine calculates the new position by just following the direction vector. + * @param position + * @param direction + * @param bendingFactor + */ + void CalculateNewPositionInStraightLine(mitk::PhotoacousticSmartVector::Pointer position, mitk::PhotoacousticSmartVector::Pointer direction, double bendingFactor, std::mt19937* rng); + + /** + * @brief CalculateRandomlyDivergingPosition calculates the new position by modifying the direction vector randomly, + * proportional to the selected bendingFactor. This means, that the vessels will bend in each expansion step, + * if bendingFactor > 0. + * + * @param position + * @param direction + * @param bendingFactor + */ + void CalculateRandomlyDivergingPosition(mitk::PhotoacousticSmartVector::Pointer position, mitk::PhotoacousticSmartVector::Pointer direction, double bendingFactor, std::mt19937* rng); + +protected: + PhotoacousticVesselMeanderStrategy(); + virtual ~PhotoacousticVesselMeanderStrategy(); + + const double RANDOMIZATION_PERCENTAGE = 0.4; +}; +} + +#endif // MITKVESSELMEANDERSTRATEGY_H diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVesselTree.cpp b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVesselTree.cpp new file mode 100644 index 0000000000..acb94954da --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVesselTree.cpp @@ -0,0 +1,76 @@ +/*=================================================================== + +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 "mitkPhotoacousticVesselTree.h" +#include "thread" +void mitk::PhotoacousticVesselTree::Initialize(mitk::PhotoacousticSmartVector::Pointer initialPosition, mitk::PhotoacousticSmartVector::Pointer initialDirection, + double initialRadius, double absorptionCoefficient, double scatteringCoefficient, double anisotopyCoefficient, + double bifurcationFrequency, std::mt19937* rng) +{ + m_CurrentSubvessels = new std::vector(); + mitk::PhotoacousticVessel::Pointer tmpVessel = mitk::PhotoacousticVessel::New(); + tmpVessel->Initialize(initialPosition, initialDirection, initialRadius, absorptionCoefficient, scatteringCoefficient, anisotopyCoefficient, + bifurcationFrequency, rng); + m_CurrentSubvessels->push_back(tmpVessel); + m_State = INITIALIZED; +} + +mitk::PhotoacousticVesselTree::PhotoacousticVesselTree() +{ + m_CurrentSubvessels = nullptr; + m_State = UNINITIALIZED; +} + +mitk::PhotoacousticVesselTree::~PhotoacousticVesselTree() +{ + m_CurrentSubvessels = nullptr; +} + +void mitk::PhotoacousticVesselTree::Step(mitk::PhotoacousticVolume::Pointer volume, mitk::PhotoacousticVessel::CalculateNewVesselPositionCallback calculateNewPosition, double bendingFactor, std::mt19937* rng) +{ + AssertState(INITIALIZED); + std::vector newVessels; + + for(unsigned int vesselTreeIndex = 0; vesselTreeIndex < m_CurrentSubvessels->size(); vesselTreeIndex++) + { + mitk::PhotoacousticVessel::Pointer currentVessel = m_CurrentSubvessels->at(vesselTreeIndex); + if(!currentVessel->IsFinished()) + { + currentVessel->ExpandVessel(volume, calculateNewPosition, bendingFactor, rng); + if(currentVessel->CanBifurcate()) + { + newVessels.push_back(currentVessel->Bifurcate(rng)); + } + } + } + + for(unsigned int newVesselsIndex = 0; newVesselsIndex < newVessels.size(); newVesselsIndex++) + { + m_CurrentSubvessels->push_back(newVessels.at(newVesselsIndex)); + } + +} + +bool mitk::PhotoacousticVesselTree::IsFinished() +{ + AssertState(INITIALIZED); + for(unsigned int vesselTreeIndex = 0; vesselTreeIndex < m_CurrentSubvessels->size(); vesselTreeIndex++) + { + if(!m_CurrentSubvessels->at(vesselTreeIndex)->IsFinished()) + return false; + } + return true; +} diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVesselTree.h b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVesselTree.h new file mode 100644 index 0000000000..88a591fbbc --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVesselTree.h @@ -0,0 +1,83 @@ +/*=================================================================== + +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 MITKVESSELSTRUCTURE_H +#define MITKVESSELSTRUCTURE_H + +//std includes +#include + +//mitk includes +#include "mitkVector.h" +#include "mitkPhotoacousticVessel.h" +#include "mitkPhotoacousticVolume.h" +#include "mitkPhotoacousticStatefulObject.h" +#include + +//Includes for smart pointer usage +#include "mitkCommon.h" +#include "itkLightObject.h" + +namespace mitk { + +class MITKPHOTOACOUSTICSIMULATION_EXPORT PhotoacousticVesselTree : public itk::LightObject, public mitk::PhotoacousticStatefulObject +{ +public: + mitkClassMacroItkParent(mitk::PhotoacousticVesselTree, itk::LightObject) + itkFactorylessNewMacro(Self) + + /** + * @brief Initializes this PhotoacousticVesselTree with the given parameters. + * + * @param initialPosition + * @param initialDirection + * @param initialRadius + * @param absorbtionCoefficient + * @param scatteringCoefficient + * @param anisotropyCoefficient + * @param bifurcationFrequency + * @param rng + */ + void Initialize(mitk::PhotoacousticSmartVector::Pointer initialPosition, mitk::PhotoacousticSmartVector::Pointer initialDirection, + double initialRadius, double absorbtionCoefficient, double scatteringCoefficient, double anisotropyCoefficient, + double bifurcationFrequency, std::mt19937* rng); + + /** + * @brief Step Performs a simulation step, in which all subvessels of this PhotoacousticVesselTree are expanded. + * + * @param volume + * @param calculateNewPosition + * @param bendingFactor + */ + void Step(mitk::PhotoacousticVolume::Pointer volume, mitk::PhotoacousticVessel::CalculateNewVesselPositionCallback calculateNewPosition, double bendingFactor, std::mt19937* rng); + + /** + * @brief IsFinished + * @return true if no subvessel can be expanded. + */ + bool IsFinished(); + +protected: + PhotoacousticVesselTree(); + virtual ~PhotoacousticVesselTree(); + +private: + std::vector* m_CurrentSubvessels; +}; + +} + +#endif // MITKVESSELSTRUCTURE_H diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVolume.cpp b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVolume.cpp new file mode 100644 index 0000000000..d388a4c943 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVolume.cpp @@ -0,0 +1,461 @@ +/*=================================================================== + +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 + +void mitk::PhotoacousticVolume::Initialize(mitk::PhotoacousticTissueGeneratorParameters::Pointer parameters) +{ + AssertState(UNINITIALIZED); + + int size = parameters->GetXDim()*parameters->GetYDim()*parameters->GetZDim(); + m_AbsorptionArray = new double[size]; + m_ScatteringArray = new double[size]; + m_AnisotropyArray = new double[size]; + m_SegmentationArray = new double[size]; + + m_ThicknessAir = parameters->GetAirThickness(); + m_ThicknessSkin = parameters->GetSkinThickness(); + + m_AbsorptionSkin = parameters->GetSkinAbsorption(); + m_ScatteringSkin = parameters->GetSkinScattering(); + m_AnisotropySkin = parameters->GetSkinAnisotropy(); + + + m_XDim = parameters->GetXDim(); + m_YDim = parameters->GetYDim(); + m_ZDim = parameters->GetZDim(); + m_TDim = 4; + + m_Spacing = parameters->GetVoxelSpacing(); + + for (int index = 0; index < size; index++) + { + m_AbsorptionArray[index]=parameters->GetBackgroundAbsorption(); + m_ScatteringArray[index]=parameters->GetBackgroundScattering(); + m_AnisotropyArray[index]=parameters->GetBackgroundAnisotropy(); + m_SegmentationArray[index] = SegmentationType::BACKGROUND; + } + + if(parameters->GetDoVolumeSmoothing()) + { + m_Sigma = parameters->GetVolumeSmoothingSigma(); + } + else + { + m_Sigma = 0; + } + + //Set properties + AddIntProperty("mcflag", parameters->GetMCflag()); + AddIntProperty("launchflag", parameters->GetMCLaunchflag()); + AddIntProperty("boundaryflag", parameters->GetMCBoundaryflag()); + AddDoubleProperty("launchPointX", parameters->GetMCLaunchPointX()); + AddDoubleProperty("launchPointY", parameters->GetMCLaunchPointY()); + AddDoubleProperty("launchPointZ", parameters->GetMCLaunchPointZ()); + AddDoubleProperty("focusPointX", parameters->GetMCFocusPointX()); + AddDoubleProperty("focusPointY", parameters->GetMCFocusPointY()); + AddDoubleProperty("focusPointZ", parameters->GetMCFocusPointZ()); + AddDoubleProperty("trajectoryVectorX", parameters->GetMCTrajectoryVectorX()); + AddDoubleProperty("trajectoryVectorY", parameters->GetMCTrajectoryVectorY()); + AddDoubleProperty("trajectoryVectorZ", parameters->GetMCTrajectoryVectorZ()); + AddDoubleProperty("radius", parameters->GetMCRadius()); + AddDoubleProperty("waist", parameters->GetMCWaist()); + AddDoubleProperty("sigma", m_Sigma); + AddDoubleProperty("standardTissueAbsorption", parameters->GetBackgroundAbsorption()); + AddDoubleProperty("standardTissueScattering", parameters->GetBackgroundScattering()); + AddDoubleProperty("standardTissueAnisotropy", parameters->GetBackgroundAnisotropy()); + AddDoubleProperty("airThickness", m_ThicknessAir); + AddDoubleProperty("skinThickness", m_ThicknessSkin); + + m_State = INITIALIZED; +} + +void mitk::PhotoacousticVolume::AddDoubleProperty(std::string label, double value) +{ + m_PropertyList->SetDoubleProperty(label.c_str(), value); + mitk::CoreServices::GetPropertyPersistence()->AddInfo(label, mitk::PropertyPersistenceInfo::New(label)); +} + +void mitk::PhotoacousticVolume::AddIntProperty(std::string label, int value) +{ + m_PropertyList->SetIntProperty(label.c_str(), value); + mitk::CoreServices::GetPropertyPersistence()->AddInfo(label, mitk::PropertyPersistenceInfo::New(label)); +} + +mitk::Image::Pointer mitk::PhotoacousticVolume::ConvertToMitkImage() +{ + AssertState(INITIALIZED); + + mitk::Image::Pointer resultImage = mitk::Image::New(); + mitk::PixelType TPixel = mitk::MakeScalarPixelType(); + unsigned int* dimensionsOfImage = new unsigned int[4]; + + // Copy dimensions + dimensionsOfImage[0] = m_YDim; + dimensionsOfImage[1] = m_XDim; + dimensionsOfImage[2] = m_ZDim; + dimensionsOfImage[3] = m_TDim; + + MITK_DEBUG << "Initializing image..."; + resultImage->Initialize(TPixel, 4, dimensionsOfImage, 1); + MITK_DEBUG << "Initializing image...[Done]"; + + mitk::Vector3D spacing; + spacing.Fill(m_Spacing); + resultImage->SetSpacing(spacing); + + MITK_DEBUG << "Set Import Volumes..."; + //Copy memory, deal with cleaning up memory yourself! + resultImage->SetImportVolume(m_AbsorptionArray, 0, 0, mitk::Image::CopyMemory); + resultImage->SetImportVolume(m_ScatteringArray, 1, 0, mitk::Image::CopyMemory); + resultImage->SetImportVolume(m_AnisotropyArray, 2, 0, mitk::Image::CopyMemory); + resultImage->SetImportVolume(m_SegmentationArray, 3, 0, mitk::Image::CopyMemory); + MITK_DEBUG << "Set Import Volumes...[Done]"; + + resultImage->SetPropertyList(m_PropertyList); + + return resultImage; +} + +mitk::PhotoacousticVolume::PhotoacousticVolume() +{ + m_State = UNINITIALIZED; + m_XDim = 0; + m_YDim = 0; + m_ZDim = 0; + + m_AbsorptionAir = 0.0001; + m_ScatteringAir = 1.0; + m_AnisotropyAir = 1.0; + + m_Sigma = 0; + + m_PropertyList = mitk::PropertyList::New(); +} + +mitk::PhotoacousticVolume::~PhotoacousticVolume() +{ + m_State = UNINITIALIZED; + m_XDim = 0; + m_YDim = 0; + m_ZDim = 0; + + if(m_AbsorptionArray!=nullptr) + { + delete[] m_AbsorptionArray; + m_AbsorptionArray = nullptr; + } + if(m_ScatteringArray!=nullptr) + { + delete[] m_ScatteringArray; + m_ScatteringArray = nullptr; + } + if(m_AnisotropyArray!=nullptr) + { + delete[] m_AnisotropyArray; + m_AnisotropyArray = nullptr; + } + +} + +int mitk::PhotoacousticVolume::GetIndex(int x, int y, int z) +{ + return z * m_XDim * m_YDim + x * m_YDim + y; +} + +void mitk::PhotoacousticVolume::SetVolumeValues(int x, int y, int z, double absorption, double scattering, double anisotropy, SegmentationType segmentType) +{ + AssertState(INITIALIZED); + if(IsInsideVolume(x, y, z)) + { + int index = GetIndex(x, y, z); + m_AbsorptionArray[index] = absorption; + m_ScatteringArray[index] = scattering; + m_AnisotropyArray[index] = anisotropy; + m_SegmentationArray[index] = segmentType; + } +} + +bool mitk::PhotoacousticVolume::IsInsideVolume(int x, int y, int z) +{ + AssertState(INITIALIZED); + return x >= 0 && x < m_XDim && y >= 0 && y < m_YDim && z >= 0 && z < m_ZDim; +} + +double mitk::PhotoacousticVolume::GetVolumeAbsorptionValue(int x, int y, int z) +{ + AssertState(INITIALIZED); + return m_AbsorptionArray[GetIndex(x, y, z)]; +} + +double mitk::PhotoacousticVolume::GetVolumeSegmentationValue(int x, int y, int z) +{ + AssertState(INITIALIZED); + return m_SegmentationArray[GetIndex(x, y, z)]; +} + +void mitk::PhotoacousticVolume::FinalizeVolume(mitk::PhotoacousticTissueGeneratorParameters::Pointer parameters) +{ + //Calculate the index location according to thickness in cm + double airvoxel = m_ThicknessAir / m_Spacing / 10; + double skinvoxel = airvoxel + m_ThicknessSkin / m_Spacing / 10; + + for(int y = 0; y < m_YDim; y++) + { + for(int x = 0; x < m_XDim; x++) + { + // Add air from index 0 to airvoxel + if(m_ThicknessAir > mitk::eps) + FillZLayer(x, y, 0, airvoxel, + m_AbsorptionAir, m_ScatteringAir, m_AnisotropyAir, + SegmentationType::AIR); + + //Add skin from index airvoxel to skinvoxel + if(m_ThicknessSkin > mitk::eps) + FillZLayer(x, y, airvoxel, skinvoxel, + m_AbsorptionSkin, m_ScatteringSkin, m_AnisotropySkin, + SegmentationType::SKIN); + } + } + +// for(int y = 0; y < m_YDim; y++) +// { +// for(int x = 0; x < m_XDim; x++) +// { +// int index = GetIndex(x, y, 37); +// m_AbsorptionArray[index] = 100; +// } +// } + + // If specified, randomize all tissue parameters + if(parameters->GetRandomizePhysicalProperties()) + RandomizeTissueCoefficients(parameters->GetUseRngSeed(), parameters->GetRngSeed(), parameters->GetRandomizePhysicalPropertiesPercentage()); + +} + +void mitk::PhotoacousticVolume::FillZLayer(int x, int y, double startIdx, double endIdx, + double absorption, double scattering, double anisotropy, + SegmentationType segmentationType) +{ + for(int z=startIdx; z < endIdx; z++) + { + int index = GetIndex(x, y, z); + if(endIdx-z < 1) + { + //Simulate partial volume effects + m_AbsorptionArray[index] = (1 - (endIdx - z)) * m_AbsorptionArray[index] + (endIdx - z) * absorption; + m_ScatteringArray[index] = (1 - (endIdx - z)) * m_ScatteringArray[index] + (endIdx - z) * scattering; + m_AnisotropyArray[index] = (1 - (endIdx - z)) * m_AnisotropyArray[index] + (endIdx - z) * anisotropy; + if(endIdx-z > 0.5) + { + //Only put the segmentation label if more than half of the partial volume is the wanted tissue type + m_SegmentationArray[index] = segmentationType; + } + } + else + { + m_AbsorptionArray[index] = absorption; + m_ScatteringArray[index] = scattering; + m_AnisotropyArray[index] = anisotropy; + m_SegmentationArray[index] = segmentationType; + } + } +} + +void mitk::PhotoacousticVolume::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_YDim; y++) + { + for(int x = 0; x < m_XDim; x++) + { + for(int z = 0; z < m_ZDim; z++) + { + int index = GetIndex(x, y, z); + m_AbsorptionArray[index] = m_AbsorptionArray[index]*percentageDistribution(rng); + m_ScatteringArray[index] = m_ScatteringArray[index]*percentageDistribution(rng); + } + } + } +} + +double mitk::PhotoacousticVolume::GetVolumeScatteringValue(int x, int y, int z) +{ + AssertState(INITIALIZED); + return m_ScatteringArray[GetIndex(x, y, z)]; +} + +double mitk::PhotoacousticVolume::GetVolumeAnisotropyValue(int x, int y, int z) +{ + AssertState(INITIALIZED); + return m_AnisotropyArray[GetIndex(x, y, z)]; +} + +void mitk::PhotoacousticVolume::GaussianBlur3D() +{ + GaussianBlur3D(m_AbsorptionArray, m_YDim, m_XDim, m_ZDim, m_Sigma); + GaussianBlur3D(m_ScatteringArray, m_YDim, m_XDim, m_ZDim, m_Sigma); + GaussianBlur3D(m_AnisotropyArray, m_YDim, m_XDim, m_ZDim, m_Sigma); +} + +/** + * @brief Fast 3D Gaussian convolution IIR approximation + * @param volume + * @param width + * @param height + * @param depth + * @param sigma + * @author Pascal Getreuer + * + * Copyright (c) 2011, Pascal Getreuer + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the simplified BSD license. + * + * You should have received a copy of these licenses along with this program. + * If not, see . + */ +void mitk::PhotoacousticVolume::GaussianBlur3D(double *volume, long width, long height, long depth, + double sigma) +{ + const long plane = width*height; + const long numel = plane*depth; + double lambda, dnu; + double nu, boundaryscale, postscale; + double *ptr; + long i, x, y, z; + int step; + + if(sigma <= 0) + return; + + lambda = (sigma*sigma)/(8.0); + dnu = (1.0 + 2.0*lambda - sqrt(1.0 + 4.0*lambda))/(2.0*lambda); + nu = dnu; + boundaryscale = 1.0/(1.0 - dnu); + postscale = pow(dnu/lambda,12); + + /* Filter horizontally along each row */ + for(z = 0; z < depth; z++) + { + for(y = 0; y < height; y++) + { + for(step = 0; step < 4; step++) + { + ptr = volume + width*(y + height*z); + ptr[0] *= boundaryscale; + + /* Filter rightwards */ + for(x = 1; x < width; x++) + { + ptr[x] += nu*ptr[x - 1]; + } + + ptr[x = width - 1] *= boundaryscale; + /* Filter leftwards */ + for(; x > 0; x--) + { + ptr[x - 1] += nu*ptr[x]; + } + } + } + } + /* Filter vertically along each column */ + for(z = 0; z < depth; z++) + { + for(x = 0; x < width; x++) + { + for(step = 0; step < 4; step++) + { + ptr = volume + x + plane*z; + ptr[0] *= boundaryscale; + + /* Filter downwards */ + for(i = width; i < plane; i += width) + { + ptr[i] += nu*ptr[i - width]; + } + + ptr[i = plane - width] *= boundaryscale; + + /* Filter upwards */ + for(; i > 0; i -= width) + { + ptr[i - width] += nu*ptr[i]; + } + } + } + } + + /* Filter along z-dimension */ + for(y = 0; y < height; y++) + { + for(x = 0; x < width; x++) + { + for(step = 0; step < 4; step++) + { + ptr = volume + x + width*y; + ptr[0] *= boundaryscale; + + for(i = plane; i < numel; i += plane) + { + ptr[i] += nu*ptr[i - plane]; + } + + ptr[i = numel - plane] *= boundaryscale; + + for(; i > 0; i -= plane) + { + ptr[i - plane] += nu*ptr[i]; + } + } + } + } + + for(i = 0; i < numel; i++) + { + volume[i] *= postscale; + } + + return; +} diff --git a/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVolume.h b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVolume.h new file mode 100644 index 0000000000..cc4992323d --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Algorithms/mitkPhotoacousticVolume.h @@ -0,0 +1,193 @@ +/*=================================================================== + +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 MITKPHOTOACOUSTICVOLUME_H +#define MITKPHOTOACOUSTICVOLUME_H + +#include +#include +#include +#include + +#include "mitkPhotoacousticStatefulObject.h" + +//Includes for smart pointer usage +#include "mitkCommon.h" +#include "itkLightObject.h" + + +namespace mitk +{ +class MITKPHOTOACOUSTICSIMULATION_EXPORT PhotoacousticVolume : public itk::LightObject, public mitk::PhotoacousticStatefulObject +{ +public: + mitkClassMacroItkParent(mitk::PhotoacousticVolume, itk::LightObject) + itkFactorylessNewMacro(Self) + + enum SegmentationType + { + AIR = -1, + BACKGROUND = 0, + VESSEL = 1, + FAT = 2, + SKIN = 3 + }; + + /** + * @brief Initialize initializes this PhotoacousticVolume with the given parameters. + * + * @param parameters + */ + void Initialize(mitk::PhotoacousticTissueGeneratorParameters::Pointer parameters); + + /** + * @brief ConvertToMitkImage + * @return a pointer to an mitk image containing this volume. + */ + mitk::Image::Pointer ConvertToMitkImage(); + + /** + * @brief SetVolumeValues sets the values for aborption, scattering and anisotropy at the specified voxel location. + * + * @param x + * @param y + * @param z + * @param absorption + * @param scattering + * @param anisotropy + * @param segmentType + */ + void SetVolumeValues(int x, int y, int z, double absorption, double scattering, double anisotropy, SegmentationType segmentType = SegmentationType::BACKGROUND); + + /** + * @brief GetVolumeAbsorptionValue + * + * @param x + * @param y + * @param z + * @return the aborption value at the specified voxel location + */ + double GetVolumeAbsorptionValue(int x, int y, int z); + + /** + * @brief GetVolumeScatteringValue + * + * @param x + * @param y + * @param z + * @return the scattering value at the specified voxel location + */ + double GetVolumeScatteringValue(int x, int y, int z); + + /** + * @brief GetVolumeAnisotropyValue + * + * @param x + * @param y + * @param z + * @return the anisotropy value at the specified voxel location + */ + double GetVolumeAnisotropyValue(int x, int y, int z); + + /** + * @brief GetVolumeSegmentationValue + * + * @param x + * @param y + * @param z + * @return the segmentation type at the specified voxel location + */ + double GetVolumeSegmentationValue(int x, int y, int z); + + /** + * @brief IsInsideVolume + * + * @param x + * @param y + * @param z + * @return true if the voxel location is inside the volume + */ + bool IsInsideVolume(int x, int y, int z); + + /** + * @brief AddDoubleProperty adds a persistent property to the volume, which will be exported to the mitk image. + * + * @param label + * @param value + */ + void AddDoubleProperty(std::string label, double value); + + /** + * @brief AddIntProperty adds a persistent property to the volume, which will be exported to the mitk image. + * + * @param label + * @param value + */ + void AddIntProperty(std::string label, int value); + + int getXDim(){return m_XDim;} + int getYDim(){return m_YDim;} + int getZDim(){return m_ZDim;} + int getTDim(){return m_TDim;} + + void FinalizeVolume(mitk::PhotoacousticTissueGeneratorParameters::Pointer parameters); + + void GaussianBlur3D(); + +protected: + PhotoacousticVolume(); + virtual ~PhotoacousticVolume(); + + double* m_AbsorptionArray; + double* m_ScatteringArray; + double* m_AnisotropyArray; + double* m_SegmentationArray; + + double m_AbsorptionAir; + double m_ScatteringAir; + double m_AnisotropyAir; + + double m_AbsorptionSkin; + double m_ScatteringSkin; + double m_AnisotropySkin; + + double m_ThicknessAir; + double m_ThicknessSkin; + + int m_XDim; + int m_YDim; + int m_ZDim; + int m_TDim; + + double m_Spacing; + double m_Sigma; + + void GaussianBlur3D(double* array, long width, long height, long depth, + double sigma); + + int GetIndex(int x, int y, int z); + + void RandomizeTissueCoefficients(long rngSeed, bool useRngSeed, double percentage); + + void FillZLayer(int x, int y, double startIdx, double endIdx, + double absorption, double scattering, double anisotropy, + SegmentationType segmentationType); + + mitk::PropertyList::Pointer m_PropertyList; +}; +} + +#endif // MITKPHOTOACOUSTICVOLUME_H diff --git a/Modules/PhotoacousticSimulation/src/IO/mitkPhotoacousticIO.cpp b/Modules/PhotoacousticSimulation/src/IO/mitkPhotoacousticIO.cpp new file mode 100644 index 0000000000..a5199793b5 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/IO/mitkPhotoacousticIO.cpp @@ -0,0 +1,224 @@ +#include "mitkPhotoacousticIO.h" + +#include "mitkIOUtil.h" +#include "mitkImageReadAccessor.h" + +#include "boost/filesystem.hpp" + +#include +#include +#include + +static std::vector splitString(const std::string &s, const char* delim) { + std::vector elems; + std::stringstream ss(s); + std::string item; + while (std::getline(ss, item, *delim)) { + int numb; + std::stringstream(item) >> numb; + elems.push_back(numb); + } + return elems; +} + +static bool hasEnding (std::string const &fullString, std::string const &ending) { + if (fullString.length() >= ending.length()) { + return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending)); + } else { + return false; + } +} + +mitk::PhotoacousticIO::PhotoacousticIO(){} + +mitk::PhotoacousticIO::~PhotoacousticIO(){} + +mitk::Photoacoustic3dVolume::Pointer mitk::PhotoacousticIO::LoadNrrd(std::string filename, double blur) +{ + if(filename.empty() || filename == "") + return nullptr; + + mitk::Image::Pointer inputImage = mitk::IOUtil::LoadImage(filename); + + if(inputImage.IsNull()) + return nullptr; + + int xDim = inputImage->GetDimensions()[1]; + int yDim = inputImage->GetDimensions()[0]; + int zDim = inputImage->GetDimensions()[2]; + + mitk::ImageReadAccessor readAccess(inputImage, inputImage->GetVolumeData(0)); + + double* dataArray = new double[xDim*yDim*zDim]; + const double* srcData = (const double*) readAccess.GetData(); + memcpy(dataArray, srcData , xDim*yDim*zDim*sizeof(double)); + + GaussianBlur3D(dataArray, yDim, xDim, zDim, blur); + + return mitk::Photoacoustic3dVolume::New(dataArray, xDim, yDim, zDim); +} + +std::map +mitk::PhotoacousticIO::LoadMultipleNrrdFiles(std::string foldername, double blur, int* progress) +{ + std::map resultMap; + + + boost::filesystem::directory_iterator end_itr; + for(boost::filesystem::directory_iterator itr(foldername); itr!=end_itr; itr++) + { + if(boost::filesystem::is_directory(itr->status())) + continue; + + std::string filename = itr->path().string(); + if(!hasEnding(filename, ".nrrd")) + continue; + + size_t s = filename.find("_p"); + size_t e = filename.find("Fluence", s); + std::string sub = filename.substr(s + 2, e - s -2); + std::vector coords = splitString(sub, ","); + + if(coords.size() != 3) + { + MITK_ERROR << "Some of the data to read was corrupted or did not match the "<< + "naming pattern *_pN,N,NFluence*.nrrd"; + mitkThrow() << "Some of the data to read was corrupted or did not match the"<< + " naming pattern *_pN,N,NFluence*.nrrd"; + } + else + { + + MITK_DEBUG << "Extracted coords: " << coords[0] << "|" << coords[1] << "|" << coords[2] << " from string " << sub; + mitk::Photoacoustic3dVolume::Pointer nrrdFile = LoadNrrd(filename, blur); + resultMap[mitk::PhotoacousticIO::Position{coords[0], coords[2]}] = nrrdFile; + *progress = *progress + 1; + } + } + + + return resultMap; +} + +/** + * @brief Fast 3D Gaussian convolution IIR approximation + * @param volume + * @param width + * @param height + * @param depth + * @param sigma + * @author Pascal Getreuer + * + * Copyright (c) 2011, Pascal Getreuer + * All rights reserved. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the simplified BSD license. + * + * You should have received a copy of these licenses along with this program. + * If not, see . + */ +void mitk::PhotoacousticIO::GaussianBlur3D(double *volume, long width, long height, long depth, + double sigma) +{ + const long plane = width*height; + const long numel = plane*depth; + double lambda, dnu; + double nu, boundaryscale, postscale; + double *ptr; + long i, x, y, z; + int step; + + if(sigma <= mitk::eps) + return; + + lambda = (sigma*sigma)/(8.0); + dnu = (1.0 + 2.0*lambda - sqrt(1.0 + 4.0*lambda))/(2.0*lambda); + nu = dnu; + boundaryscale = 1.0/(1.0 - dnu); + postscale = pow(dnu/lambda,12); + + /* Filter horizontally along each row */ + for(z = 0; z < depth; z++) + { + for(y = 0; y < height; y++) + { + for(step = 0; step < 4; step++) + { + ptr = volume + width*(y + height*z); + ptr[0] *= boundaryscale; + + /* Filter rightwards */ + for(x = 1; x < width; x++) + { + ptr[x] += nu*ptr[x - 1]; + } + + ptr[x = width - 1] *= boundaryscale; + /* Filter leftwards */ + for(; x > 0; x--) + { + ptr[x - 1] += nu*ptr[x]; + } + } + } + } + /* Filter vertically along each column */ + for(z = 0; z < depth; z++) + { + for(x = 0; x < width; x++) + { + for(step = 0; step < 4; step++) + { + ptr = volume + x + plane*z; + ptr[0] *= boundaryscale; + + /* Filter downwards */ + for(i = width; i < plane; i += width) + { + ptr[i] += nu*ptr[i - width]; + } + + ptr[i = plane - width] *= boundaryscale; + + /* Filter upwards */ + for(; i > 0; i -= width) + { + ptr[i - width] += nu*ptr[i]; + } + } + } + } + + /* Filter along z-dimension */ + for(y = 0; y < height; y++) + { + for(x = 0; x < width; x++) + { + for(step = 0; step < 4; step++) + { + ptr = volume + x + width*y; + ptr[0] *= boundaryscale; + + for(i = plane; i < numel; i += plane) + { + ptr[i] += nu*ptr[i - plane]; + } + + ptr[i = numel - plane] *= boundaryscale; + + for(; i > 0; i -= plane) + { + ptr[i - plane] += nu*ptr[i]; + } + } + } + } + + for(i = 0; i < numel; i++) + { + volume[i] *= postscale; + } + + return; +} diff --git a/Modules/PhotoacousticSimulation/src/IO/mitkPhotoacousticIO.h b/Modules/PhotoacousticSimulation/src/IO/mitkPhotoacousticIO.h new file mode 100644 index 0000000000..54ce4c0fa6 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/IO/mitkPhotoacousticIO.h @@ -0,0 +1,82 @@ +/*=================================================================== + +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 MITKPHOTOACOUSTICIO_H +#define MITKPHOTOACOUSTICIO_H + +#include "MitkPhotoacousticSimulationExports.h" + +#include +#include +#include + +//Includes for smart pointer usage +#include "mitkCommon.h" +#include "itkLightObject.h" + +#include "mitkPhotoacoustic3dVolume.h" + +namespace mitk +{ +class MITKPHOTOACOUSTICSIMULATION_EXPORT PhotoacousticIO final +{ +public: + + struct Position + { + int x, z; + + bool operator <(const Position& rhs) const + { + return (x < rhs.x || ((x == rhs.x) && z < rhs.z)); + } + }; + + /** + * @brief LoadMultipleNrrdFiles loads multiple nrrd files from a given folder + * and sorts them into a position map if such meta information is available in + * the filename.
+ * As this method was specifically designed to load many fluence files, the + * naming convention for the position values is:
+ * + * *_pN,N,NFluence*.nrrd + * + * @param foldername + * @param blur + * @param progress + * + * @return + */ + static std::map LoadMultipleNrrdFiles(std::string foldername, double blur, int* progress); + + /** + * @brief loads a nrrd file from a given filename. + * @param filename + * @param sigma + * @return nullptr if the given filename was invalid. + */ + static mitk::Photoacoustic3dVolume::Pointer LoadNrrd(std::string filename, double sigma = 0); + +private: + static void GaussianBlur3D(double *volume, long width, long height, long depth, + double sigma); + PhotoacousticIO(); + ~PhotoacousticIO(); + +}; +} + +#endif // MITKPHOTOACOUSTICIO_H diff --git a/Modules/PhotoacousticSimulation/src/ProbeDesign/mitkPhotoacousticLightSource.cpp b/Modules/PhotoacousticSimulation/src/ProbeDesign/mitkPhotoacousticLightSource.cpp new file mode 100644 index 0000000000..70f140f805 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/ProbeDesign/mitkPhotoacousticLightSource.cpp @@ -0,0 +1,416 @@ +/*=================================================================== + +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 "mitkPhotoacousticLightSource.h" +#include "math.h" + +mitk::PhotoacousticLightSource::PhotoacousticLightSource() : + m_IsValid(false) +{ +} + +mitk::PhotoacousticLightSource::PhotoacousticLightSource(TiXmlElement* element, bool verbose): + m_IsValid(true), + m_Verbose(verbose) +{ + ParseEnergy(element); + ParsePhotonSpawnArea(element); + ParsePhotonDirection(element); + + if(m_IsValid) + { + if(m_Verbose) + std::cout << "Successfully created LightSource" << std::endl; + } + else + { + if(m_Verbose) + std::cout << "Failed creating LightSource." << std::endl; + } +} + +mitk::PhotoacousticLightSource::~PhotoacousticLightSource() +{ + +} + +mitk::PhotoacousticLightSource::TransformResult mitk::PhotoacousticLightSource::BoxMuellerTransform(double u1, double u2, double mu, double sigma) +{ + TransformResult result; + result.z0 = sqrt(-2.0 * log(u1)) * cos(TWO_PI * u2) * sigma + mu; + result.z1 = sqrt(-2.0 * log(u1)) * sin(TWO_PI * u2) * sigma + mu; + return result; +} + +void mitk::PhotoacousticLightSource::ParsePhotonDirection(TiXmlElement* element) +{ + TiXmlElement* direction = element->FirstChildElement(XML_TAG_PHOTON_DIRECTION); + if(direction) + { + ParseAngle(direction, XML_TAG_X_ANGLE); + } + else + { + if(m_Verbose) + std::cerr << "No \"" << XML_TAG_X_ANGLE << "\" field in xml. Setting to default (0, 0, UNIFORM)." << std::endl; + + m_AngleXMinimum = 0; + m_AngleXMaximum = 0; + m_AngleXMode = DistributionMode::UNIFORM; + } + + direction = element->FirstChildElement(XML_TAG_PHOTON_DIRECTION); + if(direction) + { + ParseAngle(direction, XML_TAG_Y_ANGLE); + } + else + { + if(m_Verbose) + std::cerr << "No \"" << XML_TAG_Y_ANGLE << "\" field in xml. Setting to default (0, 0, UNIFORM)." << std::endl; + + m_AngleYMinimum = 0; + m_AngleYMaximum = 0; + m_AngleYMode = DistributionMode::UNIFORM; + } +} + +void mitk::PhotoacousticLightSource::ParseAngle(TiXmlElement* direction, std::string angle) +{ + double minimum; + double maximum; + DistributionMode mode; + + if(m_Verbose) + std::cout << "Parsing " << angle << std::endl; + TiXmlElement* angleElement = direction->FirstChildElement(angle); + if(angleElement) + { + TiXmlElement* angleMin = angleElement->FirstChildElement(XML_TAG_MINIMUM); + if(angleMin) + { + std::string angleMinText = angleMin->GetText(); + minimum = std::stod(angleMinText); + if(m_Verbose) + std::cout << "Setting min=" << minimum << std::endl; + } + else + { + if(m_Verbose) + std::cerr << "No \""<< XML_TAG_MINIMUM <<"\" tag in xml. Setting min=0" << std::endl; + minimum = 0; + } + + TiXmlElement* angleMax = angleElement->FirstChildElement(XML_TAG_MAXIMUM); + if(angleMax) + { + std::string angleMaxText = angleMax->GetText(); + maximum = std::stod(angleMaxText); + if(m_Verbose) + std::cout << "Setting max=" << maximum << std::endl; + } + else + { + if(m_Verbose) + std::cerr << "No \"" << XML_TAG_MAXIMUM << "\" tag in xml. Setting max=0" << std::endl; + maximum = 0; + } + + TiXmlElement* angleMode = angleElement->FirstChildElement(XML_TAG_MODE); + if(angleMode) + { + std::string angleModeText = angleMode->GetText(); + if(strcmp("UNIFORM", angleModeText.c_str()) == 0) + { + mode = DistributionMode::UNIFORM; + if(m_Verbose) + std::cout << "Setting mode=UNIFORM" << std::endl; + } + else if (strcmp("GAUSSIAN", angleModeText.c_str()) == 0) + { + mode = DistributionMode::GAUSSIAN; + if(m_Verbose) + std::cout << "Setting mode=GAUSSIAN" << std::endl; + } + } + else + { + if(m_Verbose) + std::cerr << "No \"" << XML_TAG_MODE << "\" tag in xml. Setting mode=UNIFORM" << std::endl; + mode = DistributionMode::UNIFORM; + } + } + else + { + if(m_Verbose) + std::cerr << "No \"" << angle << "\" field in xml. Setting to default (0, 0, UNIFORM)." << std::endl; + + maximum = 0; + minimum = 0; + mode = DistributionMode::UNIFORM; + } + + if(strcmp(XML_TAG_X_ANGLE.c_str(), angle.c_str()) == 0) + { + m_AngleXMinimum = minimum; + m_AngleXMaximum = maximum; + m_AngleXMode = mode; + } + else if(strcmp(XML_TAG_Y_ANGLE.c_str(), angle.c_str()) == 0) + { + m_AngleYMinimum = minimum; + m_AngleYMaximum = maximum; + m_AngleYMode = mode; + } +} + +void mitk::PhotoacousticLightSource::ParseEnergy(TiXmlElement* element) +{ + TiXmlElement* energy = element->FirstChildElement(XML_TAG_ENERGY); + if(energy) + { + std::string energyText = energy->GetText(); + m_Energy = std::stod(energyText); + if(m_Verbose) + std::cout << "Setting energy=" << m_Energy; + } + else + { + if(m_Verbose) + std::cerr << "No \"" << XML_TAG_ENERGY << "\" field in xml. Setting Energy=1" << std::endl; + m_Energy = 1.0; + } +} + +void mitk::PhotoacousticLightSource::ParsePhotonSpawnArea(TiXmlElement* element) +{ + TiXmlElement* spawnArea = element->FirstChildElement("PhotonSpawnArea"); + if(spawnArea) + { + TiXmlElement* spawnType = spawnArea->FirstChildElement(XML_TAG_SPAWN_TYPE); + if(spawnType) + { + std::string spawnTypeText = spawnType->GetText(); + if(strcmp(XML_TAG_SPAWN_TYPE_POINT.c_str(), spawnTypeText.c_str())==0) + { + m_SpawnType = SpawnType::POINT; + if(m_Verbose) + std::cout << "Setting " << XML_TAG_SPAWN_TYPE << " = " << XML_TAG_SPAWN_TYPE_POINT << std::endl; + } + else if (strcmp(XML_TAG_SPAWN_TYPE_RECTANGLE.c_str(), spawnTypeText.c_str())==0) + { + m_SpawnType = SpawnType::RECTANGLE; + if(m_Verbose) + std::cout << "Setting " << XML_TAG_SPAWN_TYPE << " = " << XML_TAG_SPAWN_TYPE_RECTANGLE << std::endl; + } + else if (strcmp(XML_TAG_SPAWN_TYPE_CIRCLE.c_str(), spawnTypeText.c_str())==0) + { + m_SpawnType = SpawnType::CIRCLE; + if(m_Verbose) + std::cout << "Setting " << XML_TAG_SPAWN_TYPE << " = " << XML_TAG_SPAWN_TYPE_CIRCLE << std::endl; + } + else + { + std::cerr << "The provided SpawnType (" << spawnTypeText << ") did not match any available spawn type. Light source is not valid." << std::endl; + m_IsValid = false; + } + } + else + { + std::cerr << "The \"" << XML_TAG_SPAWN_TYPE << "\" element was not provided for this light source. Light source is not valid." << std::endl; + m_IsValid = false; + } + + TiXmlElement* xLocation = spawnArea->FirstChildElement(XML_TAG_X); + if(xLocation) + { + std::string xLocationText = xLocation->GetText(); + m_SpawnLocationX = std::stod(xLocationText); + if(m_Verbose) + std::cout << "Setting "<< XML_TAG_X << "=" << m_SpawnLocationX; + } + else + { + if(m_Verbose) + std::cerr << "No \"" << XML_TAG_X << "\" field in xml. Setting " << XML_TAG_X << "=0" << std::endl; + m_SpawnLocationX = 0; + } + + TiXmlElement* yLocation = spawnArea->FirstChildElement(XML_TAG_Y); + if(yLocation) + { + std::string yLocationText = yLocation->GetText(); + m_SpawnLocationY = std::stod(yLocationText); + if(m_Verbose) + std::cout << "Setting " << XML_TAG_Y << "=" << m_SpawnLocationY; + } + else + { + if(m_Verbose) + std::cerr << "No \"" << XML_TAG_Y << "\" field in xml. Setting " << XML_TAG_Y << "=0" << std::endl; + m_SpawnLocationY = 0; + } + + TiXmlElement* zLocation = spawnArea->FirstChildElement(XML_TAG_Z); + if(zLocation) + { + std::string zLocationText = zLocation->GetText(); + m_SpawnLocationZ = std::stod(zLocationText); + if(m_Verbose) + std::cout << "Setting " << XML_TAG_Z << "=" << m_SpawnLocationZ; + } + else + { + if(m_Verbose) + std::cerr << "No \"" << XML_TAG_Z << "\" field in xml. Setting " << XML_TAG_Z << "=0.1" << std::endl; + m_SpawnLocationZ = 0.1; + } + + TiXmlElement* rLocation = spawnArea->FirstChildElement(XML_TAG_R); + if(rLocation) + { + std::string rLocationText = rLocation->GetText(); + m_SpawnLocationRadius = std::stod(rLocationText); + if(m_Verbose) + std::cout << "Setting " << XML_TAG_R << "=" << m_SpawnLocationRadius; + } + else + { + if(m_Verbose) + std::cerr << "No \"" << XML_TAG_R << "\" field in xml. Setting " << XML_TAG_R << "=0" << std::endl; + m_SpawnLocationRadius = 0; + } + + TiXmlElement* xLength = spawnArea->FirstChildElement(XML_TAG_X_LENGTH); + if(xLength) + { + std::string xLengthText = xLength->GetText(); + m_SpawnLocationXLength = std::stod(xLengthText); + if(m_Verbose) + std::cout << "Setting " << XML_TAG_X_LENGTH << "=" << m_SpawnLocationXLength << std::endl; + } + else + { + if(m_Verbose) + std::cerr << "No \"" << XML_TAG_X_LENGTH << "\" field in xml. Setting " << XML_TAG_X_LENGTH << "=0" << std::endl; + m_SpawnLocationXLength = 0; + } + + TiXmlElement* yLength = spawnArea->FirstChildElement(XML_TAG_Y_LENGTH); + if(yLength) + { + std::string yLengthText = yLength->GetText(); + m_SpawnLocationYLength = std::stod(yLengthText); + if(m_Verbose) + std::cout << "Setting " << XML_TAG_Y_LENGTH << "=" << m_SpawnLocationYLength << std::endl; + } + else + { + if(m_Verbose) + std::cerr << "No \"" << XML_TAG_Y_LENGTH << "\" field in xml. Setting " << XML_TAG_Y_LENGTH << "=0" << std::endl; + m_SpawnLocationYLength = 0; + } + + TiXmlElement* zLength = spawnArea->FirstChildElement(XML_TAG_Z_LENGTH); + if(zLength) + { + std::string zLengthText = zLength->GetText(); + m_SpawnLocationZLength = std::stod(zLengthText); + if(m_Verbose) + std::cout << "Setting " << XML_TAG_Z_LENGTH << "=" << m_SpawnLocationZLength << std::endl; + } + else + { + if(m_Verbose) + std::cerr << "No \"" << XML_TAG_Z_LENGTH << "\" field in xml. Setting " << XML_TAG_Z_LENGTH << "=0" << std::endl; + m_SpawnLocationZLength = 0; + } + + } + else + m_IsValid = false; +} + +mitk::PhotoacousticLightSource::PhotonInformation mitk::PhotoacousticLightSource::GetNextPhoton(double rnd1, double rnd2, double rnd3, + double rnd4, double rnd5, double gau1, double gau2) +{ + PhotonInformation returnValue; + + switch(m_SpawnType) + { + case POINT: + returnValue.xPosition = m_SpawnLocationX; + returnValue.yPosition = m_SpawnLocationY; + returnValue.zPosition = m_SpawnLocationZ; + break; + case RECTANGLE: + returnValue.xPosition = m_SpawnLocationX + rnd3 * m_SpawnLocationXLength; + returnValue.yPosition = m_SpawnLocationY + rnd4 * m_SpawnLocationYLength; + returnValue.zPosition = m_SpawnLocationZ + rnd5 * m_SpawnLocationZLength; + break; + case CIRCLE: + double radius = rnd3 * m_SpawnLocationRadius; + double angle = rnd4 * TWO_PI; + + returnValue.xPosition = m_SpawnLocationX + radius * cos(angle); + returnValue.yPosition = m_SpawnLocationY + radius * sin(angle); + returnValue.zPosition = m_SpawnLocationZ; + break; + } + + switch(m_AngleXMode) + { + case UNIFORM: + returnValue.xAngle = rnd1 * (m_AngleXMaximum - m_AngleXMinimum) + m_AngleXMinimum; + break; + case GAUSSIAN: + TransformResult trans = BoxMuellerTransform(gau1, gau2, (m_AngleXMaximum - m_AngleXMinimum)/2 + m_AngleXMinimum, (m_AngleXMaximum - m_AngleXMinimum)/2.355); + returnValue.xAngle = trans.z0; + break; + } + + switch(m_AngleYMode) + { + case UNIFORM: + returnValue.yAngle = rnd2 * (m_AngleYMaximum - m_AngleYMinimum) + m_AngleYMinimum; + break; + case GAUSSIAN: + TransformResult trans = BoxMuellerTransform(gau1, gau2, (m_AngleYMaximum - m_AngleYMinimum)/2 + m_AngleYMinimum, (m_AngleYMaximum - m_AngleYMinimum)/2.355 ); + returnValue.yAngle = trans.z1; + break; + } + + if((returnValue.xAngle*returnValue.xAngle+returnValue.yAngle*returnValue.yAngle) > 1) + { + double unify = sqrt(returnValue.xAngle*returnValue.xAngle+returnValue.yAngle*returnValue.yAngle)*1.001; + returnValue.xAngle = returnValue.xAngle / unify; + returnValue.yAngle = returnValue.yAngle / unify; + } + + returnValue.zAngle = sqrt(1 - returnValue.xAngle*returnValue.xAngle - returnValue.yAngle*returnValue.yAngle); + + if(m_Verbose) + std::cout << "Created a new photon at (" << returnValue.xPosition << "|" << returnValue.yPosition << "|" << + returnValue.zPosition << ") with angle (" << returnValue.xAngle << "|" << returnValue.yAngle << "|" << + returnValue.zAngle << ")" << std::endl; + + return returnValue; +} + +bool mitk::PhotoacousticLightSource::IsValid() +{ + return m_IsValid; +} diff --git a/Modules/PhotoacousticSimulation/src/ProbeDesign/mitkPhotoacousticLightSource.h b/Modules/PhotoacousticSimulation/src/ProbeDesign/mitkPhotoacousticLightSource.h new file mode 100644 index 0000000000..09eba012fc --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/ProbeDesign/mitkPhotoacousticLightSource.h @@ -0,0 +1,185 @@ +/*=================================================================== + +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 MITKPHOTOACOUSTICLIGHTSOURCE_H +#define MITKPHOTOACOUSTICLIGHTSOURCE_H + +#include + +#include "MitkPhotoacousticSimulationExports.h" + +//Includes for smart pointer usage +#include "mitkCommon.h" +#include "itkObject.h" +#include "itkMacro.h" + +#include + +namespace mitk { + +/** + * @brief The PhotoacousticProbe class + * The representation of a PhotoacousticProbe + */ +class MITKPHOTOACOUSTICSIMULATION_EXPORT PhotoacousticLightSource : public itk::Object +{ +public: + + mitkClassMacroItkParent(mitk::PhotoacousticLightSource, itk::Object) + itkFactorylessNewMacro(Self) + mitkNewMacro2Param(Self, TiXmlElement*, bool) + + const std::string XML_TAG_X_ANGLE = "xAngle"; + const std::string XML_TAG_Y_ANGLE = "yAngle"; + const std::string XML_TAG_PHOTON_DIRECTION = "PhotonDirection"; + const std::string XML_TAG_MINIMUM = "min"; + const std::string XML_TAG_MAXIMUM = "max"; + const std::string XML_TAG_MODE = "mode"; + const std::string XML_TAG_ENERGY = "energy"; + const std::string XML_TAG_SPAWN_TYPE = "SpawnType"; + const std::string XML_TAG_SPAWN_TYPE_POINT = "POINT"; + const std::string XML_TAG_SPAWN_TYPE_RECTANGLE = "RECTANGLE"; + const std::string XML_TAG_SPAWN_TYPE_CIRCLE = "CIRCLE"; + const std::string XML_TAG_X = "x"; + const std::string XML_TAG_Y = "y"; + const std::string XML_TAG_Z = "z"; + const std::string XML_TAG_R = "r"; + const std::string XML_TAG_X_LENGTH = "xLength"; + const std::string XML_TAG_Y_LENGTH = "yLength"; + const std::string XML_TAG_Z_LENGTH = "zLength"; + + + enum SpawnType + { + POINT, RECTANGLE, CIRCLE + }; + + enum DistributionMode + { + UNIFORM, GAUSSIAN + }; + + struct PhotonInformation + { + double xPosition; + double yPosition; + double zPosition; + double xAngle; + double yAngle; + double zAngle; + }; + + PhotonInformation GetNextPhoton(double rnd1, double rnd2, double rnd3, + double rnd4, double rnd5, double gau1, double gau2); + + bool IsValid(); + + PhotoacousticLightSource(TiXmlElement* element, bool verbose); + PhotoacousticLightSource(); + virtual ~PhotoacousticLightSource(); + + void ParseAngle(TiXmlElement* direction, std::string angle); + + itkGetMacro(SpawnType, SpawnType) + itkSetMacro(SpawnType, SpawnType) + + itkGetMacro(SpawnLocationX, double) + itkSetMacro(SpawnLocationX, double) + + itkGetMacro(SpawnLocationY, double) + itkSetMacro(SpawnLocationY, double) + + itkGetMacro(SpawnLocationZ, double) + itkSetMacro(SpawnLocationZ, double) + + itkGetMacro(SpawnLocationXLength, double) + itkSetMacro(SpawnLocationXLength, double) + + itkGetMacro(SpawnLocationYLength, double) + itkSetMacro(SpawnLocationYLength, double) + + itkGetMacro(SpawnLocationZLength, double) + itkSetMacro(SpawnLocationZLength, double) + + itkGetMacro(SpawnLocationRadius, double) + itkSetMacro(SpawnLocationRadius, double) + + itkGetMacro(Energy, double) + itkSetMacro(Energy, double) + + itkGetMacro(AngleXMinimum, double) + itkSetMacro(AngleXMinimum, double) + + itkGetMacro(AngleXMaximum, double) + itkSetMacro(AngleXMaximum, double) + + itkGetMacro(AngleYMinimum, double) + itkSetMacro(AngleYMinimum, double) + + itkGetMacro(AngleYMaximum, double) + itkSetMacro(AngleYMaximum, double) + + itkGetMacro(AngleXMode, DistributionMode) + itkSetMacro(AngleXMode, DistributionMode) + + itkGetMacro(AngleYMode, DistributionMode) + itkSetMacro(AngleYMode, DistributionMode) + + itkGetMacro(Verbose, bool) + itkSetMacro(Verbose, bool) + +protected: + + const double TWO_PI = 2.0*3.14159265358979323846; + + SpawnType m_SpawnType; + double m_SpawnLocationX; + double m_SpawnLocationY; + double m_SpawnLocationZ; + double m_SpawnLocationXLength; + double m_SpawnLocationYLength; + double m_SpawnLocationZLength; + double m_SpawnLocationRadius; + + double m_Energy; + + double m_AngleXMinimum; + double m_AngleXMaximum; + double m_AngleYMinimum; + double m_AngleYMaximum; + DistributionMode m_AngleXMode; + DistributionMode m_AngleYMode; + + bool m_IsValid; + bool m_Verbose; + + struct TransformResult + { + double z0; + double z1; + }; + + void ParsePhotonDirection(TiXmlElement* element); + void ParseEnergy(TiXmlElement* element); + void ParsePhotonSpawnArea(TiXmlElement* element); + + TransformResult BoxMuellerTransform(double u1, double u2, double mu, double sigma); + +}; + +} + +#endif // MITKPHOTOACOUSTICLIGHTSOURCE_H diff --git a/Modules/PhotoacousticSimulation/src/ProbeDesign/mitkPhotoacousticProbe.cpp b/Modules/PhotoacousticSimulation/src/ProbeDesign/mitkPhotoacousticProbe.cpp new file mode 100644 index 0000000000..23df49e71b --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/ProbeDesign/mitkPhotoacousticProbe.cpp @@ -0,0 +1,134 @@ +/*=================================================================== + +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 "mitkPhotoacousticProbe.h" + +mitk::PhotoacousticProbe::PhotoacousticProbe(std::string file, bool verbose) : + m_TotalEnergy(0), + m_Verbose(verbose) +{ + TiXmlDocument xmlDoc(file); + bool success = xmlDoc.LoadFile(TIXML_ENCODING_UTF8); + if(m_Verbose) + { + std::cout << "reading of document was " << (success ? "" : "not ") << "successful" << std::endl; + std::cout << "Content of the Xml file:" << std::endl; + xmlDoc.Print(); + } + if(success) + { + InitProbe(xmlDoc); + } + else + { + if(m_Verbose) + { + std::cerr << "Could not load xml file" << std::endl; + } + } +} + +mitk::PhotoacousticProbe::PhotoacousticProbe(const char* fileStream, bool verbose) : + m_TotalEnergy(0), + m_Verbose(verbose) +{ + TiXmlDocument xmlDoc; + const char* success = xmlDoc.Parse(fileStream, 0, TIXML_ENCODING_UTF8); + if(m_Verbose) + { + std::cout << "reading document was " << (success==nullptr ? "" : "not ")<< "successful (" << (success==nullptr ? "NULL" : success) << ")" << std::endl ; + std::cout << "Content of the Xml file:" << std::endl; + xmlDoc.Print(); + } + if(success == nullptr || atoi(success)==0) + { + InitProbe(xmlDoc); + } + else + { + if(m_Verbose) + { + std::cerr << "Could not load xml file" << std::endl; + } + } +} + +mitk::PhotoacousticProbe::~PhotoacousticProbe() +{ + +} + +mitk::PhotoacousticLightSource::PhotonInformation mitk::PhotoacousticProbe::GetNextPhoton(double rng1, double rnd2, double rnd3, double rnd4, + double rnd5, double rnd6, double rnd7, double rnd8) +{ + rng1 = rng1*m_TotalEnergy; + double currentEnergy = 0; + for(mitk::PhotoacousticLightSource::Pointer lightSource : m_LightSources) + { + currentEnergy += lightSource->GetEnergy(); + if(currentEnergy>=rng1) + return lightSource->GetNextPhoton(rnd2, rnd3, rnd4, rnd5, rnd6, rnd7, rnd8); + } + + //Last resort: If something goes wrong, return a position from the first source. + return m_LightSources[0]->GetNextPhoton(rnd2, rnd3, rnd4, rnd5, rnd6, rnd7, rnd8); +} + +bool mitk::PhotoacousticProbe::IsValid() +{ + return m_IsValid; +} + +void mitk::PhotoacousticProbe::InitProbe(TiXmlDocument xmlDoc) +{ + + m_IsValid = true; + + TiXmlElement* root= xmlDoc.FirstChildElement(XML_TAG_PROBE); + if(root) + { + for(TiXmlElement* element = root->FirstChildElement(XML_TAG_LIGHT_SOURCE); + element !=nullptr; element = element->NextSiblingElement(XML_TAG_LIGHT_SOURCE)) + { + mitk::PhotoacousticLightSource::Pointer lightSource = mitk::PhotoacousticLightSource::New(element, m_Verbose); + if(lightSource.IsNotNull() && lightSource->IsValid()) + { + m_LightSources.push_back(lightSource); + m_TotalEnergy += lightSource->GetEnergy(); + } + else + { + m_IsValid = false; + } + } + } + else + { + m_IsValid = false; + } + + if(!m_IsValid) + { + std::cerr << "Creation of a valid Photoacoustic Probe failed." << std::endl; + } + else + { + if(m_Verbose) + { + std::cout << "Successfully created Photoacoustic Probe." << std::endl; + } + } +} diff --git a/Modules/PhotoacousticSimulation/src/ProbeDesign/mitkPhotoacousticProbe.h b/Modules/PhotoacousticSimulation/src/ProbeDesign/mitkPhotoacousticProbe.h new file mode 100644 index 0000000000..005e5e3fae --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/ProbeDesign/mitkPhotoacousticProbe.h @@ -0,0 +1,71 @@ +/*=================================================================== + +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 MITKPHOTOACOUSTICPROBE_H +#define MITKPHOTOACOUSTICPROBE_H + +#include + +#include + +//Includes for smart pointer usage +#include "mitkCommon.h" +#include "itkLightObject.h" + +#include "mitkPhotoacousticLightSource.h" +#include +#include + +namespace mitk { + +/** + * @brief The PhotoacousticProbe class + * The representation of a PhotoacousticProbe + */ +class MITKPHOTOACOUSTICSIMULATION_EXPORT PhotoacousticProbe : public itk::LightObject +{ +public: + + mitkClassMacroItkParent(mitk::PhotoacousticProbe, itk::LightObject) + mitkNewMacro2Param(Self, std::string, bool) + mitkNewMacro2Param(Self, const char*, bool) + + const std::string XML_TAG_PROBE = "Probe"; + const std::string XML_TAG_LIGHT_SOURCE = "LightSource"; + + mitk::PhotoacousticLightSource::PhotonInformation GetNextPhoton(double rng1, double rnd2, double rnd3, double rnd4, + double rnd5, double rnd6, double rnd7, double rnd8); + + bool IsValid(); + + PhotoacousticProbe(std::string xmlFile, bool verbose); + PhotoacousticProbe(const char* fileStream, bool verbose); + virtual ~PhotoacousticProbe(); + +protected: + + std::vector m_LightSources; + bool m_IsValid; + double m_TotalEnergy; + bool m_Verbose; + + void InitProbe(TiXmlDocument document); + +}; + +} + +#endif // MITKPHOTOACOUSTICPROBE_H diff --git a/Modules/PhotoacousticSimulation/src/Thread/mitkMonteCarloThreadHandler.cpp b/Modules/PhotoacousticSimulation/src/Thread/mitkMonteCarloThreadHandler.cpp new file mode 100644 index 0000000000..e60909537f --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Thread/mitkMonteCarloThreadHandler.cpp @@ -0,0 +1,75 @@ +/*=================================================================== + +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 "mitkMonteCarloThreadHandler.h" +#include "mitkCommon.h" + +mitk::MonteCarloThreadHandler::MonteCarloThreadHandler(long simulationTimeMeasure, bool simulateOnTimeBasis) +{ + m_SimulateOnTimeBasis = simulateOnTimeBasis; + if(m_SimulateOnTimeBasis) + { + m_SimulationTime = simulationTimeMeasure; + m_Time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); + m_WorkPackageSize = 10000L; + } + else + { + m_NumberPhotonsToSimulate = simulationTimeMeasure; + m_NumberPhotonsRemaining = simulationTimeMeasure; + m_WorkPackageSize = 10000L; + } +} + +mitk::MonteCarloThreadHandler::~MonteCarloThreadHandler() +{ + m_Mutex.unlock(); +} + +long mitk::MonteCarloThreadHandler::GetNextWorkPackage() +{ + long workPackageSize = 0; + if(m_SimulateOnTimeBasis) + { + long now = std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); + if(now-m_Time <= m_SimulationTime) + { + workPackageSize = m_WorkPackageSize; + std::cout <<"" << std::endl; + } + } + else + { + m_Mutex.lock(); + + if(m_NumberPhotonsRemaining < m_WorkPackageSize) + workPackageSize = m_NumberPhotonsRemaining; + else + workPackageSize = m_WorkPackageSize; + + m_NumberPhotonsRemaining -= workPackageSize; + m_Mutex.unlock(); + + std::cout <<"" << std::endl; + } + + return workPackageSize; +} + +void mitk::MonteCarloThreadHandler::SetPackageSize(long packageSize) +{ + m_WorkPackageSize = packageSize; +} diff --git a/Modules/PhotoacousticSimulation/src/Thread/mitkMonteCarloThreadHandler.h b/Modules/PhotoacousticSimulation/src/Thread/mitkMonteCarloThreadHandler.h new file mode 100644 index 0000000000..df3ad8489b --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Thread/mitkMonteCarloThreadHandler.h @@ -0,0 +1,67 @@ +/*=================================================================== + +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 MITKMONTECARLOTHREADHANDLER_H +#define MITKMONTECARLOTHREADHANDLER_H + +#include +#include +#include + +//Includes for smart pointer usage +#include "mitkCommon.h" +#include "itkLightObject.h" + +namespace mitk { + +/** + * @brief The PhotoacousticStatefulObject class + * Designed for inheritence. Provides a state member variable and convenience methods to check + * for the state. + */ +class MITKPHOTOACOUSTICSIMULATION_EXPORT MonteCarloThreadHandler : public itk::LightObject +{ +public: + + mitkClassMacroItkParent(mitk::MonteCarloThreadHandler, itk::LightObject) + mitkNewMacro2Param(mitk::MonteCarloThreadHandler, long, bool) + + long GetNextWorkPackage(); + + void SetPackageSize(long packageSize); + +protected: + long m_NumberPhotonsToSimulate; + long m_NumberPhotonsRemaining; + long m_WorkPackageSize; + long m_SimulationTime; + long m_Time; + bool m_SimulateOnTimeBasis; + std::mutex m_Mutex; + + /** + * @brief PhotoacousticThreadhandler + * @param simulationTimeMeasure + * @param simulateOnTimeBasis + */ + MonteCarloThreadHandler(long simulationTimeMeasure, bool simulateOnTimeBasis); + virtual ~MonteCarloThreadHandler(); + +}; + +} + +#endif // MITKMONTECARLOTHREADHANDLER_H diff --git a/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticPropertyCalculator.cpp b/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticPropertyCalculator.cpp new file mode 100644 index 0000000000..789cbecba9 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticPropertyCalculator.cpp @@ -0,0 +1,136 @@ +#include "mitkPhotoacousticPropertyCalculator.h" +// us +#include +#include +#include +#include +#include + +mitk::PhotoacousticPropertyCalculator::Properties mitk::PhotoacousticPropertyCalculator::CalculatePropertyForSpecificWavelength(TissueType tissueType, int wavelength, double bloodOxygen) +{ + Properties returnValue; + + if(!m_Valid) + { + mitkThrow() << "PhotoacousticPropertyGenerator was not loaded properly."; + return returnValue; + } + + double bloodOxygenation = bloodOxygen; + double bloodVolumeFraction; + double waterVolumeFraction; + double fatVolumeFraction; + double melanosomesVolumeFraction; + double musp500; + double fray; + double bmie; + double g; + + switch (tissueType) + { + case AIR: + returnValue.mua = 0.0001; + returnValue.mus = 1.0; + returnValue.g = 1.0; + return returnValue; + case BLOOD: + bloodVolumeFraction = 1.0; + waterVolumeFraction = 0.95; + fatVolumeFraction = 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; + bloodOxygenation = 0.75; + waterVolumeFraction = 0.8; + fatVolumeFraction = 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; + + 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::PhotoacousticPropertyCalculator::PhotoacousticPropertyCalculator() +{ + 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::PhotoacousticPropertyCalculator::~PhotoacousticPropertyCalculator() +{ + m_SpectralLibMap.clear(); + m_Valid = false; +} diff --git a/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticPropertyCalculator.h b/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticPropertyCalculator.h new file mode 100644 index 0000000000..c6f0cd6b11 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticPropertyCalculator.h @@ -0,0 +1,74 @@ +/*=================================================================== + +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 MITKPHOTOACOUSTICPROPERTYCALCULATOR_H +#define MITKPHOTOACOUSTICPROPERTYCALCULATOR_H + +#include "MitkPhotoacousticSimulationExports.h" + +//Includes for smart pointer usage +#include "mitkCommon.h" +#include "itkLightObject.h" +#include "mitkPhotoacousticStatefulObject.h" + +namespace mitk +{ +class MITKPHOTOACOUSTICSIMULATION_EXPORT PhotoacousticPropertyCalculator : public itk::LightObject +{ +public: + + mitkClassMacroItkParent(mitk::PhotoacousticPropertyCalculator, itk::LightObject) + itkFactorylessNewMacro(Self) + + struct Properties + { + double mua; + double mus; + double g; + }; + + enum TissueType + { + AIR = 1, + BLOOD = 2, + EPIDERMIS = 3, + FAT = 4, + STANDARD_TISSUE = 5 + }; + + Properties CalculatePropertyForSpecificWavelength(TissueType tissueType, int wavelength, double oxygenSaturaton=0); + +protected: + PhotoacousticPropertyCalculator(); + virtual ~PhotoacousticPropertyCalculator(); + + bool m_Valid = false; + + std::map> m_SpectralLibMap; + + enum MapType + { + OXYGENATED = 1, + DEOXYGENATED = 2, + WATER = 3, + FATTY = 4, + MELANIN = 5 + }; + +}; +} + +#endif // MITKPHOTOACOUSTICPROPERTYCALCULATOR_H diff --git a/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticSmartVector.cpp b/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticSmartVector.cpp new file mode 100644 index 0000000000..b1b816606c --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticSmartVector.cpp @@ -0,0 +1,139 @@ +/*=================================================================== + +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 "mitkPhotoacousticSmartVector.h" +#include "chrono" +#include "math.h" +mitk::PhotoacousticSmartVector::PhotoacousticSmartVector() +{ + srand(std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count()); + m_Vector.Fill(0); +} + +mitk::PhotoacousticSmartVector::~PhotoacousticSmartVector() +{ + m_Vector.Fill(0); +} + +double mitk::PhotoacousticSmartVector::GetNorm() +{ + return m_Vector.GetNorm(); +} + +double mitk::PhotoacousticSmartVector::GetElement(unsigned short index) +{ + return m_Vector.GetElement(index); +} + +void mitk::PhotoacousticSmartVector::SetElement(unsigned short index, double value) +{ + m_Vector.SetElement(index, value); +} + +void mitk::PhotoacousticSmartVector::Normalize() +{ + double norm = m_Vector.GetNorm(); + m_Vector.SetElement(0, m_Vector.GetElement(0)/norm); + m_Vector.SetElement(1, m_Vector.GetElement(1)/norm); + m_Vector.SetElement(2, m_Vector.GetElement(2)/norm); +} + +void mitk::PhotoacousticSmartVector::SetValue(mitk::PhotoacousticSmartVector::Pointer value) +{ + m_Vector.SetElement(0, value->GetElement(0)); + m_Vector.SetElement(1, value->GetElement(1)); + m_Vector.SetElement(2, value->GetElement(2)); +} + +void mitk::PhotoacousticSmartVector::RandomizeByPercentage(double percentage, double bendingFactor, std::mt19937* rng) +{ + std::uniform_real_distribution<> range(-percentage, percentage); + m_Vector.SetElement(0, m_Vector.GetElement(0) + (bendingFactor * range(*rng))); + m_Vector.SetElement(1, m_Vector.GetElement(1) + (bendingFactor * range(*rng))); + m_Vector.SetElement(2, m_Vector.GetElement(2) + (bendingFactor * range(*rng))); +} + +void mitk::PhotoacousticSmartVector::Randomize(double xLowerLimit, double xUpperLimit, double yLowerLimit, double yUpperLimit, double zLowerLimit, double zUpperLimit, std::mt19937* rng) +{ + std::uniform_real_distribution<> rangeX(xLowerLimit, xUpperLimit); + std::uniform_real_distribution<> rangeY(yLowerLimit, yUpperLimit); + std::uniform_real_distribution<> rangeZ(zLowerLimit, zUpperLimit); + m_Vector.SetElement(0, rangeX(*rng)); + m_Vector.SetElement(1, rangeY(*rng)); + m_Vector.SetElement(2, rangeZ(*rng)); +} + +void mitk::PhotoacousticSmartVector::Randomize(double xLimit, double yLimit, double zLimit, std::mt19937* rng) +{ + Randomize(0, xLimit, 0, yLimit, 0, zLimit, rng); +} + +void mitk::PhotoacousticSmartVector::Randomize(std::mt19937* rng) +{ + Randomize(-1, 1, -1, 1, -1, 1, rng); +} + +void mitk::PhotoacousticSmartVector::PrintSelf(std::ostream& os, itk::Indent indent) const +{ + os << "X: " << m_Vector.GetElement(0) << std::endl; + os << "Y: " << m_Vector.GetElement(1) << std::endl; + os << "Z: " << m_Vector.GetElement(2) << std::endl; + os << "Length: " << m_Vector.GetNorm() << std::endl; +} + +void mitk::PhotoacousticSmartVector::Rotate(double thetaChange, double phiChange) +{ + MITK_DEBUG << "Vector before rotation: ("<SetElement(0, this->GetElement(0)); + returnVector->SetElement(1, this->GetElement(1)); + returnVector->SetElement(2, this->GetElement(2)); + return returnVector; +} diff --git a/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticSmartVector.h b/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticSmartVector.h new file mode 100644 index 0000000000..87b16d2b8b --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticSmartVector.h @@ -0,0 +1,124 @@ +/*=================================================================== + +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 MITKSMARTVECTOR_H +#define MITKSMARTVECTOR_H + +#include +#include + +#include + +//Includes for smart pointer usage +#include "mitkCommon.h" +#include "itkLightObject.h" + +namespace mitk { + + +class MITKPHOTOACOUSTICSIMULATION_EXPORT PhotoacousticSmartVector : public itk::LightObject +{ +public: + mitkClassMacroItkParent(mitk::PhotoacousticSmartVector, itk::LightObject) + itkFactorylessNewMacro(Self) + + /** + * @brief GetNorm calculates the length of this vector. + * @return the euclidean norm + */ + double GetNorm(); + + double GetElement(unsigned short index); + void SetElement(unsigned short index, double value); + + /** + * @brief Normalize normalizes this vector. After calling this GetNorm() will return 1. + */ + void Normalize(); + void SetValue(mitk::PhotoacousticSmartVector::Pointer value); + + /** + * @brief RandomizeByPercentage alters this vector randomly by [-percentage, percentage] of the bendingFactor. + * + * @param percentage + * @param bendingFactor + */ + void RandomizeByPercentage(double percentage, double bendingFactor, std::mt19937* rng); + + /** + * @brief Randomize randomizes this vector to be [lowerLimit, upperLimit] in each element + * + * @param xLowerLimit + * @param xUpperLimit + * @param yLowerLimit + * @param yUpperLimit + * @param zLowerLimit + * @param zUpperLimit + */ + void Randomize(double xLowerLimit, double xUpperLimit, double yLowerLimit, double yUpperLimit, double zLowerLimit, double zUpperLimit, std::mt19937* rng); + + /** + * @brief Randomize randomizes this vector to be [0, limit] in each element + * + * @param xLimit + * @param yLimit + * @param zLimit + */ + void Randomize(double xLimit, double yLimit, double zLimit, std::mt19937* rng); + + /** + * @brief Randomize randomizes this vector to be [-1, 1] in each element + */ + void Randomize(std::mt19937* rng); + + /** + * @brief Rotate rotates this PhotoacousticSmartVector around the x, y and z axis with the given angles in radians + * + * @param thetaChange rotation of the inclination angle in radians + * @param phiChange rotation of the azimuthal angle in radians + */ + void Rotate(double xAngle, double yAngle); + + /** + * @brief Scale scales this PhotoacousticSmartVector with the given factor + * + * @param factor the scaling factor + * + * If a negative number is provided, the direction of the vector will be inverted. + */ + void Scale(double factor); + + /** + * @brief Clone create a deep copy of this vector + * + * @return a new vector with the same values. + */ + mitk::PhotoacousticSmartVector::Pointer Clone(); + + +protected: + PhotoacousticSmartVector(); + virtual ~PhotoacousticSmartVector(); + + virtual void PrintSelf(std::ostream& os, itk::Indent indent) const override; + +private: + mitk::Vector3D m_Vector; +}; + +} + +#endif // MITKSMARTVECTOR_H diff --git a/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticStatefulObject.cpp b/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticStatefulObject.cpp new file mode 100644 index 0000000000..678e765ba1 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticStatefulObject.cpp @@ -0,0 +1,48 @@ +/*=================================================================== + +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 "mitkPhotoacousticStatefulObject.h" +#include "mitkCommon.h" + +void mitk::PhotoacousticStatefulObject::AssertState(State state) +{ + if(m_State!=state) + { + std::string msg = "Cannot do this operation with the current state."; + MITK_ERROR << msg; + mitkThrow() << msg; + } +} + +void mitk::PhotoacousticStatefulObject::AssertStateNot(State state) +{ + if(m_State==state) + { + std::string msg = "Cannot do this operation with the current state."; + MITK_ERROR << msg; + mitkThrow() << msg; + } +} + +mitk::PhotoacousticStatefulObject::PhotoacousticStatefulObject() +{ + +} + +mitk::PhotoacousticStatefulObject::~PhotoacousticStatefulObject() +{ + +} diff --git a/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticStatefulObject.h b/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticStatefulObject.h new file mode 100644 index 0000000000..d5b6d99ec0 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticStatefulObject.h @@ -0,0 +1,65 @@ +/*=================================================================== + +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 MITKPHOTOACOUSTICSTATEFULOBJECT_H +#define MITKPHOTOACOUSTICSTATEFULOBJECT_H + +#include +#include + +namespace mitk { + +/** + * @brief The PhotoacousticStatefulObject class + * Designed for inheritence. Provides a state member variable and convenience methods to check + * for the state. + */ +class MITKPHOTOACOUSTICSIMULATION_EXPORT PhotoacousticStatefulObject +{ +public: + + enum State + { + UNINITIALIZED, INITIALIZED, FINISHED + }; + + /** + * @brief AssertState Throws an mitk::Exception if the current state does + * not match the given parameter. + * + * @param state + */ + virtual void AssertState(State state); + + /** + * @brief AssertStateNot Throws an mitk::Exception if the current state + * matches the given parameter. + * + * @param state + */ + virtual void AssertStateNot(State state); + + PhotoacousticStatefulObject(); + virtual ~PhotoacousticStatefulObject(); + +protected: + State m_State; + +}; + +} + +#endif // MITKPHOTOACOUSTICSTATEFULOBJECT_H diff --git a/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticTissueGeneratorParameters.cpp b/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticTissueGeneratorParameters.cpp new file mode 100644 index 0000000000..c2a85e0ca8 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticTissueGeneratorParameters.cpp @@ -0,0 +1,81 @@ +/*=================================================================== + +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 "mitkPhotoacousticTissueGeneratorParameters.h" + +mitk::PhotoacousticTissueGeneratorParameters::PhotoacousticTissueGeneratorParameters() +{ + m_XDim = 50; + m_YDim = 50; + m_ZDim = 50; + m_VoxelSpacing = 1; + m_VolumeSmoothingSigma = 0; + m_DoVolumeSmoothing = false; + m_UseRngSeed = false; + m_RngSeed = 1337L; + m_RandomizePhysicalProperties = false; + m_RandomizePhysicalPropertiesPercentage = 0; + + m_BackgroundAbsorption = 0.1; + m_BackgroundScattering = 15; + m_BackgroundAnisotropy = 0.9; + m_AirThickness = 1; + m_SkinAbsorption = 0.1; + m_SkinScattering = 15; + m_SkinAnisotropy = 0.9; + m_SkinThickness = 0; + m_FatAbsorption = 0.1; + m_FatScattering = 15; + m_FatAnisotropy = 0.9; + m_FatPercentage = 0; + + m_CalculateNewVesselPositionCallback = &mitk::PhotoacousticVesselMeanderStrategy::CalculateRandomlyDivergingPosition; + m_MinNumberOfVessels = 0; + m_MaxNumberOfVessels = 0; + m_MinVesselBending = 0; + m_MaxVesselBending = 0.1; + m_MinVesselAbsorption = 1; + m_MaxVesselAbsorption = 8; + m_MinVesselRadius = 1; + m_MaxVesselRadius = 3; + m_VesselBifurcationFrequency = 25; + m_MinVesselScattering = 15; + m_MaxVesselScattering = 15; + m_MinVesselAnisotropy = 0.9; + m_MaxVesselAnisotropy = 0.9; + m_MinVesselZOrigin = 10; + m_MaxVesselZOrigin = 40; + + m_MCflag = 1; + m_MCLaunchflag = 0; + m_MCBoundaryflag = 2; + m_MCLaunchPointX = 25; + m_MCLaunchPointY = 25; + m_MCLaunchPointZ = 2; + m_MCFocusPointX = 25; + m_MCFocusPointY = 25; + m_MCFocusPointZ = 25; + m_MCTrajectoryVectorX = 0; + m_MCTrajectoryVectorY = 0; + m_MCTrajectoryVectorZ = 1; + m_MCRadius = 2; + m_MCWaist = 4; +} + +mitk::PhotoacousticTissueGeneratorParameters::~PhotoacousticTissueGeneratorParameters() +{ + +} diff --git a/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticTissueGeneratorParameters.h b/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticTissueGeneratorParameters.h new file mode 100644 index 0000000000..e93490c1e2 --- /dev/null +++ b/Modules/PhotoacousticSimulation/src/Utils/mitkPhotoacousticTissueGeneratorParameters.h @@ -0,0 +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. + +===================================================================*/ + +#ifndef MITKPHOTOACOUSTICTISSUEGENERATORPARAMETERS_H +#define MITKPHOTOACOUSTICTISSUEGENERATORPARAMETERS_H + +#include +#include + +//Includes for smart pointer usage +#include "mitkCommon.h" +#include "itkLightObject.h" + +namespace mitk { + + +class MITKPHOTOACOUSTICSIMULATION_EXPORT PhotoacousticTissueGeneratorParameters : public itk::Object +{ +public: + mitkClassMacroItkParent(mitk::PhotoacousticTissueGeneratorParameters, itk::Object) + itkFactorylessNewMacro(Self) + + /** + * Callback function definition of a PhotoacousticVesselMeanderStrategy + */ + typedef void (mitk::PhotoacousticVesselMeanderStrategy::*CalculateNewVesselPositionCallback) + (mitk::PhotoacousticSmartVector::Pointer, mitk::PhotoacousticSmartVector::Pointer, double, std::mt19937*); + + itkGetMacro(XDim, int) + itkGetMacro(YDim, int) + itkGetMacro(ZDim, int) + itkGetMacro(VoxelSpacing, double) + itkGetMacro(VolumeSmoothingSigma, double) + itkGetMacro(DoVolumeSmoothing, bool) + itkGetMacro(UseRngSeed, bool) + itkGetMacro(RngSeed, long) + itkGetMacro(RandomizePhysicalProperties, bool) + itkGetMacro(RandomizePhysicalPropertiesPercentage, double) + + itkGetMacro(BackgroundAbsorption, double) + itkGetMacro(BackgroundScattering, double) + itkGetMacro(BackgroundAnisotropy, double) + itkGetMacro(AirThickness, double) + itkGetMacro(SkinAbsorption, double) + itkGetMacro(SkinScattering, double) + itkGetMacro(SkinAnisotropy, double) + itkGetMacro(SkinThickness, double) + itkGetMacro(FatAbsorption, double) + itkGetMacro(FatScattering, double) + itkGetMacro(FatAnisotropy, double) + itkGetMacro(FatPercentage, double) + + itkGetMacro(CalculateNewVesselPositionCallback, CalculateNewVesselPositionCallback) + itkGetMacro(MinNumberOfVessels, int) + itkGetMacro(MaxNumberOfVessels, int) + itkGetMacro(MinVesselBending, double) + itkGetMacro(MaxVesselBending, double) + itkGetMacro(MinVesselAbsorption, double) + itkGetMacro(MaxVesselAbsorption, double) + itkGetMacro(MinVesselRadius, double) + itkGetMacro(MaxVesselRadius, double) + itkGetMacro(VesselBifurcationFrequency, int) + itkGetMacro(MinVesselScattering, double) + itkGetMacro(MaxVesselScattering, double) + itkGetMacro(MinVesselAnisotropy, double) + itkGetMacro(MaxVesselAnisotropy, double) + itkGetMacro(MinVesselZOrigin, double) + itkGetMacro(MaxVesselZOrigin, double) + + itkGetMacro(MCflag, double) + itkGetMacro(MCLaunchflag, double) + itkGetMacro(MCBoundaryflag, double) + itkGetMacro(MCLaunchPointX, double) + itkGetMacro(MCLaunchPointY, double) + itkGetMacro(MCLaunchPointZ, double) + itkGetMacro(MCFocusPointX, double) + itkGetMacro(MCFocusPointY, double) + itkGetMacro(MCFocusPointZ, double) + itkGetMacro(MCTrajectoryVectorX, double) + itkGetMacro(MCTrajectoryVectorY, double) + itkGetMacro(MCTrajectoryVectorZ, double) + itkGetMacro(MCRadius, double) + itkGetMacro(MCWaist, double) + + itkSetMacro(XDim, int) + itkSetMacro(YDim, int) + itkSetMacro(ZDim, int) + itkSetMacro(VoxelSpacing, double) + itkSetMacro(VolumeSmoothingSigma, double) + itkSetMacro(DoVolumeSmoothing, bool) + itkSetMacro(UseRngSeed, bool) + itkSetMacro(RngSeed, long) + itkSetMacro(RandomizePhysicalProperties, bool) + itkSetMacro(RandomizePhysicalPropertiesPercentage, double) + + itkSetMacro(BackgroundAbsorption, double) + itkSetMacro(BackgroundScattering, double) + itkSetMacro(BackgroundAnisotropy, double) + itkSetMacro(AirThickness, double) + itkSetMacro(SkinAbsorption, double) + itkSetMacro(SkinScattering, double) + itkSetMacro(SkinAnisotropy, double) + itkSetMacro(SkinThickness, double) + itkSetMacro(FatAbsorption, double) + itkSetMacro(FatScattering, double) + itkSetMacro(FatAnisotropy, double) + itkSetMacro(FatPercentage, double) + + itkSetMacro(CalculateNewVesselPositionCallback, CalculateNewVesselPositionCallback) + itkSetMacro(MinNumberOfVessels, int) + itkSetMacro(MaxNumberOfVessels, int) + itkSetMacro(MinVesselBending, double) + itkSetMacro(MaxVesselBending, double) + itkSetMacro(MinVesselAbsorption, double) + itkSetMacro(MaxVesselAbsorption, double) + itkSetMacro(MinVesselRadius, double) + itkSetMacro(MaxVesselRadius, double) + itkSetMacro(VesselBifurcationFrequency, int) + itkSetMacro(MinVesselScattering, double) + itkSetMacro(MaxVesselScattering, double) + itkSetMacro(MinVesselAnisotropy, double) + itkSetMacro(MaxVesselAnisotropy, double) + itkSetMacro(MinVesselZOrigin, double) + itkSetMacro(MaxVesselZOrigin, double) + + itkSetMacro(MCflag, double) + itkSetMacro(MCLaunchflag, double) + itkSetMacro(MCBoundaryflag, double) + itkSetMacro(MCLaunchPointX, double) + itkSetMacro(MCLaunchPointY, double) + itkSetMacro(MCLaunchPointZ, double) + itkSetMacro(MCFocusPointX, double) + itkSetMacro(MCFocusPointY, double) + itkSetMacro(MCFocusPointZ, double) + itkSetMacro(MCTrajectoryVectorX, double) + itkSetMacro(MCTrajectoryVectorY, double) + itkSetMacro(MCTrajectoryVectorZ, double) + itkSetMacro(MCRadius, double) + itkSetMacro(MCWaist, double) + + +protected: + PhotoacousticTissueGeneratorParameters(); + virtual ~PhotoacousticTissueGeneratorParameters(); + +private: + + int m_XDim; + int m_YDim; + int m_ZDim; + double m_VoxelSpacing; + double m_VolumeSmoothingSigma; + bool m_DoVolumeSmoothing; + bool m_UseRngSeed; + long m_RngSeed; + bool m_RandomizePhysicalProperties; + double m_RandomizePhysicalPropertiesPercentage; + + double m_BackgroundAbsorption; + double m_BackgroundScattering; + double m_BackgroundAnisotropy; + double m_AirThickness; + double m_SkinAbsorption; + double m_SkinScattering; + double m_SkinAnisotropy; + double m_SkinThickness; + double m_FatAbsorption; + double m_FatScattering; + double m_FatAnisotropy; + double m_FatPercentage; + + CalculateNewVesselPositionCallback m_CalculateNewVesselPositionCallback; + int m_MinNumberOfVessels; + int m_MaxNumberOfVessels; + double m_MinVesselBending; + double m_MaxVesselBending; + double m_MinVesselAbsorption; + double m_MaxVesselAbsorption; + double m_MinVesselRadius; + double m_MaxVesselRadius; + int m_VesselBifurcationFrequency; + double m_MinVesselScattering; + double m_MaxVesselScattering; + double m_MinVesselAnisotropy; + double m_MaxVesselAnisotropy; + double m_MinVesselZOrigin; + double m_MaxVesselZOrigin; + + double m_MCflag; + double m_MCLaunchflag; + double m_MCBoundaryflag; + double m_MCLaunchPointX; + double m_MCLaunchPointY; + double m_MCLaunchPointZ; + double m_MCFocusPointX; + double m_MCFocusPointY; + double m_MCFocusPointZ; + double m_MCTrajectoryVectorX; + double m_MCTrajectoryVectorY; + double m_MCTrajectoryVectorZ; + double m_MCRadius; + double m_MCWaist; + +}; + +} + +#endif // MITKPHOTOACOUSTICTISSUEGENERATORPARAMETERS_H diff --git a/Plugins/PluginList.cmake b/Plugins/PluginList.cmake index 4cdec681c8..8493b37f1c 100644 --- a/Plugins/PluginList.cmake +++ b/Plugins/PluginList.cmake @@ -1,85 +1,86 @@ # Plug-ins must be ordered according to their dependencies set(MITK_PLUGINS org.blueberry.core.runtime:ON org.blueberry.core.expressions:OFF org.blueberry.core.commands:OFF org.blueberry.core.jobs:OFF org.blueberry.ui.qt:OFF org.blueberry.ui.qt.help:OFF org.blueberry.ui.qt.log:ON org.blueberry.ui.qt.objectinspector:OFF #org.blueberry.test:ON #org.blueberry.uitest:ON #Testing/org.blueberry.core.runtime.tests:ON #Testing/org.blueberry.osgi.tests:ON org.mitk.core.services:ON org.mitk.gui.common:ON org.mitk.planarfigure:ON org.mitk.core.ext:OFF org.mitk.core.jobs:OFF org.mitk.diffusionimaging:OFF org.mitk.simulation:OFF org.mitk.gui.qt.application:ON org.mitk.gui.qt.coreapplication:OFF org.mitk.gui.qt.ext:OFF org.mitk.gui.qt.extapplication:OFF org.mitk.gui.qt.common:ON org.mitk.gui.qt.stdmultiwidgeteditor:ON org.mitk.gui.qt.common.legacy:OFF org.mitk.gui.qt.cmdlinemodules:OFF org.mitk.gui.qt.diffusionimagingapp:OFF org.mitk.gui.qt.datamanager:ON org.mitk.gui.qt.datamanagerlight:OFF org.mitk.gui.qt.properties:ON org.mitk.gui.qt.basicimageprocessing:OFF org.mitk.gui.qt.dicom:OFF org.mitk.gui.qt.dicominspector:OFF org.mitk.gui.qt.diffusionimaging:OFF org.mitk.gui.qt.dosevisualization:OFF org.mitk.gui.qt.geometrytools:OFF org.mitk.gui.qt.igtexamples:OFF org.mitk.gui.qt.igttracking:OFF org.mitk.gui.qt.openigtlink:OFF org.mitk.gui.qt.imagecropper:OFF org.mitk.gui.qt.imagenavigator:ON org.mitk.gui.qt.viewnavigator:OFF org.mitk.gui.qt.materialeditor:OFF org.mitk.gui.qt.measurementtoolbox:OFF org.mitk.gui.qt.moviemaker:OFF org.mitk.gui.qt.pointsetinteraction:OFF org.mitk.gui.qt.pointsetinteractionmultispectrum:OFF org.mitk.gui.qt.python:OFF org.mitk.gui.qt.registration:OFF org.mitk.gui.qt.remeshing:OFF org.mitk.gui.qt.segmentation:OFF org.mitk.gui.qt.simulation:OFF org.mitk.gui.qt.aicpregistration:OFF org.mitk.gui.qt.toftutorial:OFF org.mitk.gui.qt.tofutil:OFF org.mitk.gui.qt.tubegraph:OFF org.mitk.gui.qt.ugvisualization:OFF org.mitk.gui.qt.ultrasound:OFF org.mitk.gui.qt.volumevisualization:OFF org.mitk.gui.qt.eventrecorder:OFF org.mitk.gui.qt.xnat:OFF org.mitk.gui.qt.igt.app.echotrack:OFF org.mitk.gui.qt.spectrocamrecorder:OFF org.mitk.gui.qt.classificationsegmentation:OFF org.mitk.gui.qt.overlaymanager:OFF + org.mitk.gui.qt.photoacousticsimulation:OFF org.mitk.gui.qt.multilabelsegmentation:ON org.mitk.matchpoint.core.helper:OFF org.mitk.gui.qt.matchpoint.algorithm.browser:OFF org.mitk.gui.qt.matchpoint.algorithm.control:OFF org.mitk.gui.qt.matchpoint.algorithm.batch:OFF org.mitk.gui.qt.matchpoint.mapper:OFF org.mitk.gui.qt.matchpoint.framereg:OFF org.mitk.gui.qt.matchpoint.visualizer:OFF org.mitk.gui.qt.matchpoint.evaluator:OFF org.mitk.gui.qt.matchpoint.manipulator:OFF ) diff --git a/Plugins/org.mitk.gui.qt.photoacousticsimulation/CMakeLists.txt b/Plugins/org.mitk.gui.qt.photoacousticsimulation/CMakeLists.txt new file mode 100644 index 0000000000..3bb78c3222 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacousticsimulation/CMakeLists.txt @@ -0,0 +1,8 @@ +project(org_mitk_gui_qt_photoacousticsimulation) + +mitk_create_plugin( + EXPORT_DIRECTIVE PHOTOACOUSTICSIMULATION_EXPORT + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDS MitkPhotoacousticSimulation MitkQtWidgetsExt + PACKAGE_DEPENDS PUBLIC ITK +) diff --git a/Plugins/org.mitk.gui.qt.photoacousticsimulation/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.photoacousticsimulation/documentation/UserManual/Manual.dox new file mode 100644 index 0000000000..e9e31e8451 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacousticsimulation/documentation/UserManual/Manual.dox @@ -0,0 +1,12 @@ +/** +\page org_mitk_gui_qt_photoacousticsimulation Photoacoustic Tissue Generator + +\imageMacro{icon.png,"Icon of Photoacousticsimulation", 2.00} + +\tableofcontents + +\section org_mitk_gui_qt_photoacousticsimulationOverview Overview + +TODO Describe this!! + +*/ diff --git a/Plugins/org.mitk.gui.qt.photoacousticsimulation/documentation/UserManual/icon.xpm b/Plugins/org.mitk.gui.qt.photoacousticsimulation/documentation/UserManual/icon.xpm new file mode 100644 index 0000000000..d6b601c0af --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacousticsimulation/documentation/UserManual/icon.xpm @@ -0,0 +1,203 @@ +/* XPM */ +static char * icon_xpm[] = { +"128 128 72 1", +" c None", +". c #484848", +"+ c #2E2E2E", +"@ c #272727", +"# c #242424", +"$ c #202020", +"% c #171717", +"& c #1C1C1C", +"* c #1A1A1A", +"= c #191919", +"- c #222222", +"; c #292929", +"> c #404040", +", c #313131", +"' c #1B1B1B", +") c #0E0E0E", +"! c #070707", +"~ c #000000", +"{ c #0A0A0A", +"] c #111111", +"^ c #282828", +"/ c #2D2D2D", +"( c #050505", +"_ c #010101", +": c #0D0D0D", +"< c #151515", +"[ c #1E1E1E", +"} c #080808", +"| c #030303", +"1 c #020202", +"2 c #1D1D1D", +"3 c #0C0C0C", +"4 c #2F2F2F", +"5 c #181818", +"6 c #161616", +"7 c #232323", +"8 c #262626", +"9 c #212121", +"0 c #121212", +"a c #040404", +"b c #323232", +"c c #252525", +"d c #0B0B0B", +"e c #3C3C3C", +"f c #131313", +"g c #090909", +"h c #1F1F1F", +"i c #060606", +"j c #2C2C2C", +"k c #141414", +"l c #3A3A3A", +"m c #2A2A2A", +"n c #333333", +"o c #3B3B3B", +"p c #3D3D3D", +"q c #101010", +"r c #373737", +"s c #0F0F0F", +"t c #3E3E3E", +"u c #343434", +"v c #353535", +"w c #414141", +"x c #383838", +"y c #303030", +"z c #393939", +"A c #424242", +"B c #2B2B2B", +"C c #454545", +"D c #3F3F3F", +"E c #4D4D4D", +"F c #4B4B4B", +"G c #363636", +" ", +" .+@#$%&*=-;> ", +" ,')!~~~~~~~~~~~~~{]^ ", +" /*](~~~~~~~~~__~~~~_~~~~_:<[ ", +" ^}|~_~~~~___~~~__~~~_~~_~~~~~11* ", +" ^!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~2 ", +" '3~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~(% ", +" 4!_~~~_~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~_~~~15 ", +" -~~~~_~~~~~~~~_(!}65&[7892&0}}a_~~~~~~~~~~~~~{b ", +" +)~~~~~~_~~~~~3'$ c$d~~~~~~~~~~~~~6 ", +" c~~~~~~~~~~~1[e ef_~~~~~~~~~~~g ", +" h~~_~~~~~~~}2 f!_~~~~~~~~~1 ", +" %_~~~~~~~~38 -i~~_~~~~~~(j ", +" k~~~~~~~~~7 [~~_~~~~~~_b ", +" =~~~~~~~_3l @g~~~~~~~~~m ", +" ;1~_~~~~~9 &_~~~~~~~( ", +" e_~~~~~~1n b1~~~~~~~a ", +" i~~~~~~{o p{~_~~~~~} ", +" f~~~~~~: q~~~~~_~k ", +" ,~~~~~~: q~~~~~_~/ ", +" !~~~~~g 0~~~~~~i ", +" <~~~~~|o :~~~~~~6 ", +" |~~~~~r (~~~~~1 ", +" 6~~~~~& g~~~~~] ", +" (~~~~! 4a_~~_1r ", +" 2~~~~~j h~~~~~s ", +" ~~~~~2 k~~~~~t ", +" *~~~~{ g~~~~s ", +" a~~~~7 8_~_~| ", +" a~~~! 3~~__2 ", +" *~~~~2 u~~~~!q@ ", +" q~~~~~1 _~_~~_( ", +" i~_~~~~, [~~~~~_| ", +" a~~~~~~& &~~~~_~18 ", +" c_~~~~~~v >~~~~~_~5 ", +" h_~~~~~~ |_~~_~~f ", +" k_~__~~) 5~~_~~_( ", +" d~~_~~~h ^~_~~~~1 ", +" 51_~~~~, w~~~~~|7 ", +" %~~{q) ^9/{~! ", +" d~| =~( ", +" i~} _11_1_ '~a ", +" !~d ~~~~~~~~~~~~~~~~~ ;_| ", +" !~] ~~~~~~~~~~~~~~~~~~~~~ /11 ", +" i~< i~~~~~~~ ~~~~~~~~ x11# ", +" i~5 ~~~~~~ ~~~~~~ w11 ", +" |_* ~~~~~~~ ~~~~~~ t11 ", +" a~' ~~~~~~ ~~~~ y11+ ", +" 9-y1~* z@ ~~~~~ ~~~a 8:<-u j1~3}i7 ", +" $~~~~~5 61~~_# ~~~~~ ~~~~ 6~~~~~% h_~~_~d ", +" 6~_~_~5 f~~~_~~w ~~~~ ~~~~ ~~~~~~_n '~~~~~} ", +" =~~_~_5 i~~~~~~4 ~~~~ ~~~~ A~~~~~~~[ %~___~) ", +" *~~~~~5 b@'~__~~~~7 ~~~~ ~~~~ ;~~~~~~~~~i9A<~~_~~s ", +" =~~~~~{'}~~~~~~~~~~[ ~~~~ ~~~ 8~~~~~~~~~~~~~_~_~~f ", +" &~~~~~~~_~~~~~~~~~~k ~~~ ~~~ [~~~~_~~~~~_~~~~~~~& ", +" c~~~~~~~~~~~~~~~~~~| ~~~~ ~~~ k~~~~~~~~~~~~~~~~~~2 ", +" B_~~~~~~~~~~~~~~~~~~ ~~~ ~~~ 3~~~~~~~~~~~~~~~~~~* ", +" B|~~~~~~~~~~~~~~~~~~ ~~~ ~~~ |~~~~~~~~~~~~~~~~~~[ ", +" a~~~~~~~~~~~~~~~~~~e~~~ ~~~ ~~~~~~~~~~~~~~~~~~~[ ", +" [_~~~~~~~~~~~~~~~~~~$|~~ ~~m~~~~~~~~~~~~~~~~~~~} ", +" |~~~~~~~~~~~~~~~~~~~ka~ ~~-~~~~~~~~~~~~~~~~_~_~* ", +" h~_~~~~~~~~~~~~~~~~~~f}~ ~|9~~~~~~~~~~~~~~~~~~~~~ ", +" |~~~~~~~~~~~~~~~~~~~~0)~ ~(*~~~~~~~~~~~~~~~~~~~~~= ", +" ^~~~~~~~~~~~~~~~~~~~~~qs_ ~if~~~~~~~~~~~~~~~~~~~~~} ", +" <~~~~~~~~~~~~~~~~~~~~_d3_ ~!q~~~~~~~~~~~~~~~~~~~~~! ", +" ]~~~~~~~~~~~~~~~~~~~~~{{_ ~~ ~~_~~~_~~~ ~{]~~~~~~~~~~~~~~~~~~~~~( ", +" h~~~~~~~~~~~~~~~~~~~__{s1 ~~~~~~~~~~~~~~~~~~~~~~~ ~:]~~~~~~~~~~~~~~~~~~~~~i ", +" &~~~~~~~~~~~~~~~~~~~~_i=~ ~~~~~~~~~~~1 _~~ _~~~~ _)0~~~~~~~~~~~~~~~~~~~~~i ", +" 2~~~~~~~~~~~~~~~~~~~~_|*~ ~~~ ~~ ~~ ~~~ _d:_~~~~~~~~~~~~~~~~~~~~} ", +" 9~~~~~~~~~~~~~~~~~~~~~~%_ ~~ ~~ ~~ ~~ _{d_~~~~~~~~~~~~~~~~~~~~{ ", +" n~~~~~~~~~~~~~~~~~~~~~~'~ ~~~ ~~ ~~~ ~~~ _fg~~~~~~~~~~~~~~~~~~~~~s ", +" C~~~~~~~~~~~~~~~~~~~~~~#~ ~~ ~~ ~~ ~~ ~[i_~~~~~~~~~~~~~~~~~~~~k ", +" D~~~~~~~~~~~~~~~~~~~~~~'(_ ~~ ~~ ~~ ~~ ~2~~~~~~~~~~~~~~~~~~~~~~k ", +" ~~~~~~~~~~~~~~~~~~~~~~fg~ ~~~ ~~~ ~~ ~~~ ~~*~~~~~~~~~~~~~~~~~~~~~~5 ", +" ~~~~~~~~~~~~~~~~~~~~_~)q~ ~~ ~~ ~~_ ~~ _~9~~~~~~~~~~~~~~~~~~~~~~B ", +" _~~~~~~~~~~~~~~~~~~~~_g&~~ ~~~ ~~~~~~~~ ~~~ _~7~__~~~~~~~~~~~~~~~~~~~l ", +" g~~~~~~~~~~~~~~~~~~~~_~8~~ ~~~ ~~~~~~~~ ~~ ~~i7~~~~~~~~~~~~~~~~~~~~~~> ", +" %~~~~~~~~~~~~~~~~~~~__~9~~~ ~~ ~~~~~~~ ~~~ ~~~ ]~~~~~~~~~~~~~~~~~~~~~~ ", +" '~~~~~~~~~~~~~~~~~~~~~~#~~~ ~~~ ~~ ~1 ~~~ ~~~ g~~~~~~~~~~~~~~~~~~~~~1 ", +" #~~~~~~~~~~~~~~~~~~~__~B|~~~ ~~~ ~~~~1 ~~~ ~~~ i~~~~~~~~~~~~~~~~~~~~~{ ", +" v~~~~~~~~~~~~~~~~~~~__~9 ~~~ ~~ ~~~~1 ~~~ ~~~ _~~~~~~~~~~~~~~~~~~~~~0 ", +" E~~~~~~~~~~~~~~~~~~~~~~{ ~~~ ~~~ ~~~~ ~~ ~~~~ F~~~~~~~~~~~~~~~~~~~~~~$ ", +" i_~~~~~~~~~~~~~~~~~~~~( ~~~ ~~ ~~~~ ~~~ ~~~ v~~~~~~~~~~~~~~~~~~~~~~G ", +" %~~~~~~~~~~~~~~~~~~~~~| ~~~~ ~~_~~~~1~~ ~~~ 8~_~~~~~~~~~~~~~~~~~~~{ ", +" 7~~~~~~~~~~~~~~~~~~~~~~ ~~~ _~~~~~~_~~ ~~~ 7~~~~~~~~~~~~~~~~~~_~_h ", +" g~~~~~~~~~~~~~~~~~~~~~4 ~~~~ ~~~~~~~~~~ ~~~ 2~_~~~~~~~~~~~~~~~~~~i ", +" y~_~~~~~~~~~~~~~~~~~~~9 ~~~ ~~~~~~~~~~_ ~~~ 0~~~~~~~~~~~~~~~~~~_~@ ", +" c~~~~~~~~~~~~~~~~~~~~9 ~~~~ ~~~ ~~_ ~~~ }~~~~~~~~~~~~~~~~~~~2 ", +" :~~~~~~~~~~~~~~~~~~~[ ~~~ ~~ __~ ~~_ ~~~ _~~~~~~~~~~~~~~~~~~~9 ", +" <~~_~~~~~~~~~~~~~~~~f ~~~~ ~~ ~i ~ ~~_ ~~~ _~~~~~~~~~_~~~~_~_~~~ ", +" 6~~__~__~~~~~~~~~~~~s ~~~ ~~~~~|~~~~ ~~~ 1~~~~~~~~~~_~~~1ki_3 ", +" 0sh2:~~~~~~~~~~~~~~: ~~~ ~~~~~~~~~~ ~~~ b_~~~~~~~~~~~~{5 7 ", +" v2!~~~~~~~~~~~3 ~~~ ~~__~~~~~~ ~~~ ~~~~~~~dsds#u ", +" >y+l'~~~~~_$ ~~~ ~~1 ~~~_~~ ~~ #___~~s ", +" 6diq09 ~~~ ~~1 ~ ~ ~~ ~~~ #$=[ ", +" _~~ ~~1 ~ ~ ~~ _~~ ", +" ~~ ~~_ ~ ~1~~ ~~_ ", +" ~~ ~~~ ~ ~ ~~ ~~_ ", +" ~~ ~~~ ~ ~ ~~ ~~_ ", +" ~~_ ~~~ ~ ~ ~~ ~~~ ", +" ~~~ _~~~ ~ ~ ~~ ~~~ ", +" ~~~~ 1~~ ~ ~ ~~ ~~~~ ", +" ~~~~~~~~~~_~~~~~~~_~~~~~~~ ", +" ~~~~~~~~~~~~~~~~~~~~~~~~~~ ", +" ~~~~~~~~~~~~~~~~~~~~~~_1 ", +" 6~~~~~~~~~~~~~~~~~~~~q ", +" ]~~~~~~~~~~~~~~~~~~~~q ", +" ~~~~~~~~~~~~~~~~~~~~~d ", +" B~~~~~~~~~~~~~~~~~~~~d ", +" #~~~~~~~~~~~~~~~~~~~_6 ", +" _~~~~~~~~~~~~~~~~~~~| ", +" _~~~~~~~~~~~~~~~~~~_6 ", +" ^_~~~~~~~~~~~~~~~~~~_% ", +" |~~~~~~~~~~~~_1~1~~~1 ", +" 1~~~~~~~~~~~~~~~~~~_& ", +" @_~~~~~~~~~~~~~~~~~~_% ", +" |~~~~~~~~~~~~~~~~~~~_ ", +" dggggggggggggggggggg% ", +" #_~~~~~~~~~~~~~~~~~~~' ", +" =~~~~~~~~~~~~~~__~~~1 ", +" f~~~~~~~~~~~~:a(1~~{ ", +" *~~~~~~~~~~~~~~~~] ", +" 71~~~~~~~~~~~~~q ", +" [_~~~~~~~~~~_9 ", +" 7~~~~~~~~~1h ", +" @~~~~~~~~0 ", +" j##h1]7B ", +" "}; diff --git a/Plugins/org.mitk.gui.qt.photoacousticsimulation/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.photoacousticsimulation/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..1032079a00 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacousticsimulation/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_mitk_gui_qt_photoacousticsimulation org.mitk.gui.qt.photoacousticsimulation + \ingroup MITKPlugins + + \brief Describe your plugin here. + +*/ + +/** + \defgroup org_mitk_gui_qt_photoacousticsimulation_internal Internal + \ingroup org_mitk_gui_qt_photoacousticsimulation + + \brief This subcategory includes the internal classes of the org.mitk.gui.qt.photoacousticsimulation plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/Plugins/org.mitk.gui.qt.photoacousticsimulation/files.cmake b/Plugins/org.mitk.gui.qt.photoacousticsimulation/files.cmake new file mode 100644 index 0000000000..5a8f60bb2b --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacousticsimulation/files.cmake @@ -0,0 +1,42 @@ +set(SRC_CPP_FILES + +) + +set(INTERNAL_CPP_FILES + org_mitk_gui_qt_photoacousticsimulation_Activator.cpp + PASimulator.cpp +) + +set(UI_FILES + src/internal/PASimulatorControls.ui +) + +set(MOC_H_FILES + src/internal/org_mitk_gui_qt_photoacousticsimulation_Activator.h + src/internal/PASimulator.h +) + +# list of resource files which can be used by the plug-in +# system without loading the plug-ins shared library, +# for example the icon used in the menu and tabs for the +# plug-in views in the workbench +set(CACHED_RESOURCE_FILES + resources/icon.xpm + plugin.xml +) + +# list of Qt .qrc files which contain additional resources +# specific to this plugin +set(QRC_FILES + +) + +set(CPP_FILES ) + +foreach(file ${SRC_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/${file}) +endforeach(file ${SRC_CPP_FILES}) + +foreach(file ${INTERNAL_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/internal/${file}) +endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.photoacousticsimulation/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.photoacousticsimulation/manifest_headers.cmake new file mode 100644 index 0000000000..4580c5bd1b --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacousticsimulation/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "Photoacousticsimulation") +set(Plugin-Version "0.1") +set(Plugin-Vendor "DKFZ") +set(Plugin-ContactAddress "") +set(Require-Plugin org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.photoacousticsimulation/plugin.xml b/Plugins/org.mitk.gui.qt.photoacousticsimulation/plugin.xml new file mode 100644 index 0000000000..c582f965b0 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacousticsimulation/plugin.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.photoacousticsimulation/resources/icon.xpm b/Plugins/org.mitk.gui.qt.photoacousticsimulation/resources/icon.xpm new file mode 100644 index 0000000000..d6b601c0af --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacousticsimulation/resources/icon.xpm @@ -0,0 +1,203 @@ +/* XPM */ +static char * icon_xpm[] = { +"128 128 72 1", +" c None", +". c #484848", +"+ c #2E2E2E", +"@ c #272727", +"# c #242424", +"$ c #202020", +"% c #171717", +"& c #1C1C1C", +"* c #1A1A1A", +"= c #191919", +"- c #222222", +"; c #292929", +"> c #404040", +", c #313131", +"' c #1B1B1B", +") c #0E0E0E", +"! c #070707", +"~ c #000000", +"{ c #0A0A0A", +"] c #111111", +"^ c #282828", +"/ c #2D2D2D", +"( c #050505", +"_ c #010101", +": c #0D0D0D", +"< c #151515", +"[ c #1E1E1E", +"} c #080808", +"| c #030303", +"1 c #020202", +"2 c #1D1D1D", +"3 c #0C0C0C", +"4 c #2F2F2F", +"5 c #181818", +"6 c #161616", +"7 c #232323", +"8 c #262626", +"9 c #212121", +"0 c #121212", +"a c #040404", +"b c #323232", +"c c #252525", +"d c #0B0B0B", +"e c #3C3C3C", +"f c #131313", +"g c #090909", +"h c #1F1F1F", +"i c #060606", +"j c #2C2C2C", +"k c #141414", +"l c #3A3A3A", +"m c #2A2A2A", +"n c #333333", +"o c #3B3B3B", +"p c #3D3D3D", +"q c #101010", +"r c #373737", +"s c #0F0F0F", +"t c #3E3E3E", +"u c #343434", +"v c #353535", +"w c #414141", +"x c #383838", +"y c #303030", +"z c #393939", +"A c #424242", +"B c #2B2B2B", +"C c #454545", +"D c #3F3F3F", +"E c #4D4D4D", +"F c #4B4B4B", +"G c #363636", +" ", +" .+@#$%&*=-;> ", +" ,')!~~~~~~~~~~~~~{]^ ", +" /*](~~~~~~~~~__~~~~_~~~~_:<[ ", +" ^}|~_~~~~___~~~__~~~_~~_~~~~~11* ", +" ^!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~2 ", +" '3~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~(% ", +" 4!_~~~_~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~_~~~15 ", +" -~~~~_~~~~~~~~_(!}65&[7892&0}}a_~~~~~~~~~~~~~{b ", +" +)~~~~~~_~~~~~3'$ c$d~~~~~~~~~~~~~6 ", +" c~~~~~~~~~~~1[e ef_~~~~~~~~~~~g ", +" h~~_~~~~~~~}2 f!_~~~~~~~~~1 ", +" %_~~~~~~~~38 -i~~_~~~~~~(j ", +" k~~~~~~~~~7 [~~_~~~~~~_b ", +" =~~~~~~~_3l @g~~~~~~~~~m ", +" ;1~_~~~~~9 &_~~~~~~~( ", +" e_~~~~~~1n b1~~~~~~~a ", +" i~~~~~~{o p{~_~~~~~} ", +" f~~~~~~: q~~~~~_~k ", +" ,~~~~~~: q~~~~~_~/ ", +" !~~~~~g 0~~~~~~i ", +" <~~~~~|o :~~~~~~6 ", +" |~~~~~r (~~~~~1 ", +" 6~~~~~& g~~~~~] ", +" (~~~~! 4a_~~_1r ", +" 2~~~~~j h~~~~~s ", +" ~~~~~2 k~~~~~t ", +" *~~~~{ g~~~~s ", +" a~~~~7 8_~_~| ", +" a~~~! 3~~__2 ", +" *~~~~2 u~~~~!q@ ", +" q~~~~~1 _~_~~_( ", +" i~_~~~~, [~~~~~_| ", +" a~~~~~~& &~~~~_~18 ", +" c_~~~~~~v >~~~~~_~5 ", +" h_~~~~~~ |_~~_~~f ", +" k_~__~~) 5~~_~~_( ", +" d~~_~~~h ^~_~~~~1 ", +" 51_~~~~, w~~~~~|7 ", +" %~~{q) ^9/{~! ", +" d~| =~( ", +" i~} _11_1_ '~a ", +" !~d ~~~~~~~~~~~~~~~~~ ;_| ", +" !~] ~~~~~~~~~~~~~~~~~~~~~ /11 ", +" i~< i~~~~~~~ ~~~~~~~~ x11# ", +" i~5 ~~~~~~ ~~~~~~ w11 ", +" |_* ~~~~~~~ ~~~~~~ t11 ", +" a~' ~~~~~~ ~~~~ y11+ ", +" 9-y1~* z@ ~~~~~ ~~~a 8:<-u j1~3}i7 ", +" $~~~~~5 61~~_# ~~~~~ ~~~~ 6~~~~~% h_~~_~d ", +" 6~_~_~5 f~~~_~~w ~~~~ ~~~~ ~~~~~~_n '~~~~~} ", +" =~~_~_5 i~~~~~~4 ~~~~ ~~~~ A~~~~~~~[ %~___~) ", +" *~~~~~5 b@'~__~~~~7 ~~~~ ~~~~ ;~~~~~~~~~i9A<~~_~~s ", +" =~~~~~{'}~~~~~~~~~~[ ~~~~ ~~~ 8~~~~~~~~~~~~~_~_~~f ", +" &~~~~~~~_~~~~~~~~~~k ~~~ ~~~ [~~~~_~~~~~_~~~~~~~& ", +" c~~~~~~~~~~~~~~~~~~| ~~~~ ~~~ k~~~~~~~~~~~~~~~~~~2 ", +" B_~~~~~~~~~~~~~~~~~~ ~~~ ~~~ 3~~~~~~~~~~~~~~~~~~* ", +" B|~~~~~~~~~~~~~~~~~~ ~~~ ~~~ |~~~~~~~~~~~~~~~~~~[ ", +" a~~~~~~~~~~~~~~~~~~e~~~ ~~~ ~~~~~~~~~~~~~~~~~~~[ ", +" [_~~~~~~~~~~~~~~~~~~$|~~ ~~m~~~~~~~~~~~~~~~~~~~} ", +" |~~~~~~~~~~~~~~~~~~~ka~ ~~-~~~~~~~~~~~~~~~~_~_~* ", +" h~_~~~~~~~~~~~~~~~~~~f}~ ~|9~~~~~~~~~~~~~~~~~~~~~ ", +" |~~~~~~~~~~~~~~~~~~~~0)~ ~(*~~~~~~~~~~~~~~~~~~~~~= ", +" ^~~~~~~~~~~~~~~~~~~~~~qs_ ~if~~~~~~~~~~~~~~~~~~~~~} ", +" <~~~~~~~~~~~~~~~~~~~~_d3_ ~!q~~~~~~~~~~~~~~~~~~~~~! ", +" ]~~~~~~~~~~~~~~~~~~~~~{{_ ~~ ~~_~~~_~~~ ~{]~~~~~~~~~~~~~~~~~~~~~( ", +" h~~~~~~~~~~~~~~~~~~~__{s1 ~~~~~~~~~~~~~~~~~~~~~~~ ~:]~~~~~~~~~~~~~~~~~~~~~i ", +" &~~~~~~~~~~~~~~~~~~~~_i=~ ~~~~~~~~~~~1 _~~ _~~~~ _)0~~~~~~~~~~~~~~~~~~~~~i ", +" 2~~~~~~~~~~~~~~~~~~~~_|*~ ~~~ ~~ ~~ ~~~ _d:_~~~~~~~~~~~~~~~~~~~~} ", +" 9~~~~~~~~~~~~~~~~~~~~~~%_ ~~ ~~ ~~ ~~ _{d_~~~~~~~~~~~~~~~~~~~~{ ", +" n~~~~~~~~~~~~~~~~~~~~~~'~ ~~~ ~~ ~~~ ~~~ _fg~~~~~~~~~~~~~~~~~~~~~s ", +" C~~~~~~~~~~~~~~~~~~~~~~#~ ~~ ~~ ~~ ~~ ~[i_~~~~~~~~~~~~~~~~~~~~k ", +" D~~~~~~~~~~~~~~~~~~~~~~'(_ ~~ ~~ ~~ ~~ ~2~~~~~~~~~~~~~~~~~~~~~~k ", +" ~~~~~~~~~~~~~~~~~~~~~~fg~ ~~~ ~~~ ~~ ~~~ ~~*~~~~~~~~~~~~~~~~~~~~~~5 ", +" ~~~~~~~~~~~~~~~~~~~~_~)q~ ~~ ~~ ~~_ ~~ _~9~~~~~~~~~~~~~~~~~~~~~~B ", +" _~~~~~~~~~~~~~~~~~~~~_g&~~ ~~~ ~~~~~~~~ ~~~ _~7~__~~~~~~~~~~~~~~~~~~~l ", +" g~~~~~~~~~~~~~~~~~~~~_~8~~ ~~~ ~~~~~~~~ ~~ ~~i7~~~~~~~~~~~~~~~~~~~~~~> ", +" %~~~~~~~~~~~~~~~~~~~__~9~~~ ~~ ~~~~~~~ ~~~ ~~~ ]~~~~~~~~~~~~~~~~~~~~~~ ", +" '~~~~~~~~~~~~~~~~~~~~~~#~~~ ~~~ ~~ ~1 ~~~ ~~~ g~~~~~~~~~~~~~~~~~~~~~1 ", +" #~~~~~~~~~~~~~~~~~~~__~B|~~~ ~~~ ~~~~1 ~~~ ~~~ i~~~~~~~~~~~~~~~~~~~~~{ ", +" v~~~~~~~~~~~~~~~~~~~__~9 ~~~ ~~ ~~~~1 ~~~ ~~~ _~~~~~~~~~~~~~~~~~~~~~0 ", +" E~~~~~~~~~~~~~~~~~~~~~~{ ~~~ ~~~ ~~~~ ~~ ~~~~ F~~~~~~~~~~~~~~~~~~~~~~$ ", +" i_~~~~~~~~~~~~~~~~~~~~( ~~~ ~~ ~~~~ ~~~ ~~~ v~~~~~~~~~~~~~~~~~~~~~~G ", +" %~~~~~~~~~~~~~~~~~~~~~| ~~~~ ~~_~~~~1~~ ~~~ 8~_~~~~~~~~~~~~~~~~~~~{ ", +" 7~~~~~~~~~~~~~~~~~~~~~~ ~~~ _~~~~~~_~~ ~~~ 7~~~~~~~~~~~~~~~~~~_~_h ", +" g~~~~~~~~~~~~~~~~~~~~~4 ~~~~ ~~~~~~~~~~ ~~~ 2~_~~~~~~~~~~~~~~~~~~i ", +" y~_~~~~~~~~~~~~~~~~~~~9 ~~~ ~~~~~~~~~~_ ~~~ 0~~~~~~~~~~~~~~~~~~_~@ ", +" c~~~~~~~~~~~~~~~~~~~~9 ~~~~ ~~~ ~~_ ~~~ }~~~~~~~~~~~~~~~~~~~2 ", +" :~~~~~~~~~~~~~~~~~~~[ ~~~ ~~ __~ ~~_ ~~~ _~~~~~~~~~~~~~~~~~~~9 ", +" <~~_~~~~~~~~~~~~~~~~f ~~~~ ~~ ~i ~ ~~_ ~~~ _~~~~~~~~~_~~~~_~_~~~ ", +" 6~~__~__~~~~~~~~~~~~s ~~~ ~~~~~|~~~~ ~~~ 1~~~~~~~~~~_~~~1ki_3 ", +" 0sh2:~~~~~~~~~~~~~~: ~~~ ~~~~~~~~~~ ~~~ b_~~~~~~~~~~~~{5 7 ", +" v2!~~~~~~~~~~~3 ~~~ ~~__~~~~~~ ~~~ ~~~~~~~dsds#u ", +" >y+l'~~~~~_$ ~~~ ~~1 ~~~_~~ ~~ #___~~s ", +" 6diq09 ~~~ ~~1 ~ ~ ~~ ~~~ #$=[ ", +" _~~ ~~1 ~ ~ ~~ _~~ ", +" ~~ ~~_ ~ ~1~~ ~~_ ", +" ~~ ~~~ ~ ~ ~~ ~~_ ", +" ~~ ~~~ ~ ~ ~~ ~~_ ", +" ~~_ ~~~ ~ ~ ~~ ~~~ ", +" ~~~ _~~~ ~ ~ ~~ ~~~ ", +" ~~~~ 1~~ ~ ~ ~~ ~~~~ ", +" ~~~~~~~~~~_~~~~~~~_~~~~~~~ ", +" ~~~~~~~~~~~~~~~~~~~~~~~~~~ ", +" ~~~~~~~~~~~~~~~~~~~~~~_1 ", +" 6~~~~~~~~~~~~~~~~~~~~q ", +" ]~~~~~~~~~~~~~~~~~~~~q ", +" ~~~~~~~~~~~~~~~~~~~~~d ", +" B~~~~~~~~~~~~~~~~~~~~d ", +" #~~~~~~~~~~~~~~~~~~~_6 ", +" _~~~~~~~~~~~~~~~~~~~| ", +" _~~~~~~~~~~~~~~~~~~_6 ", +" ^_~~~~~~~~~~~~~~~~~~_% ", +" |~~~~~~~~~~~~_1~1~~~1 ", +" 1~~~~~~~~~~~~~~~~~~_& ", +" @_~~~~~~~~~~~~~~~~~~_% ", +" |~~~~~~~~~~~~~~~~~~~_ ", +" dggggggggggggggggggg% ", +" #_~~~~~~~~~~~~~~~~~~~' ", +" =~~~~~~~~~~~~~~__~~~1 ", +" f~~~~~~~~~~~~:a(1~~{ ", +" *~~~~~~~~~~~~~~~~] ", +" 71~~~~~~~~~~~~~q ", +" [_~~~~~~~~~~_9 ", +" 7~~~~~~~~~1h ", +" @~~~~~~~~0 ", +" j##h1]7B ", +" "}; diff --git a/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/PASimulator.cpp b/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/PASimulator.cpp new file mode 100644 index 0000000000..73a1745da6 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/PASimulator.cpp @@ -0,0 +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/PASimulator.h b/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/PASimulator.h new file mode 100644 index 0000000000..0983f3692f --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/PASimulator.h @@ -0,0 +1,78 @@ +/*=================================================================== + +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 PASimulator_h +#define PASimulator_h + +#include + +#include + +#include "ui_PASimulatorControls.h" + +#include "mitkPhotoacousticTissueGenerator.h" +#include "mitkPhotoacousticTissueGeneratorParameters.h" +#include "mitkPhotoacousticVolume.h" +#include "mitkPhotoacousticPropertyCalculator.h" + + +/** + \brief PASimulator + + \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. + + \sa QmitkAbstractView + \ingroup ${plugin_target}_internal +*/ +class PASimulator : public QmitkAbstractView +{ + // this is needed for all Qt objects that should have a Qt meta-object + // (everything that derives from QObject and wants to have signal/slots) + Q_OBJECT + + public: + + static const std::string VIEW_ID; + + protected slots: + + /// \brief Called when the user clicks the GUI button + void DoImageProcessing(); + void ClickedGaussBox(); + void ClickedCheckboxFixedSeed(); + void ClickedRandomizePhysicalParameters(); + void OpenFolder(); + void OpenBinary(); + void UpdateVisibilityOfBatchCreation(); + void UpdateParametersAccordingToWavelength(); + + protected: + + virtual void CreateQtPartControl(QWidget *parent) override; + + virtual void SetFocus() override; + + Ui::PASimulatorControls m_Controls; + + mitk::PhotoacousticPropertyCalculator::Pointer m_PhotoacousticPropertyCalculator; + + private: + + +}; + +#endif // PASimulator_h diff --git a/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/PASimulatorControls.ui b/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/PASimulatorControls.ui new file mode 100644 index 0000000000..4a7f6608cb --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/PASimulatorControls.ui @@ -0,0 +1,5069 @@ + + + PASimulatorControls + + + + 0 + 0 + 433 + 655 + + + + + 0 + 0 + + + + + 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 + + + 1 + + + + + + + + 0 + 25 + + + + + 16777215 + 25 + + + + to + + + + + + + + 0 + 25 + + + + + 16777215 + 25 + + + + The maximum number of blood vessels + + + 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 + + + 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 + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/org_mitk_gui_qt_photoacousticsimulation_Activator.cpp b/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/org_mitk_gui_qt_photoacousticsimulation_Activator.cpp new file mode 100644 index 0000000000..397fe254f5 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/org_mitk_gui_qt_photoacousticsimulation_Activator.cpp @@ -0,0 +1,40 @@ +/*=================================================================== + +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 "org_mitk_gui_qt_photoacousticsimulation_Activator.h" + +#include + +#include "PASimulator.h" + +namespace mitk { + +void org_mitk_gui_qt_photoacousticsimulation_Activator::start(ctkPluginContext* context) +{ + BERRY_REGISTER_EXTENSION_CLASS(PASimulator, context) +} + +void org_mitk_gui_qt_photoacousticsimulation_Activator::stop(ctkPluginContext* context) +{ + Q_UNUSED(context) +} + +} + +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) + Q_EXPORT_PLUGIN2(org_mitk_gui_qt_photoacousticsimulation, mitk::org_mitk_gui_qt_photoacousticsimulation_Activator) +#endif diff --git a/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/org_mitk_gui_qt_photoacousticsimulation_Activator.h b/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/org_mitk_gui_qt_photoacousticsimulation_Activator.h new file mode 100644 index 0000000000..76472b6d88 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.photoacousticsimulation/src/internal/org_mitk_gui_qt_photoacousticsimulation_Activator.h @@ -0,0 +1,43 @@ +/*=================================================================== + +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 org_mitk_gui_qt_photoacousticsimulation_Activator_h +#define org_mitk_gui_qt_photoacousticsimulation_Activator_h + +#include + +namespace mitk { + +class org_mitk_gui_qt_photoacousticsimulation_Activator : + public QObject, public ctkPluginActivator +{ + Q_OBJECT +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_photoacousticsimulation") +#endif + Q_INTERFACES(ctkPluginActivator) + +public: + + void start(ctkPluginContext* context); + void stop(ctkPluginContext* context); + +}; // org_mitk_gui_qt_photoacousticsimulation_Activator + +} + +#endif // org_mitk_gui_qt_photoacousticsimulation_Activator_h