<commit_before>#include <algorithm>
#include <iostream>
#include <iomanip>
#include <ios>
#include <stan/mcmc/chains.hpp>

int calculate_size(const Eigen::VectorXd& x,
                   const std::string& name,
                   const int digits,
                   std::ios_base::fmtflags& format) {
  using std::max;
  using std::ceil;
  using std::log10;

  double padding = 0;
  if (digits > 0)
    padding = digits + 2;

  double fixed_size = 0.0;

  if (x.maxCoeff() > 0)
    fixed_size = ceil(log10(x.maxCoeff() + 0.001)) + padding;
  if (x.minCoeff() < 0)
    fixed_size = max(fixed_size, ceil(log10(-x.minCoeff() + 0.01)) + (padding + 1));

  format = std::ios_base::fixed;

  if (fixed_size < 7) {
    return max(fixed_size,
               max(name.length(), std::string("-0.0").length()) + 0.0);
  }

  double scientific_size = digits + 2;

  if (x.minCoeff() < 0) scientific_size += 1.0;
  scientific_size += 2.0;   // decimal (.) and exponent (e)

  double exponent_size = 0;
  if (x.maxCoeff() > 0) {
    exponent_size = ceil(fabs(log10(fabs(log10(x.maxCoeff())))));
  }
  if (x.minCoeff() < 0) {
    exponent_size = max(exponent_size,
                        ceil(fabs(log10(fabs(log10(-x.minCoeff()))))));
  }

  exponent_size = exponent_size > 2 ? exponent_size : 2;

  scientific_size += fmin(exponent_size, 3);
  format = std::ios_base::scientific;

  return scientific_size > name.length() ? scientific_size : name.length();

}

Eigen::VectorXi calculate_sizes(const Eigen::MatrixXd& values,
                                const Eigen::Matrix<std::string, Eigen::Dynamic, 1>& headers,
                                const Eigen::VectorXi& digits,
                                Eigen::Matrix<std::ios_base::fmtflags, Eigen::Dynamic, 1>& formats) {
  int n = values.cols();
  Eigen::VectorXi column_lengths(n);
  formats.resize(n);
  for (int i = 0; i < n; i++) {
    column_lengths(i) = calculate_size(values.col(i), headers(i), digits(i), formats(i)) + 1;
  }
  return column_lengths;
}

void print_usage() {

  std::cout << "USAGE:  print <filename 1> [<filename 2> ... <filename N>]"
            << std::endl
            << std::endl;

  std::cout << "OPTIONS:" << std::endl << std::endl;
  std::cout << "  --autocorr=<chain_index>\tAppend the autocorrelations for the given chain"
            << std::endl
            << std::endl;
  std::cout << "  --precision=<int>\tSet output precision"
            << std::endl
            << std::endl;

}

/**
 * The Stan print function.
 *
 * @param argc Number of arguments
 * @param argv Arguments
 *
 * @return 0 for success,
 *         non-zero otherwise
 */
int main(int argc, const char* argv[]) {

  if (argc == 1) {
    print_usage();
    return 0;
  }

  std::ifstream ifstream;
  std::vector<std::string> filenames;

  for (int i = 1; i < argc; i++) {

    if (std::string(argv[i]).find("--autocorr=") != std::string::npos)
      continue;

    if (std::string(argv[i]).find("--precision=") != std::string::npos)
      continue;

    if (std::string("--help") == std::string(argv[i])) {
      print_usage();
      return 0;
    }

    ifstream.open(argv[i]);

    if (ifstream.good()) {
      filenames.push_back(argv[i]);
      ifstream.close();
    } else {
      std::cout << "File " << argv[i] << " not found" << std::endl;
    }

  }

  if (!filenames.size()) {
    std::cout << "No valid input files, exiting." << std::endl;
    return 0;
  }

  Eigen::VectorXd warmup_times(filenames.size());
  Eigen::VectorXd sampling_times(filenames.size());

  Eigen::VectorXi thin(filenames.size());

  ifstream.open(filenames[0].c_str());

  stan::io::stan_csv stan_csv = stan::io::stan_csv_reader::parse(ifstream);
  warmup_times(0) = stan_csv.timing.warmup;
  sampling_times(0) = stan_csv.timing.sampling;

  stan::mcmc::chains<> chains(stan_csv);
  ifstream.close();

  thin(0) = stan_csv.metadata.thin;

  for (int chain = 1; chain < filenames.size(); chain++) {
    ifstream.open(filenames[chain].c_str());
    stan_csv = stan::io::stan_csv_reader::parse(ifstream);
    chains.add(stan_csv);
    ifstream.close();
    thin(chain) = stan_csv.metadata.thin;

    warmup_times(chain) = stan_csv.timing.warmup;
    sampling_times(chain) = stan_csv.timing.sampling;

  }

  double total_warmup_time = warmup_times.sum();
  double total_sampling_time = sampling_times.sum();

  // print
  const int skip = 4;
  std::string model_name = stan_csv.metadata.model;
  int max_name_length = 0;
  for (int i = skip; i < chains.num_params(); i++)
    if (chains.param_name(i).length() > max_name_length)
      max_name_length = chains.param_name(i).length();
  for (int i = 0; i < 2; i++)
    if (chains.param_name(i).length() > max_name_length)
      max_name_length = chains.param_name(i).length();

  int n = 11;

  Eigen::MatrixXd values(chains.num_params(), n);
  values.setZero();
  Eigen::VectorXd probs(5);
  probs << 0.025, 0.25, 0.5, 0.75, 0.975;

  for (int i = 0; i < chains.num_params(); i++) {
    double sd = chains.sd(i);
    double n_eff = chains.effective_sample_size(i);
    values(i,0) = chains.mean(i);
    values(i,1) = sd / sqrt(n_eff);
    values(i,2) = sd;
    Eigen::VectorXd quantiles = chains.quantiles(i,probs);
    for (int j = 0; j < 5; j++)
      values(i,3+j) = quantiles(j);
    values(i,8) = n_eff;
    values(i,9) = n_eff / total_sampling_time;
    values(i,10) = chains.split_potential_scale_reduction(i);
  }

  Eigen::Matrix<std::string, Eigen::Dynamic, 1> headers(n);
  headers <<
    "mean", "se_mean", "sd",
    "2.5%", "25%", "50%", "75%", "97.5%",
    "n_eff", "n_eff/time", "Rhat";
  Eigen::VectorXi digits(n);

  int precision = 1;

  for (int k = 1; k < argc; k++)
    if (std::string(argv[k]).find("--precision=") != std::string::npos)
      precision = atoi(std::string(argv[k]).substr(12).c_str());

  digits.setConstant(precision);

  // Want per row:
  //   scientific vs floating point
  // Want per column:
  //   length

  Eigen::VectorXi column_lengths(n);
  // Formats should be a vector of length chains.num_params()
  Eigen::Matrix<std::ios_base::fmtflags, Eigen::Dynamic, 1> formats(n);
  column_lengths = calculate_sizes(values, headers, digits, formats);

  std::cout << "Inference for Stan model: " << model_name << std::endl
            << chains.num_chains() << " chains: each with iter=(" << chains.num_kept_samples(0);
  for (int chain = 1; chain < chains.num_chains(); chain++)
    std::cout << "," << chains.num_kept_samples(chain);
  std::cout << ")";

  std::cout << "; warmup=(" << chains.warmup(0);
  for (int chain = 1; chain < chains.num_chains(); chain++)
    std::cout << "," << chains.warmup(chain);
  std::cout << ")";

  std::cout << "; thin=(" << thin(0);

  for (int chain = 1; chain < chains.num_chains(); chain++)
    std::cout << "," << thin(chain);
  std::cout << ")";

  std::cout << "; " << chains.num_samples() << " iterations saved."
            << std::endl << std::endl;

  std::string warmup_unit = "seconds";

  if (total_warmup_time / 3600 > 1) {
    total_warmup_time /= 3600;
    warmup_unit = "hours";
  } else if (total_warmup_time / 60 > 1) {
    total_warmup_time /= 60;
    warmup_unit = "minutes";
  }

  std::cout << "Warmup took (" << warmup_times(0);
  for (int chain = 1; chain < chains.num_chains(); chain++)
    std::cout << ", " << warmup_times(chain);
  std::cout << ") seconds, ";
  std::cout << total_warmup_time << " " << warmup_unit << " total" << std::endl;

  std::string sampling_unit = "seconds";

  if (total_sampling_time / 3600 > 1) {
    total_sampling_time /= 3600;
    sampling_unit = "hours";
  } else if (total_sampling_time / 60 > 1) {
    total_sampling_time /= 60;
    sampling_unit = "minutes";
  }

  std::cout << "Sampling took (" << sampling_times(0);
  for (int chain = 1; chain < chains.num_chains(); chain++)
    std::cout << ", " << sampling_times(chain);
  std::cout << ") seconds, ";
  std::cout << total_sampling_time << " " << sampling_unit << " total" << std::endl;
  std::cout << std::endl;

  using std::setprecision;
  using std::setw;

  // header
  std::cout << std::setw(max_name_length+1) << "";
  for (int i = 0; i < n; i++) {
    std::cout << setw(column_lengths(i)) << headers(i);
  }
  std::cout << std::endl;
  // each row
  for (int i = skip; i < chains.num_params(); i++) {
    std::cout << setw(max_name_length+1) << std::left << chains.param_name(i);
    std::cout << std::right;
    for (int j = 0; j < n; j++) {
      std::cout.setf(formats(j), std::ios::floatfield);
      std::cout << setprecision(digits(j)) << setw(column_lengths(j)) << values(i,j);
    }
    std::cout << std::endl;
  }
  // lp__, treedepth__
  for (int i = 0; i < 4; i++) {
    std::cout << setw(max_name_length+1) << std::left << chains.param_name(i);
    std::cout << std::right;
    for (int j = 0; j < n; j++) {
      std::cout.setf(formats(j), std::ios::floatfield);
      std::cout << setprecision(digits(j)) << setw(column_lengths(j)) << values(i,j);
    }
    std::cout << std::endl;
  }

  std::cout << std::endl;
  std::cout << "Samples were drawn using " << stan_csv.metadata.algorithm << "." << std::endl
            << "For each parameter, n_eff is a crude measure of effective sample size," << std::endl
            << "and Rhat is the potential scale reduction factor on split chains (at " << std::endl
            << "convergence, Rhat=1)." << std::endl
            << std::endl;

  for (int k = 1; k < argc; k++) {

    if (std::string(argv[k]).find("--autocorr=") != std::string::npos) {

      const int c = atoi(std::string(argv[k]).substr(11).c_str());

      if (c < 0 || c >= chains.num_chains()) {
        std::cout << "Bad chain index " << c << ", aborting autocorrelation display." << std::endl;
        break;
      }

      Eigen::MatrixXd autocorr(chains.num_params(), chains.num_samples(c));

      for (int i = 0; i < chains.num_params(); i++) {
        autocorr.row(i) = chains.autocorrelation(c, i);
      }

      // Format and print header
      std::cout << "Displaying the autocorrelations for chain " << c << ":" << std::endl;
      std::cout << std::endl;

      const int n_autocorr = autocorr.row(0).size();

      int lag_width = 1;
      int number = n_autocorr;
      while ( number != 0) { number /= 10; lag_width++; }

      std::cout << setw(lag_width > 4 ? lag_width : 4) << "Lag";
      for (int i = 0; i < chains.num_params(); ++i) {
        std::cout << setw(max_name_length + 1) << std::right << chains.param_name(i);
      }
      std::cout << std::endl;

      // Print body
      for (int n = 0; n < n_autocorr; ++n) {
        std::cout << setw(lag_width) << std::right << n;
        for (int i = 0; i < chains.num_params(); ++i) {
          std::cout << setw(max_name_length + 1) << std::right << autocorr(i, n);
        }
        std::cout << std::endl;
      }

    }

  }

  return 0;

}

