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 ); } }
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 ); } }