Find ID Example Source Files

Main.cpp

  1/*
  2 * Copyright (c) 2014-2023 National Technology and Engineering
  3 * Solutions of Sandia, LLC. Under the terms of Contract DE-NA0003525
  4 * with National Technology and Engineering Solutions of Sandia, LLC,
  5 * the U.S. Government retains certain rights in this software.
  6 *
  7 * Redistribution and use in source and binary forms, with or without
  8 * modification, are permitted provided that the following conditions
  9 * are met:
 10 *
 11 * 1. Redistributions of source code must retain the above copyright
 12 * notice, this list of conditions and the following disclaimer.
 13 *
 14 * 2. Redistributions in binary form must reproduce the above copyright
 15 * notice, this list of conditions and the following disclaimer in the
 16 * documentation and/or other materials provided with the distribution.
 17 *
 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 22 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 29 */
 30
 31#include <tracktable/CommandLineFactories/AssemblerFromCommandLine.h>
 32#include <tracktable/CommandLineFactories/PointReaderFromCommandLine.h>
 33#include <tracktable/Domain/Terrestrial.h>
 34
 35#include <boost/timer/timer.hpp>
 36
 37#include <algorithm>
 38#include <memory>
 39#include <string>
 40#include <vector>
 41
 42using TrajectoryT = tracktable::domain::terrestrial::trajectory_type;
 43using PointT = typename TrajectoryT::point_type;
 44using PointReaderT = tracktable::PointReader<PointT>;
 45using PointReaderIteratorT = typename PointReaderT::iterator;
 46using AssemblerT = tracktable::AssembleTrajectories<TrajectoryT, PointReaderIteratorT>;
 47
 48static constexpr auto helpmsg = R"(
 49--------------------------------------------------------------------------------
 50The findid example demonstrates:
 51    - Using command line factories to read points and assemble trajectories
 52    - Reading a list of ids from a file
 53    - Searching trajectories for specific object ids
 54
 55Typical use:
 56    ./assemble --input=/data/flights.tsv --idfile=/data/mapping_ids.txt
 57
 58Defaults assume a tab separated points file formatted as :
 59
 60OBJECTID TIMESTAMP LON LAT
 61
 62And an id file with a single object id per line.
 63
 64Default output is just a count of how many trajectories were found.
 65--------------------------------------------------------------------------------)";
 66
 67int main(int _argc, char* _argv[]) {
 68    // Set log level to reduce unecessary output
 69    tracktable::set_log_level(tracktable::log::info);
 70    // Create a basic command line option with boost
 71    boost::program_options::options_description commandLineOptions;
 72    // clang-format off
 73    commandLineOptions.add_options()
 74      ("help", "Print help")  // And a command line option for output
 75      ("idfile",
 76        bpo::value<std::string>()->default_value("mapping-ids.txt"),
 77       "file to read ids from")
 78    ;
 79    // clang-format on
 80    // Reader factories, which add lots of command line options
 81    tracktable::PointReaderFromCommandLine<PointT> readerFactory;
 82    tracktable::AssemblerFromCommandLine<TrajectoryT> assemblerFactory;
 83    readerFactory.addOptions(commandLineOptions);
 84    assemblerFactory.addOptions(commandLineOptions);
 85    /** Boost program options using a variable map to tie everything together.
 86     * one parse will have a single variable map. We need to let the factories know
 87     * about this variable map so they can pull information out of it */
 88    auto vm = std::make_shared<boost::program_options::variables_map>();
 89    readerFactory.setVariables(vm);
 90    assemblerFactory.setVariables(vm);
 91    // Parse the command lines, don't forget the 'notify' after
 92    try {
 93        boost::program_options::store(
 94            boost::program_options::command_line_parser(_argc, _argv).options(commandLineOptions).run(), *vm);
 95        boost::program_options::notify(*vm);
 96    } catch (boost::program_options::error& e) {
 97        std::cerr << helpmsg << "\n\n" << e.what() << "\n\n" << commandLineOptions << std::endl;
 98        return 1;
 99    }
100    /** Parsing will give an error of an incorrect option is used, but it won't
101     * display the help unless we tell it too */
102    if (vm->count("help") != 0) {
103        std::cerr << helpmsg << commandLineOptions << std::endl;
104        return 1;
105    }
106
107    // Create Point Reader and assembler
108    auto pointReader = readerFactory.createPointReader();
109    auto assembler = assemblerFactory.createAssembler(pointReader);
110
111    std::vector<std::shared_ptr<TrajectoryT>> trajectories = {};
112    {
113        std::cerr << "Assemble Trajectories" << std::endl;
114        boost::timer::auto_cpu_timer assembleTimer(std::cerr);
115        auto count = 0u;
116        std::cerr << std::right;
117        for (auto tIter = assembler->begin(); tIter != assembler->end(); ++tIter) {
118            std::cerr << "\b\b\b\b\b\b\b\b\b\b" << std::setw(10)  // Using backspaces for in place counter
119                      << count++;
120            trajectories.push_back(std::make_shared<TrajectoryT>(*tIter));
121        }
122        std::cerr << std::left << "\nStarting with " << trajectories.size() << " trajectories" << std::endl;
123    }
124
125    // Read ObjectIds from file
126    auto fileName = (*vm)["idfile"].as<std::string>();
127    std::vector<std::string> idList;
128    {
129        boost::timer::auto_cpu_timer searchTimer(std::cerr);
130        std::ifstream idFile(fileName);
131        if (!idFile.is_open()) {
132            std::cerr << "Could not open id file: " << fileName << std::endl;
133        }
134        std::string id;
135        while (std::getline(idFile, id)) {
136            std::cerr << id << std::endl;
137            idList.push_back(id);
138        }
139        std::sort(idList.begin(), idList.end());
140        std::cerr << idList.size() << " ids found" << std::endl;
141    }
142
143    // separate the trajectories based on whether they are on the id list.
144    std::vector<std::shared_ptr<TrajectoryT>> foundTrajectories;
145
146    /*Copy everything except where the lambda is true, this is an alternative to  copy_if
147      think of remove_copy_if as dont_copy_if; It only copies if the function returns false*/
148    std::remove_copy_if(trajectories.begin(), trajectories.end(), std::back_inserter(foundTrajectories),
149                        [&idList /*capture idList*/](const std::shared_ptr<TrajectoryT>& _t) {
150                            // search idList for current object id
151                            return !std::binary_search(idList.begin(), idList.end(), _t->object_id());
152                        });
153
154    /*Remove the copied trajectories, remove_if shifts all unwanted entries to the end of vector and returns
155      an iterator to the first 'bad' element, erase takes that iterator and deletes everything after it, the
156      lambda is similar to that used above, but is missing the negation(!) and operating on a separate
157      vector*/
158    std::sort(foundTrajectories.begin(), foundTrajectories.end());
159    trajectories.erase(std::remove_if(trajectories.begin(), trajectories.end(),
160                                      [&foundTrajectories](const std::shared_ptr<TrajectoryT>& _t) {
161                                          return std::binary_search(foundTrajectories.begin(),
162                                                                    foundTrajectories.end(), _t);
163                                      }),
164                       trajectories.end());
165
166    std::cout << "trajectories.size() = " << trajectories.size() << std::endl;
167    std::cout << "foundTrajectories.size() = " << foundTrajectories.size() << std::endl;
168
169    return 0;
170}