<commit_msg>Format zero values appropriately<commit_after>#include <algorithm>
#include <iostream>
#include <iomanip>
#include <ios>
#include <stan/mcmc/chains.hpp>

int calculate_size(const Eigen::VectorXd& x,
                   const std::string& name,
                   const int digits,
                   std::ios_base::fmtflags& format) {
  using std::max;
  using std::ceil;
  using std::log10;

  double padding = 0;
  if (digits > 0)
    padding = digits + 2;

  double fixed_size = padding;

  if (x.maxCoeff() > 0)
    fixed_size += ceil(log10(x.maxCoeff() + 0.001));
  if (x.minCoeff() < 0)
    fixed_size += max(fixed_size, ceil(log10(-x.minCoeff() + 0.01)) + 1);

  format = std::ios_base::fixed;

  if (fixed_size < 7) {
    return max(fixed_size,
               max(name.length(), std::string("-0.0").length()) + 0.0);
  }

  double scientific_size = digits + 2;

  if (x.minCoeff() < 0) scientific_size += 1.0;
  scientific_size += 2.0;   // decimal (.) and exponent (e)

  double exponent_size = 0;
  if (x.maxCoeff() > 0) {
    exponent_size = ceil(fabs(log10(fabs(log10(x.maxCoeff())))));
  }
  if (x.minCoeff() < 0) {
    exponent_size = max(exponent_size,
                        ceil(fabs(log10(fabs(log10(-x.minCoeff()))))));
  }

  exponent_size = exponent_size > 2 ? exponent_size : 2;

  scientific_size += fmin(exponent_size, 3);
  format = std::ios_base::scientific;

  return scientific_size > name.length() ? scientific_size : name.length();

}

Eigen::VectorXi calculate_sizes(const Eigen::MatrixXd& values,
                                const Eigen::Matrix<std::string, Eigen::Dynamic, 1>& headers,
                                const Eigen::VectorXi& digits,
                                Eigen::Matrix<std::ios_base::fmtflags, Eigen::Dynamic, 1>& formats) {
  int n = values.cols();
  Eigen::VectorXi column_lengths(n);
  formats.resize(n);
  for (int i = 0; i < n; i++) {
    column_lengths(i) = calculate_size(values.col(i), headers(i), digits(i), formats(i)) + 1;
  }
  return column_lengths;
}

void print_usage() {

  std::cout << "USAGE:  print <filename 1> [<filename 2> ... <filename N>]"
            << std::endl
            << std::endl;

  std::cout << "OPTIONS:" << std::endl << std::endl;
  std::cout << "  --autocorr=<chain_index>\tAppend the autocorrelations for the given chain"
            << std::endl
            << std::endl;
  std::cout << "  --precision=<int>\tSet output precision"
            << std::endl
            << std::endl;

}

/**
 * The Stan print function.
 *
 * @param argc Number of arguments
 * @param argv Arguments
 *
 * @return 0 for success,
 *         non-zero otherwise
 */
int main(int argc, const char* argv[]) {

  if (argc == 1) {
    print_usage();
    return 0;
  }

  std::ifstream ifstream;
  std::vector<std::string> filenames;

  for (int i = 1; i < argc; i++) {

    if (std::string(argv[i]).find("--autocorr=") != std::string::npos)
      continue;

    if (std::string(argv[i]).find("--precision=") != std::string::npos)
      continue;

    if (std::string("--help") == std::string(argv[i])) {
      print_usage();
      return 0;
    }

    ifstream.open(argv[i]);

    if (ifstream.good()) {
      filenames.push_back(argv[i]);
      ifstream.close();
    } else {
      std::cout << "File " << argv[i] << " not found" << std::endl;
    }

  }

  if (!filenames.size()) {
    std::cout << "No valid input files, exiting." << std::endl;
    return 0;
  }

  Eigen::VectorXd warmup_times(filenames.size());
  Eigen::VectorXd sampling_times(filenames.size());

  Eigen::VectorXi thin(filenames.size());

  ifstream.open(filenames[0].c_str());

  stan::io::stan_csv stan_csv = stan::io::stan_csv_reader::parse(ifstream);
  warmup_times(0) = stan_csv.timing.warmup;
  sampling_times(0) = stan_csv.timing.sampling;

  stan::mcmc::chains<> chains(stan_csv);
  ifstream.close();

  thin(0) = stan_csv.metadata.thin;

  for (int chain = 1; chain < filenames.size(); chain++) {
    ifstream.open(filenames[chain].c_str());
    stan_csv = stan::io::stan_csv_reader::parse(ifstream);
    chains.add(stan_csv);
    ifstream.close();
    thin(chain) = stan_csv.metadata.thin;

    warmup_times(chain) = stan_csv.timing.warmup;
    sampling_times(chain) = stan_csv.timing.sampling;

  }

  double total_warmup_time = warmup_times.sum();
  double total_sampling_time = sampling_times.sum();

  // print
  const int skip = 4;
  std::string model_name = stan_csv.metadata.model;
  int max_name_length = 0;
  for (int i = skip; i < chains.num_params(); i++)
    if (chains.param_name(i).length() > max_name_length)
      max_name_length = chains.param_name(i).length();
  for (int i = 0; i < 2; i++)
    if (chains.param_name(i).length() > max_name_length)
      max_name_length = chains.param_name(i).length();

  int n = 11;

  Eigen::MatrixXd values(chains.num_params(), n);
  values.setZero();
  Eigen::VectorXd probs(5);
  probs << 0.025, 0.25, 0.5, 0.75, 0.975;

  for (int i = 0; i < chains.num_params(); i++) {
    double sd = chains.sd(i);
    double n_eff = chains.effective_sample_size(i);
    values(i,0) = chains.mean(i);
    values(i,1) = sd / sqrt(n_eff);
    values(i,2) = sd;
    Eigen::VectorXd quantiles = chains.quantiles(i,probs);
    for (int j = 0; j < 5; j++)
      values(i,3+j) = quantiles(j);
    values(i,8) = n_eff;
    values(i,9) = n_eff / total_sampling_time;
    values(i,10) = chains.split_potential_scale_reduction(i);
  }

  Eigen::Matrix<std::string, Eigen::Dynamic, 1> headers(n);
  headers <<
    "mean", "se_mean", "sd",
    "2.5%", "25%", "50%", "75%", "97.5%",
    "n_eff", "n_eff/time", "Rhat";
  Eigen::VectorXi digits(n);

  int precision = 1;

  for (int k = 1; k < argc; k++)
    if (std::string(argv[k]).find("--precision=") != std::string::npos)
      precision = atoi(std::string(argv[k]).substr(12).c_str());

  digits.setConstant(precision);

  // Want per row:
  //   scientific vs floating point
  // Want per column:
  //   length

  Eigen::VectorXi column_lengths(n);
  // Formats should be a vector of length chains.num_params()
  Eigen::Matrix<std::ios_base::fmtflags, Eigen::Dynamic, 1> formats(n);
  column_lengths = calculate_sizes(values, headers, digits, formats);

  std::cout << "Inference for Stan model: " << model_name << std::endl
            << chains.num_chains() << " chains: each with iter=(" << chains.num_kept_samples(0);
  for (int chain = 1; chain < chains.num_chains(); chain++)
    std::cout << "," << chains.num_kept_samples(chain);
  std::cout << ")";

  std::cout << "; warmup=(" << chains.warmup(0);
  for (int chain = 1; chain < chains.num_chains(); chain++)
    std::cout << "," << chains.warmup(chain);
  std::cout << ")";

  std::cout << "; thin=(" << thin(0);

  for (int chain = 1; chain < chains.num_chains(); chain++)
    std::cout << "," << thin(chain);
  std::cout << ")";

  std::cout << "; " << chains.num_samples() << " iterations saved."
            << std::endl << std::endl;

  std::string warmup_unit = "seconds";

  if (total_warmup_time / 3600 > 1) {
    total_warmup_time /= 3600;
    warmup_unit = "hours";
  } else if (total_warmup_time / 60 > 1) {
    total_warmup_time /= 60;
    warmup_unit = "minutes";
  }

  std::cout << "Warmup took (" << warmup_times(0);
  for (int chain = 1; chain < chains.num_chains(); chain++)
    std::cout << ", " << warmup_times(chain);
  std::cout << ") seconds, ";
  std::cout << total_warmup_time << " " << warmup_unit << " total" << std::endl;

  std::string sampling_unit = "seconds";

  if (total_sampling_time / 3600 > 1) {
    total_sampling_time /= 3600;
    sampling_unit = "hours";
  } else if (total_sampling_time / 60 > 1) {
    total_sampling_time /= 60;
    sampling_unit = "minutes";
  }

  std::cout << "Sampling took (" << sampling_times(0);
  for (int chain = 1; chain < chains.num_chains(); chain++)
    std::cout << ", " << sampling_times(chain);
  std::cout << ") seconds, ";
  std::cout << total_sampling_time << " " << sampling_unit << " total" << std::endl;
  std::cout << std::endl;

  using std::setprecision;
  using std::setw;

  // header
  std::cout << std::setw(max_name_length+1) << "";
  for (int i = 0; i < n; i++) {
    std::cout << setw(column_lengths(i)) << headers(i);
  }
  std::cout << std::endl;
  // each row
  for (int i = skip; i < chains.num_params(); i++) {
    std::cout << setw(max_name_length+1) << std::left << chains.param_name(i);
    std::cout << std::right;
    for (int j = 0; j < n; j++) {
      std::cout.setf(formats(j), std::ios::floatfield);
      std::cout << setprecision(digits(j)) << setw(column_lengths(j)) << values(i,j);
    }
    std::cout << std::endl;
  }
  // lp__, treedepth__
  for (int i = 0; i < 4; i++) {
    std::cout << setw(max_name_length+1) << std::left << chains.param_name(i);
    std::cout << std::right;
    for (int j = 0; j < n; j++) {
      std::cout.setf(formats(j), std::ios::floatfield);
      std::cout << setprecision(digits(j)) << setw(column_lengths(j)) << values(i,j);
    }
    std::cout << std::endl;
  }

  std::cout << std::endl;
  std::cout << "Samples were drawn using " << stan_csv.metadata.algorithm << "." << std::endl
            << "For each parameter, n_eff is a crude measure of effective sample size," << std::endl
            << "and Rhat is the potential scale reduction factor on split chains (at " << std::endl
            << "convergence, Rhat=1)." << std::endl
            << std::endl;

  for (int k = 1; k < argc; k++) {

    if (std::string(argv[k]).find("--autocorr=") != std::string::npos) {

      const int c = atoi(std::string(argv[k]).substr(11).c_str());

      if (c < 0 || c >= chains.num_chains()) {
        std::cout << "Bad chain index " << c << ", aborting autocorrelation display." << std::endl;
        break;
      }

      Eigen::MatrixXd autocorr(chains.num_params(), chains.num_samples(c));

      for (int i = 0; i < chains.num_params(); i++) {
        autocorr.row(i) = chains.autocorrelation(c, i);
      }

      // Format and print header
      std::cout << "Displaying the autocorrelations for chain " << c << ":" << std::endl;
      std::cout << std::endl;

      const int n_autocorr = autocorr.row(0).size();

      int lag_width = 1;
      int number = n_autocorr;
      while ( number != 0) { number /= 10; lag_width++; }

      std::cout << setw(lag_width > 4 ? lag_width : 4) << "Lag";
      for (int i = 0; i < chains.num_params(); ++i) {
        std::cout << setw(max_name_length + 1) << std::right << chains.param_name(i);
      }
      std::cout << std::endl;

      // Print body
      for (int n = 0; n < n_autocorr; ++n) {
        std::cout << setw(lag_width) << std::right << n;
        for (int i = 0; i < chains.num_params(); ++i) {
          std::cout << setw(max_name_length + 1) << std::right << autocorr(i, n);
        }
        std::cout << std::endl;
      }

    }

  }

  return 0;

}

