Ejemplo n.º 1
0
bool MainWindow::serverArgs(QStringList& args, QString& app)
{
	app = appPath(appConfig().synergysName(), appConfig().synergys());

	if (!QFile::exists(app))
	{
		if (QMessageBox::warning(this, tr("Synergy server not found"), tr("The executable for the synergy server does not exist. Do you want to browse for the synergy server now?"), QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
			return false;

		app = SettingsDialog::browseForSynergys(this, appConfig().synergyProgramDir(), appConfig().synergysName());

		if (app.isEmpty())
			return false;

		appConfig().setSynergys(app);
	}

	if (appConfig().logToFile())
	{
		appConfig().persistLogDir();
		args << "--log" << appConfig().logFilename();
	}

	args << "-c" << configFilename() << "--address" << address();

	return true;
}
Ejemplo n.º 2
0
void WINAPI ServiceMain( DWORD argc, LPSTR *argv )
{
	std::memset( &SPEPService::serviceStatus, 0, sizeof(SPEPService::serviceStatus) );
	SPEPService::serviceStatus.dwServiceType = SERVICE_WIN32;
	SPEPService::serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;

	SPEPService::updateStatus( SERVICE_START_PENDING );

	std::vector<saml2::Handler*> handlers;

	std::auto_ptr<spep::daemon::StreamLogHandler> logHandler;
	std::auto_ptr<std::ostream> stream;

	std::string logFilename;

	boost::program_options::variables_map configFileVariableMap;
	bool readConfig = false;

	// Open the registry to get the filename
	RegistryKey rKeySoftware( HKEY_LOCAL_MACHINE, REGISTRY_KEY_SOFTWARE, KEY_ENUMERATE_SUB_KEYS );
	if( rKeySoftware.valid() )
	{
		RegistryKey rKeyESOEProject( rKeySoftware, REGISTRY_KEY_ESOEPROJECT, KEY_ENUMERATE_SUB_KEYS );
		if( rKeyESOEProject.valid() )
		{
			RegistryKey rKeySPEP( rKeyESOEProject, REGISTRY_KEY_SPEP, KEY_READ );
			if( rKeySPEP.valid() )
			{
				std::string configFilename( rKeySPEP.queryValueString( "ConfigFile" ) );
				logFilename = ( rKeySPEP.queryValueString( "LogFile" ) );

				if( logFilename.length() != 0 )
				{
					stream.reset( new std::ofstream( logFilename.c_str() ) );
					logHandler.reset( new spep::daemon::StreamLogHandler( *stream, spep::DEBUG ) );

					handlers.push_back( logHandler.get() );
				}

				// Read the file
				std::ifstream configFileInput( configFilename.c_str() );

				if( configFileInput.good() )
				{
					parseConfig( configFileVariableMap, configFileInput, handlers );

					readConfig = true;
				}
				else
				{
					directLog( handlers, "The config file specified in the registry key doesn't exist." );
					return;
				}
			}
			else
			{
				directLog( handlers, "Couldn't open HKEY_LOCAL_MACHINE\Software\ESOE Project\SPEP" );
				return;
			}
		}
int main(int argc, char *argv[]) {
	if (argc < 3)
		return EXIT_FAILURE;
	std::string port(argv[1]);
	std::string configFilename(argv[2]);

	std::cout << "Welcome to Megaman 3 Server Edition" << std::endl;

	// Seed rand
	srand(time(NULL));

	Logger::getInstance().log(1, "Server starting...");

	Server server = Server(port, configFilename);
	server.run();

	Logger::getInstance().log(1, "Server quitting...");

	return EXIT_SUCCESS;
}
Ejemplo n.º 4
0
AppConfig* AppConfig::Instance()
{
	static AppConfig* instance = 0;
	if (!instance)
	{
		std::string configFilename(FileUtils::Join(
			Host::GetInstance()->GetApplication()->getPath().c_str(),
			CONFIG_FILENAME, 0));
		GetLogger()->Debug("Loading config file: %s", configFilename.c_str());
		if (!FileUtils::IsFile(configFilename))
		{
			GetLogger()->Critical("Cannot load config file: %s",
				configFilename.c_str());
			throw ValueException::FromFormat("Cannot load config file: %s",
				configFilename.c_str());
		}

		instance = new AppConfig(configFilename);
	}

	return instance;
}
Ejemplo n.º 5
0
//--------------------------------------------------------------------------------------------------
int main( int argc, char** argv )
{
    // Read in a configuration file
    if ( argc < 2 )
    {
        fprintf( stderr, "No configuration file provided\n" );
        showUsage( argv[ 0 ] );
        return -1;
    }

    initialiseTestPositions();

    //std::string configFilename = Utilities::getDataDir() + std::string( "/" ) + std::string( argv[ 1 ] );
    std::string configFilename( argv[ 1 ] );

    cv::FileStorage configFileStorage;
    configFileStorage.open( configFilename, cv::FileStorage::READ );

    if ( !configFileStorage.isOpened() )
    {
        fprintf( stderr, "Unable to open %s\n", configFilename.c_str() );
        return -1;
    }

    cv::Mat kinectDepthCameraPos;
    cv::Mat kinectDepthCameraRotXYZDeg;
    double kinectDepthFocalLengthPixel;
    int32_t kinectDepthImageWidth;
    int32_t kinectDepthImageHeight;

    cv::Mat kinectRGBCameraPos;
    cv::Mat kinectRGBCameraRotXYZDeg;
    double kinectRGBFocalLengthPixel;
    int32_t kinectRGBImageWidth;
    int32_t kinectRGBImageHeight;

    cv::Mat highResCameraPos;
    cv::Mat highResCameraRotXYZDeg;
    double highResFocalLengthPixel;
    int32_t highResImageWidth;
    int32_t highResImageHeight;

    // The camera poses are defined in a coordinate system with the Kinect depth camera at the
    // origin looking down the +ve z-axis, so z values increase into the image. The x and y axes
    // of the depth camera are aligned with its image plane, so +ve x points to its right, and
    // +ve y points down through the base of the camera. To position the camera in world space, it
    // is rotated 180 degrees about the z axis, the chessboard positions are defined in world space.

    configFileStorage[ "kinectDepthFocalLengthPixel" ] >> kinectDepthFocalLengthPixel;
    configFileStorage[ "kinectDepthImageWidth" ] >> kinectDepthImageWidth;
    configFileStorage[ "kinectDepthImageHeight" ] >> kinectDepthImageHeight;

    configFileStorage[ "kinectRGBCameraPos" ] >> kinectRGBCameraPos;
    configFileStorage[ "kinectRGBCameraRotXYZDeg" ] >> kinectRGBCameraRotXYZDeg;
    configFileStorage[ "kinectRGBFocalLengthPixel" ] >> kinectRGBFocalLengthPixel;
    configFileStorage[ "kinectRGBImageWidth" ] >> kinectRGBImageWidth;
    configFileStorage[ "kinectRGBImageHeight" ] >> kinectRGBImageHeight;

    configFileStorage[ "highResCameraPos" ] >> highResCameraPos;
    configFileStorage[ "highResCameraRotXYZDeg" ] >> highResCameraRotXYZDeg;
    configFileStorage[ "highResFocalLengthPixel" ] >> highResFocalLengthPixel;
    configFileStorage[ "highResImageWidth" ] >> highResImageWidth;
    configFileStorage[ "highResImageHeight" ] >> highResImageHeight;

    // Construct camera matrices
    cv::Mat zeroVec = cv::Mat::zeros( 3, 1, CV_64FC1 );
    cv::Mat kinectDepthCalibMtx = createCameraCalibrationMatrix(
        kinectDepthFocalLengthPixel, kinectDepthImageWidth, kinectDepthImageHeight );
    cv::Mat kinectDepthWorldMtx = createCameraWorldMatrix( zeroVec, zeroVec );

    cv::Mat kinectRGBCalibMtx = createCameraCalibrationMatrix(
        kinectRGBFocalLengthPixel, kinectRGBImageWidth, kinectRGBImageHeight );
    cv::Mat kinectRGBWorldMtx = createCameraWorldMatrix(
        kinectRGBCameraPos, kinectRGBCameraRotXYZDeg );

    cv::Mat highResCalibMtx = createCameraCalibrationMatrix(
        highResFocalLengthPixel, highResImageWidth, highResImageHeight );
    cv::Mat highResWorldMtx = createCameraWorldMatrix(
        highResCameraPos, highResCameraRotXYZDeg );

    // First generate calibration images for the high resolution camera
    for ( uint32_t testPosIdx = 0; testPosIdx < gHighResCalibrationPositions.size(); testPosIdx++ )
    {
        cv::Mat chessboardPoseMtx = createChessboardPoseMatrix( gHighResCalibrationPositions[ testPosIdx ] );

        // Generate an image from the high resolution camera
        cv::Mat highResRgbImage = generateRGBImageOfChessboard( highResWorldMtx, highResCalibMtx,
            highResImageWidth, highResImageHeight, chessboardPoseMtx );

        cv::imwrite( createOutputFilename( "chessboard_highres", testPosIdx + 1, ".png" ), highResRgbImage );
    }

    // Now generate images to identify the relative poses of the cameras
    for ( uint32_t testPosIdx = 0; testPosIdx < gRelativeCalibrationPositions.size(); testPosIdx++ )
    {
        cv::Mat chessboardPoseMtx = createChessboardPoseMatrix( gRelativeCalibrationPositions[ testPosIdx ] );

        // Generate a point cloud from the Kinect
        PointCloud::Ptr pCloud = generatePointCloudOfChessboard( kinectDepthWorldMtx, kinectDepthCalibMtx,
            kinectDepthImageWidth, kinectDepthImageHeight, chessboardPoseMtx );

        pCloud->saveToSpcFile( createOutputFilename( "relative_chessboard", testPosIdx + 1, ".spc" ), true );

        // Generate an image from the Kinect RGB camera
        cv::Mat rgbImage = generateRGBImageOfChessboard( kinectRGBWorldMtx, kinectRGBCalibMtx,
            kinectRGBImageWidth, kinectRGBImageHeight, chessboardPoseMtx );

        cv::imwrite( createOutputFilename( "relative_chessboard", testPosIdx + 1, ".png" ), rgbImage );

        // Generate an image from the high resolution camera
        cv::Mat highResRgbImage = generateRGBImageOfChessboard( highResWorldMtx, highResCalibMtx,
            highResImageWidth, highResImageHeight, chessboardPoseMtx );

        cv::imwrite( createOutputFilename( "relative_chessboard_highres", testPosIdx + 1, ".png" ), highResRgbImage );
    }

    // Generate ideal calibration files

    // First the kinect calibration
    cv::FileStorage dataFile( "kinect_calib.yaml", cv::FileStorage::WRITE );

    dataFile << "DepthCameraCalibrationMtx" << kinectDepthCalibMtx;
    dataFile << "ColorCameraCalibrationMtx" << kinectRGBCalibMtx;

    cv::Mat kinectRGBInKinectDepthSpace = (kinectDepthWorldMtx.inv())*kinectRGBWorldMtx;
    dataFile << "DepthToColorCameraRotation" << cv::Mat( kinectRGBInKinectDepthSpace, cv::Rect( 0, 0, 3, 3 ) );
    dataFile << "DepthToColorCameraTranslation" << cv::Mat( kinectRGBInKinectDepthSpace, cv::Rect( 3, 0, 1, 3 ) );

    dataFile.release();

    // Now the high resolution camera calibration
    dataFile = cv::FileStorage( "high_res_calib.yaml", cv::FileStorage::WRITE );
    dataFile << "cameraMatrix" << highResCalibMtx;
    dataFile.release();

    // Finally, the position of the high resolution colour camera in Kinect colour camera space
    dataFile = cv::FileStorage( "colour_stereo_calib.yaml", cv::FileStorage::WRITE );

    cv::Mat highResInKinectRGBSpace = (kinectRGBWorldMtx.inv())*highResWorldMtx;
    dataFile << "R" << cv::Mat( highResInKinectRGBSpace, cv::Rect( 0, 0, 3, 3 ) );
    dataFile << "T" << cv::Mat( highResInKinectRGBSpace, cv::Rect( 3, 0, 1, 3 ) );

    dataFile.release();

    //std::cout << kinectRGBWorldMtx << std::endl;
    //std::cout << highResWorldMtx << std::endl;
    //std::cout << highResInKinectRGBSpace << std::endl;

    return 0;
}
Ejemplo n.º 6
0
int main( int argc, char *argv[] )
{
//    try {

    time_t programStartTime(time(NULL) );
    boost::filesystem::path workingDir( boost::filesystem::current_path() );


    // ========== PROGRAM PARAMETERS ==========

    std::string progName( "buildrandctree" );
    std::string configFilename( "/home/raid2/moreno/Code/hClustering/config/"+progName+".cfg" );

    // program parameters
    std::string roiFilename, inputFolder, outputFolder;
    float memory( 0.5 ), maxNbDist( 1 );
    unsigned int nbLevel( 26 ), threads( 0 );
    bool keepDiscarded( false ), niftiMode( true ), debug( false );
    TC_GROWTYPE growType( TC_GROWOFF );
    size_t baseSize( 0 );

    // Declare a group of options that will be allowed only on command line
    boost::program_options::options_description genericOptions( "Generic options" );
    genericOptions.add_options()
    ( "version", "Program version" )
    ( "help,h", "Produce extended program help message" )
    ( "roi,r", boost::program_options::value< std::string >(&roiFilename), "file with the seed voxels coordinates." )
    ( "inputf,I",  boost::program_options::value< std::string >(&inputFolder), "input data folder (seed tractograms)." )
    ( "outputf,O",  boost::program_options::value< std::string >(&outputFolder), "output folder" )
    ( "maxnbdist,d",  boost::program_options::value< float >(&maxNbDist)->implicit_value(1), "[opt] maximum dissimilarity a seed voxel tract must have to its most similar neighbor not be discarded. (0,1]." )
    ( "cnbhood,c",  boost::program_options::value< unsigned int >(&nbLevel)->implicit_value(26), "[opt] centroid method neighborhood level. Valid values: 6, 18, 26(default), 32, 96, 124." )
    ( "basesize,S",  boost::program_options::value< size_t >(&baseSize), "[opt] grow homogeneous base nodes (meta-leaves) of size S. (>=2)." )
    ( "basenum,N",  boost::program_options::value< size_t >(&baseSize), "[opt] grow N homogeneous base nodes (meta-leaves). (>=10)." )
    ;

    // Declare a group of options that will be allowed both on command line and in config file
    boost::program_options::options_description configOptions( "Configuration" );
    configOptions.add_options()
    ( "verbose,v", "[opt] verbose output." )
    ( "vista", "[opt] use vista file format (default is nifti)." )
    ( "cache-mem,m",  boost::program_options::value< float >(&memory)->implicit_value(0.5), "[opt] maximum of memory (in GBytes) to use for tractogram cache memory. Default: 0.5." )
    ( "keep-disc,k", "[opt] keep discarded voxels data in a section of the tree file." )
    ( "debugout", "[opt] write additional detailed outputs meant for debug." )
    ( "pthreads,p",  boost::program_options::value< unsigned int >(&threads), "[opt] number of processing cores to run the program in. Default: all available." )
    ;

    // Hidden options, will be allowed both on command line and in config file, but will not be shown to the user.
    boost::program_options::options_description hiddenOptions( "Hidden options" );
    //hiddenOptions.add_options() ;

    boost::program_options::options_description cmdlineOptions;
    cmdlineOptions.add(genericOptions).add(configOptions).add(hiddenOptions);
    boost::program_options::options_description configFileOptions;
    configFileOptions.add(configOptions).add(hiddenOptions);
    boost::program_options::options_description visibleOptions( "Allowed options" );
    visibleOptions.add(genericOptions).add(configOptions);
    boost::program_options::positional_options_description posOpt; //this arguments do not need to specify the option descriptor when typed in
    //posOpt.add( "roi", -1);

    boost::program_options::variables_map variableMap;
    store(boost::program_options::command_line_parser(argc, argv).options(cmdlineOptions).positional(posOpt).run(), variableMap);

    std::ifstream ifs(configFilename.c_str() );
    store(parse_config_file(ifs, configFileOptions), variableMap);
    notify( variableMap);



    if ( variableMap.count( "help" ) )
    {
        std::cout << "---------------------------------------------------------------------------" << std::endl;
        std::cout << std::endl;
        std::cout << " Project: hClustering" << std::endl;
        std::cout << std::endl;
        std::cout << " Whole-Brain Connectivity-Based Hierarchical Parcellation Project" << std::endl;
        std::cout << " David Moreno-Dominguez" << std::endl;
        std::cout << " [email protected]" << std::endl;
        std::cout << " [email protected]" << std::endl;
        std::cout << " www.cbs.mpg.de/~moreno" << std::endl;
        std::cout << std::endl;
        std::cout << " For more reference on the underlying algorithm and research they have been used for refer to:" << std::endl;
        std::cout << " - Moreno-Dominguez, D., Anwander, A., & Knösche, T. R. (2014)." << std::endl;
        std::cout << "   A hierarchical method for whole-brain connectivity-based parcellation." << std::endl;
        std::cout << "   Human Brain Mapping, 35(10), 5000-5025. doi: http://dx.doi.org/10.1002/hbm.22528" << std::endl;
        std::cout << " - Moreno-Dominguez, D. (2014)." << std::endl;
        std::cout << "   Whole-brain cortical parcellation: A hierarchical method based on dMRI tractography." << std::endl;
        std::cout << "   PhD Thesis, Max Planck Institute for Human Cognitive and Brain Sciences, Leipzig." << std::endl;
        std::cout << "   ISBN 978-3-941504-45-5" << std::endl;
        std::cout << std::endl;
        std::cout << " hClustering is free software: you can redistribute it and/or modify" << std::endl;
        std::cout << " it under the terms of the GNU Lesser General Public License as published by" << std::endl;
        std::cout << " the Free Software Foundation, either version 3 of the License, or" << std::endl;
        std::cout << " (at your option) any later version." << std::endl;
        std::cout << " http://creativecommons.org/licenses/by-nc/3.0" << std::endl;
        std::cout << std::endl;
        std::cout << " hClustering is distributed in the hope that it will be useful," << std::endl;
        std::cout << " but WITHOUT ANY WARRANTY; without even the implied warranty of" << std::endl;
        std::cout << " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the" << std::endl;
        std::cout << " GNU Lesser General Public License for more details." << std::endl;
        std::cout << std::endl;
        std::cout << "---------------------------------------------------------------------------" << std::endl << std::endl;
        std::cout << "buildrandctree" << std::endl << std::endl;
        std::cout << "Build a centroid hierarchical tree from a set of artificially pre-generated set of tractograms yoielding a uniformly random similarity matrix and a seed neighborhood information voxel list." << std::endl << std::endl;
        std::cout << "* Arguments:" << std::endl << std::endl;
        std::cout << " --version:       Program version." << std::endl << std::endl;
        std::cout << " -h --help:       Produce extended program help message." << std::endl << std::endl;
        std::cout << " -r --roi:        A text file with the seed voxel coordinates and the corresponding tractogram index (if tractogram naming is based on index rather than coordinates)." << std::endl << std::endl;
        std::cout << " -I --inputf:     input data folder (containing the compact tractograms)." << std::endl << std::endl;
        std::cout << " -O --outputf:    Output folder where tree files will be written." << std::endl << std::endl;
        std::cout << "[-d --maxnbdist]: Maximum dissimilarity a seed voxel tract must have to its most similar neighbor not be discarded." << std::endl;
        std::cout << "                   Valid values: (0,1] Use a value of 1 (default) if no discarding is desired." << std::endl << std::endl;
        std::cout << "[-c --cnbhood]:   Use centroid method with C neighborhood level. Valid values: 6, 18, 24(default), 32, 96, 124." << std::endl << std::endl;
        std::cout << "[-S --basesize]:  Merge homogeneous base nodes of size S. (mutually exclusive with -N option). Default: 0 (no homogeneous merging)." << std::endl << std::endl;
        std::cout << "[-N --basenum]:   Grow N homogeneous base nodes. (mutually exclusive with -S option). Default: 0 (no homogeneous merging)." << std::endl << std::endl;
        std::cout << "[-v --verbose]:   Verbose output (recommended)." << std::endl << std::endl;
        std::cout << "[--vista]: 	    Read/write vista (.v) files [default is nifti (.nii) and compact (.cmpct) files]." << std::endl << std::endl;
        std::cout << "[-m --cache-mem]: Maximum amount of RAM memory (in GBytes) to use for temporal tractogram cache storing. Valid values [0.1,50]. Default: 0.5." << std::endl << std::endl;
        std::cout << "[-k --keep-disc]: Keep discarded voxel information in a specialiced section of the tree." << std::endl << std::endl;
        std::cout << "[--debugout]:     Write additional detailed outputs meant to be used for debugging." << std::endl << std::endl;
        std::cout << "[-p --pthreads]:  Number of processing threads to run the program in parallel. Default: use all available processors." << std::endl << std::endl;
        std::cout << std::endl;
        std::cout << "* Usage example:" << std::endl << std::endl;
        std::cout << " buildrandctree -r roi_lh.txt -I tractograms/ -O results/ -c 26 -N 1000 -k -m 2 -v " << std::endl << std::endl;
        std::cout << std::endl;
        std::cout << "* Outputs (in output folder defined at option -O):" << std::endl << std::endl;
        std::cout << " - 'cX_bin_nmt.txt' - (where X is the neighborhood level defined at option -c) non-monotonic binary-branching hierarchical tree without tree processing (if desired use processtree command)." << std::endl;
        std::cout << " - 'baselist_nmt.txt' - meta-leaves (base nodes defined by the us of option -N or -S) list with IDs corresponding to the non-monotonic tree file." << std::endl;
        std::cout << " - 'success.txt' - An empty file created when the program has sucessfully exited after completion (to help for automatic re-running scripting after failure)." << std::endl;
        std::cout << " - 'buildrandtree_log.txt' - A text log file containing the parameter details and in-run and completion information of the program." << std::endl;
        std::cout << std::endl;
        std::cout << " [extra outputs when using --debugout option)" << std::endl << std::endl;
        std::cout << " - 'cX_bin_nmt_debug.txt' - version of the counterpart file without '_debug' suffix with redundant information for debugging purposes." << std::endl;
        std::cout << std::endl;
        exit(0);
    }

    if ( variableMap.count( "verbose" ) ) {
        std::cout << "verbose output" << std::endl;
        verbose=true;
    }

    if ( variableMap.count( "pthreads" ) )
    {
        if ( threads == 1 )
        {
            std::cout << "Using a single processor" << std::endl;
        }
        else if( threads == 0 || threads >= omp_get_num_procs() )
        {
            threads = omp_get_num_procs();
            std::cout << "Using all available processors ( " << threads << " )." << std::endl;
        }
        else
        {
            std::cout << "Using a maximum of " << threads << " processors " << std::endl;
        }
        omp_set_num_threads( threads );
    }
    else
    {
        threads = omp_get_num_procs();
        omp_set_num_threads( threads );
        std::cout << "Using all available processors ( " << threads << " )." << std::endl;
    }

    if ( variableMap.count( "vista" ) )
    {
        if( verbose )
        {
            std::cout << "Using vista format" << std::endl;
        }
        fileManagerFactory fmf;
        fmf.setVista();
        niftiMode = false;
    }
    else
    {
        if( verbose )
        {
            std::cout << "Using nifti format" << std::endl;
        }
        fileManagerFactory fmf;
        fmf.setNifti();
        niftiMode = true;
    }

    if ( variableMap.count( "debugout" ) )
    {
        if( verbose )
        {
            std::cout << "Debug output files activated" << std::endl;
        }
        debug = true;
    }

    if ( variableMap.count( "version" ) )
    {
        std::cout << progName << ", version 2.0" << std::endl;
        exit(0);
    }

    if ( variableMap.count( "roi" ) )
    {
        if( !boost::filesystem::is_regular_file( boost::filesystem::path( roiFilename ) ) )
        {
            std::cerr << "ERROR: roi file \"" <<roiFilename<< "\" is not a regular file" << std::endl;
            std::cerr << visibleOptions << std::endl;
            exit(-1);
        }
        else if( verbose )
        {
            std::cout << "Seed voxels roi file: " << roiFilename << std::endl;
        }
    }
    else
    {
        std::cerr << "ERROR: no seed voxels roi file stated" << std::endl;
        std::cerr << visibleOptions << std::endl;
        exit(-1);
    }


    if( verbose )
    {
        std::cout << "Maximum distance to most similar neighbor: " << maxNbDist << std::endl;
    }

    if ( maxNbDist <= 0 || maxNbDist > 1 )
    {
        std::cerr << "ERROR: distance value used is out of bounds please use a value within (0,1]" << std::endl;
        std::cerr << visibleOptions << std::endl;
        exit(-1);
    }
    else if ( maxNbDist == 1 && verbose )
    {
        std::cout << "No neighbor distance restrictions will be applied" << std::endl;
    }
    else if( verbose )
    {
        std::cout << "Seed voxels with no neighbors with tract dissimilarity lower than " << maxNbDist << " will be discarded as outliers" << std::endl;
    }

    if( verbose )
    {
        std::cout << "Centroid neighborhood level: " << nbLevel << std::endl;
    }

    if ( ( nbLevel != 6 ) && ( nbLevel != 18 ) && ( nbLevel != 26 ) && ( nbLevel != 32 ) && ( nbLevel != 92 ) && ( nbLevel != 124 ) )
    {
        std::cerr << "ERROR: invalid nbhood level, only (6,18,26,32,92,124) are accepted" << std::endl;
        std::cerr << visibleOptions << std::endl;
        exit(-1);
    }

    if ( ( variableMap.count( "basesize" ) && variableMap.count( "basenum" ) ) )
    {
        std::cerr << "ERROR: options --basesize (-S) and --basenum (-N) are mutually exclusive" << std::endl;
        std::cerr << visibleOptions << std::endl;
        exit(-1);
    }
    if ( variableMap.count( "basesize" ) )
    {
        if( baseSize <= 1 )
        {
            std::cerr << "ERROR: base node (meta-leaf) size must be greater than 1" << std::endl;
            std::cerr << visibleOptions << std::endl;
            exit(-1);
        }
        else
        {
            if( verbose )
            {
                std::cout << "Initial merging stage up to homogeneous base nodes of size: " << baseSize << std::endl;
            }
            growType = TC_GROWSIZE;
        }
    }
    if ( variableMap.count( "basenum" ) )
    {
        if( baseSize < 10 )
        {
            std::cerr << "ERROR: base node (meta-leaf) number must be equal or greater than 10" << std::endl;
            std::cerr << visibleOptions << std::endl;
            exit(-1);
        }
        else
        {
            if( verbose )
            {
                std::cout << "Initial merging stage up to " << baseSize << " homogeneous base nodes (meta-leaves)" << std::endl;
            }
            growType = TC_GROWNUM;
        }
    }

    if( growType == TC_GROWOFF && verbose )
    {
        std::cout << "No homogeneous merging stage" << std::endl;
    }

    if ( variableMap.count( "keep-disc" ) )
    {
        if( verbose )
        {
            std::cout << "Discarded voxel coordinates will be saved in an special section fo the tree file" << std::endl;
        }
        keepDiscarded = true;
    }
    else
    {
        if( verbose )
        {
            std::cout << "Discarded voxel coordinates will not be saved" << std::endl;
        }
        keepDiscarded = false;
    }

    if ( variableMap.count( "inputf" ) )
    {
        if( !boost::filesystem::is_directory( boost::filesystem::path( inputFolder ) ) )
        {
            std::cerr << "ERROR: input seed tractogram folder \"" <<inputFolder<< "\" is not a directory" << std::endl;
            std::cerr << visibleOptions << std::endl;
            exit(-1);

        }
        else if( verbose )
        {
            std::cout << "Input seed tractogram folder: " << inputFolder << std::endl;
        }
    }
    else
    {
        std::cerr << "ERROR: no input seed tractogram stated" << std::endl;
        std::cerr << visibleOptions << std::endl;
        exit(-1);
    }

    if ( variableMap.count( "outputf" ) )
    {
        if( !boost::filesystem::is_directory( boost::filesystem::path( outputFolder ) ) )
        {
            std::cerr << "ERROR: output folder \"" <<outputFolder<< "\" is not a directory" << std::endl;
            std::cerr << visibleOptions << std::endl;
            exit(-1);

        }
        else if( verbose )
        {
            std::cout << "Output folder: " << outputFolder << std::endl;
        }
    }
    else
    {
        std::cerr << "ERROR: no output folder stated" << std::endl;
        std::cerr << visibleOptions << std::endl;
        exit(-1);
    }


    if ( memory < 0.1 || memory > 50)
    {
        std::cerr << "ERROR: cache size must be a positive float between 0.1 and 50 (GB)" << std::endl;
        std::cerr << visibleOptions << std::endl;
        exit(-1);
    }
    else if( verbose )
    {
        std::cout << "Tractogram cache memory: " << memory << " GBytes" << std::endl;
    }


    std::string logFilename(outputFolder+"/"+progName+"_log.txt" );
    std::ofstream logFile(logFilename.c_str() );
    if(!logFile)
    {
        std::cerr << "ERROR: unable to open log file: \"" <<logFilename<< "\"" << std::endl;
        exit(-1);
    }


    logFile << "Start Time:\t" << ctime(&programStartTime) << std::endl;
    logFile << "Working directory:\t" << workingDir.string() << std::endl;
    logFile << "Verbose:\t" << verbose << std::endl;
    logFile << "Processors used:\t" << threads << std::endl;
    if( niftiMode )
    {
        logFile << "Using nifti file format" << std::endl;
    }
    else
    {
        logFile << "Using vista file format" << std::endl;
    }
    logFile << "Vista mode flag:\t" << verbose << std::endl;
    logFile << "Roi file:\t" << roiFilename << std::endl;
    logFile << "Max nb distance:\t" << maxNbDist << std::endl;
    logFile << "Nbhood restriction level:\t" <<nbLevel<< std::endl;
    switch(growType)
    {
    case TC_GROWOFF:
        logFile << "Region growing: None" << std::endl;
        break;
    case TC_GROWSIZE:
        logFile << "Region growing: Size: " << baseSize << std::endl;
        break;
    case TC_GROWNUM:
        logFile << "Region growing: Number: " << baseSize << std::endl;
        break;
    }
    logFile << "Input seed tract folder:\t" << inputFolder << std::endl;
    logFile << "Output folder:\t" << outputFolder << std::endl;
    logFile << "Memory cache size:\t" << memory << " GB" << std::endl;
    logFile << "Debug outputr:\t" << debug << std::endl;
    logFile << "-------------" << std::endl;


    /////////////////////////////////////////////////////////////////


    randCnbTreeBuilder builder( roiFilename, verbose );

    logFile << "Roi size:\t" << builder.roiSize() << std::endl;
    builder.log( &logFile );
    builder.setInputFolder( inputFolder );
    builder.setOutputFolder( outputFolder );
    builder.setDebugOutput( debug );
    builder.buildRandCentroid( nbLevel, memory, growType, baseSize, keepDiscarded );


    /////////////////////////////////////////////////////////////////


    // save and print total time
    time_t programEndTime(time(NULL) );
    int totalTime( difftime(programEndTime,programStartTime) );
    std::cout << "Program Finished, total time: " << totalTime/3600 << "h " <<  (totalTime%3600)/60 << "' " << ((totalTime%3600)%60) << "\"   " << std::endl;
    logFile << "-------------" << std::endl;
    logFile << "Finish Time:\t" << ctime(&programEndTime) << std::endl;
    logFile << "Elapsed time : " << totalTime/3600 << "h " <<  (totalTime%3600)/60 << "' " << ((totalTime%3600)%60) << "\"" << std::endl;


    // create file that indicates process was finished successfully
    std::string successFilename(outputFolder+"/success.txt" );
    std::ofstream successFile(successFilename.c_str() );
    if(!successFile)
    {
        std::cerr << "ERROR: unable to create success file: \"" <<successFile<< "\"" << std::endl;
        exit(-1);
    }
    successFile << "success";


//    }
//    catch(std::exception& e)
//    {
//        std::cout << e.what() << std::endl;
//        return 1;
//    }
    return 0;
}
Ejemplo n.º 7
0
int main( int argc, char *argv[] )
{
//    try {

        time_t programStartTime(time(NULL));
        boost::filesystem::path workingDir( boost::filesystem::current_path());


        // ========== PROGRAM PARAMETERS ==========

        std::string progName("partitiontree");
        std::string configFilename("../../config/"+progName+".cfg");
        unsigned int threads(0), levelDepth(3), filterRadius(0);
        bool verbose(false), niftiMode( true );

        // program parameters
        std::string treeFilename, outputFolder;

        // Declare a group of options that will be allowed only on command line
        boost::program_options::options_description genericOptions("Generic options");
        genericOptions.add_options()
                ( "version", "Program version" )
                ( "help,h", "Produce extended program help message" )
                ( "tree,t",  boost::program_options::value< std::string >(&treeFilename), "file with the tree to compute partitions from")
                ( "outputf,O",  boost::program_options::value< std::string >(&outputFolder), "output folder where partition files will be written")
                ( "search-depth,d", boost::program_options::value< unsigned int >(&levelDepth)->implicit_value(3), "[opt] optimal partition search depth (default = 3)")
                ( "filter-radius,r", boost::program_options::value< unsigned int >(&filterRadius)->implicit_value(0), "[opt] output partition filter kernel radius (default = 0 | no filtering)")
                ( "hoz", "[opt] obtain horizontal cut partitions (instead of Spread-Separation ones)")
                ( "maxgran,m", "[opt] obtain only the maximum granularity partition")
                ;

        // Declare a group of options that will be allowed both on command line and in config file
        boost::program_options::options_description configOptions("Configuration");
        configOptions.add_options()
                ( "verbose,v", "[opt] verbose output." )
                ( "vista", "[opt] use vista file format (default is nifti)." )
                ( "pthreads,p",  boost::program_options::value< unsigned int >(&threads), "[opt] number of processing threads to run the program in parallel, default: all available")
                ;

        // Hidden options, will be allowed both on command line and in config file, but will not be shown to the user.
        boost::program_options::options_description hiddenOptions("Hidden options");
        //hiddenOptions.add_options() ;

        boost::program_options::options_description cmdlineOptions;
        cmdlineOptions.add(genericOptions).add(configOptions).add(hiddenOptions);
        boost::program_options::options_description configFileOptions;
        configFileOptions.add(configOptions).add(hiddenOptions);
        boost::program_options::options_description visibleOptions("Allowed options");
        visibleOptions.add(genericOptions).add(configOptions);
        boost::program_options::positional_options_description posOpt; //this arguments do not need to specify the option descriptor when typed in
        //posOpt.add("roi-file", -1);

        boost::program_options::variables_map variableMap;
        store(boost::program_options::command_line_parser(argc, argv).options(cmdlineOptions).positional(posOpt).run(), variableMap);

        std::ifstream ifs(configFilename.c_str());
        store(parse_config_file(ifs, configFileOptions), variableMap);
        notify(variableMap);


        if (variableMap.count("help"))
        {
            std::cout << "---------------------------------------------------------------------------" << std::endl;
            std::cout << std::endl;
            std::cout << " Project: hClustering" << std::endl;
            std::cout << std::endl;
            std::cout << " Whole-Brain Connectivity-Based Hierarchical Parcellation Project" << std::endl;
            std::cout << " David Moreno-Dominguez" << std::endl;
            std::cout << " [email protected]" << std::endl;
            std::cout << " [email protected]" << std::endl;
            std::cout << " www.cbs.mpg.de/~moreno" << std::endl;
            std::cout << std::endl;
            std::cout << " For more reference on the underlying algorithm and research they have been used for refer to:" << std::endl;
            std::cout << " - Moreno-Dominguez, D., Anwander, A., & Knösche, T. R. (2014)." << std::endl;
            std::cout << "   A hierarchical method for whole-brain connectivity-based parcellation." << std::endl;
            std::cout << "   Human Brain Mapping, 35(10), 5000-5025. doi: http://dx.doi.org/10.1002/hbm.22528" << std::endl;
            std::cout << " - Moreno-Dominguez, D. (2014)." << std::endl;
            std::cout << "   Whole-brain cortical parcellation: A hierarchical method based on dMRI tractography." << std::endl;
            std::cout << "   PhD Thesis, Max Planck Institute for Human Cognitive and Brain Sciences, Leipzig." << std::endl;
            std::cout << "   ISBN 978-3-941504-45-5" << std::endl;
            std::cout << std::endl;
            std::cout << " hClustering is free software: you can redistribute it and/or modify" << std::endl;
            std::cout << " it under the terms of the GNU Lesser General Public License as published by" << std::endl;
            std::cout << " the Free Software Foundation, either version 3 of the License, or" << std::endl;
            std::cout << " (at your option) any later version." << std::endl;
            std::cout << " http://creativecommons.org/licenses/by-nc/3.0" << std::endl;
            std::cout << std::endl;
            std::cout << " hClustering is distributed in the hope that it will be useful," << std::endl;
            std::cout << " but WITHOUT ANY WARRANTY; without even the implied warranty of" << std::endl;
            std::cout << " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the" << std::endl;
            std::cout << " GNU Lesser General Public License for more details." << std::endl;
            std::cout << std::endl;
            std::cout << "---------------------------------------------------------------------------" << std::endl << std::endl;
            std::cout << "partitiontree" << std::endl << std::endl;
            std::cout << "Obtain tree partitions at all granularity levels using the Spread-Separation method (finding the the partition with highest SS index at each granularity)." << std::endl;
            std::cout << " Optimal SS value for each partition is searched within a defined search-depth hierarchical levels. Final partitions can be filtered with a defined kernel size." << std::endl;
            std::cout << " to keep local SS maxima within that kernel. For SS index refer to (Moreno-Dominguez, 2014)" << std::endl;
            std::cout << " For an interactive 3D partition management with more options please use the Hierarchcial Clustering module developed in OpenWalnut (www.openwalnut.org)." << std::endl << std::endl;
            std::cout << "* Arguments:" << std::endl << std::endl;
            std::cout << " --version:       Program version." << std::endl << std::endl;
            std::cout << " -h --help:       produce extended program help message." << std::endl << std::endl;
            std::cout << " -t --tree:       File with the hierarchical tree to extract partitions from." << std::endl << std::endl;
            std::cout << " -O --outputf:    Output folder where partition files will be written." << std::endl << std::endl;
            std::cout << "[-d --search-depth]:  Search optimal partition for each granularity within d hierarchical levels." << std::endl;
            std::cout << "                       A higher value will produce more optimized partition but will increase computing time." << std::endl;
            std::cout << "                       Default: 3. Recommendened values: 3 for good quality and fast computation, 4 for enhanced quality." << std::endl << std::endl;
            std::cout << "[-r --filter-radius]: Filter output partitions to keep only local SS (partition quality) maxima" << std::endl;
            std::cout << "                       within a r-sized kernel across the granularity dimension." << std::endl << std::endl;
            std::cout << "[-h --hoz]:       Write horizontal cut partitions instead of SS ones (optimal partition search is still based on SS index)." << std::endl << std::endl;
            std::cout << "[-m --maxgran]:   Compute and write only the maximum granularity (meta-leaves) partition." << std::endl << std::endl;
            std::cout << "[-v --verbose]:   verbose output (recommended)." << std::endl << std::endl;
            std::cout << "[--vista]: 	    write output tree in vista coordinates (default is nifti)." << std::endl << std::endl;
            std::cout << "[-p --pthreads]:  number of processing threads to run the program in parallel. Default: use all available processors." << std::endl << std::endl;
            std::cout << std::endl;
            std::cout << "* Usage example:" << std::endl << std::endl;
            std::cout << " partitiontree -t tree_lh.txt -O results/ -d 3 -r 50 -v" << std::endl << std::endl;
            std::cout << std::endl;
            std::cout << "* Outputs (in output folder defined at option -O):" << std::endl << std::endl;
            std::cout << " (default outputs)" << std::endl;
            std::cout << " - 'allSSparts_dX.txt' - (where X is the search depth level defined at parameter -d) Contains a summary of the partition information (cut value and size) for all granularities." << std::endl;
            std::cout << " - 'TREE_SSparts_dX.txt' - (where TREE is the filename of the input tree defined at parameter -t) contains a copy of the original tree file with the partitions at all granularities included in the relevant fields." << std::endl;
            std::cout << " - 'partitiontree_log.txt' - A text log file containing the parameter details and in-run and completion information of the program." << std::endl;
            std::cout << std::endl;
            std::cout << " (additional if using option -r)" << std::endl;
            std::cout << " - 'filtSSparts_dX_rY.txt' - (where Y is the filter radius defined at parameter -r) Contains a summary of the resulting filtered partitions." << std::endl;
            std::cout << " - 'TREE_SSparts_dX_rY.txt' - contains a copy of the original tree file with the resulting filtered partitions included in the relevant fields." << std::endl;
            std::cout << std::endl;
            std::cout << " (when using --hoz option, the prefix 'SS' will be replaced by 'Hoz'')" << std::endl;
            std::cout << std::endl;
            std::cout << " (alternative outputs when using option --maxgran)" << std::endl;
            std::cout << " - 'fmaxgranPart.txt' - Contains the size information of the resulting maximal granularity partition for that tree." << std::endl;
            std::cout << " - 'TREE_maxgranPart.txt' - contains a copy of the original tree file with the resulting max granularity partition included in the relevant fields." << std::endl;
            std::cout << std::endl;
            exit(0);
        }
        if (variableMap.count("version"))
        {
            std::cout << progName <<", version 2.0"<<std::endl;
            exit(0);
        }
        if (variableMap.count("verbose"))
        {
            std::cout << "verbose output"<<std::endl;
            verbose=true;
        }

        if (variableMap.count("pthreads"))
        {
            if (threads==1)
            {
                std::cout <<"Using a single processor"<< std::endl;
            }
            else if(threads==0 || threads>=omp_get_num_procs())
            {
                threads = omp_get_num_procs();
                std::cout <<"Using all available processors ("<< threads <<")." << std::endl;
            }
            else
            {
                std::cout <<"Using a maximum of "<< threads <<" processors "<< std::endl;
            }
            omp_set_num_threads( threads );
        }
        else
        {
            threads = omp_get_num_procs();
            omp_set_num_threads( threads );
            std::cout <<"Using all available processors ("<< threads <<")." << std::endl;
        }

        if ( variableMap.count( "vista" ) )
        {
            if( verbose )
            {
                std::cout << "Using vista format" << std::endl;
            }
            fileManagerFactory fmf;
            fmf.setVista();
            niftiMode = false;
        }
        else
        {
            if( verbose )
            {
                std::cout << "Using nifti format" << std::endl;
            }
            fileManagerFactory fmf;
            fmf.setNifti();
            niftiMode = true;
        }

        if (variableMap.count("tree"))
        {
            if(!boost::filesystem::is_regular_file(boost::filesystem::path(treeFilename)))
            {
                std::cerr << "ERROR: tree file \""<<treeFilename<<"\" is not a regular file"<<std::endl;
                std::cerr << visibleOptions << std::endl;
                exit(-1);
            }
            std::cout << "Roi voxels file: "<< treeFilename << std::endl;
        }
        else
        {
            std::cerr << "ERROR: no tree file stated"<<std::endl;
            std::cerr << visibleOptions << std::endl;
            exit(-1);
        }


        if (variableMap.count("outputf"))
        {
            if(!boost::filesystem::is_directory(boost::filesystem::path(outputFolder)))
            {
                std::cerr << "ERROR: output folder \""<<outputFolder<<"\" is not a directory"<<std::endl;
                std::cerr << visibleOptions << std::endl;
                exit(-1);

            }
            std::cout << "Output folder: "<< outputFolder << std::endl;
        }
        else
        {
            std::cerr << "ERROR: no output folder stated"<<std::endl;
            std::cerr << visibleOptions << std::endl;
            exit(-1);

        }



        if (variableMap.count("maxgran"))
        {
            std::cout<<"Obtaining only max. granularity partition..."<<std::endl;

            WHtree tree(treeFilename);
            std::cout<<tree.getReport( false )<<std::endl;
            if( tree.testRootBaseNodes() )
            {
                std::vector<size_t > maxpart( tree.getRootBaseNodes() );
                std::vector<std::vector<size_t > > partitionVector( 1, maxpart);
                std::vector<float > partitionValues(1,0);
                std::cout<<"maxgranpart size: "<<std::endl<<maxpart.size()<<std::endl;
                WHtreePartition partitioner(&tree);
                std::string outPartFilename( outputFolder + "/maxgranPart.txt" );
                partitioner.writePartitionSet( outPartFilename, partitionValues,partitionVector);
                tree.insertPartitions( partitionVector, partitionValues );
                std::string outTreeFilename( outputFolder + "/" + tree.getName() + "_maxgranPart" );
                outTreeFilename += ( ".txt" );
                tree.writeTree( outTreeFilename, niftiMode );
                return 0;
            }
            else
            {
                std::cout<<"ERROR: tree  does not have a maximum granularity meta-leaf partition"<<std::endl;
                return(-1);
            }
        }

        if( levelDepth > 5 )
        {
            std::cout << "Level depth indicated: " << levelDepth << " is too high, setting to a maximum of 5" << std::endl;
            levelDepth = 5;
        }
        std::cout << "Using a search depth of: " << levelDepth << std::endl;

        if( filterRadius > 1000 )
        {
            std::cout << "filter radius indicated: " << filterRadius << " is too high (max is 1000), setting to 100" << std::endl;
            filterRadius = 10;
        }
        if( filterRadius == 0 )
        {
            std::cout << "using no filtering (radius 0)" << std::endl;
        }
        else if( filterRadius < 0 )
        {
            std::cout << "filter radius indicated: " << filterRadius << " must be positive. using no filtering (radius 0)" << std::endl;
            filterRadius = 0;
        }
        else
        {
            std::cout << "Using a filter radius of: " << filterRadius << std::endl;
        }

        /////////////////////////////////////////////////////////////////



        std::string logFilename(outputFolder+"/"+progName+"_log.txt");
        std::ofstream logFile(logFilename.c_str());
        if(!logFile) {
            std::cerr << "ERROR: unable to open log file: \""<<logFilename<<"\""<<std::endl;
            exit(-1);
        }
        logFile <<"Start Time:\t"<< ctime(&programStartTime) <<std::endl;
        logFile <<"Working directory:\t"<< workingDir.string() <<std::endl;
        logFile <<"Verbose:\t"<< verbose <<std::endl;
        logFile <<"Tree file:\t"<< treeFilename <<std::endl;
        logFile <<"Output folder:\t"<< outputFolder <<std::endl;
        logFile <<"Verbose:\t"<< verbose <<std::endl;
        if( niftiMode )
        {
            logFile << "Using nifti file format" << std::endl;
        }
        else
        {
            logFile << "Using vista file format" << std::endl;
        }

        WHtree tree(treeFilename);

        logFile << tree.getReport( false ) <<std::endl;
        std::cout<<tree.getReport( false )<<std::endl;

        std::vector< float > partitionValues;
        std::vector< std::vector< size_t> > partitionVector;

        WHtreePartition treePartition(&tree);

        std::string prefix;

        if (variableMap.count("hoz"))
        {
            prefix = "Hoz";
            std::cout <<"getting hoz partitions at all levels..." <<std::endl;
            treePartition.scanHozPartitions( &partitionValues, &partitionVector );

            std::cout << partitionValues.size() << " Partitions obtained, writing to file..." <<std::endl;
            logFile <<"Initial partitions:\t"<< partitionValues.size() <<std::endl;
            std::string outPartFilename( outputFolder + "/all" + prefix + "parts.txt" );
            treePartition.writePartitionSet( outPartFilename, partitionValues, partitionVector);

            tree.insertPartitions( partitionVector, partitionValues );
            std::string outTreeFilename( outputFolder + "/" + tree.getName() + "_" + prefix + "parts_d" + boost::lexical_cast<std::string>(levelDepth) );
            outTreeFilename += ( ".txt" );
            tree.writeTree( outTreeFilename, niftiMode );
        }
        else
        {

            prefix = "SS";
            std::cout <<"getting SS partitions at all levels..." <<std::endl;
            treePartition.scanOptimalPartitions( levelDepth, &partitionValues, &partitionVector );

            std::cout << partitionValues.size() << " Partitions obtained, writing to file..." <<std::endl;
            logFile <<"Initial partitions:\t"<< partitionValues.size() <<std::endl;
            std::string outPartFilename( outputFolder + "/all" + prefix + "parts_d" + boost::lexical_cast<std::string>(levelDepth) + ".txt" );
            treePartition.writePartitionSet( outPartFilename, partitionValues, partitionVector);

            tree.insertPartitions( partitionVector, partitionValues );
            std::string outTreeFilename( outputFolder + "/" + tree.getName() + "_" + prefix + "parts_d" + boost::lexical_cast<std::string>(levelDepth) );
            outTreeFilename += ( ".txt" );
            tree.writeTree( outTreeFilename, niftiMode );

        }


        std::vector < unsigned int > filterRadii;
        //filterRadii.reserve( 6 );
        //        filterRadii.push_back( 1 );
        //        filterRadii.push_back( 2 );
        //        filterRadii.push_back( 5 );
        //        filterRadii.push_back( 10 );
        //        filterRadii.push_back( 15 );
        //        filterRadii.push_back( 20 );
        filterRadii.push_back( filterRadius );



        for(size_t i=0; i< filterRadii.size(); ++i)
        {
            if( filterRadii[i] <= 0 )
            {
                continue;
            }
            std::vector< float > filtPartValues( partitionValues );
            std::vector< std::vector< size_t> > filtPartVector( partitionVector );

            std::cout << "Filtering with a radius of "<< filterRadii[i] << "..." <<std::endl;
            treePartition.filterMaxPartitions( filterRadii[i], &filtPartValues, &filtPartVector );

            std::cout << filtPartValues.size() << " Filtered partitions obtained, writing to file..." <<std::endl;
            logFile <<"Filtered partitions:\t"<< filtPartValues.size() <<std::endl;
            std::string outPartFilename( outputFolder + "/filt" + prefix + "parts_d" + boost::lexical_cast<std::string>(levelDepth) );
            outPartFilename += ( "_r" + boost::lexical_cast<std::string>(filterRadii[i]) +  ".txt" );
            treePartition.writePartitionSet(outPartFilename, filtPartValues, filtPartVector);

            std::cout << "Adding filtered partitions to tree and writing..." <<std::endl;

            std::string outTreeFilename( outputFolder + "/" + tree.getName() + "_" + prefix + "parts_d" + boost::lexical_cast<std::string>(levelDepth) );
            outTreeFilename += ( "_r" + boost::lexical_cast<std::string>(filterRadii[i]) +  ".txt" );

            tree.insertPartitions( filtPartVector, filtPartValues );
            tree.writeTree( outTreeFilename, niftiMode );
        }



        /////////////////////////////////////////////////////////////////


        // save and print total time
        time_t programEndTime(time(NULL));
        int totalTime( difftime(programEndTime,programStartTime) );
        std::cout <<"Program Finished, total time: "<< totalTime/3600 <<"h "<<  (totalTime%3600)/60 <<"' "<< ((totalTime%3600)%60) <<"\"   "<< std::endl;
        logFile <<"-------------"<<std::endl;
        logFile <<"Finish Time:\t"<< ctime(&programEndTime) <<std::endl;
        logFile <<"Elapsed time : "<< totalTime/3600 <<"h "<<  (totalTime%3600)/60 <<"' "<< ((totalTime%3600)%60) <<"\""<< std::endl;


//    }
//    catch(std::exception& e)
//    {
//        std::cout << e.what() << std::endl;
//        return 1;
//    }
    return 0;
}
Ejemplo n.º 8
0
//--------------------------------------------------------------------------------------------------
int main(int argc, char** argv)
{
    // Read in a configuration file
    if ( argc < 2 )
    {
        fprintf( stderr, "No configuration file provided\n" );
        showUsage( argv[ 0 ] );
        return -1;
    }

	std::cout << "Starting Camera Calibration" << std::endl;

	cv::Size boardSize; 
	cv::Size boardSizeMm;

	cv::Size imageSize;

	std::string cameraName;
	bool bUseDotPattern;

	std::string configFilename( argv[ 1 ] );
	std::vector<std::string> NameLocation = LoadConfig(
	    configFilename,&boardSize,&boardSizeMm,&cameraName,&bUseDotPattern);

	float squareWidth = ((float)boardSizeMm.width/1000.0f)/(boardSize.width-1);
	float squareHeight = ((float)boardSizeMm.height/1000.0f)/(boardSize.height-1);

	std::cout << squareWidth << "    " << squareHeight << std::endl;

	std::vector<cv::Point3f> objectCorners;

	//The points in the world coordinates 
	std::vector<std::vector<cv::Point3f>> objectPoints;

	//The points positions in pixels
	std::vector<std::vector<cv::Point2f>> imagePoints;

	//Camera output matrices
	cv::Mat cameraMatrix;
	cv::Mat distCoeffs;

	int successes = 0;

	//3D Scene Points
	//Initialize the chessboard corners
	//in the chessboard reference frame
	//The corners are at 3D location (x,y,z) = (i,j,0)
	for(int i=boardSize.height-1; i>=0; i--)
		for(int j=0; j<boardSize.width; j++)
			objectCorners.push_back(cv::Point3f(j*squareWidth,i*squareHeight,0.0f));

	for(int i = 0; i < (int)NameLocation.size(); i++)
	{
		std::string ImageAddress = NameLocation.at(i);
		std::cout << "Image Name " <<ImageAddress << std::endl;
		cv::Mat image,colorimage1,colorimage2;
		image =cv::imread(ImageAddress, CV_LOAD_IMAGE_GRAYSCALE);
		//colorimage1 =cv::imread(ImageAddress, CV_LOAD_IMAGE_COLOR);
		//colorimage2 =cv::imread(ImageAddress, CV_LOAD_IMAGE_COLOR);

		imageSize.height = image.rows;
		imageSize.width = image.cols;

		/*cv::imshow("Image",image);
		cv::waitKey();
		cv::destroyWindow("Image");*/

		// output vector of image points
		std::vector<cv::Point2f> imageCorners;

		// number of corners on the chessboard
		bool found = false;
		if ( !bUseDotPattern )
		{
		    found = cv::findChessboardCorners(image,boardSize,imageCorners);

		    if ( found )
		    {
                //cv::drawChessboardCorners(colorimage1,boardSize,imageCorners,found);

                //Get subpixel accuracy on the corners
                //cv::cornerSubPix(image,imageCorners,cv::Size(5,5),cv::Size(-1,-1),cv::TermCriteria(cv::TermCriteria::MAX_ITER + cv::TermCriteria::EPS,100,0.225));

                //cv::drawChessboardCorners(colorimage2,boardSize,imageCorners,found);
		    }
		}
		else
		{
		    printf( "Looking for circles...\n" );
		    //found = cv::findCirclesGrid(image,boardSize,imageCorners);


            BlobDetector::Params params;

            //params.minArea = 5.0;
            //params.minArea = 5.0;
            params.maxArea = 20000.0;
            //params.minCircularity = 0.5;
            //params.minDistBetweenBlobs = 1.0;
            //params.filterByCircularity = false;
            //params.filterByInertia = false;
            //params.filterByConvexity = false;
            //printf( "minDistBetweenBlobs is %f\n", params.min );


            cv::Ptr<cv::FeatureDetector> pDetector = new BlobDetector( params );

            found = findCirclesGridAB( image, boardSize, imageCorners,
                cv::CALIB_CB_SYMMETRIC_GRID, pDetector );



            if ( !found )
            {
            	cv::Mat scaled;

                float scale;
                if ( image.rows < 480 )
                {
                    scale = 2.0;
                }
                else
                {
                    scale = 0.25;
                }

            	cv::resize( image, scaled, cv::Size( 0, 0 ), scale, scale );

				found = findCirclesGridAB( scaled, boardSize, imageCorners,
					cv::CALIB_CB_SYMMETRIC_GRID, pDetector );
				std::cout << "Found " << imageCorners.size() << " corners" << std::endl;

				for ( uint32_t i = 0; i < imageCorners.size(); i++ )
				{
					imageCorners[ i ].x /= scale;
					imageCorners[ i ].y /= scale;
				}
            }

            /*cv::namedWindow("Corners", CV_WINDOW_NORMAL);
			cv::drawChessboardCorners(image,boardSize,imageCorners,found);
			cv::imshow( "Corners", image );
			cv::waitKey();*/

            //cv::destroyWindow("Corners");
		}

		if ( !found )
		{
		    printf( "Warning: Unable to find corners in %s\n", ImageAddress.c_str() );
		    continue;
		}

		//cv::drawChessboardCorners(colorimage1,boardSize,imageCorners,found);


		//If we have a good board, add it to our data
		if(imageCorners.size() == (uint32_t)boardSize.area())
		{
			//Add Image and scene points from one view
			imagePoints.push_back(imageCorners);
			objectPoints.push_back(objectCorners);
			std::cout << "Successfully found " << imageCorners.size() << " corners" << std::endl;
			successes++;
		}
		else
			std::cout << "Failed" << std::endl;

		//cv::resize(colorimage1,colorimage1,cv::Size(1024,768));
		//cv::resize(colorimage2,colorimage2,cv::Size(1024,768));
		//cv::imshow("Pre Sub Pixel",colorimage1);
		//cv::imshow("Post Sub Pixel",colorimage2);
		//cv::waitKey();
		//cv::destroyWindow("Pre Sub Pixel");
		//cv::destroyWindow("Post Sub Pixel");

	}

	std::vector<cv::Mat> rvecs,tvecs;

	cameraMatrix = cv::Mat::eye( 3, 3, CV_64F );
	cameraMatrix.at<double>( 0, 0 ) = 5458.0;
	cameraMatrix.at<double>( 1, 1 ) = 5458.0;
	cameraMatrix.at<double>( 0, 2 ) = 2272.0/2.0;
	cameraMatrix.at<double>( 1, 2 ) = 1704.0/2.0;
	distCoeffs = cv::Mat::zeros( 8, 1, CV_64F );

	std::cout << cv::calibrateCamera(
	    objectPoints,imagePoints,imageSize,cameraMatrix,distCoeffs,rvecs,tvecs,
	    	CV_CALIB_USE_INTRINSIC_GUESS
	    	//| CV_CALIB_FIX_PRINCIPAL_POINT
	    	//| CV_CALIB_FIX_ASPECT_RATIO
	        // | CV_CALIB_ZERO_TANGENT_DIST | CV_CALIB_FIX_K1 | CV_CALIB_FIX_K2 | CV_CALIB_FIX_K3
	        //| CV_CALIB_FIX_K4 | CV_CALIB_FIX_K5 | CV_CALIB_FIX_K6
	        )<< std::endl;

	cv::FileStorage fs((cameraName + "_cameraMatrix.yml").c_str(), cv::FileStorage::WRITE);
    fs << "cameraMatrix" << cameraMatrix;
	fs << "distCoeffs" << distCoeffs;

	std::cout << cameraMatrix << std::endl;

	std::cout << "Finished Camera Calibration" << std::endl;

	return 0;
}
Ejemplo n.º 9
0
int main( int argc, char *argv[] )
{
//    try {

        time_t programStartTime(time(NULL));
        boost::filesystem::path workingDir( boost::filesystem::current_path());


        // ========== PROGRAM PARAMETERS ==========

        std::string progName("cpcc");
        std::string configFilename("../../config/"+progName+".cfg");

        // program parameters
        std::string treeFilename;
        std::string distMatrixFolder;
        unsigned int threads(0);
        bool niftiMode( true );
        bool verbose(false);


        // Declare a group of options that will be allowed only on command line
        boost::program_options::options_description genericOptions("Generic options");
        genericOptions.add_options()
                ( "version", "Program version" )
                ( "help,h", "Produce extended program help message" )
                ( "tree,t",  boost::program_options::value< std::string >(&treeFilename), "file with the hierarchical tree to compute the cpcc value from")
                ( "inputf,I", boost::program_options::value< std::string >(&distMatrixFolder), "Input data folder with the distance matrix files.")
                ;

        // Declare a group of options that will be allowed both on command line and in config file
        boost::program_options::options_description configOptions("Configuration");
        configOptions.add_options()
                ( "verbose,v", "[opt] verbose output." )
                ( "vista", "[opt] use vista file format (default is nifti)." )
                ( "pthreads,p",  boost::program_options::value< unsigned int >(&threads), "[opt] number of processing cores to run the program in. Default: all available." )
                ;

        // Hidden options, will be allowed both on command line and in config file, but will not be shown to the user.
        boost::program_options::options_description hiddenOptions("Hidden options");
        //hiddenOptions.add_options() ;

        boost::program_options::options_description cmdlineOptions;
        cmdlineOptions.add(genericOptions).add(configOptions).add(hiddenOptions);
        boost::program_options::options_description configFileOptions;
        configFileOptions.add(configOptions).add(hiddenOptions);
        boost::program_options::options_description visibleOptions("Allowed options");
        visibleOptions.add(genericOptions).add(configOptions);
        boost::program_options::positional_options_description posOpt; //this arguments do not need to specify the option descriptor when typed in
        posOpt.add("tree", -1);

        boost::program_options::variables_map variableMap;
        store(boost::program_options::command_line_parser(argc, argv).options(cmdlineOptions).positional(posOpt).run(), variableMap);

        std::ifstream ifs(configFilename.c_str());
        store(parse_config_file(ifs, configFileOptions), variableMap);
        notify(variableMap);

        if (variableMap.count("help"))
        {
            std::cout << "---------------------------------------------------------------------------" << std::endl;
            std::cout << std::endl;
            std::cout << " Project: hClustering" << std::endl;
            std::cout << std::endl;
            std::cout << " Whole-Brain Connectivity-Based Hierarchical Parcellation Project" << std::endl;
            std::cout << " David Moreno-Dominguez" << std::endl;
            std::cout << " [email protected]" << std::endl;
            std::cout << " [email protected]" << std::endl;
            std::cout << " www.cbs.mpg.de/~moreno" << std::endl;
            std::cout << std::endl;
            std::cout << " For more reference on the underlying algorithm and research they have been used for refer to:" << std::endl;
            std::cout << " - Moreno-Dominguez, D., Anwander, A., & Knösche, T. R. (2014)." << std::endl;
            std::cout << "   A hierarchical method for whole-brain connectivity-based parcellation." << std::endl;
            std::cout << "   Human Brain Mapping, 35(10), 5000-5025. doi: http://dx.doi.org/10.1002/hbm.22528" << std::endl;
            std::cout << " - Moreno-Dominguez, D. (2014)." << std::endl;
            std::cout << "   Whole-brain cortical parcellation: A hierarchical method based on dMRI tractography." << std::endl;
            std::cout << "   PhD Thesis, Max Planck Institute for Human Cognitive and Brain Sciences, Leipzig." << std::endl;
            std::cout << "   ISBN 978-3-941504-45-5" << std::endl;
            std::cout << std::endl;
            std::cout << " hClustering is free software: you can redistribute it and/or modify" << std::endl;
            std::cout << " it under the terms of the GNU Lesser General Public License as published by" << std::endl;
            std::cout << " the Free Software Foundation, either version 3 of the License, or" << std::endl;
            std::cout << " (at your option) any later version." << std::endl;
            std::cout << " http://creativecommons.org/licenses/by-nc/3.0" << std::endl;
            std::cout << std::endl;
            std::cout << " hClustering is distributed in the hope that it will be useful," << std::endl;
            std::cout << " but WITHOUT ANY WARRANTY; without even the implied warranty of" << std::endl;
            std::cout << " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the" << std::endl;
            std::cout << " GNU Lesser General Public License for more details." << std::endl;
            std::cout << std::endl;
            std::cout << "---------------------------------------------------------------------------" << std::endl << std::endl;
            std::cout << "cpcc" << std::endl << std::endl;
            std::cout << "Compute the cophenetic correlation coefficient (Farris, 1969) of a hierarchical tree." << std::endl << std::endl;
            std::cout << "* Arguments:" << std::endl << std::endl;
            std::cout << " --version:       Program version." << std::endl << std::endl;
            std::cout << " -h --help:       produce extended program help message." << std::endl << std::endl;
            std::cout << " -t --tree:       File with the hierarchical tree to compute cpcc from." << std::endl << std::endl;
            std::cout << " -I --inputf:     Input data folder containing the blocks of the precomputed tract pairwise distance matrix." << std::endl << std::endl;
            std::cout << "[-v --verbose]:   verbose output (recommended)." << std::endl << std::endl;
            std::cout << "[--vista]: 	     read/write vista (.v) files [default is nifti (.nii) and compact (.cmpct) files]." << std::endl << std::endl;
            std::cout << "[-p --pthreads]:  number of processing threads to run the program in parallel. Default: use all available processors." << std::endl << std::endl;
            std::cout << std::endl;
            std::cout << "* Usage example:" << std::endl << std::endl;
            std::cout << " cpcc -t tree_lh.txt -I distBlocks/ -v" << std::endl << std::endl;
            std::cout << std::endl;
            std::cout << "* Outputs:" << std::endl << std::endl;
            std::cout << " - Introduces the cpcc value in the #cpcc field of the tree file defined at option -t." << std::endl;
            std::cout << std::endl;
            exit(0);
        }
        if (variableMap.count("version")) {
            std::cout << progName <<", version 2.0"<<std::endl;
            exit(0);
        }
        if (variableMap.count("verbose")) {
            std::cout << "verbose output"<<std::endl;
            verbose=true;
        }
        if (variableMap.count("pthreads"))
        {
            if (threads==1)
            {
                std::cout <<"Using a single processor"<< std::endl;
            }
            else if(threads==0 || threads>=omp_get_max_threads())
            {
                threads = omp_get_max_threads();
                std::cout <<"Using all available processors ("<< threads <<")." << std::endl;
            }
            else
            {
                std::cout <<"Using a maximum of "<< threads <<" processors "<< std::endl;
            }
            omp_set_num_threads( threads );
        }
        else
        {
            threads = omp_get_max_threads();
            omp_set_num_threads( threads );
            std::cout <<"Using all available processors ("<< threads <<")." << std::endl;
        }

        if (variableMap.count("tree")) {
            if(!boost::filesystem::is_regular_file(boost::filesystem::path(treeFilename))) {
                std::cerr << "ERROR: tree file \""<<treeFilename<<"\" is not a regular file"<<std::endl;
                std::cerr << visibleOptions << std::endl;
                exit(-1);
            }
            std::cout << "Input tree file: "<< treeFilename << std::endl;
        } else {
            std::cerr << "ERROR: no tree file stated"<<std::endl;
            std::cerr << visibleOptions << std::endl;
            exit(-1);
        }

        if (variableMap.count("inputf")) {
            if(!boost::filesystem::is_directory(boost::filesystem::path(distMatrixFolder))) {
                std::cerr << "ERROR: distance matrix folder \""<<distMatrixFolder<<"\" is not a directory"<<std::endl;
                std::cerr << visibleOptions << std::endl;
                exit(-1);
            }
            std::cout << "Distance matrix folder: "<< distMatrixFolder << std::endl;
        } else {
            std::cerr << "ERROR: no distance matrix folder stated"<<std::endl;
            std::cerr << visibleOptions << std::endl;
            exit(-1);
        }


        if ( variableMap.count( "vista" ) )
        {
            if( verbose )
            {
                std::cout << "Using vista format" << std::endl;
            }
            fileManagerFactory fmf;
            fmf.setVista();
            niftiMode = false;
        }
        else
        {
            if( verbose )
            {
                std::cout << "Using nifti format" << std::endl;
            }
            fileManagerFactory fmf;
            fmf.setNifti();
            niftiMode = true;
        }

        /////////////////////////////////////////////////////////////////

        WHtree tree(treeFilename);
        if (verbose)
        {
            std::cout<<tree.getReport()<<std::endl;
        }
        if( !tree.isLoaded() )
        {
            std::cerr << "Error while loading tree "<< std::endl;
            exit(-1);
        }

        treeManager treeMngr(&tree, verbose);



        treeMngr.setDistMatrixFolder(distMatrixFolder);
        float cpcc(treeMngr.doCpcc());

        tree.writeTree(treeFilename,niftiMode);

        std::cout<<std::endl<<std::endl<<"CPCC: "<< cpcc <<std::endl<<std::endl;

        /////////////////////////////////////////////////////////////////

        // save and print total time
        time_t programEndTime(time(NULL));
        int totalTime( difftime(programEndTime,programStartTime) );
        std::cout << "Program Finished, total time: " << totalTime/3600 <<"h "<<  (totalTime%3600)/60 <<"' "<< ((totalTime%3600)%60) <<"\""<< std::endl;



//    }
//    catch(std::exception& e)
//    {
//        std::cout << e.what() << std::endl;
//        return 1;
//    }
    return 0;
}
Ejemplo n.º 10
0
int main( int argc, char *argv[] )
{
//    try {
        time_t programStartTime(time(NULL));
        boost::filesystem::path workingDir( boost::filesystem::current_path());

        // ========== PROGRAM PARAMETERS ==========

        std::string progName("matchpartition");
        std::string configFilename("../../config/"+progName+".cfg");

        // program parameters
        std::string refTreeFilename, targetTreeFilename, matchTableFilename, outputFolder;
        unsigned int searchDepth(1);
        float lambda(0);
        bool signaturePart(false), colorMatching(false), overlapPart(false), exclusive(false);
        bool verbose(false), niftiMode( true );


        // Declare a group of options that will be allowed only on command line
        boost::program_options::options_description genericOptions("Generic options");
        genericOptions.add_options()
                ( "version", "Program version" )
                ( "help,h", "Produce extended program help message" )
                ( "reference,r",  boost::program_options::value< std::string >(&refTreeFilename), "file with reference partitioned tree" )
                ( "target,t",  boost::program_options::value< std::string >(&targetTreeFilename), "file with target tree to be partitioned-matched" )
                ( "leafmatch,m",  boost::program_options::value< std::string >(&matchTableFilename), "file with meta-leaves (base-nodes) matching table" )
                ( "outputf,O",  boost::program_options::value< std::string >(&outputFolder), "output folder where partition-matched trees will be written" )
                ( "signature,s",  boost::program_options::value< float >(&lambda), "[xor with -o and -c] Signature-based partition matching, inster lambda coefficient value" )
                ( "overlap,o", "[xor with -s and -c] Meta-leaf overlap-based partition matching")
                ( "depth,d", boost::program_options::value< unsigned int >(&searchDepth)->implicit_value(0), "[opt] partition search depth. Default: 0 (automatic partition-size based adaptive depth, recommended)")
                ( "justcolor,c",  "[xor with -s and -o] Perform only olor matching (requires pre-computed partitions in both trees)")
                ( "excl,x",  "[opt] color exclusively clusters that have a match, clusters without match will be white")
                ;

        // Declare a group of options that will be allowed both on command line and in config file
        boost::program_options::options_description configOptions("Configuration");
        configOptions.add_options()
                ( "verbose,v", "[opt] verbose output." )
                ( "vista", "[opt] Write output tree in vista coordinates (default is nifti)." )
                ;

        // Hidden options, will be allowed both on command line and in config file, but will not be shown to the user.
        boost::program_options::options_description hiddenOptions("Hidden options");
        //hiddenOptions.add_options() ;

        boost::program_options::options_description cmdlineOptions;
        cmdlineOptions.add(genericOptions).add(configOptions).add(hiddenOptions);
        boost::program_options::options_description configFileOptions;
        configFileOptions.add(configOptions).add(hiddenOptions);
        boost::program_options::options_description visibleOptions("Allowed options");
        visibleOptions.add(genericOptions).add(configOptions);
        boost::program_options::positional_options_description posOpt; //this arguments do not need to specify the option descriptor when typed in
        //posOpt.add("roi-file", -1);

        boost::program_options::variables_map variableMap;
        store(boost::program_options::command_line_parser(argc, argv).options(cmdlineOptions).positional(posOpt).run(), variableMap);

        std::ifstream ifs(configFilename.c_str());
        store(parse_config_file(ifs, configFileOptions), variableMap);
        notify(variableMap);

        if (variableMap.count( "help" ) )
        {
            std::cout << "---------------------------------------------------------------------------" << std::endl;
            std::cout << std::endl;
            std::cout << " Project: hClustering" << std::endl;
            std::cout << std::endl;
            std::cout << " Whole-Brain Connectivity-Based Hierarchical Parcellation Project" << std::endl;
            std::cout << " David Moreno-Dominguez" << std::endl;
            std::cout << " [email protected]" << std::endl;
            std::cout << " [email protected]" << std::endl;
            std::cout << " www.cbs.mpg.de/~moreno" << std::endl;
            std::cout << std::endl;
            std::cout << " For more reference on the underlying algorithm and research they have been used for refer to:" << std::endl;
            std::cout << " - Moreno-Dominguez, D., Anwander, A., & Knösche, T. R. (2014)." << std::endl;
            std::cout << "   A hierarchical method for whole-brain connectivity-based parcellation." << std::endl;
            std::cout << "   Human Brain Mapping, 35(10), 5000-5025. doi: http://dx.doi.org/10.1002/hbm.22528" << std::endl;
            std::cout << " - Moreno-Dominguez, D. (2014)." << std::endl;
            std::cout << "   Whole-brain cortical parcellation: A hierarchical method based on dMRI tractography." << std::endl;
            std::cout << "   PhD Thesis, Max Planck Institute for Human Cognitive and Brain Sciences, Leipzig." << std::endl;
            std::cout << "   ISBN 978-3-941504-45-5" << std::endl;
            std::cout << std::endl;
            std::cout << " hClustering is free software: you can redistribute it and/or modify" << std::endl;
            std::cout << " it under the terms of the GNU Lesser General Public License as published by" << std::endl;
            std::cout << " the Free Software Foundation, either version 3 of the License, or" << std::endl;
            std::cout << " (at your option) any later version." << std::endl;
            std::cout << " http://creativecommons.org/licenses/by-nc/3.0" << std::endl;
            std::cout << std::endl;
            std::cout << " hClustering is distributed in the hope that it will be useful," << std::endl;
            std::cout << " but WITHOUT ANY WARRANTY; without even the implied warranty of" << std::endl;
            std::cout << " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the" << std::endl;
            std::cout << " GNU Lesser General Public License for more details." << std::endl;
            std::cout << std::endl;
            std::cout << "---------------------------------------------------------------------------" << std::endl << std::endl;
            std::cout << "matchpartition" << std::endl << std::endl;
            std::cout << "Finds the best matching corresponding partitions in a target tree to those present in an unrelated reference tree (meta-leaf matching across these two trees must have been precomputed using comparetrees)." << std::endl;
            std::cout << " Two partition matching algorithms are available: signature matching and overlap matching. Found target partitions will be color-matched as best as possible." << std::endl;
            std::cout << " There is also the possibility of only color-matching predefined partitions of the target tree to predefined partitions of the reference tree." << std::endl << std::endl;
            std::cout << "* Arguments:" << std::endl << std::endl;
            std::cout << " --version:       Program version." << std::endl << std::endl;
            std::cout << " -h --help:       produce extended program help message." << std::endl << std::endl;
            std::cout << " -r --reference:  The tree file with the reference partitioned tree." << std::endl << std::endl;
            std::cout << " -t --target:     The tree file with the target tree to find matching partitions in (or with partitions to be color-matched)." << std::endl << std::endl;
            std::cout << " -m --leafmatch   File with the meta-leaf matching information across both trees (output of comparetrees command)." << std::endl << std::endl;
            std::cout << " -O --outputf:    Output folder where partitioned/color matched tree files will be written." << std::endl << std::endl;
            std::cout << "[-s --signature]: Signature-based partition matching, instert lambda coefficient value. [xor with -o and -c]." << std::endl;
            std::cout << "                   In this method a pair signature matrices are computed for each reference-target partitions to find the quality of the match." << std::endl;
            std::cout << "                   Each signature matrix defines a value for each pair of base-nodes of the tree it belongs to: 1 the base nodes are found in the same cluster, 0 if otherwise." << std::endl;
            std::cout << "                   The higher the correlation between the reference and target-derived matrices, the best match is the target tree partition to the reference tree one." << std::endl;
            std::cout << "                   A smart hierarchical search through possible partritions is conducted to find the one with best signature matching." << std::endl;
            std::cout << "                  The lambda coefficient determines if and how a similar number of clusters in both partitions affects the matching quality value," << std::endl;
            std::cout << "                   Lambda=0 -> cluster number does not affect the quality value. Lambda=1 -> cluster value similarity has as much weight as singature correlation." << std::endl << std::endl;
            std::cout << "[-o --overlap]:   Overlap-based partition matching. [xor with -o and -c]." << std::endl;
            std::cout << "                   A match between two partititionsis found by iteratively matching clusters with higher base-node overlap and resolving possible ambiguities." << std::endl;
            std::cout << "                   The matching quality between partitions is defined as the number of base-nodes pairs that are classified in the same way in both partitions" << std::endl;
            std::cout << "                   (both in the smae cluster r both in different clusters) against the total number of pair combinations." << std::endl;
            std::cout << "                   A smart hierarchical search through possible partritions is conducted to find the one with best signature matching." << std::endl << std::endl;
            std::cout << "[-d --depth]:     Partition search depth (for signature and overlap matching. A higher value will mean a more exhaustive search of the possible partitions," << std::endl;
            std::cout << "                   but also a higher computation time, specially if the partition to be matched has a high number of clusters (>100)." << std::endl;
            std::cout << "                   The default value (0, recommended) will adaptively give high search depth to low-cluster partitions and lower search depth to high-cluster partittions." << std::endl << std::endl;
            std::cout << "[-c --justcolor]: Perform only color matching across reference and target tree parttitions (both trees need to have the same number of precompouted partitions)." << std::endl;
            std::cout << "                   In multiple-to-one matching cases clusters from the reference tree might also be recolored to better identify matching relationships across partitions." << std::endl << std::endl;
            std::cout << "[-x --excl]:      Color exclusively clusters that have a match, clusters without match will be recolored white (on both reference and target trees)" << std::endl << std::endl;
            std::cout << "[-v --verbose]:   Verbose output (recommended)." << std::endl << std::endl;
            std::cout << "[--vista]:        Write output tree files in vista coordinates (default is nifti)." << std::endl << std::endl;
            std::cout << std::endl;
            std::cout << "* Usage example:" << std::endl << std::endl;
            std::cout << " matchpartition -r refTree.txt -t targetTree.txt -m matching.txt -O results/ -s 0.5 -v" << std::endl << std::endl;
            exit(0);
        }
        if (variableMap.count( "version" ) )
        {
            std::cout << progName <<", version 2.0"<<std::endl;
            exit(0);
        }
        if ( variableMap.count( "verbose" ) )
        {
            std::cout << "verbose output" << std::endl;
            verbose=true;
        }

        if ( variableMap.count( "vista" ) )
        {
            if( verbose )
            {
                std::cout << "Using vista coordinates" << std::endl;
            }
            fileManagerFactory fmf;
            fmf.setVista();
            niftiMode = false;
        }
        else
        {
            if( verbose )
            {
                std::cout << "Using nifti coordinates" << std::endl;
            }
            fileManagerFactory fmf;
            fmf.setNifti();
            niftiMode = true;
        }


        if (variableMap.count("reference"))
        {
            if(!boost::filesystem::is_regular_file( boost::filesystem::path( refTreeFilename ) ) )
            {
                std::cerr << "ERROR: reference tree file \""<<refTreeFilename<<"\" is not a regular file"<<std::endl;
                std::cerr << visibleOptions << std::endl;
                exit(-1);
            }
            std::cout << "Reference tree file: "<< refTreeFilename << std::endl;
        }
        else
        {
            std::cerr << "ERROR: no reference tree file stated"<<std::endl;
            std::cerr << visibleOptions << std::endl;
            exit(-1);
        }

        if (variableMap.count( "target" ) )
         {
            if(!boost::filesystem::is_regular_file(boost::filesystem::path( targetTreeFilename ) ) )
            {
                std::cerr << "ERROR: target tree file \""<<targetTreeFilename<<"\" is not a regular file"<<std::endl;
                std::cerr << visibleOptions << std::endl;
                exit(-1);
            }
            std::cout << "Target tree file: "<< targetTreeFilename << std::endl;
        } else {
            std::cerr << "ERROR: no target tree file stated"<<std::endl;
            std::cerr << visibleOptions << std::endl;
            exit(-1);
        }

        if (variableMap.count( "leafmatch" ) )
        {
            if(!boost::filesystem::is_regular_file(boost::filesystem::path( matchTableFilename ) ) )
            {
                std::cerr << "ERROR: match table file \""<<matchTableFilename<<"\" is not a regular file"<<std::endl;
                std::cerr << visibleOptions << std::endl;
                exit(-1);
            }
            std::cout << "Match table file: "<< matchTableFilename << std::endl;
        }
        else
        {
            std::cerr << "ERROR: no match Table file stated"<<std::endl;
            std::cerr << visibleOptions << std::endl;
            exit(-1);
        }

        if( variableMap.count( "signature" ) + variableMap.count( "overlap" ) + variableMap.count( "justcolor" ) > 1 )
        {
            std::cerr << "ERROR: multiple matching types selected, please use only one from  -s, -o, -c."<<std::endl;
            std::cerr << visibleOptions << std::endl;
            exit(-1);
        }

        if (variableMap.count( "signature" ) )
        {
            std::cout << "Performing Signature partition matching (and color matching)" << std::endl;
            std::cout <<" Using a lambda factor of "<< lambda << std::endl;
            signaturePart = true;
            colorMatching = true;
        }
        else if (variableMap.count( "overlap" ) )
        {
            std::cout << "Performing Overlap partition matching (and color matching): " << std::endl;
            overlapPart = true;
            colorMatching = true;
        }
        else if (variableMap.count( "justcolor" ) )
        {
            std::cout << "Performing only color matching: " << std::endl;
            colorMatching = true;
        }
        else
        {
            std::cerr << "ERROR: no matching type selected, select signature, overlap or color matching"<<std::endl;
            std::cerr << visibleOptions << std::endl;
            exit(-1);
        }

        if (variableMap.count( "excl" ) )
        {
            std::cout << "Color exclusively matched clusters (unmatched clusters will be white) " << std::endl;
            exclusive = true;
        }

        if( signaturePart || overlapPart )
        {
            if( searchDepth > 5 )
            {
                std::cout << "Level depth indicated: " << searchDepth << " is too high, setting to a maximum of 5" << std::endl;
                searchDepth = 5;
            }
            else if ( searchDepth = 0 )
            {
                std::cout << "Using automatic parttion-size based adaptive search depth " << std::endl;
            }
            else
            {
                std::cout << "Using a search depth of: " << searchDepth << std::endl;
            }
        }


        if (variableMap.count( "outputf" ) )
        {
            if(!boost::filesystem::is_directory(boost::filesystem::path( outputFolder ) ) )
            {
                std::cerr << "ERROR: output folder \""<<outputFolder<<"\" is not a directory"<<std::endl;
                std::cerr << visibleOptions << std::endl;
                exit(-1);

            }
            std::cout << "Output folder: "<< outputFolder << std::endl;
        }
        else
        {
            std::cerr << "ERROR: no output folder stated"<<std::endl;
            std::cerr << visibleOptions << std::endl;
            exit(-1);

        }


        std::string logFilename(outputFolder+"/"+progName+"_log.txt");
        std::ofstream logFile(logFilename.c_str());
        if(!logFile) {
            std::cerr << "ERROR: unable to open log file: \""<<logFilename<<"\""<<std::endl;
            exit(-1);
        }
        logFile <<"Start Time:\t"<< ctime(&programStartTime) <<std::endl;
        logFile <<"Working directory:\t"<< workingDir.string() <<std::endl;
        logFile <<"Verbose:\t"<< verbose <<std::endl;
        logFile <<"Reference tree:\t"<< refTreeFilename <<std::endl;
        logFile <<"Target tree:\t"<< targetTreeFilename <<std::endl;
        logFile <<"Matching table:\t"<< matchTableFilename <<std::endl;
        logFile <<"Output folder:\t"<< outputFolder <<std::endl;
        if( niftiMode )
        {
            logFile << "Using nifti coordinates" << std::endl;
        }
        else
        {
            logFile << "Using vista coordinates" << std::endl;
        }
        logFile <<"-------------"<<std::endl;


        /////////////////////////////////////////////////////////////////


        WHtree refTree( refTreeFilename );
        WHtree targetTree( targetTreeFilename );


        if (!refTree.isLoaded() || !targetTree.isLoaded() )
        {
            throw std::runtime_error ("ERROR @ compareTrees(): trees are not loaded");
        }

        logFile <<"Reference Tree: "<< refTree.getReport(false) <<std::endl;
        logFile <<"Target Tree: "<< targetTree.getReport(false) <<std::endl;

        if (refTree.getDataSize() != targetTree.getDataSize() )
        {
            std::cerr <<"Reference Tree: "<< refTree.getReport() <<std::endl;
            std::cerr <<"Target Tree: "<< targetTree.getReport() <<std::endl;
            throw std::runtime_error ("ERROR @ compareTrees() datasets have different dimensions");
        }

        if (verbose) {
            std::cout <<"Reference Tree: "<< refTree.getReport(false) <<std::endl;
            std::cout <<"Target Tree: "<< targetTree.getReport(false) <<std::endl;
        }


        partitionMatcher matcher(&refTree,&targetTree,matchTableFilename, verbose);
        std::string depthString;
        if( searchDepth > 0 )
        {
            depthString = "_d"+string_utils::toString< unsigned int >( searchDepth ) ;
        }

        std::cout <<matcher.reportBaseNodes()<<std::endl;
        std::string suffixPart("_pm_Signature_l" + string_utils::toString< float >( lambda ) + depthString + ".txt");
        std::string suffixNew("_pm_Overlap" + depthString + ".txt");
        std::string suffixColor("_colorMatch.txt");
        bool refTreeColorsChanged( false );


        if( signaturePart )
        {
            logFile <<  "Signature Matching" << std::endl;
            logFile <<  "Lambda:\t" << lambda <<std::endl;
            logFile <<  "Search depth:\t" << searchDepth <<std::endl;
            matcher.findMatchingPartitions( lambda );
        }
        else if ( overlapPart )
        {
            logFile <<  "Overlap Matching" <<std::endl;
            logFile <<  "Search depth:\t" << searchDepth <<std::endl;
            matcher.findMatchingPartitions( -1 );
        }

        if( colorMatching )
        {
            logFile <<  "Color Matching" <<std::endl;
            refTreeColorsChanged = matcher.matchColors( exclusive );

        }

        std::string refOutput;
        std::string targetOutput;

        if ( signaturePart )
        {
            targetOutput = outputFolder + "/" + targetTree.getName() + suffixPart;
        }
        else if ( overlapPart )
        {
            targetOutput = outputFolder + "/" + targetTree.getName() + suffixNew ;
        }
        else
        {
            targetOutput = outputFolder + "/" + targetTree.getName() + suffixColor;
        }

        if( refTreeColorsChanged )
        {
            refOutput = outputFolder + "/" + refTree.getName() + suffixColor;
        }
        else
        {
            refOutput = outputFolder + "/" + refTree.getName() + ".txt";
        }

        if( verbose )
        {
            std::cout <<  "Writing output target tree file to " << targetOutput << std::endl;
            std::cout <<  "Writing output reference tree file to " << refOutput << std::endl;
        }

        targetTree.writeTree( targetOutput, niftiMode );
        refTree.writeTree( refOutput, niftiMode );

        logFile <<  "Written output target tree file to " << targetOutput << std::endl;
        logFile <<  "Written output reference tree file to " << refOutput << std::endl;

        /////////////////////////////////////////////////////////////////

        // save and print total time
        time_t programEndTime( time( NULL ) );
        int totalTime( difftime( programEndTime, programStartTime ) );
        std::cout <<"Program Finished, total time: "<< totalTime/3600 <<"h "<<  (totalTime%3600)/60 <<"' "<< ((totalTime%3600)%60) <<"\"   "<< std::endl;
        logFile <<"-------------"<<std::endl;
        logFile <<"Finish Time:\t"<< ctime(&programEndTime) <<std::endl;
        logFile <<"Elapsed time : "<< totalTime/3600 <<"h "<<  (totalTime%3600)/60 <<"' "<< ((totalTime%3600)%60) <<"\""<< std::endl;




//    }
//    catch(std::exception& e)
//    {
//        std::cout << e.what() << std::endl;
//        return 1;
//    }
    return 0;
}
Ejemplo n.º 11
0
/**
   Find out operating system name and version

   This method caches system information in m_osName, m_osVersion and m_osAlias.
   It requires m_unameInfo to be set prior to call.

*/
void SCXOSTypeInfo::Init()  // private
{
    m_osVersion = L"";
    m_osName = L"Unknown";

    assert(m_unameIsValid);

#if defined(hpux) || defined(sun)

    if (m_unameIsValid)
    {
        m_osName = StrFromUTF8(m_unameInfo.sysname);
        m_osVersion = StrFromUTF8(m_unameInfo.release);
    }
#if defined(hpux)
    m_osAlias = L"HPUX";
    m_osManufacturer = L"Hewlett-Packard Company";
#elif defined(sun)
    m_osAlias = L"Solaris";
    m_osManufacturer = L"Oracle Corporation";
#endif
#elif defined(aix)

    if (m_unameIsValid)
    {
        m_osName = StrFromUTF8(m_unameInfo.sysname);

        // To get "5.3" we must read "5" and "3" from different fields.
        string ver(m_unameInfo.version);
        ver.append(".");
        ver.append(m_unameInfo.release);
        m_osVersion = StrFromUTF8(ver);
    }
    m_osAlias = L"AIX";
    m_osManufacturer = L"International Business Machines Corporation";
#elif defined(linux)
    vector<wstring> lines;
    SCXStream::NLFs nlfs;
#if defined(PF_DISTRO_SUSE)
    static const string relFileName = "/etc/SuSE-release";
    wifstream relfile(relFileName.c_str());
    wstring version(L"");
    wstring patchlevel(L"");

    SCXStream::ReadAllLines(relfile, lines, nlfs);

    if (!lines.empty()) {
        m_osName = ExtractOSName(lines[0]);
    }

    // Set the Linux Caption (get first line of the /etc/SuSE-release file)
    m_linuxDistroCaption = lines[0];
    if (0 == m_linuxDistroCaption.length())
    {
        // Fallback - should not normally happen
        m_linuxDistroCaption = L"SuSE";
    }

    // File contains one or more lines looking like this:
    // SUSE Linux Enterprise Server 10 (i586)
    // VERSION = 10
    // PATCHLEVEL = 1
    for (size_t i = 0; i<lines.size(); i++)
    {
        if (StrIsPrefix(StrTrim(lines[i]), L"VERSION", true))
        {
            wstring::size_type n = lines[i].find_first_of(L"=");
            if (n != wstring::npos)
            {
                version = StrTrim(lines[i].substr(n+1));
            }
        }
        else if (StrIsPrefix(StrTrim(lines[i]), L"PATCHLEVEL", true))
        {
            wstring::size_type n = lines[i].find_first_of(L"=");
            if (n != wstring::npos)
            {
                patchlevel = StrTrim(lines[i].substr(n+1));
            }
        }
    }

    if (version.length() > 0)
    {
        m_osVersion = version;

        if (patchlevel.length() > 0)
        {
            m_osVersion = version.append(L".").append(patchlevel);
        }
    }

    if (std::wstring::npos != m_osName.find(L"Desktop"))
    {
        m_osAlias = L"SLED";
    }
    else
    {   // Assume server.
        m_osAlias = L"SLES";
    }
    m_osManufacturer = L"SUSE GmbH";
#elif defined(PF_DISTRO_REDHAT)
    static const string relFileName = "/etc/redhat-release";
    wifstream relfile(relFileName.c_str());

    SCXStream::ReadAllLines(relfile, lines, nlfs);

    if (!lines.empty()) {
        m_osName = ExtractOSName(lines[0]);
    }

    // Set the Linux Caption (get first line of the /etc/redhat-release file)
    m_linuxDistroCaption = lines[0];
    if (0 == m_linuxDistroCaption.length())
    {
        // Fallback - should not normally happen
        m_linuxDistroCaption = L"Red Hat";
    }

    // File should contain one line that looks like this:
    // Red Hat Enterprise Linux Server release 5.1 (Tikanga)
    if (lines.size() > 0)
    {
        wstring::size_type n = lines[0].find_first_of(L"0123456789");
        if (n != wstring::npos)
        {
            wstring::size_type n2 = lines[0].substr(n).find_first_of(L" \t\n\t");
            m_osVersion = StrTrim(lines[0].substr(n,n2));
        }
    }

    if ((std::wstring::npos != m_osName.find(L"Client")) // RHED5
            || (std::wstring::npos != m_osName.find(L"Desktop"))) // RHED4
    {
        m_osAlias = L"RHED";
    }
    else
    {   // Assume server.
        m_osAlias = L"RHEL";
    }
    m_osManufacturer = L"Red Hat, Inc.";

#elif defined(PF_DISTRO_ULINUX)
    // The release file is created at agent start time by init.d startup script
    // This is done to insure that we can write to the appropriate directory at
    // the time (since, at agent run-time, we may not have root privileges).
    //
    // If we CAN create the file here (if we're running as root), then we'll
    // do so here. But in the normal case, this shouldn't be necessary.  Only
    // in "weird" cases (i.e. starting omiserver by hand, for example).

    // Create the release file by running GetLinuxOS.sh script
    // (if we have root privileges)

    try
    {
        if ( !SCXFile::Exists(m_deps->getReleasePath()) &&
                SCXFile::Exists(m_deps->getScriptPath()) &&
                m_deps->isReleasePathWritable() )
        {
            std::istringstream in;
            std::ostringstream out;
            std::ostringstream err;

            int ret = SCXCoreLib::SCXProcess::Run(m_deps->getScriptPath().c_str(), in, out, err, 10000);

            if ( ret || out.str().length() || err.str().length() )
            {
                wostringstream sout;
                sout << L"Unexpected errors running script: " << m_deps->getScriptPath().c_str()
                     << L", return code: " << ret
                     << L", stdout: " << StrFromUTF8(out.str())
                     << L", stderr: " << StrFromUTF8(err.str());

                SCX_LOGERROR(m_log, sout.str() );
            }
        }
    }
    catch(SCXCoreLib::SCXInterruptedProcessException &e)
    {
        wstring msg;
        msg = L"Timeout running script \"" + m_deps->getScriptPath() +
              L"\", " + e.Where() + L'.';
        SCX_LOGERROR(m_log, msg );
    };

    // Look in release file for O/S information

    string sFile = StrToUTF8(m_deps->getReleasePath());
    wifstream fin(sFile.c_str());
    SCXStream::ReadAllLines(fin, lines, nlfs);

    if (!lines.empty())
    {
        ExtractToken(L"OSName",     lines, m_osName);
        ExtractToken(L"OSVersion",  lines, m_osVersion);
        ExtractToken(L"OSFullName", lines, m_linuxDistroCaption);
        ExtractToken(L"OSAlias",    lines, m_osAlias);
        ExtractToken(L"OSManufacturer", lines, m_osManufacturer);
    }
    else
    {
        m_osAlias = L"Universal";
    }

    // Behavior for m_osCompatName (method GetOSName) should be as follows:
    //   PostInstall scripts will first look for SCX-RELEASE file (only on universal kits)
    //   If found, add "ORIGINAL_KIT_TYPE=Universal" to scxconfig.conf file,
    //      else   add "ORIGINAL_KIT_TYPE=!Universal" to scxconfig.conf file.
    //   After that is set up, the SCX-RELEASE file is created.
    //
    //   A RHEL system should of OSAlias of "RHEL, SLES system should have "SuSE" (in scx-release)
    //
    //   We need to mimic return values for RHEL and SLES on universal kits that did not
    //   have a universal kit installed previously, but only for RHEL and SLES kits.  In
    //   all other cases, continue to return "Linux Distribution".

    wstring configFilename(m_deps->getConfigPath());
    SCXConfigFile configFile(configFilename);

    try
    {
        configFile.LoadConfig();
    }
    catch(SCXFilePathNotFoundException &e)
    {
        // Something's whacky with postinstall, so we can't follow algorithm
        static SCXCoreLib::LogSuppressor suppressor(SCXCoreLib::eError, SCXCoreLib::eTrace);
        wstring logMessage(L"Unable to load configuration file " + configFilename);
        SCX_LOG(m_log, suppressor.GetSeverity(logMessage), logMessage);

        m_osCompatName = L"Unknown Linux Distribution";
    }

    if ( m_osCompatName.empty() )
    {
        wstring kitType;
        if ( configFile.GetValue(L"ORIGINAL_KIT_TYPE", kitType) )
        {
            if ( L"!Universal" == kitType )
            {
                if ( L"RHEL" == m_osAlias )
                {
                    m_osCompatName = L"Red Hat Distribution";
                }
                else if ( L"SLES" == m_osAlias )
                {
                    m_osCompatName = L"SuSE Distribution";
                }
            }
        }

        if ( m_osCompatName.empty() )
        {
            m_osCompatName = L"Linux Distribution";
        }
    }
#else
#error "Linux Platform not supported";
#endif

#elif defined(macos)
    m_osAlias = L"MacOS";
    m_osManufacturer = L"Apple Inc.";
    if (m_unameIsValid)
    {
        // MacOS is called "Darwin" in uname info, so we hard-code here
        m_osName = L"Mac OS";

        // This value we could read dynamically from the xml file
        // /System/Library/CoreServices/SystemVersion.plist, but that
        // file may be named differently based on client/server, and
        // reading the plist file would require framework stuff.
        //
        // Rather than using the plist, we'll use Gestalt, which is an
        // API designed to figure out versions of anything and everything.
        // Note that use of Gestalt requires the use of framework stuff
        // as well, so the Makefiles for MacOS are modified for that.

        SInt32 major, minor, bugfix;
        if (0 != Gestalt(gestaltSystemVersionMajor, &major)
                || 0 != Gestalt(gestaltSystemVersionMinor, &minor)
                || 0 != Gestalt(gestaltSystemVersionBugFix, &bugfix))
        {
            throw SCXCoreLib::SCXErrnoException(L"Gestalt", errno, SCXSRCLOCATION);
        }

        wostringstream sout;
        sout << major << L"." << minor << L"." << bugfix;
        m_osVersion = sout.str();
    }

#else
#error "Platform not supported"
#endif
}
// this is just a workbench. most of the stuff here will go into the Frontend class.
int main(int argc, char **argv) {

  ros::init(argc, argv, "okvis_node_synchronous");

  google::InitGoogleLogging(argv[0]);
  FLAGS_stderrthreshold = 0; // INFO: 0, WARNING: 1, ERROR: 2, FATAL: 3
  FLAGS_colorlogtostderr = 1;

  if (argc != 3 && argc != 4) {
    LOG(ERROR) <<
        "Usage: ./" << argv[0] << " configuration-yaml-file bag-to-read-from [skip-first-seconds]";
    return -1;
  }

  okvis::Duration deltaT(0.0);
  if (argc == 4) {
    deltaT = okvis::Duration(atof(argv[3]));
  }

  // set up the node
  ros::NodeHandle nh("okvis_node");

  // publisher
  okvis::Publisher publisher(nh);

  // read configuration file
  std::string configFilename(argv[1]);

  okvis::RosParametersReader vio_parameters_reader(configFilename);
  okvis::VioParameters parameters;
  vio_parameters_reader.getParameters(parameters);

  okvis::ThreadedKFVio okvis_estimator(parameters);

  okvis_estimator.setFullStateCallback(std::bind(&okvis::Publisher::publishFullStateAsCallback,&publisher,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,std::placeholders::_4));
  okvis_estimator.setLandmarksCallback(std::bind(&okvis::Publisher::publishLandmarksAsCallback,&publisher,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3));
  okvis_estimator.setStateCallback(std::bind(&okvis::Publisher::publishStateAsCallback,&publisher,std::placeholders::_1,std::placeholders::_2));
  okvis_estimator.setBlocking(true);
  publisher.setParameters(parameters); // pass the specified publishing stuff

  // extract the folder path
  std::string bagname(argv[2]);
  size_t pos = bagname.find_last_of("/");
  std::string path;
  if (pos == std::string::npos)
    path = ".";
  else
    path = bagname.substr(0, pos);

  const unsigned int numCameras = parameters.nCameraSystem.numCameras();

  // setup files to be written
  publisher.setCsvFile(path + "/okvis_estimator_output.csv");
  publisher.setLandmarksCsvFile(path + "/okvis_estimator_landmarks.csv");
  okvis_estimator.setImuCsvFile(path + "/imu0_data.csv");
  for (size_t i = 0; i < numCameras; ++i) {
    std::stringstream num;
    num << i;
    okvis_estimator.setTracksCsvFile(i, path + "/cam" + num.str() + "_tracks.csv");
  }

  // open the bag
  rosbag::Bag bag(argv[2], rosbag::bagmode::Read);
  // views on topics. the slash is needs to be correct, it's ridiculous...
  std::string imu_topic("/imu0");
  rosbag::View view_imu(
      bag,
      rosbag::TopicQuery(imu_topic));
  if (view_imu.size() == 0) {
    LOG(ERROR) << "no imu topic";
    return -1;
  }
  rosbag::View::iterator view_imu_iterator = view_imu.begin();
  LOG(INFO) << "No. IMU messages: " << view_imu.size();

  std::vector<std::shared_ptr<rosbag::View> > view_cams_ptr;
  std::vector<rosbag::View::iterator> view_cam_iterators;
  std::vector<okvis::Time> times;
  okvis::Time latest(0);
  for(size_t i=0; i<numCameras;++i) {
    std::string camera_topic("/cam"+std::to_string(i)+"/image_raw");
    std::shared_ptr<rosbag::View> view_ptr(
        new rosbag::View(
            bag,
            rosbag::TopicQuery(camera_topic)));
    if (view_ptr->size() == 0) {
      LOG(ERROR) << "no camera topic";
      return 1;
    }
    view_cams_ptr.push_back(view_ptr);
    view_cam_iterators.push_back(view_ptr->begin());
    sensor_msgs::ImageConstPtr msg1 = view_cam_iterators[i]
        ->instantiate<sensor_msgs::Image>();
    times.push_back(
        okvis::Time(msg1->header.stamp.sec, msg1->header.stamp.nsec));
    if (times.back() > latest)
      latest = times.back();
    LOG(INFO) << "No. cam " << i << " messages: " << view_cams_ptr.back()->size();
  }

  for(size_t i=0; i<numCameras;++i) {
    if ((latest - times[i]).toSec() > 0.01)
      view_cam_iterators[i]++;
  }

  int counter = 0;
  okvis::Time start(0.0);
  while (ros::ok()) {
    ros::spinOnce();
	okvis_estimator.display();

    // check if at the end
    if (view_imu_iterator == view_imu.end()){
      std::cout << std::endl << "Finished. Press any key to exit." << std::endl << std::flush;
      char k = 0;
      while(k==0 && ros::ok()){
        k = cv::waitKey(1);
        ros::spinOnce();
      }
      return 0;
    }
    for (size_t i = 0; i < numCameras; ++i) {
      if (view_cam_iterators[i] == view_cams_ptr[i]->end()) {
        std::cout << std::endl << "Finished. Press any key to exit." << std::endl << std::flush;
        char k = 0;
        while(k==0 && ros::ok()){
          k = cv::waitKey(1);
          ros::spinOnce();
        }
        return 0;
      }
    }

    // add images
    okvis::Time t;
    for(size_t i=0; i<numCameras;++i) {
      sensor_msgs::ImageConstPtr msg1 = view_cam_iterators[i]
          ->instantiate<sensor_msgs::Image>();
      cv::Mat filtered(msg1->height, msg1->width, CV_8UC1);
      memcpy(filtered.data, &msg1->data[0], msg1->height * msg1->width);
      t = okvis::Time(msg1->header.stamp.sec, msg1->header.stamp.nsec);
      if (start == okvis::Time(0.0)) {
        start = t;
      }

      // get all IMU measurements till then
      okvis::Time t_imu=start;
      do {
        sensor_msgs::ImuConstPtr msg = view_imu_iterator
            ->instantiate<sensor_msgs::Imu>();
        Eigen::Vector3d gyr(msg->angular_velocity.x, msg->angular_velocity.y,
                            msg->angular_velocity.z);
        Eigen::Vector3d acc(msg->linear_acceleration.x,
                            msg->linear_acceleration.y,
                            msg->linear_acceleration.z);

        t_imu = okvis::Time(msg->header.stamp.sec, msg->header.stamp.nsec);

        // add the IMU measurement for (blocking) processing
        if (t_imu - start > deltaT)
          okvis_estimator.addImuMeasurement(t_imu, acc, gyr);

        view_imu_iterator++;
      } while (view_imu_iterator != view_imu.end() && t_imu <= t);

      // add the image to the frontend for (blocking) processing
      if (t - start > deltaT)
        okvis_estimator.addImage(t, i, filtered);

      view_cam_iterators[i]++;
    }
    ++counter;

    // display progress
    if (counter % 20 == 0) {
      std::cout
          << "\rProgress: "
          << int(double(counter) / double(view_cams_ptr.back()->size()) * 100)
          << "%  " ;
    }

  }

  std::cout << std::endl;
  return 0;
}