KJB
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mcmcda_association.h
Go to the documentation of this file.
1 #ifndef MCMCDA_ASSOCIATION_H_INCLUDED
2 #define MCMCDA_ASSOCIATION_H_INCLUDED
3 
6 #include <l_cpp/l_exception.h>
7 #include <l_cpp/l_functors.h>
8 #include <m_cpp/m_vector.h>
9 #include <set>
10 #include <algorithm>
11 #include <iterator>
12 #include <functional>
13 #include <string>
14 #include <fstream>
15 #include <boost/bind.hpp>
16 #include <boost/foreach.hpp>
17 #include <boost/lexical_cast.hpp>
18 #include <boost/lambda/lambda.hpp>
19 #include <boost/algorithm/string.hpp>
20 
21 namespace kjb {
22 namespace mcmcda {
23 
32 template<class Track>
34 {
36  bool operator()(const Track& t1, const Track& t2) const
37  {
38  return std::lexicographical_compare(t1.begin(), t1.end(),
39  t2.begin(), t2.end(), boost::bind(
41  }
42 
44  bool compare_elements
45  (
46  const typename Track::value_type& p1,
47  const typename Track::value_type& p2
48  ) const
49  {
50  if(p1.first < p2.first) return true;
51  if(p2.first < p1.first) return false;
52  return *p1.second < *p2.second;
53  }
54 };
55 
65 template<class Track>
66 class Association : private std::set<Track, Compare_tracks<Track> >
67 {
68 public:
69  typedef typename Track::Element Element;
70 
71 private:
72  typedef std::set<Track, Compare_tracks<Track> > Parent;
73  typedef std::set<const Element*> Elementp_set;
74 
75 private:
76  const Data<Element>* Y;
77 
78 public:
79  typedef std::vector<Elementp_set> Available_data;
80 
85  Association() : Y(0)
86  {}
87 
91  Association(const Data<Element>& data) : Y(&data)
92  {}
93 
100  template<class Iterator>
102  (
103  const Data<Element>& data,
104  Iterator first,
105  Iterator last
106  ) :
107  Parent(first, last), Y(&data)
108  {}
109 
110  // pass-throughs
111  using Parent::empty;
112  using Parent::begin;
113  using Parent::end;
114  using Parent::rbegin;
115  using Parent::rend;
116  using Parent::size;
117  using Parent::insert;
118  using Parent::clear;
119  using Parent::erase;
120  using Parent::find;
121  typedef typename Parent::iterator iterator;
122  typedef typename Parent::const_iterator const_iterator;
123  typedef typename Parent::const_reference const_reference;
124 
126  const Data<Element>& get_data() const
127  {
128  return *Y;
129  }
130 
132  void set_data(const Data<Element>& data)
133  {
134  Y = &data;
135  }
136 
144  {
145  using namespace std;
146 
147  Available_data a_data(Y->size());
148  vector<int> time(Y->size());
149  generate(time.begin(), time.end(), Increment<int>(1));
150  transform(time.begin(), time.end(), a_data.begin(), boost::bind(
152 
153  return a_data;
154  }
155 
159  Elementp_set get_live_points_at_time(int t) const;
160 
165  int count_live_points_at_time(int t) const;
166 
170  Elementp_set get_dead_points_at_time(int t) const
171  {
172  using namespace std;
173 
174  Elementp_set dead_data_t;
175  Elementp_set live_data_t = get_live_points_at_time(t);
176  Elementp_set data_t_addrs;
177  transform((*Y)[t - 1].begin(), (*Y)[t - 1].end(),
178  inserter(data_t_addrs, data_t_addrs.begin()), &boost::lambda::_1);
179 
180  set_difference(data_t_addrs.begin(), data_t_addrs.end(),
181  live_data_t.begin(), live_data_t.end(),
182  inserter(dead_data_t, dead_data_t.begin()));
183 
184  return dead_data_t;
185  }
186 
191  int count_dead_points_at_time(int t) const
192  {
193  int cdt = (*Y)[t - 1].size();
194  int clp = count_live_points_at_time(t);
195 
196  return cdt - clp;
197  }
198 
203  Elementp_set valid_starting_points
204  (
205  int t,
206  int d,
207  int d_bar,
208  double v_bar,
209  double sg,
210  const typename Data<Element>::Convert& to_vector
211  ) const
212  {
213  IFT(t > 0 && d > 0, Illegal_argument,
214  "valid_starting_points: t and d must be positive");
215 
216  IFTD(d <= d_bar, Illegal_argument,
217  "valid_starting_points: d (%d) cannot be greater than d^bar (%d)",
218  (d)(d_bar));
219 
220  using namespace std;
221  Elementp_set dead_pts_t = get_dead_points_at_time(t);
222  Elementp_set vsp;
223 
224  //remove_copy_if(dead_pts_t.begin(), dead_pts_t.end(),
225  // inserter(vsp, vsp.begin()), !boost::bind(
226  // &Data<Element>::neighborhood_size, Y, _1,
227  // t, d, d_bar, v_bar, sg, to_vector));
228 
229  BOOST_FOREACH(const Element* elem_p, dead_pts_t)
230  {
231  if(Y->neighborhood_size(*elem_p, t, d, d_bar,
232  v_bar, sg, to_vector) != 0)
233  {
234  vsp.insert(elem_p);
235  }
236  }
237 
238  return vsp;
239  }
240 
247  (
248  int t,
249  int d,
250  int d_bar,
251  double v_bar,
252  double sg,
253  const typename Data<Element>::Convert& to_vector
254  ) const
255  {
256  IFT(t > 0 && d > 0, Illegal_argument,
257  "valid_starting_points: t and d must be positive");
258 
259  IFTD(d <= d_bar, Illegal_argument,
260  "valid_starting_points: d (%d) cannot be greater than d^bar (%d)",
261  (d)(d_bar));
262 
263  Elementp_set dead_pts_t = get_dead_points_at_time(t);
264  //int bad_pts = std::count_if(dead_pts_t.begin(), dead_pts_t.end(),
265  // !boost::bind(&Data<Element>::neighborhood_size, Y, _1,
266  // t, d, d_bar, v_bar, sg, to_vector));
267 
268  int num_valid = 0;
269  BOOST_FOREACH(const Element* elem_p, dead_pts_t)
270  {
271  if(Y->neighborhood_size(*elem_p, t, d, d_bar,
272  v_bar, sg, to_vector) != 0)
273  {
274  num_valid++;
275  }
276  }
277 
278 
279  return num_valid;
280  }
281 
285  Elementp_set dead_neighbors
286  (
287  const Element& y,
288  int t,
289  int d,
290  int d_bar,
291  double v_bar,
292  double sg,
293  const typename Data<Element>::Convert& to_vector
294  ) const
295  {
296  Elementp_set d_neighbors;
297  Elementp_set neighbors = Y->neighborhood(y, t, d, d_bar,
298  v_bar, sg, to_vector);
299 
300  if(!neighbors.empty())
301  {
302  Elementp_set live_points = get_live_points_at_time(t + d);
303  std::set_difference(neighbors.begin(), neighbors.end(),
304  live_points.begin(), live_points.end(),
305  std::inserter(d_neighbors, d_neighbors.begin()));
306  }
307 
308  return d_neighbors;
309  }
310 
316  (
317  const Element& y,
318  int t,
319  int d,
320  int d_bar,
321  double v_bar,
322  double sg,
323  const typename Data<Element>::Convert& to_vector
324  ) const
325  {
326  return dead_neighbors(y, t, d, d_bar, v_bar, sg, to_vector).size();
327  }
328 
332  void read(const std::string& filename, const Track& def = Track());
333 
337  void write(const std::string& filename) const;
338 
342  bool is_valid
343  (
344  double v_bar,
345  int d_bar,
346  double sg,
347  const typename Data<Element>::Convert& convert
348  ) const;
349 
353  friend
354  void swap(Association& a1, Association& a2)
355  {
356  using std::swap;
357 
358  swap(a1.Y, a2.Y);
359  std::set<Track, Compare_tracks<Track> >& s1 = a1;
360  std::set<Track, Compare_tracks<Track> >& s2 = a2;
361  swap(s1, s2);
362  }
363 };
364 
365 /*============================================================================*
366  * MEMBER FUNCTION DEFINITIONS *
367  *----------------------------------------------------------------------------*/
368 
369 template<class Track>
370 typename Association<Track>::Elementp_set
372 {
373  Elementp_set lp;
374 
375  for(const_iterator p = begin(); p != end(); p++)
376  {
377  typedef typename Track::const_iterator Tr_it;
378  std::pair<Tr_it, Tr_it> erp = p->equal_range(t);
379  for(Tr_it q = erp.first; q != erp.second; q++)
380  {
381  lp.insert(q->second);
382  }
383  }
384 
385  return lp;
386 }
387 
388 /* \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ */
389 
390 template<class Track>
392 {
393  int count = 0;
394 
395  for(const_iterator p = begin(); p != end(); p++)
396  {
397  typename Track::const_iterator q = p->find(t);
398  if(q != p->end())
399  {
400  count++;
401  }
402  }
403 
404  return count;
405 }
406 
407 /* \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ */
408 
409 template<class Track>
410 void Association<Track>::read(const std::string& filename, const Track& def)
411 {
412  using namespace std;
413 
414  this->clear();
415 
416  ifstream ifs(filename.c_str());
417  IFTD(ifs, IO_error, "Cannot read association; could not open file %s",
418  (filename.c_str()));
419 
420  size_t T = Y->size();
421  string line;
422  while(getline(ifs, line))
423  {
424  if(line.empty() || line[0] == '#')
425  {
426  continue;
427  }
428 
429  istringstream istr(line);
430  vector<string> strs;
431  copy(istream_iterator<string>(istr),
432  istream_iterator<string>(),
433  back_inserter(strs));
434 
435  Track track = def;
436  IFTD(strs.size() == T, Illegal_argument,
437  "Cannot read association; file %s has incorrect format.",
438  (filename.c_str()));
439 
440  for(int t = 0; t < strs.size(); t++)
441  {
442  vector<string> idxs;
443  boost::split(idxs, strs[t], boost::is_any_of(","));
444 
445  for(size_t i = 0; i < idxs.size(); i++)
446  {
447  int idx = boost::lexical_cast<int>(idxs[i]);
448  IFTD(idx >= -1 && idx < static_cast<int>((*Y)[t].size()),
449  Illegal_argument,
450  "Cannot read association; file %s has bad format.",
451  (filename.c_str()));
452 
453  if(i == 0)
454  {
455  if(idx == -1)
456  {
457  continue;
458  }
459  }
460  else
461  {
462  IFTD(idx != -1, Illegal_argument,
463  "Cannot read association; file %s has bad format.",
464  (filename.c_str()));
465  }
466 
467  typename std::set<Element>::const_iterator vec_p
468  = (*Y)[t].begin();
469  advance(vec_p, idx);
470  track.insert(make_pair(t + 1, &(*vec_p)));
471  }
472  }
473 
474  this->insert(track);
475  }
476 
477  ifs.close();
478 }
479 
480 /* \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ */
481 
482 template<class Track>
483 void Association<Track>::write(const std::string& filename) const
484 {
485  std::ofstream ofs(filename.c_str());
486  if(!ofs)
487  {
489  "Cannot write association; could not open file %s",
490  (filename.c_str()));
491  }
492 
493  typedef typename Track::const_iterator Tr_it;
494  typedef std::set<Element> E_set;
495  BOOST_FOREACH(const Track& track, *this)
496  {
497  for(Tr_it pair_p = track.begin(); pair_p != track.end(); pair_p++)
498  {
499  int t = pair_p->first;
500  const Element& elem = *pair_p->second;
501 
502  if(pair_p == track.begin())
503  {
504  for(int s = 1; s < t; s++)
505  {
506  ofs << "-1 ";
507  }
508  }
509 
510  const E_set& data_t = (*Y)[t - 1];
511  typename E_set::const_iterator elem_p = data_t.find(elem);
512 
513  ofs << std::distance(data_t.begin(), elem_p);
514 
515  Tr_it pair_q = pair_p;
516  pair_q++;
517  if(pair_q == track.end())
518  {
519  for(int s = t + 1; s <= Y->size(); s++)
520  {
521  ofs << " -1";
522  }
523  }
524  else
525  {
526  if(pair_q->first == t)
527  {
528  ofs << ",";
529  }
530  else
531  {
532  ofs << " ";
533  for(int s = t + 1; s < pair_q->first; s++)
534  {
535  ofs << "-1 ";
536  }
537  }
538  }
539  }
540 
541  ofs << std::endl;
542  }
543 
544  ofs.close();
545 }
546 
547 /* \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ */
548 
549 template<class Track>
551 (
552  double v_bar,
553  int d_bar,
554  double sg,
555  const typename Data<Element>::Convert& convert
556 ) const
557 {
558  // check whether distances between points are OK.
559  const_iterator invalid_track_p = std::find_if(begin(), end(),
560  !boost::bind(&Track::is_valid, _1, v_bar, d_bar, sg, convert));
561 
562  if(invalid_track_p != end())
563  {
564  return false;
565  }
566 
567  // checks data is not repeated, etc.
568  Available_data used_data(Y->size());
569  for(const_iterator track_p = begin(); track_p != end(); track_p++)
570  {
571  for(typename Track::const_iterator pair_p = track_p->begin();
572  pair_p != track_p->end();
573  pair_p++)
574  {
575  if(pair_p->second == NULL)
576  {
577  return false;
578  }
579 
580  // check to see if this points to something in data
581  const std::set<Element>& data_t = (*Y)[pair_p->first - 1];
582  if(std::count_if(data_t.begin(), data_t.end(),
583  Compare_address<Element>(pair_p->second)) == 0)
584  {
585  return false;
586  }
587 
588  // insert point and check whether or not already used :-)
589  if(!used_data[pair_p->first - 1].insert(pair_p->second).second)
590  {
591  return false;
592  }
593  }
594  }
595 
596  return true;
597 }
598 
603 template<class Track>
605 (
606  const Association<Track>& w,
607  size_t& m,
608  size_t& e,
609  size_t& d,
610  size_t& a,
611  size_t& n,
612  size_t& l
613 )
614 {
615  m = w.size();
616 
617  e = d = a = l = 0;
618 
619  const size_t T = w.get_data().size();
620  BOOST_FOREACH(const Track& track, w)
621  {
622  int sf = track.get_start_time();
623  int ef = track.get_end_time();
624  assert(sf != -1 && ef != -1);
625 
626  if(sf != 1) e++;
627 
628  if(ef != T) d++;
629 
630  a += track.size();
631  l += ef - sf + 1;
632  }
633 
634  size_t N = 0;
635  for(size_t t = 1; t <= T; t++)
636  {
637  N += w.get_data()[t - 1].size();
638  }
639 
640  n = N - a;
641 }
642 
643 }} //namespace kjb::mcmcda
644 
645 #endif /*MCMCDA_ASSOCIATION_H_INCLUDED */
646 
Functor to compare two tracks. If this were not defined, an association would order its tracks using ...
Definition: mcmcda_association.h:33
bool compare_elements(const typename Track::value_type &p1, const typename Track::value_type &p2) const
Compare two track elements.
Definition: mcmcda_association.h:45
Available_data get_available_data() const
Computes "available data".
Definition: mcmcda_association.h:143
Elementp_set get_dead_points_at_time(int t) const
Computes points at time t that do not belong to any track.
Definition: mcmcda_association.h:170
Parent::const_iterator const_iterator
Definition: mcmcda_association.h:122
void write(const std::string &filename) const
Writes association to file.
Definition: mcmcda_association.h:483
friend void swap(Association &a1, Association &a2)
Efficiently swap two associations.
Definition: mcmcda_association.h:354
A class that holds data for the tracking problem.
Definition: mcmcda_data.h:50
Parent::iterator iterator
Definition: mcmcda_association.h:121
A class that represents a MCMCDA association.
Definition: mcmcda_association.h:66
Elementp_set get_live_points_at_time(int t) const
Computes points at time t that belong to some track.
Definition: mcmcda_association.h:371
Elementp_set valid_starting_points(int t, int d, int d_bar, double v_bar, double sg, const typename Data< Element >::Convert &to_vector) const
Computes points at time t that are valid starting points for a track.
Definition: mcmcda_association.h:204
Association()
Default constructor – meaningless association. Use with care!!
Definition: mcmcda_association.h:85
int is_valid(const Doubly_connected_edge_list &dcel)
slowly test invariants on the structure, return ERROR or NO_ERROR
Definition: dcel.cpp:1530
Generator that increments (++) its state everytime it is called. Useful for creating sequences of con...
Definition: l_functors.h:39
bool is_valid(double v_bar, int d_bar, double sg, const typename Data< Element >::Convert &convert) const
Determines whether this association is valid.
Definition: mcmcda_association.h:551
int neighbors
Definition: triangle.c:718
#define IFT(a, ex, msg)
Definition: l_exception.h:101
int count_valid_starting_points(int t, int d, int d_bar, double v_bar, double sg, const typename Data< Element >::Convert &to_vector) const
Counts points at time t that are valid starting track points. This is usually faster than finding the...
Definition: mcmcda_association.h:247
Track::Element Element
Definition: mcmcda_association.h:69
Predicate that returns true if address of element equals given.
Definition: l_functors.h:197
boost::function1< Vector, const Element & > Convert
Definition: mcmcda_data.h:53
Parent::const_reference const_reference
Definition: mcmcda_association.h:123
const Data< Element > & get_data() const
Returns data set const-ref.
Definition: mcmcda_association.h:126
count
Definition: APPgetLargeConnectedEdges.m:71
void set_data(const Data< Element > &data)
Set data.
Definition: mcmcda_association.h:132
void swap(kjb::Gsl_Multimin_fdf &m1, kjb::Gsl_Multimin_fdf &m2)
Swap two wrapped multimin objects.
Definition: gsl_multimin.h:693
#define KJB_THROW_3(ex, fmt, params)
Definition: l_exception.h:56
int count_live_points_at_time(int t) const
Counts points at time t that belong to some track. This is usually faster than computing the points a...
Definition: mcmcda_association.h:391
int count_dead_points_at_time(int t) const
Counts points at time t that do not belong to any track. This is usually faster than computing the po...
Definition: mcmcda_association.h:191
void get_association_totals(const Association< Track > &w, size_t &m, size_t &e, size_t &d, size_t &a, size_t &n, size_t &l)
Get total tracks, entrances, exits, true detections, noisy detections, and track lengths of a given a...
Definition: mcmcda_association.h:605
Elementp_set dead_neighbors(const Element &y, int t, int d, int d_bar, double v_bar, double sg, const typename Data< Element >::Convert &to_vector) const
Computes neighbors of vector that are available.
Definition: mcmcda_association.h:286
int getline(FILE *fp, std::string *line, char EOL= '\n')
Like C's fgets but with std::string, or C++'s getline but with FILE*.
Object thrown when an argument to a function is not acceptable.
Definition: l_exception.h:377
void read(const std::string &filename, const Track &def=Track())
Read association from file.
Definition: mcmcda_association.h:410
get the indices of edges in each direction for i
Definition: APPgetLargeConnectedEdges.m:48
Object thrown when input or output fails.
Definition: l_exception.h:496
int count_dead_neighbors(const Element &y, int t, int d, int d_bar, double v_bar, double sg, const typename Data< Element >::Convert &to_vector) const
Computes neighbors of vector that are available. This is usually faster than computing the points and...
Definition: mcmcda_association.h:316
for m
Definition: APPgetLargeConnectedEdges.m:64
Support for error handling exception classes in libKJB.
#define IFTD(a, ex, msg, params)
Definition: l_exception.h:112
std::vector< Elementp_set > Available_data
Definition: mcmcda_association.h:79
Definition for the Vector class, a thin wrapper on the KJB Vector struct and its related functionalit...
Association(const Data< Element > &data)
Constructor.
Definition: mcmcda_association.h:91
bool operator()(const Track &t1, const Track &t2) const
Compare two tracks.
Definition: mcmcda_association.h:36