<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (c) 2009 Juergen Riegel (FreeCAD@juergen-riegel.net)        *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  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 Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"
#ifdef __GNUC__
# include <unistd.h>
#endif

#include <QString>
#include <QLocale>
#include "Exception.h"
#include "UnitsApi.h"
#include "UnitsSchemaMKS.h"
#include <cmath>

using namespace Base;

QString UnitsSchemaMKS::schemaTranslate(const Quantity &quant, double &factor, QString &unitString)
{
    double UnitValue = std::abs(quant.getValue());
    Unit unit = quant.getUnit();

    // now do special treatment on all cases seems necessary:
    if (unit == Unit::Length) {  // Length handling ============================
        if (UnitValue < 0.000000001) {// smaller then 0.001 nm -> scientific notation
            unitString = QString::fromLatin1("mm");
            factor = 1.0;
        }
        else if(UnitValue < 0.001) {
            unitString = QString::fromLatin1("nm");
            factor = 0.000001;
        }
        else if(UnitValue < 0.1) {
            unitString = QString::fromUtf8("\xC2\xB5m");
            factor = 0.001;
        }
        else if(UnitValue < 100.0) {
            unitString = QString::fromLatin1("mm");
            factor = 1.0;
        }
        else if(UnitValue < 10000000.0) {
            unitString = QString::fromLatin1("m");
            factor = 1000.0;
        }
        else if(UnitValue < 100000000000.0 ) {
            unitString = QString::fromLatin1("km");
            factor = 1000000.0;
        }
        else { // bigger then 1000 km -> scientific notation
            unitString = QString::fromLatin1("mm");
            factor = 1.0;
        }
    }
    else if (unit == Unit::Area) {
        if (UnitValue < 100.0) {// smaller than 1 square cm
            unitString = QString::fromLatin1("mm^2");
            factor = 1.0;
        }
        else if (UnitValue < 10000000000000.0) {
            unitString = QString::fromLatin1("m^2");
            factor = 1000000.0;
        }
        else { // bigger then 1 square kilometer
            unitString = QString::fromLatin1("km^2");
            factor = 1000000000000.0;
        }
    }
    else if (unit == Unit::Mass) {
        // TODO Cascade for the wights
        // default action for all cases without special treatment:
        unitString = quant.getUnit().getString();
        factor = 1.0;
    }
    else if (unit == Unit::Volume) {
        if (UnitValue < 1000000.0) {// smaller than 10 cubic cm
            unitString = QString::fromLatin1("mm^3");
            factor = 1.0;
        }
        else if (UnitValue < 1000000000000000000.0) {
            unitString = QString::fromLatin1("m^3");
            factor = 1000000000.0;
        }
        else { // bigger then 1 cubic kilometer
            unitString = QString::fromLatin1("km^3");
            factor = 1000000000000000000.0;
        }
    }
    else if ((unit == Unit::Pressure) || (unit == Unit::Stress)) {
        if (UnitValue < 10.0) {// Pa is the smallest
            unitString = QString::fromLatin1("Pa");
            factor = 0.001;
        }
        else if (UnitValue < 10000.0) {
            unitString = QString::fromLatin1("kPa");
            factor = 1.0;
        }
        else if (UnitValue < 10000000.0) {
            unitString = QString::fromLatin1("MPa");
            factor = 1000.0;
        }
        else if (UnitValue < 10000000000.0) {
            unitString = QString::fromLatin1("GPa");
            factor = 1000000.0;
        }
        else { // bigger then 1000 GPa -> scientific notation
            unitString = QString::fromLatin1("Pa");
            factor = 0.001;
        }
    }
    else if (unit == Unit::ThermalConductivity) {
        if (UnitValue < 1000) {
            unitString = QString::fromLatin1("W/mm/K");
            factor = 1000000.0;
        }
        else {
            unitString = QString::fromLatin1("W/m/K");
            factor = 1000.0;
        }
    }
    else if (unit == Unit::ThermalExpansionCoefficient) {
        if (UnitValue < 0.001) {
            unitString = QString::fromUtf8("\xC2\xB5m/m/K");
            factor = 0.000001;
        }
        else {
            unitString = QString::fromLatin1("m/m/K");
            factor = 1.0;
        }
    }
    else if (unit == Unit::SpecificHeat) {
        unitString = QString::fromLatin1("J/kg/K");
        factor = 1000000.0;
    }
    else if (unit == Unit::ThermalTransferCoefficient) {
        unitString = QString::fromLatin1("W/m^2/K");
        factor = 1.0;
    }
    else if (unit == Unit::Power) {
        unitString = QString::fromLatin1("W");
        factor = 1000000;
    }
    else if (unit == Unit::SpecificEnergy) {
        unitString = QString::fromLatin1("m^2/s^2");
        factor = 1000000;
    }
    else if (unit == Unit::HeatFlux) {
        unitString = QString::fromLatin1("W/m^2");
        factor = 1.0;
    }
    else if (unit == Unit::Velocity) {
        unitString = QString::fromLatin1("mm/s");
        factor = 1.0;
    }
    else if (unit == Unit::DynamicViscosity) {
        unitString = QString::fromLatin1("kg/(m*s)");
        factor = 0.001;
    }
    else {
        // default action for all cases without special treatment:
        unitString = quant.getUnit().getString();
        factor = 1.0;
    }

    return toLocale(quant, factor, unitString);
}
<commit_msg>Base: Fixes in MKS units schema<commit_after>/***************************************************************************
 *   Copyright (c) 2009 Juergen Riegel (FreeCAD@juergen-riegel.net)        *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  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 Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"
#ifdef __GNUC__
# include <unistd.h>
#endif

#include <QString>
#include <QLocale>
#include "Exception.h"
#include "UnitsApi.h"
#include "UnitsSchemaMKS.h"
#include <cmath>

using namespace Base;

QString UnitsSchemaMKS::schemaTranslate(const Quantity &quant, double &factor, QString &unitString)
{
    double UnitValue = std::abs(quant.getValue());
    Unit unit = quant.getUnit();

    // now do special treatment on all cases seems necessary:
    if (unit == Unit::Length) {  // Length handling ============================
        if (UnitValue < 0.000000001) {// smaller then 0.001 nm -> scientific notation
            unitString = QString::fromLatin1("m");
            factor = 1000.0;
        }
        else if(UnitValue < 0.001) {
            unitString = QString::fromLatin1("nm");
            factor = 0.000001;
        }
        else if(UnitValue < 0.1) {
            unitString = QString::fromUtf8("\xC2\xB5m");
            factor = 0.001;
        }
        else if(UnitValue < 100.0) {
            unitString = QString::fromLatin1("mm");
            factor = 1.0;
        }
        else if(UnitValue < 10000000.0) {
            unitString = QString::fromLatin1("m");
            factor = 1000.0;
        }
        else if(UnitValue < 100000000000.0 ) {
            unitString = QString::fromLatin1("km");
            factor = 1000000.0;
        }
        else { // bigger then 1000 km -> scientific notation
            unitString = QString::fromLatin1("m");
            factor = 1000.0;
        }
    }
    else if (unit == Unit::Area) {
        if (UnitValue < 100.0) {// smaller than 1 square cm
            unitString = QString::fromLatin1("mm^2");
            factor = 1.0;
        }
        else if (UnitValue < 10000000000000.0) {
            unitString = QString::fromLatin1("m^2");
            factor = 1000000.0;
        }
        else { // bigger then 1 square kilometer
            unitString = QString::fromLatin1("km^2");
            factor = 1000000000000.0;
        }
    }
    else if (unit == Unit::Mass) {
        // TODO Cascade for the wights
        // default action for all cases without special treatment:
        unitString = quant.getUnit().getString();
        factor = 1.0;
    }
    else if (unit == Unit::Density) {
        if (UnitValue < 0.0001) {
            unitString = QString::fromLatin1("kg/m^3");
            factor = 0.000000001;
        }
        else if (UnitValue < 1.0) {
            unitString = QString::fromLatin1("kg/cm^3");
            factor = 0.001;
        }
        else {
            unitString = QString::fromLatin1("kg/mm^3");
            factor = 1.0;
        }
    }
    else if (unit == Unit::Volume) {
        if (UnitValue < 1000000.0) {// smaller than 10 cubic cm
            unitString = QString::fromLatin1("mm^3");
            factor = 1.0;
        }
        else if (UnitValue < 1000000000000000000.0) {
            unitString = QString::fromLatin1("m^3");
            factor = 1000000000.0;
        }
        else { // bigger then 1 cubic kilometer
            unitString = QString::fromLatin1("km^3");
            factor = 1000000000000000000.0;
        }
    }
    else if ((unit == Unit::Pressure) || (unit == Unit::Stress)) {
        if (UnitValue < 10.0) {// Pa is the smallest
            unitString = QString::fromLatin1("Pa");
            factor = 0.001;
        }
        else if (UnitValue < 10000.0) {
            unitString = QString::fromLatin1("kPa");
            factor = 1.0;
        }
        else if (UnitValue < 10000000.0) {
            unitString = QString::fromLatin1("MPa");
            factor = 1000.0;
        }
        else if (UnitValue < 10000000000.0) {
            unitString = QString::fromLatin1("GPa");
            factor = 1000000.0;
        }
        else { // bigger then 1000 GPa -> scientific notation
            unitString = QString::fromLatin1("Pa");
            factor = 0.001;
        }
    }
    else if (unit == Unit::ThermalConductivity) {
        if (UnitValue < 1000) {
            unitString = QString::fromLatin1("W/mm/K");
            factor = 1000000.0;
        }
        else {
            unitString = QString::fromLatin1("W/m/K");
            factor = 1000.0;
        }
    }
    else if (unit == Unit::ThermalExpansionCoefficient) {
        if (UnitValue < 0.001) {
            unitString = QString::fromUtf8("\xC2\xB5m/m/K");
            factor = 0.000001;
        }
        else {
            unitString = QString::fromLatin1("m/m/K");
            factor = 1.0;
        }
    }
    else if (unit == Unit::SpecificHeat) {
        unitString = QString::fromLatin1("J/kg/K");
        factor = 1000000.0;
    }
    else if (unit == Unit::ThermalTransferCoefficient) {
        unitString = QString::fromLatin1("W/m^2/K");
        factor = 1.0;
    }
    else if (unit == Unit::Power) {
        unitString = QString::fromLatin1("W");
        factor = 1000000;
    }
    else if (unit == Unit::SpecificEnergy) {
        unitString = QString::fromLatin1("m^2/s^2");
        factor = 1000000;
    }
    else if (unit == Unit::HeatFlux) {
        unitString = QString::fromLatin1("W/m^2");
        factor = 1.0;
    }
    else if (unit == Unit::Velocity) {
        unitString = QString::fromLatin1("m/s");
        factor = 1000.0;
    }
    else if (unit == Unit::DynamicViscosity) {
        unitString = QString::fromLatin1("kg/(m*s)");
        factor = 0.001;
    }
    else {
        // default action for all cases without special treatment:
        unitString = quant.getUnit().getString();
        factor = 1.0;
    }

    return toLocale(quant, factor, unitString);
}
<|endoftext|>


<commit_before>/*
* Basic camera class
*
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
*
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/

#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>

class Camera
{
private:
	float fov;
	float znear, zfar;

	void updateViewMatrix()
	{
		glm::mat4 rotM = glm::mat4();
		glm::mat4 transM;

		rotM = glm::rotate(rotM, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
		rotM = glm::rotate(rotM, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
		rotM = glm::rotate(rotM, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));

		transM = glm::translate(glm::mat4(), position);

		if (type == CameraType::firstperson)
		{
			matrices.view = rotM * transM;
		}
		else
		{
			matrices.view = transM * rotM;
		}
	};
public:
	enum CameraType { lookat, firstperson };
	CameraType type = CameraType::lookat;

	glm::vec3 rotation = glm::vec3();
	glm::vec3 position = glm::vec3();

	float rotationSpeed = 1.0f;
	float movementSpeed = 1.0f;

	struct
	{
		glm::mat4 perspective;
		glm::mat4 view;
	} matrices;

	struct
	{
		bool left = false;
		bool right = false;
		bool up = false;
		bool down = false;
	} keys;

	bool moving()
	{
		return keys.left || keys.right || keys.up || keys.down;
	}

	void setPerspective(float fov, float aspect, float znear, float zfar)
	{
		this->fov = fov;
		this->znear = znear;
		this->zfar = zfar;
		matrices.perspective = glm::perspective(glm::radians(fov), aspect, znear, zfar);
	};

	void updateAspectRatio(float aspect)
	{
		matrices.perspective = glm::perspective(glm::radians(fov), aspect, znear, zfar);
	}

	void setRotation(glm::vec3 rotation)
	{
		this->rotation = rotation;
		updateViewMatrix();
	};

	void rotate(glm::vec3 delta)
	{
		this->rotation += delta;
		updateViewMatrix();
	}

	void setTranslation(glm::vec3 translation)
	{
		this->position = translation;
		updateViewMatrix();
	};

	void translate(glm::vec3 delta)
	{
		this->position += delta;
		updateViewMatrix();
	}

	void update(float deltaTime)
	{
		if (type == CameraType::firstperson)
		{
			if (moving())
			{
				glm::vec3 camFront;
				camFront.x = -cos(glm::radians(rotation.x)) * sin(glm::radians(rotation.y));
				camFront.y = sin(glm::radians(rotation.x));
				camFront.z = cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y));
				camFront = glm::normalize(camFront);

				float moveSpeed = deltaTime * movementSpeed;

				if (keys.up)
					position += camFront * moveSpeed;
				if (keys.down)
					position -= camFront * moveSpeed;
				if (keys.left)
					position -= glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * moveSpeed;
				if (keys.right)
					position += glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * moveSpeed;

				updateViewMatrix();
			}
		}
	};

	// Update camera passing separate axis data (gamepad)
	// Returns true if view or position has been changed
	bool updatePad(glm::vec2 axisLeft, glm::vec2 axisRight, float deltaTime)
	{
		bool retVal = false;

		if (type == CameraType::firstperson)
		{
			// Use the common console thumbstick layout
			// Left = view, right = move

			const float deadZone = 0.0015f;
			const float range = 1.0f - deadZone;

			glm::vec3 camFront;
			camFront.x = -cos(glm::radians(rotation.x)) * sin(glm::radians(rotation.y));
			camFront.y = sin(glm::radians(rotation.x));
			camFront.z = cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y));
			camFront = glm::normalize(camFront);

			float moveSpeed = deltaTime * movementSpeed * 2.0f;
			float rotSpeed = deltaTime * rotationSpeed * 50.0f;

			// Move
			if (fabsf(axisLeft.y) > deadZone)
			{
				float pos = (fabsf(axisLeft.y) - deadZone) / range;
				position -= camFront * pos * ((axisLeft.y < 0.0f) ? -1.0f : 1.0f) * moveSpeed;
				retVal = true;
			}
			if (fabsf(axisLeft.x) > deadZone)
			{
				float pos = (fabsf(axisLeft.x) - deadZone) / range;
				position += glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * pos * ((axisLeft.x < 0.0f) ? -1.0f : 1.0f) * moveSpeed;
				retVal = true;
			}

			// Rotate
			if (fabsf(axisRight.x) > deadZone)
			{
				float pos = (fabsf(axisRight.x) - deadZone) / range;
				rotation.y += pos * ((axisRight.x < 0.0f) ? -1.0f : 1.0f) * rotSpeed;
				retVal = true;
			}
			if (fabsf(axisRight.y) > deadZone)
			{
				float pos = (fabsf(axisRight.y) - deadZone) / range;
				rotation.x -= pos * ((axisRight.y < 0.0f) ? -1.0f : 1.0f) * rotSpeed;
				retVal = true;
			}
		}
		else
		{
			// todo: move code from example base class for look-at
		}

		if (retVal)
		{
			updateViewMatrix();
		}

		return retVal;
	}

};<commit_msg>Setter for camera position<commit_after>/*
* Basic camera class
*
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
*
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/

#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>

class Camera
{
private:
	float fov;
	float znear, zfar;

	void updateViewMatrix()
	{
		glm::mat4 rotM = glm::mat4();
		glm::mat4 transM;

		rotM = glm::rotate(rotM, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
		rotM = glm::rotate(rotM, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
		rotM = glm::rotate(rotM, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));

		transM = glm::translate(glm::mat4(), position);

		if (type == CameraType::firstperson)
		{
			matrices.view = rotM * transM;
		}
		else
		{
			matrices.view = transM * rotM;
		}
	};
public:
	enum CameraType { lookat, firstperson };
	CameraType type = CameraType::lookat;

	glm::vec3 rotation = glm::vec3();
	glm::vec3 position = glm::vec3();

	float rotationSpeed = 1.0f;
	float movementSpeed = 1.0f;

	struct
	{
		glm::mat4 perspective;
		glm::mat4 view;
	} matrices;

	struct
	{
		bool left = false;
		bool right = false;
		bool up = false;
		bool down = false;
	} keys;

	bool moving()
	{
		return keys.left || keys.right || keys.up || keys.down;
	}

	void setPerspective(float fov, float aspect, float znear, float zfar)
	{
		this->fov = fov;
		this->znear = znear;
		this->zfar = zfar;
		matrices.perspective = glm::perspective(glm::radians(fov), aspect, znear, zfar);
	};

	void updateAspectRatio(float aspect)
	{
		matrices.perspective = glm::perspective(glm::radians(fov), aspect, znear, zfar);
	}

	void setPosition(glm::vec3 position)
	{
		this->position = position;
		updateViewMatrix();
	}

	void setRotation(glm::vec3 rotation)
	{
		this->rotation = rotation;
		updateViewMatrix();
	};

	void rotate(glm::vec3 delta)
	{
		this->rotation += delta;
		updateViewMatrix();
	}

	void setTranslation(glm::vec3 translation)
	{
		this->position = translation;
		updateViewMatrix();
	};

	void translate(glm::vec3 delta)
	{
		this->position += delta;
		updateViewMatrix();
	}

	void update(float deltaTime)
	{
		if (type == CameraType::firstperson)
		{
			if (moving())
			{
				glm::vec3 camFront;
				camFront.x = -cos(glm::radians(rotation.x)) * sin(glm::radians(rotation.y));
				camFront.y = sin(glm::radians(rotation.x));
				camFront.z = cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y));
				camFront = glm::normalize(camFront);

				float moveSpeed = deltaTime * movementSpeed;

				if (keys.up)
					position += camFront * moveSpeed;
				if (keys.down)
					position -= camFront * moveSpeed;
				if (keys.left)
					position -= glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * moveSpeed;
				if (keys.right)
					position += glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * moveSpeed;

				updateViewMatrix();
			}
		}
	};

	// Update camera passing separate axis data (gamepad)
	// Returns true if view or position has been changed
	bool updatePad(glm::vec2 axisLeft, glm::vec2 axisRight, float deltaTime)
	{
		bool retVal = false;

		if (type == CameraType::firstperson)
		{
			// Use the common console thumbstick layout
			// Left = view, right = move

			const float deadZone = 0.0015f;
			const float range = 1.0f - deadZone;

			glm::vec3 camFront;
			camFront.x = -cos(glm::radians(rotation.x)) * sin(glm::radians(rotation.y));
			camFront.y = sin(glm::radians(rotation.x));
			camFront.z = cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y));
			camFront = glm::normalize(camFront);

			float moveSpeed = deltaTime * movementSpeed * 2.0f;
			float rotSpeed = deltaTime * rotationSpeed * 50.0f;

			// Move
			if (fabsf(axisLeft.y) > deadZone)
			{
				float pos = (fabsf(axisLeft.y) - deadZone) / range;
				position -= camFront * pos * ((axisLeft.y < 0.0f) ? -1.0f : 1.0f) * moveSpeed;
				retVal = true;
			}
			if (fabsf(axisLeft.x) > deadZone)
			{
				float pos = (fabsf(axisLeft.x) - deadZone) / range;
				position += glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * pos * ((axisLeft.x < 0.0f) ? -1.0f : 1.0f) * moveSpeed;
				retVal = true;
			}

			// Rotate
			if (fabsf(axisRight.x) > deadZone)
			{
				float pos = (fabsf(axisRight.x) - deadZone) / range;
				rotation.y += pos * ((axisRight.x < 0.0f) ? -1.0f : 1.0f) * rotSpeed;
				retVal = true;
			}
			if (fabsf(axisRight.y) > deadZone)
			{
				float pos = (fabsf(axisRight.y) - deadZone) / range;
				rotation.x -= pos * ((axisRight.y < 0.0f) ? -1.0f : 1.0f) * rotSpeed;
				retVal = true;
			}
		}
		else
		{
			// todo: move code from example base class for look-at
		}

		if (retVal)
		{
			updateViewMatrix();
		}

		return retVal;
	}

};<|endoftext|>


<commit_before><commit_msg>PyCXX: In Python 3.9 Unicode API are being deprecated<commit_after><|endoftext|>


<commit_before>#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <gdk-pixbuf/gdk-pixbuf.h>

#include "ltiRGBPixel.h"
#include "ltiScaling.h"
#include "ltiDraw.h"                  // drawing tool
#include "ltiALLFunctor.h"            // image loader
#include "ltiCannyEdges.h"            // edge detector
#include "ltiFastEllipseExtraction.h" // ellipse detector
#include "ltiScaleSpacePyramid.h"
#include "ltiSplitImageToHSV.h"

#include "circles4.h"
#include "lib_filter.h"

GList *circles;   // for gui only, not filter

typedef struct {
  lti::image inputImg;
  lti::scaleSpacePyramid<lti::image> imgPyramid;
  lti::image scaledInputImg;
  std::vector<lti::channel8> edges;
  lti::channel8 scaledEdges;
  lti::image result;

  int minRadius;
  int maxRadius;

  std::vector<lti::fastEllipseExtraction> fee;
} circles_state_t;

// helper function for glist
static void free_1_circle(gpointer data, gpointer user_data) {
  g_free((circle_type *) data);
}

static void do_canny(circles_state_t *ct) {
  // params
  lti::cannyEdges::parameters cannyParam;
  cannyParam.thresholdMax = 0.10;
  cannyParam.thresholdMin = 0.04;
  cannyParam.kernelSize = 7;

  // run
  lti::cannyEdges canny(cannyParam);
  ct->edges.clear();
  for (int i = 0; i < ct->imgPyramid.size(); i++) {
    printf("canny[%d]: %dx%d\n", i, ct->imgPyramid[i].columns(),
	   ct->imgPyramid[i].rows());
    ct->edges.push_back(lti::channel8());
    canny.apply(ct->imgPyramid[i], ct->edges[i]);
  }
}

static GList *do_fee(circles_state_t *ct) {
  GList *result = NULL;

  // create FEE functor
  lti::fastEllipseExtraction::parameters feeParam;
  feeParam.maxArcGap = 120;
  feeParam.minLineLen = 3;

  ct->fee.clear();
  for (unsigned int i = 0; i < ct->edges.size(); i++) {
    lti::fastEllipseExtraction fee2(feeParam);
    ct->fee.push_back(fee2);

    // extract some ellipses
    ct->fee[i].apply(ct->edges[i]);

    // build list
    std::vector<lti::fastEllipseExtraction::ellipseEntry>
      &ellipses = ct->fee[i].getEllipseList();

    for(unsigned int j=0; i<ellipses.size(); i++) {
      circle_type *c = (circle_type *)g_malloc(sizeof(circle_type));

      c->x = ellipses[j].x;
      c->y = ellipses[j].y;
      c->a = ellipses[j].a;
      c->b = ellipses[j].b;
      c->t = ellipses[j].t;

      result = g_list_prepend(result, c);

      // print ellipse data
      printf(" ellipse[%i]: center=(%.0f,%.0f) semiaxis=(%.0f,%.0f) "
	     "angle=%.1f coverage=%.1f%% \n",
	     j, ellipses[j].x, ellipses[j].y,
	     ellipses[j].a, ellipses[j].b,
	     ellipses[j].t*180/3.14, ellipses[j].coverage*100);
    }
  }

  return result;
}

static circles_state_t staticState;
static GList *circlesFromImage2(circles_state_t *ct,
				const int width, const int height,
				const int stride, void *data) {
  // load image
  lti::image img(false, height, width);
  for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
      guchar *d = ((guchar *) data) + (x * 3 + y * stride);
      lti::rgbPixel p(d[0], d[1], d[2]);
      img[y][x] = p;
    }
  }
  ct->inputImg = img;

  // make pyramid
  lti::scaleSpacePyramid<lti::image>::parameters pyramidParams;
  pyramidParams.factor = 0.5;
  int levels = (int)log2(MIN(ct->inputImg.rows(), ct->inputImg.columns()));
  ct->imgPyramid = lti::scaleSpacePyramid<lti::image>(levels, pyramidParams);
  ct->imgPyramid.generate(ct->inputImg);

  // initial run
  do_canny(ct);
  return do_fee(ct);
}

// called from GUI
void circlesFromImage(const int width, const int height,
		      const int stride, void *data) {
  circles = circlesFromImage2(&staticState, width,
			      height, stride, data);
}

// 3 functions for diamond filter interface

int f_init_circles (int num_arg, char **args,
		    int bloblen, void *blob_data,
		    const char *filter_name,
		    void **filter_args) {
  circles_state_t *cr;

  // check parameters
  if (num_arg != 8) {
    return -1;
  }

  // init state
  cr = new circles_state_t;

  cr->minRadius = g_ascii_strtoull(args[0], NULL, 10);
  cr->maxRadius = g_ascii_strtoull(args[1], NULL, 10);

  // we're good
  *filter_args = cr;
  return 0;
}

int f_eval_circles (lf_obj_handle_t ohandle, void *filter_args) {
  // circles
  GList *clist;
  circles_state_t *cr = (circles_state_t *) filter_args;
  int num_circles;

  // for attributes from diamond
  size_t len;
  unsigned char *data;

  // get the data from the ohandle, convert to IplImage
  int w;
  int h;

  // width
  lf_ref_attr(ohandle, "_rows.int", &len, &data);
  w = *((int *) data);

  // height
  lf_ref_attr(ohandle, "_cols.int", &len, &data);
  h = *((int *) data);

  // image data
  lf_ref_attr(ohandle, "_rgb_image.rgbimage", &len, &data);

  // feed it to our processor
  clist = circlesFromImage2(cr, w, h, w * 3, data);

  data = NULL;

  // add the list of circles to the cache and the object
  // XXX
  num_circles = g_list_length(clist);
  if (num_circles > 0) {
    GList *l = clist;
    int i = 0;
    data = (unsigned char *) g_malloc(sizeof(float) * 5 * num_circles);

    // pack in
    while (l != NULL) {
      float *p = ((float *) data) + i;
      circle_type *c = (circle_type *) l->data;
      p[0] = c->x;
      p[1] = c->y;
      p[2] = c->a;
      p[3] = c->b;
      p[4] = c->t;

      i += 5;
      l = g_list_next(l);
    }
    lf_write_attr(ohandle, "circle-data", sizeof(float) * 5 * num_circles, data);
  }

  // free others
  g_list_foreach(clist, free_1_circle, NULL);
  g_list_free(clist);
  clist = NULL;
  g_free(data);
  data = NULL;

  // return number of circles
  return num_circles;
}

int f_fini_circles (void *filter_args) {
  delete((circles_state_t *) filter_args);

  return 0;
}
<commit_msg>fix bug, simplify<commit_after>#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <gdk-pixbuf/gdk-pixbuf.h>

#include "ltiRGBPixel.h"
#include "ltiScaling.h"
#include "ltiDraw.h"                  // drawing tool
#include "ltiALLFunctor.h"            // image loader
#include "ltiCannyEdges.h"            // edge detector
#include "ltiFastEllipseExtraction.h" // ellipse detector
#include "ltiScaleSpacePyramid.h"
#include "ltiSplitImageToHSV.h"

#include "circles4.h"
#include "lib_filter.h"

GList *circles;   // for gui only, not filter

typedef struct {
  int minRadius;
  int maxRadius;
} circles_state_t;

// helper function for glist
static void free_1_circle(gpointer data, gpointer user_data) {
  g_free((circle_type *) data);
}

static void do_canny(lti::scaleSpacePyramid<lti::image> &imgPyramid,
		     std::vector<lti::channel8> &edges) {
  // params
  lti::cannyEdges::parameters cannyParam;
  cannyParam.thresholdMax = 0.10;
  cannyParam.thresholdMin = 0.04;
  cannyParam.kernelSize = 7;

  // run
  lti::cannyEdges canny(cannyParam);
  edges.clear();
  for (int i = 0; i < imgPyramid.size(); i++) {
    printf("canny[%d]: %dx%d\n", i, imgPyramid[i].columns(),
	   imgPyramid[i].rows());
    edges.push_back(lti::channel8());
    canny.apply(imgPyramid[i], edges[i]);
  }
}

static GList *do_fee(std::vector<lti::fastEllipseExtraction> &fee,
		     std::vector<lti::channel8> &edges) {
  GList *result = NULL;

  // create FEE functor
  lti::fastEllipseExtraction::parameters feeParam;
  feeParam.maxArcGap = 120;
  feeParam.minLineLen = 3;

  fee.clear();
  for (unsigned int i = 0; i < edges.size(); i++) {
    lti::fastEllipseExtraction fee2(feeParam);
    fee.push_back(fee2);

    // extract some ellipses
    printf("extracting from pyramid %d\n", i);
    fee[i].apply(edges[i]);

    // build list
    std::vector<lti::fastEllipseExtraction::ellipseEntry>
      &ellipses = fee[i].getEllipseList();

    for(unsigned int j=0; j<ellipses.size(); j++) {
      circle_type *c = (circle_type *)g_malloc(sizeof(circle_type));

      c->x = ellipses[j].x;
      c->y = ellipses[j].y;
      c->a = ellipses[j].a;
      c->b = ellipses[j].b;
      c->t = ellipses[j].t;

      result = g_list_prepend(result, c);

      // print ellipse data
      printf(" ellipse[%i]: center=(%.0f,%.0f) semiaxis=(%.0f,%.0f) "
	     "angle=%.1f coverage=%.1f%% \n",
	     j, ellipses[j].x, ellipses[j].y,
	     ellipses[j].a, ellipses[j].b,
	     ellipses[j].t*180/3.14, ellipses[j].coverage*100);
    }
  }

  return result;
}

static circles_state_t staticState;
static GList *circlesFromImage2(circles_state_t *ct,
				const int width, const int height,
				const int stride, void *data) {
  // load image
  lti::image img(false, height, width);
  for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
      guchar *d = ((guchar *) data) + (x * 3 + y * stride);
      lti::rgbPixel p(d[0], d[1], d[2]);
      img[y][x] = p;
    }
  }

  // make pyramid
  lti::scaleSpacePyramid<lti::image>::parameters pyramidParams;
  pyramidParams.factor = 0.5;
  int levels = (int)log2(MIN(img.rows(), img.columns()));
  lti::scaleSpacePyramid<lti::image> imgPyramid(levels, pyramidParams);
  imgPyramid.generate(img);

  // make vectors
  std::vector<lti::channel8> edges;
  std::vector<lti::fastEllipseExtraction> fee;

  // run
  do_canny(imgPyramid, edges);
  return do_fee(fee, edges);
}

// called from GUI
void circlesFromImage(const int width, const int height,
		      const int stride, void *data) {
  circles = circlesFromImage2(&staticState, width,
			      height, stride, data);
}

// 3 functions for diamond filter interface

int f_init_circles (int num_arg, char **args,
		    int bloblen, void *blob_data,
		    const char *filter_name,
		    void **filter_args) {
  circles_state_t *cr;

  // check parameters
  if (num_arg != 8) {
    return -1;
  }

  // init state
  cr = new circles_state_t;

  cr->minRadius = g_ascii_strtoull(args[0], NULL, 10);
  cr->maxRadius = g_ascii_strtoull(args[1], NULL, 10);

  // we're good
  *filter_args = cr;
  return 0;
}

int f_eval_circles (lf_obj_handle_t ohandle, void *filter_args) {
  // circles
  GList *clist;
  circles_state_t *cr = (circles_state_t *) filter_args;
  int num_circles;

  // for attributes from diamond
  size_t len;
  unsigned char *data;

  // get the data from the ohandle, convert to IplImage
  int w;
  int h;

  // width
  lf_ref_attr(ohandle, "_rows.int", &len, &data);
  w = *((int *) data);

  // height
  lf_ref_attr(ohandle, "_cols.int", &len, &data);
  h = *((int *) data);

  // image data
  lf_ref_attr(ohandle, "_rgb_image.rgbimage", &len, &data);

  // feed it to our processor
  clist = circlesFromImage2(cr, w, h, w * 3, data);

  data = NULL;

  // add the list of circles to the cache and the object
  // XXX
  num_circles = g_list_length(clist);
  if (num_circles > 0) {
    GList *l = clist;
    int i = 0;
    data = (unsigned char *) g_malloc(sizeof(float) * 5 * num_circles);

    // pack in
    while (l != NULL) {
      float *p = ((float *) data) + i;
      circle_type *c = (circle_type *) l->data;
      p[0] = c->x;
      p[1] = c->y;
      p[2] = c->a;
      p[3] = c->b;
      p[4] = c->t;

      i += 5;
      l = g_list_next(l);
    }
    lf_write_attr(ohandle, "circle-data", sizeof(float) * 5 * num_circles, data);
  }

  // free others
  g_list_foreach(clist, free_1_circle, NULL);
  g_list_free(clist);
  clist = NULL;
  g_free(data);
  data = NULL;

  // return number of circles
  return num_circles;
}

int f_fini_circles (void *filter_args) {
  delete((circles_state_t *) filter_args);

  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013-2014 Kajetan Swierk <k0zmo@outlook.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

#include "Logic/NodeType.h"
#include "Logic/NodeFactory.h"
#include "Kommon/StringUtils.h"

#include <opencv2/nonfree/features2d.hpp>

class SiftFeatureDetectorNodeType : public NodeType
{
public:
    SiftFeatureDetectorNodeType()
        : _nFeatures(0)
        , _nOctaveLayers(3)
        , _contrastThreshold(0.04)
        , _edgeThreshold(10)
        , _sigma(1.6)
    {
    }

    bool setProperty(PropertyID propId, const NodeProperty& newValue) override
    {
        switch(static_cast<pid>(propId))
        {
        case pid::NumFeatures:
            _nFeatures = newValue.toInt();
            return true;
        case pid::NumOctaveLayers:
            _nOctaveLayers = newValue.toInt();
            return true;
        case pid::ContrastThreshold:
            _contrastThreshold = newValue.toDouble();
            return true;
        case pid::EdgeThreshold:
            _edgeThreshold = newValue.toDouble();
            return true;
        case pid::Sigma:
            _sigma = newValue.toDouble();
            return true;
        }
        return false;
    }

    NodeProperty property(PropertyID propId) const override
    {
        switch(static_cast<pid>(propId))
        {
        case pid::NumFeatures: return _nFeatures;
        case pid::NumOctaveLayers: return _nOctaveLayers;
        case pid::ContrastThreshold: return _contrastThreshold;
        case pid::EdgeThreshold: return _edgeThreshold;
        case pid::Sigma: return _sigma;
        }

        return NodeProperty();
    }

    ExecutionStatus execute(NodeSocketReader& reader, NodeSocketWriter& writer) override
    {
        // Read input sockets
        const cv::Mat& src = reader.readSocket(0).getImageMono();
        // Acquire output sockets
        KeyPoints& kp = writer.acquireSocket(0).getKeypoints();

        // Validate inputs
        if(src.empty())
            return ExecutionStatus(EStatus::Ok);

        // Do stuff
        cv::SiftFeatureDetector detector(_nFeatures, _nOctaveLayers,
            _contrastThreshold, _edgeThreshold, _sigma);
        detector.detect(src, kp.kpoints);
        kp.image = src;

        return ExecutionStatus(EStatus::Ok,
            string_format("Keypoints detected: %d", (int) kp.kpoints.size()));
    }

    void configuration(NodeConfig& nodeConfig) const override
    {
        static const InputSocketConfig in_config[] = {
            { ENodeFlowDataType::ImageMono, "image", "Image", "" },
            { ENodeFlowDataType::Invalid, "", "", "" }
        };
        static const OutputSocketConfig out_config[] = {
            { ENodeFlowDataType::Keypoints, "keypoints", "Keypoints", "" },
            { ENodeFlowDataType::Invalid, "", "", "" }
        };
        static const PropertyConfig prop_config[] = {
            { EPropertyType::Integer, "Number of best features to retain", "min:0" },
            { EPropertyType::Integer, "Number of layers in each octave", "min:2" },
            { EPropertyType::Double, "Contrast threshold", "" },
            { EPropertyType::Double, "Edge threshold", "" },
            { EPropertyType::Double, "Input image sigma", "" },
            { EPropertyType::Unknown, "", "" }
        };

        nodeConfig.description = "Extracts keypoints using difference of gaussians (DoG) algorithm.";
        nodeConfig.pInputSockets = in_config;
        nodeConfig.pOutputSockets = out_config;
        nodeConfig.pProperties = prop_config;
    }

protected:
    enum class pid
    {
        NumFeatures,
        NumOctaveLayers,
        ContrastThreshold,
        EdgeThreshold,
        Sigma
    };

    int _nFeatures;
    int _nOctaveLayers;
    double _contrastThreshold;
    double _edgeThreshold;
    double _sigma;
};

class SiftDescriptorExtractorNodeType : public NodeType
{
public:
    ExecutionStatus execute(NodeSocketReader& reader, NodeSocketWriter& writer) override
    {
        // Read input sockets
        const KeyPoints& kp = reader.readSocket(0).getKeypoints();

        // Validate inputs
        if(kp.kpoints.empty() || kp.image.empty())
            return ExecutionStatus(EStatus::Ok);

        // Acquire output sockets
        KeyPoints& outKp = writer.acquireSocket(0).getKeypoints();
        cv::Mat& outDescriptors = writer.acquireSocket(1).getArray();
        outKp = kp;

        // Do stuff
        cv::SiftDescriptorExtractor extractor;
        extractor.compute(kp.image, outKp.kpoints, outDescriptors);

        return ExecutionStatus(EStatus::Ok);
    }

    void configuration(NodeConfig& nodeConfig) const override
    {
        static const InputSocketConfig in_config[] = {
            { ENodeFlowDataType::Keypoints, "keypoints", "Keypoints", "" },
            { ENodeFlowDataType::Invalid, "", "", "" }
        };
        static const OutputSocketConfig out_config[] = {
            { ENodeFlowDataType::Keypoints, "output", "Keypoints", "" },
            { ENodeFlowDataType::Array, "output", "Descriptors", "" },
            { ENodeFlowDataType::Invalid, "", "", "" }
        };

        nodeConfig.description = "Computes descriptors using the Scale Invariant Feature Transform (SIFT) algorithm.";
        nodeConfig.pInputSockets = in_config;
        nodeConfig.pOutputSockets = out_config;
    }
};

class SiftNodeType : public SiftFeatureDetectorNodeType
{
public:
    ExecutionStatus execute(NodeSocketReader& reader, NodeSocketWriter& writer) override
    {
        // Read input sockets
        const cv::Mat& src = reader.readSocket(0).getImageMono();
        // Acquire output sockets
        KeyPoints& kp = writer.acquireSocket(0).getKeypoints();
        cv::Mat& descriptors = writer.acquireSocket(1).getArray();

        // Validate inputs
        if(src.empty())
            return ExecutionStatus(EStatus::Ok);

        // Do stuff
        cv::SIFT sift(_nFeatures, _nOctaveLayers,
            _contrastThreshold, _edgeThreshold, _sigma);
        sift(src, cv::noArray(), kp.kpoints, descriptors);
        kp.image = src;

        return ExecutionStatus(EStatus::Ok,
            string_format("Keypoints detected: %d", (int) kp.kpoints.size()));
    }

    void configuration(NodeConfig& nodeConfig) const override
    {
        SiftFeatureDetectorNodeType::configuration(nodeConfig);

        // Just add one more output socket
        static const OutputSocketConfig out_config[] = {
            { ENodeFlowDataType::Keypoints, "keypoints", "Keypoints", "" },
            { ENodeFlowDataType::Array, "output", "Descriptors", "" },
            { ENodeFlowDataType::Invalid, "", "", "" }
        };

        nodeConfig.description = "Extracts keypoints and computes descriptors using the Scale Invariant Feature Transform (SIFT) algorithm.";
        nodeConfig.pOutputSockets = out_config;
    }
};

REGISTER_NODE("Features/Descriptors/SIFT", SiftDescriptorExtractorNodeType)
REGISTER_NODE("Features/Detectors/SIFT", SiftFeatureDetectorNodeType)
REGISTER_NODE("Features/SIFT", SiftNodeType)
<commit_msg>updated SIFT nodes for new node conf. interface [WIP]<commit_after>/*
 * Copyright (c) 2013-2014 Kajetan Swierk <k0zmo@outlook.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

#include "Logic/NodeType.h"
#include "Logic/NodeFactory.h"
#include "Kommon/StringUtils.h"

#include <opencv2/nonfree/features2d.hpp>

class SiftFeatureDetectorNodeType : public NodeType
{
public:
    SiftFeatureDetectorNodeType()
        : _nFeatures(0)
        , _nOctaveLayers(3)
        , _contrastThreshold(0.04)
        , _edgeThreshold(10)
        , _sigma(1.6)
    {
        addInput("Image", ENodeFlowDataType::ImageMono);
        addOutput("Keypoints", ENodeFlowDataType::Keypoints);
        addProperty("Number of best features to retain", _nFeatures)
            .setValidator(make_validator<MinPropertyValidator<int>>(0))
            .setUiHints("min:0");
        addProperty("Number of layers in each octave", _nOctaveLayers)
            .setValidator(make_validator<MinPropertyValidator<int>>(2))
            .setUiHints("min:2");
        addProperty("Contrast threshold", _contrastThreshold);
        addProperty("Edge threshold", _edgeThreshold);
        addProperty("Input image sigma", _sigma);
        setDescription("Extracts keypoints using difference of gaussians (DoG) algorithm.");
    }

    ExecutionStatus execute(NodeSocketReader& reader, NodeSocketWriter& writer) override
    {
        // Read input sockets
        const cv::Mat& src = reader.readSocket(0).getImageMono();
        // Acquire output sockets
        KeyPoints& kp = writer.acquireSocket(0).getKeypoints();

        // Validate inputs
        if(src.empty())
            return ExecutionStatus(EStatus::Ok);

        // Do stuff
        cv::SiftFeatureDetector detector(_nFeatures, _nOctaveLayers,
            _contrastThreshold, _edgeThreshold, _sigma);
        detector.detect(src, kp.kpoints);
        kp.image = src;

        return ExecutionStatus(EStatus::Ok,
            string_format("Keypoints detected: %d", (int) kp.kpoints.size()));
    }

protected:
    TypedNodeProperty<int> _nFeatures;
    TypedNodeProperty<int> _nOctaveLayers;
    TypedNodeProperty<double> _contrastThreshold;
    TypedNodeProperty<double> _edgeThreshold;
    TypedNodeProperty<double> _sigma;
};

class SiftDescriptorExtractorNodeType : public NodeType
{
public:
    SiftDescriptorExtractorNodeType()
    {
        addInput("Keypoints", ENodeFlowDataType::Keypoints);
        addOutput("Keypoints", ENodeFlowDataType::Keypoints);
        addOutput("Descriptors", ENodeFlowDataType::Array);
        setDescription("Computes descriptors using the Scale Invariant Feature Transform (SIFT) algorithm.");
    }

    ExecutionStatus execute(NodeSocketReader& reader, NodeSocketWriter& writer) override
    {
        // Read input sockets
        const KeyPoints& kp = reader.readSocket(0).getKeypoints();

        // Validate inputs
        if(kp.kpoints.empty() || kp.image.empty())
            return ExecutionStatus(EStatus::Ok);

        // Acquire output sockets
        KeyPoints& outKp = writer.acquireSocket(0).getKeypoints();
        cv::Mat& outDescriptors = writer.acquireSocket(1).getArray();
        outKp = kp;

        // Do stuff
        cv::SiftDescriptorExtractor extractor;
        extractor.compute(kp.image, outKp.kpoints, outDescriptors);

        return ExecutionStatus(EStatus::Ok);
    }
};

class SiftNodeType : public SiftFeatureDetectorNodeType
{
public:
    SiftNodeType()
        : SiftFeatureDetectorNodeType()
    {
        // Just add one more output socket
        clearOutputs();
        addOutput("Keypoints", ENodeFlowDataType::Keypoints);
        addOutput("Descriptors", ENodeFlowDataType::Array);
        setDescription("Extracts keypoints and computes descriptors using "
            "the Scale Invariant Feature Transform (SIFT) algorithm.");
    }

    ExecutionStatus execute(NodeSocketReader& reader, NodeSocketWriter& writer) override
    {
        // Read input sockets
        const cv::Mat& src = reader.readSocket(0).getImageMono();
        // Acquire output sockets
        KeyPoints& kp = writer.acquireSocket(0).getKeypoints();
        cv::Mat& descriptors = writer.acquireSocket(1).getArray();

        // Validate inputs
        if(src.empty())
            return ExecutionStatus(EStatus::Ok);

        // Do stuff
        cv::SIFT sift(_nFeatures, _nOctaveLayers,
            _contrastThreshold, _edgeThreshold, _sigma);
        sift(src, cv::noArray(), kp.kpoints, descriptors);
        kp.image = src;

        return ExecutionStatus(EStatus::Ok,
            string_format("Keypoints detected: %d", (int) kp.kpoints.size()));
    }
};

REGISTER_NODE("Features/Descriptors/SIFT", SiftDescriptorExtractorNodeType)
REGISTER_NODE("Features/Detectors/SIFT", SiftFeatureDetectorNodeType)
REGISTER_NODE("Features/SIFT", SiftNodeType)
<|endoftext|>


<commit_before> /**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

#include <TMath.h>
#include "AliMUONConstants.h"

ClassImp(AliMUONConstants)

Int_t   AliMUONConstants::fgNCh = 14;
Int_t   AliMUONConstants::fgNTrackingCh = 10;
Int_t   AliMUONConstants::fgNTriggerCh = 4;
Int_t   AliMUONConstants::fgNTriggerCircuit = 234;
Int_t   AliMUONConstants::fgNDetElem = 228;

Float_t AliMUONConstants::fgDefaultChamberZ[14] =
  {-526.16, -545.24, -676.4, -695.4, // St12
   -967.5, -998.5, -1276.5, -1307.5, -1406.6, -1437.6,// updated 08/05, EDMS id 335328 (A. Tournaire)
   -1603.5, -1620.5, -1703.5, -1720.5}; // M1 & M2

Float_t  AliMUONConstants::fgDzCh   = 15.5/2.;
Float_t  AliMUONConstants::fgDzSlat = 8.5/2.;

Float_t  AliMUONConstants::fgSqrtKx3 = 0.7131;
Float_t  AliMUONConstants::fgSqrtKy3 = 0.7642;

Float_t  AliMUONConstants::fgSqrtKx3St1 = 0.7000;
Float_t  AliMUONConstants::fgSqrtKy3St1 = 0.7550;

Float_t  AliMUONConstants::fgChargeCorrel    = 0.11;
Float_t  AliMUONConstants::fgChargeCorrelSt1 = 1.0; //???
Float_t  AliMUONConstants::fgPitch     = 0.25;
Float_t  AliMUONConstants::fgPitchSt1  = 0.21;

// From Alain TOURNAIRE
// ALICE / ALICE Engineering baseline / Dimuonspectrometer (DIS) v7-1
// EDMS Id 335328 for "search in EDMS
// These are the diameter (innner and ounner) values of the active surface
Float_t  AliMUONConstants::fgDmin[7]  = {   36.4,  46.2,  63.0,   79.0,   79.0,  99.0,  100.0};
Float_t  AliMUONConstants::fgDmax[7]  = {  176.6, 229.0, 308.84, 418.2,  522.0, 1224.0, 1300.0};

Int_t    AliMUONConstants::fgMaxZoom = 20;

//______________________________________________________________________________
Int_t AliMUONConstants::ChamberNumber(Float_t z)
{
  // return chamber number according z position of hit. Should be taken from geometry ?

  Float_t dMaxChamber = DzSlat() + DzCh() + 0.25; // cm st 3 &4 & 5
  if ( z >  (DefaultChamberZ(4)+50.)) dMaxChamber = 7.; // cm stations 1 & 2
  Int_t iChamber;

  for (iChamber = 0; iChamber < 10; iChamber++) {

    if (TMath::Abs(z-DefaultChamberZ(iChamber)) < dMaxChamber) {
      return iChamber;
    }
  }
  return -1;
}
<commit_msg>overlaps fixed<commit_after> /**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

#include <TMath.h>
#include "AliMUONConstants.h"

ClassImp(AliMUONConstants)

Int_t   AliMUONConstants::fgNCh = 14;
Int_t   AliMUONConstants::fgNTrackingCh = 10;
Int_t   AliMUONConstants::fgNTriggerCh = 4;
Int_t   AliMUONConstants::fgNTriggerCircuit = 234;
Int_t   AliMUONConstants::fgNDetElem = 228;

Float_t AliMUONConstants::fgDefaultChamberZ[14] =
  {-526.16, -545.24, -676.4, -695.4, // St12
   -967.5, -998.5, -1276.5, -1307.5, -1406.6, -1437.6,// updated 08/05, EDMS id 335328 (A. Tournaire)
   -1603.5, -1620.5, -1703.5, -1720.5}; // M1 & M2

Float_t  AliMUONConstants::fgDzCh   = 15.5/2.;
Float_t  AliMUONConstants::fgDzSlat = 8.5/2.;

Float_t  AliMUONConstants::fgSqrtKx3 = 0.7131;
Float_t  AliMUONConstants::fgSqrtKy3 = 0.7642;

Float_t  AliMUONConstants::fgSqrtKx3St1 = 0.7000;
Float_t  AliMUONConstants::fgSqrtKy3St1 = 0.7550;

Float_t  AliMUONConstants::fgChargeCorrel    = 0.11;
Float_t  AliMUONConstants::fgChargeCorrelSt1 = 1.0; //???
Float_t  AliMUONConstants::fgPitch     = 0.25;
Float_t  AliMUONConstants::fgPitchSt1  = 0.21;

// From Alain TOURNAIRE
// ALICE / ALICE Engineering baseline / Dimuonspectrometer (DIS) v7-1
// EDMS Id 335328 for "search in EDMS
// These are the diameter (innner and ounner) values of the active surface
Float_t  AliMUONConstants::fgDmin[7]  = {   36.4,  46.2,  63.0,   79.0,   79.0,  99.0,  100.0};
Float_t  AliMUONConstants::fgDmax[7]  = {  176.6, 229.0, 308.84, 418.2,  522.0, 850.0, 900.0};

Int_t    AliMUONConstants::fgMaxZoom = 20;

//______________________________________________________________________________
Int_t AliMUONConstants::ChamberNumber(Float_t z)
{
  // return chamber number according z position of hit. Should be taken from geometry ?

  Float_t dMaxChamber = DzSlat() + DzCh() + 0.25; // cm st 3 &4 & 5
  if ( z >  (DefaultChamberZ(4)+50.)) dMaxChamber = 7.; // cm stations 1 & 2
  Int_t iChamber;

  for (iChamber = 0; iChamber < 10; iChamber++) {

    if (TMath::Abs(z-DefaultChamberZ(iChamber)) < dMaxChamber) {
      return iChamber;
    }
  }
  return -1;
}
<|endoftext|>


<commit_before> /**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

#include "AliMUONConstants.h"

#include "AliLog.h"

#include "TMath.h"
#include "TClass.h"
#include "AliMpConstants.h"

//-----------------------------------------------------------------------------
/// \class AliMUONConstants
/// This class holds various constants to be used in many places,
/// such as the number of tracking and trigger chambers,
/// some geometrical constants (to build the initial geometry for simulation)
/// and mathieson distribution default values.
/// Those constants should as much as possible replace hard-coded values
/// which are to be considered strictly illegal in the MUON code (or any code,
/// by the way).
//-----------------------------------------------------------------------------

/// \cond CLASSIMP
ClassImp(AliMUONConstants)
/// \endcond

Int_t   AliMUONConstants::fgNTrackingSt = 5;
Int_t   AliMUONConstants::fgNTriggerCircuit = 234;
Int_t   AliMUONConstants::fgNDetElem = 228;
Int_t   AliMUONConstants::fgNGeomModules = 20;
Float_t AliMUONConstants::fgkTriggerTofLimit = 75E-9;

Float_t AliMUONConstants::fgDefaultChamberZ[14] =
  {-526.16, -545.24, -676.4, -695.4, // St12
   -967.5, -998.5, -1276.5, -1307.5, -1406.6, -1437.6,// updated 08/05, EDMS id 335328 (A. Tournaire)
   -1603.5, -1620.5, -1703.5, -1720.5}; // M1 & M2

// These are used by AliMUONConstants::ChamberNumber and must be calculated once
// by that method from fgDzCh, fgDzSlat, fgDefaultChamberZ and fgSt345inclination,
// so for now we set everything to zero.
Float_t AliMUONConstants::fgDefaultChamberMinZ[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
Float_t AliMUONConstants::fgDefaultChamberMaxZ[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

Float_t AliMUONConstants::fgDefaultRatioTriggerChamber[4] =
{1., 1.01060, 1.06236, 1.07296};

Float_t  AliMUONConstants::fgSt345inclination = 0.794; // in degrees, rotation axis is X axis

Float_t  AliMUONConstants::fgDzCh   = 15.5/2.;
Float_t  AliMUONConstants::fgDzSlat = 8.5/2.;

Float_t  AliMUONConstants::fgSqrtKx3 = 0.7131;
Float_t  AliMUONConstants::fgSqrtKy3 = 0.7642;

Float_t  AliMUONConstants::fgSqrtKx3St1 = 0.7000;
Float_t  AliMUONConstants::fgSqrtKy3St1 = 0.7550;

Float_t  AliMUONConstants::fgChargeCorrel    = 0.11;
Float_t  AliMUONConstants::fgChargeCorrelSt1 = 1.0; //???
Float_t  AliMUONConstants::fgPitch     = 0.25;
Float_t  AliMUONConstants::fgPitchSt1  = 0.21;

// From Alain TOURNAIRE
// ALICE / ALICE Engineering baseline / Dimuonspectrometer (DIS) v7-1
// EDMS Id 335328 for "search in EDMS
// These are the diameter (Dmin == innner and Dmax - outner) values of the active surface
// In the case of Dmax, the value corresponds to the maximum diameter of the active surface with 2pi coverture in phi
Float_t  AliMUONConstants::fgDmin[7]  = {   36.4,  46.2,  63.0,   79.0,   79.0,  99.0,  100.0};  // cm
Float_t  AliMUONConstants::fgDmax[7]  = {  176.6, 229.0, 308.84, 418.2,  522.0, 850.0, 900.0};   // cm

Int_t    AliMUONConstants::fgMaxZoom = 20;

// Defaults parameters for dipole magnet
// From ALICE Dimuon - parameters / geometry table,
// V7-3 (version 7 created 24/03/2004 updated 25/10/2005)
Double_t AliMUONConstants::fgCoilZ = -994.05;
Double_t AliMUONConstants::fgCoilL = 502.1;
Double_t AliMUONConstants::fgYokeZ = -986.6;
Double_t AliMUONConstants::fgYokeL = 309.4;

// Defaults parameters for absorber (27/06/07)
const Double_t AliMUONConstants::fgkAbsZBeg = -90.;
const Double_t AliMUONConstants::fgkAbsZEnd = -505.;

// Default trigger chamber resolution (cm)
const Double_t AliMUONConstants::fgkTriggerNonBendingReso = 1.;
const Double_t AliMUONConstants::fgkTriggerBendingReso = 1.;

// Defaults parameters for muon filter (19/11/07)
const Double_t AliMUONConstants::fgkMuonFilterZBeg = -1471.;
const Double_t AliMUONConstants::fgkMuonFilterZEnd = -1471.-120.;
const Double_t AliMUONConstants::fgkMuonFilterX0 = 1.76;

// Defaults parameters for track reconstruction
Double_t  AliMUONConstants::fgChamberThicknessInX0 = 0.03;

const Double_t AliMUONConstants::fgkMostProbBendingMomentum = 2.0;

//______________________________________________________________________________
Int_t AliMUONConstants::NCh()
{
  return AliMpConstants::NofChambers();
}

//______________________________________________________________________________
Int_t AliMUONConstants::NTrackingCh()
{
  return AliMpConstants::NofTrackingChambers();
}

//______________________________________________________________________________
Int_t AliMUONConstants::ChamberNumber(Float_t z, bool warn)
{
  // return chamber number according z position of hit. Should be taken from geometry ?

  if (fgDefaultChamberMinZ[0] == 0) // Are the min/max Z arrays initialised?
  {
    // The min and max Z arrays need to be calculated.
    for (Int_t i = 0; i < NCh(); i++)
    {
      Float_t a = 0, b = 0;
      if (4 <= i and i < 10)
      {
        Float_t dzAngle = TMath::Tan(TMath::Pi()*St345Inclination()/180.) * Rmax(i/2);
        // We add 2.5mm since Rmax is an under-estimate.
        a = DefaultChamberZ(i) + DzSlat() + DzCh() + dzAngle + 0.25;
        b = DefaultChamberZ(i) - DzSlat() - DzCh() - dzAngle - 0.25;
      }
      else
      {
        a = DefaultChamberZ(i) + DzSlat();
        b = DefaultChamberZ(i) - DzSlat();
      }
      fgDefaultChamberMinZ[i] = TMath::Min(a, b);
      fgDefaultChamberMaxZ[i] = TMath::Max(a, b);
    }
  }

  // We can apply a binary search for the chamber since the fgDefaultChamberMinZ and
  // fgDefaultChamberMaxZ arrays are ordered.
  Int_t mini = 0, maxi = NCh()-1;
  while (mini <= maxi)
  {
    Int_t iChamber = (maxi + mini) / 2;
    if (z < fgDefaultChamberMinZ[iChamber])
      mini = iChamber+1;
    else if (z > fgDefaultChamberMaxZ[iChamber])
      maxi = iChamber-1;
    else
      // We are between min and max Z of chamber number iChamber so we found our chamber.
      return iChamber;
  }

  if (warn) AliWarningClass(Form("No chamber number found for z = %f",z));
  return -1;
}
<commit_msg>Fixing overlap: decrease inner diameter of the active area envelope of MT1  by 2 mm. (Bogdan)<commit_after> /**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

#include "AliMUONConstants.h"

#include "AliLog.h"

#include "TMath.h"
#include "TClass.h"
#include "AliMpConstants.h"

//-----------------------------------------------------------------------------
/// \class AliMUONConstants
/// This class holds various constants to be used in many places,
/// such as the number of tracking and trigger chambers,
/// some geometrical constants (to build the initial geometry for simulation)
/// and mathieson distribution default values.
/// Those constants should as much as possible replace hard-coded values
/// which are to be considered strictly illegal in the MUON code (or any code,
/// by the way).
//-----------------------------------------------------------------------------

/// \cond CLASSIMP
ClassImp(AliMUONConstants)
/// \endcond

Int_t   AliMUONConstants::fgNTrackingSt = 5;
Int_t   AliMUONConstants::fgNTriggerCircuit = 234;
Int_t   AliMUONConstants::fgNDetElem = 228;
Int_t   AliMUONConstants::fgNGeomModules = 20;
Float_t AliMUONConstants::fgkTriggerTofLimit = 75E-9;

Float_t AliMUONConstants::fgDefaultChamberZ[14] =
  {-526.16, -545.24, -676.4, -695.4, // St12
   -967.5, -998.5, -1276.5, -1307.5, -1406.6, -1437.6,// updated 08/05, EDMS id 335328 (A. Tournaire)
   -1603.5, -1620.5, -1703.5, -1720.5}; // M1 & M2

// These are used by AliMUONConstants::ChamberNumber and must be calculated once
// by that method from fgDzCh, fgDzSlat, fgDefaultChamberZ and fgSt345inclination,
// so for now we set everything to zero.
Float_t AliMUONConstants::fgDefaultChamberMinZ[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
Float_t AliMUONConstants::fgDefaultChamberMaxZ[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

Float_t AliMUONConstants::fgDefaultRatioTriggerChamber[4] =
{1., 1.01060, 1.06236, 1.07296};

Float_t  AliMUONConstants::fgSt345inclination = 0.794; // in degrees, rotation axis is X axis

Float_t  AliMUONConstants::fgDzCh   = 15.5/2.;
Float_t  AliMUONConstants::fgDzSlat = 8.5/2.;

Float_t  AliMUONConstants::fgSqrtKx3 = 0.7131;
Float_t  AliMUONConstants::fgSqrtKy3 = 0.7642;

Float_t  AliMUONConstants::fgSqrtKx3St1 = 0.7000;
Float_t  AliMUONConstants::fgSqrtKy3St1 = 0.7550;

Float_t  AliMUONConstants::fgChargeCorrel    = 0.11;
Float_t  AliMUONConstants::fgChargeCorrelSt1 = 1.0; //???
Float_t  AliMUONConstants::fgPitch     = 0.25;
Float_t  AliMUONConstants::fgPitchSt1  = 0.21;

// From Alain TOURNAIRE
// ALICE / ALICE Engineering baseline / Dimuonspectrometer (DIS) v7-1
// EDMS Id 335328 for "search in EDMS
// These are the diameter (Dmin == innner and Dmax - outner) values of the active surface
// In the case of Dmax, the value corresponds to the maximum diameter of the active surface with 2pi coverture in phi
Float_t  AliMUONConstants::fgDmin[7]  = {   36.4,  46.2,  63.0,   79.0,   79.0,  98.8,  100.0};  // cm
Float_t  AliMUONConstants::fgDmax[7]  = {  176.6, 229.0, 308.84, 418.2,  522.0, 850.0, 900.0};   // cm

Int_t    AliMUONConstants::fgMaxZoom = 20;

// Defaults parameters for dipole magnet
// From ALICE Dimuon - parameters / geometry table,
// V7-3 (version 7 created 24/03/2004 updated 25/10/2005)
Double_t AliMUONConstants::fgCoilZ = -994.05;
Double_t AliMUONConstants::fgCoilL = 502.1;
Double_t AliMUONConstants::fgYokeZ = -986.6;
Double_t AliMUONConstants::fgYokeL = 309.4;

// Defaults parameters for absorber (27/06/07)
const Double_t AliMUONConstants::fgkAbsZBeg = -90.;
const Double_t AliMUONConstants::fgkAbsZEnd = -505.;

// Default trigger chamber resolution (cm)
const Double_t AliMUONConstants::fgkTriggerNonBendingReso = 1.;
const Double_t AliMUONConstants::fgkTriggerBendingReso = 1.;

// Defaults parameters for muon filter (19/11/07)
const Double_t AliMUONConstants::fgkMuonFilterZBeg = -1471.;
const Double_t AliMUONConstants::fgkMuonFilterZEnd = -1471.-120.;
const Double_t AliMUONConstants::fgkMuonFilterX0 = 1.76;

// Defaults parameters for track reconstruction
Double_t  AliMUONConstants::fgChamberThicknessInX0 = 0.03;

const Double_t AliMUONConstants::fgkMostProbBendingMomentum = 2.0;

//______________________________________________________________________________
Int_t AliMUONConstants::NCh()
{
  return AliMpConstants::NofChambers();
}

//______________________________________________________________________________
Int_t AliMUONConstants::NTrackingCh()
{
  return AliMpConstants::NofTrackingChambers();
}

//______________________________________________________________________________
Int_t AliMUONConstants::ChamberNumber(Float_t z, bool warn)
{
  // return chamber number according z position of hit. Should be taken from geometry ?

  if (fgDefaultChamberMinZ[0] == 0) // Are the min/max Z arrays initialised?
  {
    // The min and max Z arrays need to be calculated.
    for (Int_t i = 0; i < NCh(); i++)
    {
      Float_t a = 0, b = 0;
      if (4 <= i and i < 10)
      {
        Float_t dzAngle = TMath::Tan(TMath::Pi()*St345Inclination()/180.) * Rmax(i/2);
        // We add 2.5mm since Rmax is an under-estimate.
        a = DefaultChamberZ(i) + DzSlat() + DzCh() + dzAngle + 0.25;
        b = DefaultChamberZ(i) - DzSlat() - DzCh() - dzAngle - 0.25;
      }
      else
      {
        a = DefaultChamberZ(i) + DzSlat();
        b = DefaultChamberZ(i) - DzSlat();
      }
      fgDefaultChamberMinZ[i] = TMath::Min(a, b);
      fgDefaultChamberMaxZ[i] = TMath::Max(a, b);
    }
  }

  // We can apply a binary search for the chamber since the fgDefaultChamberMinZ and
  // fgDefaultChamberMaxZ arrays are ordered.
  Int_t mini = 0, maxi = NCh()-1;
  while (mini <= maxi)
  {
    Int_t iChamber = (maxi + mini) / 2;
    if (z < fgDefaultChamberMinZ[iChamber])
      mini = iChamber+1;
    else if (z > fgDefaultChamberMaxZ[iChamber])
      maxi = iChamber-1;
    else
      // We are between min and max Z of chamber number iChamber so we found our chamber.
      return iChamber;
  }

  if (warn) AliWarningClass(Form("No chamber number found for z = %f",z));
  return -1;
}
<|endoftext|>