view src/program_options.cpp @ 0:add35537fdbb tip

Initial import
author irh <ian.r.hobson@gmail.com>
date Thu, 25 Aug 2011 11:05:55 +0100
parents
children
line wrap: on
line source
//  Copyright 2011, Ian Hobson.
//
//  This file is part of gpsynth.
//
//  gpsynth is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  gpsynth is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with gpsynth in the file COPYING. 
//  If not, see http://www.gnu.org/licenses/.

#include "program_options.hpp"

#include "boost/filesystem.hpp"
#include "boost/program_options.hpp"

#include <ctime>

namespace bf = boost::filesystem;
namespace bo = boost::program_options;

namespace {

const std::string g_default_sc_app_path = "/Applications/SuperCollider";

void PrintHelpAndQuit(const bo::options_description& options,
                      int exit_code = 0) {
  bo::arg = "value";
  std::cout << '\n' << options << std::endl;
  exit(exit_code);
}

std::string GetTimeString() {
  std::time_t raw_time;
  time(&raw_time);
  tm* time_info = localtime(&raw_time);
  char buffer[20];
  strftime(buffer, 20, "%Y-%m-%d_%H:%M:%S", time_info);
  return buffer;
}

  
} // namespace


void ParseCommandLine(int argument_count,
                      const char* arguments[],
                      ProgramOptions* options) {
  bo::options_description description;
  description.add_options()
  ("help,?", "Displays this message")
  ("target,t",
   bo::value<std::string>(&options->target_path_)->required(),
   "Target sound file path")
  ("grammar,g",
   bo::value<std::string>(&options->grammar_path_),
   "Grammar file path")
  ("scpath,s", 
   bo::value<std::string>(&options->sc_app_path_),
   "Path to SuperCollider application folder")
  ("workfolder,w", 
   bo::value<std::string>(&options->work_folder_),
   "Path of folder to place files in")
  ("population,p",
   bo::value<std::size_t>(&options->population_size_)->default_value(500),
   "Population size")
  ("generations,G",
   bo::value<std::size_t>(&options->generations_)->default_value(20),
   "Number of Generations")
  ("fitness,f",
   bo::value<double>(&options->fitness_threshold_)->default_value(0),
   "Fitness threshold")
  ("tournament,T",
   bo::value<std::size_t>(&options->tournament_size_)->default_value(7),
   "Tournament selection size")
  ("crossover,c",
   bo::value<double>(&options->crossover_rate_)->default_value(0.6, "0.6"),
   "Crossover rate")
  ("mutation,m",
   bo::value<double>(&options->mutation_rate_)->default_value(0.35, "0.35"),
   "Mutation rate")
  ("reproducebest,r",
   bo::value<bool>(&options->reproduce_best_individual_)->default_value(false),
   "Automatically reproduce best individual when populating next generation.")
  ("features,F",
   bo::value<std::string>(&options->fitness_features_),
   "Set of features that the fitness function will measure when comparing files."
   " Must be a comma separated list of feature names, which can be any of the following:"
   " pitch, energy, mfccs, dmfccs, ddmfccs, mag, logmag, centroid, spread, flux."
   " Default value is 'mfccs,dmfccs,ddmfccs'.")
  ("windowsize,w",
   bo::value<std::size_t>(&options->analysis_window_size_)->default_value(1024),
   "Analysis Window Size")
  ("hopsize,h",
   bo::value<std::size_t>(&options->analysis_hop_size_)->default_value(256),
   "Analysis Hop Size")
  ("maxtreedepth,M",
   bo::value<std::size_t>(&options->maximum_tree_depth_)->default_value(3),
   "Maximum generated tree depth (can grow bigger through mutation).")
  ("keepfolders,k",
   bo::value<bool>(&options->keep_temp_folders_)->default_value(false),
   "When set to 1 the temporary generation folders won't be deleted")
  ("corelimit,C",
   bo::value<std::size_t>(&options->core_limit_)->default_value(0),
   "Limits the number of cores gpsynth will use simultaneously, 0=unlimited.")
  ;
  
  bo::command_line_parser parser(argument_count, arguments);
  parser.options(description);
  bo::variables_map config;
  try {
    bo::store(parser.run(), config);
    bo::notify(config);
  } catch (std::exception& e) {
    std::cout << "Error parsing options: " << e.what() << ".\n";
    PrintHelpAndQuit(description, -1);
  }
  
  if (config.count("help")) {
    PrintHelpAndQuit(description);
  }
  
  if (config.count("workfolder") == 0) {
    options->work_folder_ = bf::current_path().string();
  }
  // validate the work folder path
  if (!bf::is_directory(options->work_folder_)) {
    std::cout << "Work folder path '" << options->work_folder_ 
              << "' doesn't exist.\n";
    exit(-1);
  }
  options->work_folder_ += "/gpsynth_" + GetTimeString() + "/";
  
  if (config.count("scpath") == 0) {
    options->sc_app_path_ = g_default_sc_app_path;
  }
  if (!bf::is_directory(options->sc_app_path_)) {
    std::cout << "SC App path '" << options->sc_app_path_ 
              << "' doesn't exist.\n";
    exit(-1);
  }
  
  if (options->tournament_size_ < 1) {
    std::cout << "Tournament size must be greater than zero.\n";
    exit(-1);
  }
  
  if (options->tournament_size_ > options->population_size_) {
    std::cout << "Tournament size can not be larger than population size.\n";
    exit(-1);
  }
  
  if (options->crossover_rate_ < 0 || options->crossover_rate_ > 1) {
    std::cout << "The crossover rate should be between 0-1.\n";
    exit(-1);
  }
  
  if (options->mutation_rate_ < 0 || options->mutation_rate_ > 1) {
    std::cout << "The mutation rate should be between 0-1.\n";
    exit(-1);
  }
  
  if (options->maximum_tree_depth_ < 1) {
    std::cout << "Maximum tree depth must be greater than zero.\n";
    exit(-1);
  }
  
  if (options->fitness_features_.empty()) {
    options->fitness_features_ = "mfccs,dmfccs,ddmfccs";
  }
}