SceneGraph::TransformPtr VolumeCreateTool::CreateNode() { #ifdef SCENE_DEBUG_RUNTIME_DATA_SELECTION VolumePtr v = new Volume( s_Shape ); v->RectifyRuntimeData(); VolumePtr volume = new SceneGraph::Volume( m_Scene, v ); m_Scene->AddObject( volume ); { OS_SceneNodeDumbPtr selection; selection.push_back( volume ); m_Scene->GetSelection().SetItems( selection ); m_Scene->GetSelection().Clear(); } m_Scene->RemoveObject( volume ); return volume; #else VolumePtr volume = new Volume(); volume->SetOwner( m_Scene ); volume->SetShape( s_Shape ); return volume; #endif }
int addTrainingInstance(std::vector<DataInstance>& training_data, std::vector<int>& labels, const Instance& instance, const VolumePtr<short>& gt) { const VolumePtr<unsigned char>& mask = std::get<2>(instance); int width, height, depth; std::tie(width, height, depth) = getVolumeDimension<unsigned char>(mask); const std::array<double, 5> rate = { 0.05, 1.0, 1.0, 1.0, 1.0 }; int n_voxels = 0; for (int z = 0; z < depth; ++z) { for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { itk::Index<3> index; index[0] = x; index[1] = y; index[2] = z; if (mask->GetPixel(index) == 0) continue; const short label = gt->GetPixel(index); assert(label <= 4); const double p = (double)rand() / RAND_MAX; if (p > rate[label]) continue; training_data.push_back(DataInstance(instance, x, y, z)); labels.push_back(label); ++n_voxels; } } } return n_voxels; }
void sample() { ::fivox::URI uri = getURI(); // for compatibility if( _vm.count( "size" )) uri.addQuery( "size", std::to_string( _vm["size"].as< size_t >( ))); const ::fivox::URIHandler params( uri ); auto source = params.newImageSource< fivox::FloatVolume >(); const fivox::Vector3f& extent( source->getSizeInMicrometer( )); const size_t size( std::ceil( source->getSizeInVoxel().find_max( ))); const VolumeHandler volumeHandler( size, extent ); VolumePtr output = source->GetOutput(); output->SetRegions( volumeHandler.computeRegion( _decompose )); output->SetSpacing( volumeHandler.computeSpacing( )); const fivox::AABBf& bbox = source->getBoundingBox(); output->SetOrigin( volumeHandler.computeOrigin( bbox.getCenter( ))); ::fivox::EventSourcePtr loader = source->getEventSource(); const fivox::Vector2ui frameRange( getFrameRange( loader->getDt( ))); const std::string& datatype( _vm["datatype"].as< std::string >( )); if( datatype == "char" ) { LBINFO << "Sampling volume as char (uint8_t) data" << std::endl; _sample< uint8_t >( source, frameRange, params, _outputFile ); } else if( datatype == "short" ) { LBINFO << "Sampling volume as short (uint16_t) data" << std::endl; _sample< uint16_t >( source, frameRange, params, _outputFile ); } else if( datatype == "int" ) { LBINFO << "Sampling volume as int (uint32_t) data" << std::endl; _sample< uint32_t >( source, frameRange, params, _outputFile ); } else { LBINFO << "Sampling volume as floating point data" << std::endl; _sample< float >( source, frameRange, params, _outputFile ); } }
/** * Write a floating point 2D image containing the Voltage-Sensitive Dye * projection, using a Beer-Lambert projection filter. The projection filter * computes the output using the real value of the data, i.e. not limited by * the precision of the final image * * @param input 3d volume used as input to generate the 2D projection * @param filename name of the output image file */ void projectVSD( VolumePtr input, const std::string& filename ) { typedef BeerLambertProjectionImageFilter < fivox::FloatVolume, FloatImageType > FilterType; FilterType::Pointer projection = FilterType::New(); projection->SetInput( input ); projection->SetProjectionDimension( 1 ); // projection along Y-axis projection->SetPixelSize( input->GetSpacing( ).GetElement( 0 )); const double sigma = _vm["sigma"].as< double >(); projection->SetSigma( sigma ); // Write output image typedef itk::ImageFileWriter< FloatImageType > ImageWriter; ImageWriter::Pointer imageWriter = ImageWriter::New(); imageWriter->SetInput( projection->GetOutput( )); const std::string& imageFile = filename + ".vtk"; imageWriter->SetFileName( imageFile ); imageWriter->Update(); LBINFO << "VSD projection written as '" << imageFile << "' using a sigma value of " << sigma << std::endl; }
livre::MemoryUnitPtr sample( const livre::LODNode& node, const livre::VolumeInformation& info ) const { ::fivox::EventSourcePtr loader = source->getFunctor()->getSource(); const uint32_t frame = node.getNodeId().getFrame(); if( !loader->load( frame )) return livre::MemoryUnitPtr(); // Alloc voxels const vmml::Vector3i& voxels = info.maximumBlockSize; ByteVolume::SizeType vSize; vSize[0] = voxels[0]; vSize[1] = voxels[1]; vSize[2] = voxels[2]; ByteVolume::RegionType region; region.SetSize( vSize ); // Real-world coordinate setup const ::fivox::AABBf& bbox = loader->getBoundingBox(); const Vector3f& baseSpacing = ( bbox.getSize() + _borders ) / info.voxels; const int32_t levelFromBottom = info.rootNode.getDepth() - 1 - node.getRefLevel(); const float spacingFactor = 1 << levelFromBottom; ByteVolume::SpacingType spacing; spacing[0] = baseSpacing.find_max() * spacingFactor; spacing[1] = spacing[0]; spacing[2] = spacing[0]; const Vector3f& offset = ( bbox.getMin() - _borders / 2.0f ) + node.getRelativePosition() * Vector3f( bbox.getSize() + _borders ); ByteVolume::PointType origin; origin[0] = offset[0]; origin[1] = offset[1]; origin[2] = offset[2]; // called from multiple render threads, only have one update running lunchbox::ScopedWrite mutex( _lock ); VolumePtr output = source->GetOutput(); output->SetRegions( region ); output->SetSpacing( spacing ); output->SetOrigin( origin ); #ifdef LIVRE_DEBUG_RENDERING std::cout << "Sample " << node.getRefLevel() << ' ' << node.getRelativePosition() << " (" << spacing << " @ " << origin << 'x' << baseSpacing * spacingFactor * voxels << ")" << std::endl; #endif source->Modified(); source->Update(); livre::AllocMemoryUnitPtr memoryUnit( new livre::AllocMemoryUnit ); const size_t size = voxels[0] * voxels[1] * voxels[2] * info.compCount * info.getBytesPerVoxel(); memoryUnit->allocAndSetData( output->GetBufferPointer(), size ); return memoryUnit; }
void sample() { ::fivox::URI uri = getURI(); const size_t sensorRes( _vm["sensor-res"].as< size_t >( )); const size_t sensorDim( _vm["sensor-dim"].as< size_t >( )); const float resolution = (float)sensorDim / sensorRes; // the URI handler takes voxels/unit as resolution uri.addQuery( "resolution", std::to_string( 1 / resolution )); const ::fivox::URIHandler params( uri ); ImageSourcePtr source = params.newImageSource< fivox::FloatVolume >(); _eventSource = source->getEventSource(); std::shared_ptr< fivox::VSDLoader > vsdLoader = std::static_pointer_cast< fivox::VSDLoader >( _eventSource ); const float v0 = _vm["v0"].as< float >(); const float g0 = _vm["g0"].as< float >(); LBINFO << "VSD info: V0 = " << v0 << " mV; G0 = " << g0 << std::endl; vsdLoader->setRestingPotential( v0 ); vsdLoader->setAreaMultiplier( g0 ); if( _vm.count( "ap-threshold" )) { vsdLoader->setSpikeFilter( true ); const float apThreshold = _vm["ap-threshold"].as< float >(); LBINFO << "Action potential threshold set to " << apThreshold << " mV." << std::endl; vsdLoader->setApThreshold( apThreshold ); } if( _vm.count( "curve" )) { const std::string& curveFile = _vm["curve"].as< std::string >(); const float depth = _vm["depth"].as< float >(); const bool interpolate = _vm.count( "interpolate-attenuation" ); LBINFO << "Using '" << curveFile << "' as the dye curve file; " << "depth of " << depth << " micrometers. " << "Attenuation values will" << (!interpolate ? " not " :" ") << "be interpolated." << std::endl; const fivox::AttenuationCurve dye( curveFile, depth ); vsdLoader->setCurve( dye ); vsdLoader->setInterpolation( interpolate ); } const size_t size( std::ceil( source->getSizeInVoxel().find_max( ))); // crop the volume region to the specified sensor dimensions fivox::Vector3f extent( source->getSizeInMicrometer( )); extent[0] = sensorDim; extent[2] = sensorDim; const fivox::VolumeHandler volumeHandler( size, extent ); fivox::FloatVolume::IndexType vIndex; vIndex.Fill(0); fivox::FloatVolume::SizeType vSize; vSize[0] = extent[0] / resolution; vSize[1] = extent[1] / resolution; vSize[2] = extent[2] / resolution; VolumePtr output = source->GetOutput(); output->SetRegions( fivox::FloatVolume::RegionType( vIndex, vSize )); fivox::AABBf bboxSomas; const auto& somaPositions = vsdLoader->getSomaPositions(); for( const auto& position : somaPositions ) bboxSomas.merge( position ); // pixel/voxel size const auto spacing = volumeHandler.computeSpacing(); // left bottom corner of the image/volume const auto origin = volumeHandler.computeOrigin( bboxSomas.getCenter()); if( _vm.count( "soma-pixels" )) { const auto& fileName = _vm["soma-pixels"].as< std::string >(); std::ofstream file( fileName ); if( !file.is_open( )) LBERROR << "File " << fileName << " could not be opened" << std::endl; else { file << "# Soma position and corresponding pixel index for " "each cell, in the following format:\n" << "# gid [ posX posY posZ ]: i j\n" << "# File version: 1\n" << "# Fivox version: " << fivox::Version::getString() << std::endl; size_t i = 0; const auto& gids = vsdLoader->getGIDs(); for( const auto& gid : gids ) { if( file.bad( )) break; const auto& pos = somaPositions[i++]; file << gid << " " << pos << ": " << std::floor((pos[0] - origin[0]) / spacing[0]) << " " << std::floor((pos[2] - origin[2]) / spacing[1]) << std::endl; } } if( file.good( )) LBINFO << "Soma positions written as " << fileName << std::endl; else LBERROR << "Error while writing to " << fileName << std::endl; } output->SetSpacing( spacing ); output->SetOrigin( origin ); VolumeWriter< float > writer( output, fivox::Vector2ui( )); const fivox::Vector2ui frameRange( getFrameRange( _eventSource->getDt( ))); size_t numDigits = std::to_string( frameRange.y( )).length(); if( _vm.count( "times" )) { const float endTime = _vm["times"].as< fivox::Vector2f >()[1]; std::ostringstream s; s << std::fixed << std::setprecision(1) << endTime; numDigits = s.str().length(); } if( _vm.count( "export-point-sprites" )) { _writePointSpriteHeader(); _writePointSpritePositions(); } for( uint32_t i = frameRange.x(); i < frameRange.y(); ++i ) { std::string filename = _outputFile; if( frameRange.y() - frameRange.x() > 1 ) { // append the frame number if --frames, timestamp otherwise std::ostringstream os; os << filename << std::setfill('0') << std::setw( numDigits ); if( _vm.count( "times" )) os << std::fixed << std::setprecision(1) << i * vsdLoader->getDt(); else os << i; filename = os.str(); } _eventSource->setFrame( i ); source->Modified(); if( _vm.count( "export-volume" )) { const std::string& volumeName = filename + ".mhd"; writer->SetFileName( volumeName ); source->Modified(); writer->Update(); // Run pipeline to write volume LBINFO << "Volume written as " << volumeName << std::endl; } projectVSD( output, filename ); if( _vm.count( "export-point-sprites" )) _writePointSpriteIntensities( filename ); } }
int addInstance(const fs::path& instance_path, std::vector<VolumeVector<short>>& mrs, VolumeVector<unsigned char>& masks, VolumeVector<short>& gts, std::vector<std::vector<double>>& gmm_data, std::vector<int>& counts) { const fs::path flair_path(instance_path / fs::path("VSD.Brain.XX.O.MR_Flair")); const fs::path t1_path(instance_path / fs::path("VSD.Brain.XX.O.MR_T1")); const fs::path t1c_path(instance_path / fs::path("VSD.Brain.XX.O.MR_T1c")); const fs::path t2_path(instance_path / fs::path("VSD.Brain.XX.O.MR_T2")); const fs::path gt_path(instance_path / fs::path("VSD.Brain_3more.XX.XX.OT")); const vector<fs::path> volume_paths = { flair_path, t1_path, t1c_path, t2_path }; const VolumePtr<short> gt = readVolume<short>(findMHA(gt_path).string()); gts.push_back(gt); VolumeVector<short> volumes; int width, height, depth; std::tie(width, height, depth) = getVolumeDimension<short>(gt); for (const fs::path& p : volume_paths) { volumes.push_back(readVolume<short>(findMHA(p).string())); } mrs.push_back(volumes); const short lower_thres = 1; const VolumePtr<unsigned char> mask = createMask<short>(volumes[0], lower_thres); masks.push_back(mask); const std::array<double, 5> rate = { 0.01, 0.6, 0.1, 1.0, 0.3 }; int n_voxels = 0; for (int z = 0; z < depth; ++z) { for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { itk::Index<3> index; index[0] = x; index[1] = y; index[2] = z; if (mask->GetPixel(index) == 0) continue; ++n_voxels; const short label = gt->GetPixel(index); assert(label <= 4); ++counts[label]; const double p = (double)rand() / RAND_MAX; if (p > rate[label]) continue; for (int i = 0; i < 4; ++i) { const double v = static_cast<double>(volumes[i]->GetPixel(index)); gmm_data[label].push_back(v); } } } } return n_voxels; }