<commit_before>#include <boost/property_tree/json_parser.hpp>
#include <boost/algorithm/string.hpp>

#include <QProgressDialog>
#include <QMessageBox>

#include "video_annotation.h"

namespace fish_annotator { namespace video_annotator {

namespace {
  template<typename L, typename R>
  boost::bimap<L, R> 
  makeBimap(std::initializer_list<
      typename boost::bimap<L, R>::value_type> list) {
    return boost::bimap<L, R>(list.begin(), list.end());
  }
  static const auto count_label_map = makeBimap<CountLabel, std::string>({
      {kIgnore, "ignore"},
      {kEntering, "entering"},
      {kExiting, "exiting"}});
} // namespace

namespace fs = boost::filesystem;
namespace pt = boost::property_tree;

DetectionAnnotation::DetectionAnnotation(
  uint64_t frame,
  uint64_t id,
  const Rect &rect,
  enum AnnotationType type,
  std::string species,
  double prob)
  : frame_(frame)
  , id_(id)
  , area_(rect)
  , type_(type)
  , species_(species)
  , prob_(prob) {
}

DetectionAnnotation::DetectionAnnotation()
  : frame_(0)
  , id_(0)
  , area_(0, 0, 0, 0)
  , type_(kBox)
  , species_()
  , prob_(0.0) {
}

bool DetectionAnnotation::operator==(const DetectionAnnotation &rhs) const {
  if(frame_ != rhs.frame_) return false;
  if(id_ != rhs.id_) return false;
  if(area_.x != rhs.area_.x) return false;
  if(area_.y != rhs.area_.y) return false;
  if(area_.w != rhs.area_.w) return false;
  if(area_.h != rhs.area_.h) return false;
  if(type_ != rhs.type_) return false;
  return true;
}

bool DetectionAnnotation::operator!=(const DetectionAnnotation &rhs) const {
  return !operator==(rhs);
}

pt::ptree DetectionAnnotation::write() const {
  pt::ptree tree;
  tree.put("frame", frame_);
  tree.put("id", id_);
  tree.put("x", area_.x);
  tree.put("y", area_.y);
  tree.put("w", area_.w);
  tree.put("h", area_.h);
  switch(type_) {
    case kBox:
      tree.put("type", "box");
      break;
    case kLine:
      tree.put("type", "line");
      break;
    case kDot:
      tree.put("type", "dot");
      break;
  }
  tree.put("species", species_);
  tree.put("prob", prob_);
  return tree;
}

void DetectionAnnotation::read(const pt::ptree &tree) {
  frame_ = tree.get<uint64_t>("frame");
  id_ = tree.get<uint64_t>("id");
  area_.x = tree.get<uint64_t>("x");
  area_.y = tree.get<uint64_t>("y");
  area_.w = tree.get<uint64_t>("w");
  area_.h = tree.get<uint64_t>("h");
  type_ = kBox; // default
  auto opt_type_str = tree.get_optional<std::string>("type");
  if(opt_type_str != boost::none) {
    auto type_str = opt_type_str.get();
    if(type_str == "box") {
      type_ = kBox;
    }
    else if(type_str == "line") {
      type_ = kLine;
    }
    else if(type_str == "dot") {
      type_ = kDot;
    }
  }
  species_ = ""; // default
  auto opt_species = tree.get_optional<std::string>("species");
  if(opt_species != boost::none) {
    species_ = opt_species.get();
  }
  prob_ = 0.0; // default
  auto opt_prob = tree.get_optional<double>("prob");
  if(opt_prob != boost::none) {
    prob_ = opt_prob.get();
  }
}

TrackAnnotation::TrackAnnotation(
  uint64_t id,
  const std::string &species,
  const std::string &subspecies,
  uint64_t frame_added,
  CountLabel count_label)
  : id_(id)
  , species_(species)
  , subspecies_(subspecies)
  , frame_added_(frame_added)
  , count_label_(count_label) {
  boost::algorithm::to_lower(species_);
  boost::algorithm::to_lower(subspecies_);
}

TrackAnnotation::TrackAnnotation()
  : id_(0)
  , species_()
  , subspecies_()
  , frame_added_(0)
  , count_label_(kIgnore) {
}

bool TrackAnnotation::operator==(const TrackAnnotation &rhs) const {
  if(id_ != rhs.id_) return false;
  if(species_ != rhs.species_) return false;
  if(subspecies_ != rhs.subspecies_) return false;
  if(frame_added_ != rhs.frame_added_) return false;
  if(count_label_ != rhs.count_label_) return false;
  return true;
}

bool TrackAnnotation::operator!=(const TrackAnnotation &rhs) const {
  return !operator==(rhs);
}

std::string TrackAnnotation::getSpecies() {
  return species_;
}

pt::ptree TrackAnnotation::write() const {
  pt::ptree tree;
  tree.put("id", id_);
  tree.put("species", species_);
  tree.put("subspecies", subspecies_);
  tree.put("frame_added", frame_added_);
  tree.put("count_label", count_label_map.left.at(count_label_));
  return tree;
}

void TrackAnnotation::read(const pt::ptree &tree) {
  id_ = tree.get<decltype(id_)>("id");
  species_ = tree.get<decltype(species_)>("species");
  subspecies_ = tree.get<decltype(subspecies_)>("subspecies");
  frame_added_ = tree.get<decltype(frame_added_)>("frame_added");
  auto count_label_str = count_label_map.right.at(
    tree.get<std::string>("count_label"));
}

std::string TrackAnnotation::write_csv(double fps) const {
  std::string csv_row;
  double time_added = static_cast<double>(frame_added_) / fps;
  csv_row += ","; csv_row += std::to_string(id_);
  csv_row += ","; csv_row += species_;
  csv_row += ","; csv_row += subspecies_;
  csv_row += ","; csv_row += std::to_string(frame_added_);
  csv_row += ","; csv_row += std::to_string(time_added);
  switch(count_label_) {
    case kIgnore: csv_row += ",Ignore"; break;
    case kEntering: csv_row += ",Entering"; break;
    case kExiting: csv_row += ",Exiting"; break;
  }
  return csv_row;
}

void TrackAnnotation::read_csv(const std::string &csv_row) {
  std::vector<std::string> vals;
  boost::split(vals, csv_row, boost::is_any_of(","));<commit_msg>Convert to lowercase when reading species from new file format<commit_after>#include <boost/property_tree/json_parser.hpp>
#include <boost/algorithm/string.hpp>

#include <QProgressDialog>
#include <QMessageBox>

#include "video_annotation.h"

namespace fish_annotator { namespace video_annotator {

namespace {
  template<typename L, typename R>
  boost::bimap<L, R> 
  makeBimap(std::initializer_list<
      typename boost::bimap<L, R>::value_type> list) {
    return boost::bimap<L, R>(list.begin(), list.end());
  }
  static const auto count_label_map = makeBimap<CountLabel, std::string>({
      {kIgnore, "ignore"},
      {kEntering, "entering"},
      {kExiting, "exiting"}});
} // namespace

namespace fs = boost::filesystem;
namespace pt = boost::property_tree;

DetectionAnnotation::DetectionAnnotation(
  uint64_t frame,
  uint64_t id,
  const Rect &rect,
  enum AnnotationType type,
  std::string species,
  double prob)
  : frame_(frame)
  , id_(id)
  , area_(rect)
  , type_(type)
  , species_(species)
  , prob_(prob) {
  boost::algorithm::to_lower(species_);
}

DetectionAnnotation::DetectionAnnotation()
  : frame_(0)
  , id_(0)
  , area_(0, 0, 0, 0)
  , type_(kBox)
  , species_()
  , prob_(0.0) {
}

bool DetectionAnnotation::operator==(const DetectionAnnotation &rhs) const {
  if(frame_ != rhs.frame_) return false;
  if(id_ != rhs.id_) return false;
  if(area_.x != rhs.area_.x) return false;
  if(area_.y != rhs.area_.y) return false;
  if(area_.w != rhs.area_.w) return false;
  if(area_.h != rhs.area_.h) return false;
  if(type_ != rhs.type_) return false;
  return true;
}

bool DetectionAnnotation::operator!=(const DetectionAnnotation &rhs) const {
  return !operator==(rhs);
}

pt::ptree DetectionAnnotation::write() const {
  pt::ptree tree;
  tree.put("frame", frame_);
  tree.put("id", id_);
  tree.put("x", area_.x);
  tree.put("y", area_.y);
  tree.put("w", area_.w);
  tree.put("h", area_.h);
  switch(type_) {
    case kBox:
      tree.put("type", "box");
      break;
    case kLine:
      tree.put("type", "line");
      break;
    case kDot:
      tree.put("type", "dot");
      break;
  }
  tree.put("species", species_);
  tree.put("prob", prob_);
  return tree;
}

void DetectionAnnotation::read(const pt::ptree &tree) {
  frame_ = tree.get<uint64_t>("frame");
  id_ = tree.get<uint64_t>("id");
  area_.x = tree.get<uint64_t>("x");
  area_.y = tree.get<uint64_t>("y");
  area_.w = tree.get<uint64_t>("w");
  area_.h = tree.get<uint64_t>("h");
  type_ = kBox; // default
  auto opt_type_str = tree.get_optional<std::string>("type");
  if(opt_type_str != boost::none) {
    auto type_str = opt_type_str.get();
    if(type_str == "box") {
      type_ = kBox;
    }
    else if(type_str == "line") {
      type_ = kLine;
    }
    else if(type_str == "dot") {
      type_ = kDot;
    }
  }
  species_ = ""; // default
  auto opt_species = tree.get_optional<std::string>("species");
  if(opt_species != boost::none) {
    species_ = opt_species.get();
    boost::algorithm::to_lower(species_);
  }
  prob_ = 0.0; // default
  auto opt_prob = tree.get_optional<double>("prob");
  if(opt_prob != boost::none) {
    prob_ = opt_prob.get();
  }
}

TrackAnnotation::TrackAnnotation(
  uint64_t id,
  const std::string &species,
  const std::string &subspecies,
  uint64_t frame_added,
  CountLabel count_label)
  : id_(id)
  , species_(species)
  , subspecies_(subspecies)
  , frame_added_(frame_added)
  , count_label_(count_label) {
  boost::algorithm::to_lower(species_);
  boost::algorithm::to_lower(subspecies_);
}

TrackAnnotation::TrackAnnotation()
  : id_(0)
  , species_()
  , subspecies_()
  , frame_added_(0)
  , count_label_(kIgnore) {
}

bool TrackAnnotation::operator==(const TrackAnnotation &rhs) const {
  if(id_ != rhs.id_) return false;
  if(species_ != rhs.species_) return false;
  if(subspecies_ != rhs.subspecies_) return false;
  if(frame_added_ != rhs.frame_added_) return false;
  if(count_label_ != rhs.count_label_) return false;
  return true;
}

bool TrackAnnotation::operator!=(const TrackAnnotation &rhs) const {
  return !operator==(rhs);
}

std::string TrackAnnotation::getSpecies() {
  return species_;
}

pt::ptree TrackAnnotation::write() const {
  pt::ptree tree;
  tree.put("id", id_);
  tree.put("species", species_);
  tree.put("subspecies", subspecies_);
  tree.put("frame_added", frame_added_);
  tree.put("count_label", count_label_map.left.at(count_label_));
  return tree;
}

void TrackAnnotation::read(const pt::ptree &tree) {
  id_ = tree.get<decltype(id_)>("id");
  species_ = tree.get<decltype(species_)>("species");
  subspecies_ = tree.get<decltype(subspecies_)>("subspecies");
  frame_added_ = tree.get<decltype(frame_added_)>("frame_added");
  auto count_label_str = count_label_map.right.at(
    tree.get<std::string>("count_label"));
  boost::algorithm::to_lower(species_);
  boost::algorithm::to_lower(subspecies_);
}

std::string TrackAnnotation::write_csv(double fps) const {
  std::string csv_row;
  double time_added = static_cast<double>(frame_added_) / fps;
  csv_row += ","; csv_row += std::to_string(id_);
  csv_row += ","; csv_row += species_;
  csv_row += ","; csv_row += subspecies_;
  csv_row += ","; csv_row += std::to_string(frame_added_);
  csv_row += ","; csv_row += std::to_string(time_added);
  switch(count_label_) {
    case kIgnore: csv_row += ",Ignore"; break;
    case kEntering: csv_row += ",Entering"; break;
    case kExiting: csv_row += ",Exiting"; break;
  }
  return csv_row;
}

void TrackAnnotation::read_csv(const std::string &csv_row) {
  std::vector<std::string> vals;
  boost::split(vals, csv_row, boost::is_any_of(","));
{'fraction_non_alphanumeric': 0.1674191800614051, 'fraction_numerical': 0.0057793028715911144, 'mean_word_length': 4.554162487462387, 'pattern_counts': {'":': 0, '<': 55, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6526749', 'n_tokens_mistral': 4072, 'n_tokens_neox': 3977, 'n_words': 752}