<commit_before>/** @file
    @brief Main file for a unified video-based and inertial tracking system.

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include "ImageSources/ImageSource.h"
#include "ImageSources/ImageSourceFactories.h"

#include "MakeHDKTrackingSystem.h"
#include "TrackingSystem.h"
#include "ThreadsafeBodyReporting.h"

#include "HDKLedIdentifierFactory.h"
#include "CameraParameters.h"
#include "HDKData.h"
#include <osvr/AnalysisPluginKit/AnalysisPluginKitC.h>
#include <osvr/PluginKit/PluginKit.h>
#include <osvr/PluginKit/TrackerInterfaceC.h>
#include <osvr/PluginKit/AnalogInterfaceC.h>

#include "ConfigurationParser.h"

// Generated JSON header file
#include "org_osvr_unifiedvideoinertial_json.h"

// Library/third-party includes
#include <opencv2/core/core.hpp> // for basic OpenCV types
#include <opencv2/core/operations.hpp>
#include <opencv2/highgui/highgui.hpp> // for image capture
#include <opencv2/imgproc/imgproc.hpp> // for image scaling
#include <json/value.h>
#include <json/reader.h>

#include <boost/noncopyable.hpp>

#include <util/Stride.h>

// Standard includes
#include <iostream>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <memory>
#include <thread>
#include <mutex>
#include <stdexcept>

// Anonymous namespace to avoid symbol collision
namespace {
static const auto DRIVER_NAME = "UnifiedTrackingSystem";

static const auto DEBUGGABLE_BEACONS = 34;
static const auto DATAPOINTS_PER_BEACON = 5;
using TrackingSystemPtr = std::unique_ptr<osvr::vbtracker::TrackingSystem>;
using BodyReportingVector = std::vector<osvr::vbtracker::BodyReportingPtr>;
class TrackerThread : boost::noncopyable {
  public:
    TrackerThread(osvr::vbtracker::TrackingSystem &trackingSystem,
                  osvr::vbtracker::ImageSource &imageSource,
                  BodyReportingVector &reportingVec,
                  osvr::vbtracker::CameraParameters const &camParams)
        : m_trackingSystem(trackingSystem), m_cam(imageSource),
          m_reportingVec(reportingVec), m_camParams(camParams) {
        msg() << "Tracker thread object created." << std::endl;
    }

    void operator()() {
        msg() << "Tracker thread object invoked." << std::endl;
        bool keepGoing = true;
        while (keepGoing) {
            doFrame();

            {
                /// Copy the run flag.
                std::lock_guard<std::mutex> lock(m_runMutex);
                keepGoing = m_run;
            }
            if (!keepGoing) {
                msg() << "Tracker thread object: Just checked our run flag and noticed it turned false..." << std::endl;
            }
        }
        msg() << "Tracker thread object: functor exiting." << std::endl;
    }

    /// Call from the main thread!
    void triggerStop() {
        msg() << "Tracker thread object: triggerStop() called" << std::endl;
        std::lock_guard<std::mutex> lock(m_runMutex);
        m_run = false;
    }

  private:
    std::ostream &msg() const { return std::cout << "[UnifiedTracker] "; }
    std::ostream &warn() const { return msg() << "Warning: "; }
    void doFrame() {
        // Check camera status.
        if (!m_cam.ok()) {
            // Hmm, camera seems bad. Might regain it? Skip for now...
            warn() << "Camera is reporting it is not OK." << std::endl;
            return;
        }
        // Trigger a grab.
        if (!m_cam.grab()) {
            // Again failing without quitting, in hopes we get better luck next
            // time...
            warn() << "Camera grab failed." << std::endl;
            return;
        }
        // When we triggered the grab is our current best guess of the time for
        // the image
        /// @todo backdate to account for image transfer image, exposure time,
        /// etc.
        auto tv = osvr::util::time::getNow();

        // Pull the image into an OpenCV matrix named m_frame.
        m_cam.retrieve(m_frame, m_frameGray);
        if (!m_frame.data || !m_frameGray.data) {
            warn()
                << "Camera retrieve appeared to fail: frames had null pointers!"
                << std::endl;
            return;
        }

        // Submit to the tracking system.
        auto bodyIds = m_trackingSystem.processFrame(tv, m_frame, m_frameGray,
                                                     m_camParams);

        for (auto const &bodyId : bodyIds) {
            /// @todo stick stuff in m_reportingVec here.
        }
    }
    osvr::vbtracker::TrackingSystem &m_trackingSystem;
    osvr::vbtracker::ImageSource &m_cam;
    BodyReportingVector &m_reportingVec;
    osvr::vbtracker::CameraParameters m_camParams;
    cv::Mat m_frame;
    cv::Mat m_frameGray;
    std::mutex m_runMutex;
    volatile bool m_run = true;
};

class UnifiedVideoInertialTracker : boost::noncopyable {
  public:
    using size_type = std::size_t;
    UnifiedVideoInertialTracker(OSVR_PluginRegContext ctx,
                                osvr::vbtracker::ImageSourcePtr &&source,
                                osvr::vbtracker::ConfigParams params,
                                TrackingSystemPtr &&trackingSystem)
        : m_source(std::move(source)),
          m_trackingSystem(std::move(trackingSystem)) {

        /// Create the initialization options
        OSVR_DeviceInitOptions opts = osvrDeviceCreateInitOptions(ctx);

        // Configure the tracker interface.
        osvrDeviceTrackerConfigure(opts, &m_tracker);
#if 0
        osvrDeviceAnalogConfigure(opts, &m_analog,
                                  DEBUGGABLE_BEACONS * DATAPOINTS_PER_BEACON);
#endif

        /// Create the analysis device token with the options
        OSVR_DeviceToken dev;
        if (OSVR_RETURN_FAILURE ==
            osvrAnalysisSyncInit(ctx, DRIVER_NAME, opts, &dev, &m_clientCtx)) {
            throw std::runtime_error("Could not initialize analysis plugin!");
        }
        m_dev = osvr::pluginkit::DeviceToken(dev);

        /// Send JSON descriptor
        m_dev.sendJsonDescriptor(org_osvr_unifiedvideoinertial_json);

        /// Set up thread communication.
        setupBodyReporting();

        /// Set up the object that will run in the other thread, and spawn the
        /// thread.
        startTrackerThread();

        /// Register update callback
        m_dev.registerUpdateCallback(this);
    }

    ~UnifiedVideoInertialTracker() { stopTrackerThread(); }

    /// Create a "BodyReporting" interchange structure for each body we track.
    void setupBodyReporting() {
        m_bodyReportingVector.clear();
        auto n = m_trackingSystem->getNumBodies();
        for (size_type i = 0; i < n; ++i) {
            m_bodyReportingVector.emplace_back(
                osvr::vbtracker::BodyReporting::make());
        }
    }

    OSVR_ReturnCode update();

    void startTrackerThread() {
        if (m_trackerThreadFunctor) {
            throw std::logic_error("Trying to start the tracker thread when "
                                   "it's already started!");
        }
        std::cout << "Starting the tracker thread..." << std::endl;
        m_trackerThreadFunctor.reset(new TrackerThread(
            *m_trackingSystem, *m_source, m_bodyReportingVector,
            osvr::vbtracker::getHDKCameraParameters()));
        m_trackerThread = std::thread([&] { (*m_trackerThreadFunctor)(); });
    }
    void stopTrackerThread() {
        if (m_trackerThreadFunctor) {
            std::cout << "Shutting down the tracker thread..." << std::endl;
            m_trackerThreadFunctor->triggerStop();
            m_trackerThread.join();
            m_trackerThreadFunctor.reset();
            m_trackerThread = std::thread();
        }
    }

  private:
    osvr::pluginkit::DeviceToken m_dev;
    OSVR_ClientContext m_clientCtx;
    OSVR_ClientInterface m_clientInterface;
    OSVR_TrackerDeviceInterface m_tracker;
#if 0
    OSVR_AnalogDeviceInterface m_analog;
#endif
    osvr::vbtracker::ImageSourcePtr m_source;
    cv::Mat m_frame;
    cv::Mat m_imageGray;
    TrackingSystemPtr m_trackingSystem;
    std::vector<osvr::vbtracker::BodyReportingPtr> m_bodyReportingVector;
    std::unique_ptr<TrackerThread> m_trackerThreadFunctor;
    std::thread m_trackerThread;
};

inline OSVR_ReturnCode UnifiedVideoInertialTracker::update() {
    /// @todo use the m_bodyReportingVector to report stuff.

    return OSVR_RETURN_SUCCESS;
}

class ConfiguredDeviceConstructor {
  public:
    /// @brief This is the required signature for a device instantiation
    /// callback.
    OSVR_ReturnCode operator()(OSVR_PluginRegContext ctx, const char *params) {
        // Read the JSON data from parameters.
        Json::Value root;
        if (params) {
            Json::Reader r;
            if (!r.parse(params, root)) {
                std::cerr << "Could not parse parameters!" << std::endl;
            }
        }

        // Read these parameters from a "params" field in the device Json
        // configuration file.

        // This is in a separate function/header for sharing and for clarity.
        auto config = osvr::vbtracker::parseConfigParams(root);

#ifdef _WIN32
        auto cam = osvr::vbtracker::openHDKCameraDirectShow();
#else // !_WIN32
        /// @todo This is rather crude, as we can't select the exact camera we
        /// want, nor set the "50Hz" high-gain mode (and only works with HDK
        /// camera firmware v7 and up). Presumably eventually use libuvc on
        /// other platforms instead, at least for the HDK IR camera.

        auto cam = osvr::vbtracker::openOpenCVCamera(0);
#endif

        if (!cam || !cam->ok()) {
            std::cerr << "Could not access the tracking camera, skipping "
                         "video-based tracking!"
                      << std::endl;
            return OSVR_RETURN_FAILURE;
        }

        auto trackingSystem = osvr::vbtracker::makeHDKTrackingSystem(config);
        // OK, now that we have our parameters, create the device.
        osvr::pluginkit::PluginContext context(ctx);
        auto newTracker = osvr::pluginkit::registerObjectForDeletion(
            ctx, new UnifiedVideoInertialTracker(ctx, std::move(cam), config,
                                                 std::move(trackingSystem)));

        return OSVR_RETURN_SUCCESS;
    }
};

} // namespace

OSVR_PLUGIN(org_osvr_unifiedvideoinertial) {
    osvr::pluginkit::PluginContext context(ctx);

    /// Tell the core we're available to create a device object.
    osvr::pluginkit::registerDriverInstantiationCallback(
        ctx, DRIVER_NAME, new ConfiguredDeviceConstructor);

    return OSVR_RETURN_SUCCESS;
}
<commit_msg>Re-enable thread capping for OpenCV<commit_after>/** @file
    @brief Main file for a unified video-based and inertial tracking system.

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Sensics, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Internal Includes
#include "ImageSources/ImageSource.h"
#include "ImageSources/ImageSourceFactories.h"

#include "MakeHDKTrackingSystem.h"
#include "TrackingSystem.h"
#include "ThreadsafeBodyReporting.h"

#include "HDKLedIdentifierFactory.h"
#include "CameraParameters.h"
#include "HDKData.h"
#include <osvr/AnalysisPluginKit/AnalysisPluginKitC.h>
#include <osvr/PluginKit/PluginKit.h>
#include <osvr/PluginKit/TrackerInterfaceC.h>
#include <osvr/PluginKit/AnalogInterfaceC.h>

#include "ConfigurationParser.h"

// Generated JSON header file
#include "org_osvr_unifiedvideoinertial_json.h"

// Library/third-party includes
#include <opencv2/core/core.hpp> // for basic OpenCV types
#include <opencv2/core/operations.hpp>
#include <opencv2/highgui/highgui.hpp> // for image capture
#include <opencv2/imgproc/imgproc.hpp> // for image scaling
#include <json/value.h>
#include <json/reader.h>

#include <boost/noncopyable.hpp>

#include <util/Stride.h>

// Standard includes
#include <iostream>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <memory>
#include <thread>
#include <mutex>
#include <stdexcept>

// Anonymous namespace to avoid symbol collision
namespace {
static const auto DRIVER_NAME = "UnifiedTrackingSystem";

static const auto DEBUGGABLE_BEACONS = 34;
static const auto DATAPOINTS_PER_BEACON = 5;
using TrackingSystemPtr = std::unique_ptr<osvr::vbtracker::TrackingSystem>;
using BodyReportingVector = std::vector<osvr::vbtracker::BodyReportingPtr>;
class TrackerThread : boost::noncopyable {
  public:
    TrackerThread(osvr::vbtracker::TrackingSystem &trackingSystem,
                  osvr::vbtracker::ImageSource &imageSource,
                  BodyReportingVector &reportingVec,
                  osvr::vbtracker::CameraParameters const &camParams)
        : m_trackingSystem(trackingSystem), m_cam(imageSource),
          m_reportingVec(reportingVec), m_camParams(camParams) {
        msg() << "Tracker thread object created." << std::endl;
    }

    void operator()() {
        msg() << "Tracker thread object invoked." << std::endl;
        bool keepGoing = true;
        while (keepGoing) {
            doFrame();

            {
                /// Copy the run flag.
                std::lock_guard<std::mutex> lock(m_runMutex);
                keepGoing = m_run;
            }
            if (!keepGoing) {
                msg() << "Tracker thread object: Just checked our run flag and "
                         "noticed it turned false..."
                      << std::endl;
            }
        }
        msg() << "Tracker thread object: functor exiting." << std::endl;
    }

    /// Call from the main thread!
    void triggerStop() {
        msg() << "Tracker thread object: triggerStop() called" << std::endl;
        std::lock_guard<std::mutex> lock(m_runMutex);
        m_run = false;
    }

  private:
    std::ostream &msg() const { return std::cout << "[UnifiedTracker] "; }
    std::ostream &warn() const { return msg() << "Warning: "; }
    void doFrame() {
        // Check camera status.
        if (!m_cam.ok()) {
            // Hmm, camera seems bad. Might regain it? Skip for now...
            warn() << "Camera is reporting it is not OK." << std::endl;
            return;
        }
        // Trigger a grab.
        if (!m_cam.grab()) {
            // Again failing without quitting, in hopes we get better luck next
            // time...
            warn() << "Camera grab failed." << std::endl;
            return;
        }
        // When we triggered the grab is our current best guess of the time for
        // the image
        /// @todo backdate to account for image transfer image, exposure time,
        /// etc.
        auto tv = osvr::util::time::getNow();

        // Pull the image into an OpenCV matrix named m_frame.
        m_cam.retrieve(m_frame, m_frameGray);
        if (!m_frame.data || !m_frameGray.data) {
            warn()
                << "Camera retrieve appeared to fail: frames had null pointers!"
                << std::endl;
            return;
        }

        // Submit to the tracking system.
        auto bodyIds = m_trackingSystem.processFrame(tv, m_frame, m_frameGray,
                                                     m_camParams);

        for (auto const &bodyId : bodyIds) {
            /// @todo stick stuff in m_reportingVec here.
        }
    }
    osvr::vbtracker::TrackingSystem &m_trackingSystem;
    osvr::vbtracker::ImageSource &m_cam;
    BodyReportingVector &m_reportingVec;
    osvr::vbtracker::CameraParameters m_camParams;
    cv::Mat m_frame;
    cv::Mat m_frameGray;
    std::mutex m_runMutex;
    volatile bool m_run = true;
};

class UnifiedVideoInertialTracker : boost::noncopyable {
  public:
    using size_type = std::size_t;
    UnifiedVideoInertialTracker(OSVR_PluginRegContext ctx,
                                osvr::vbtracker::ImageSourcePtr &&source,
                                osvr::vbtracker::ConfigParams params,
                                TrackingSystemPtr &&trackingSystem)
        : m_source(std::move(source)),
          m_trackingSystem(std::move(trackingSystem)) {
        if (params.numThreads > 0) {
            // Set the number of threads for OpenCV to use.
            cv::setNumThreads(params.numThreads);
        }

        /// Create the initialization options
        OSVR_DeviceInitOptions opts = osvrDeviceCreateInitOptions(ctx);

        // Configure the tracker interface.
        osvrDeviceTrackerConfigure(opts, &m_tracker);
#if 0
        osvrDeviceAnalogConfigure(opts, &m_analog,
                                  DEBUGGABLE_BEACONS * DATAPOINTS_PER_BEACON);
#endif

        /// Create the analysis device token with the options
        OSVR_DeviceToken dev;
        if (OSVR_RETURN_FAILURE ==
            osvrAnalysisSyncInit(ctx, DRIVER_NAME, opts, &dev, &m_clientCtx)) {
            throw std::runtime_error("Could not initialize analysis plugin!");
        }
        m_dev = osvr::pluginkit::DeviceToken(dev);

        /// Send JSON descriptor
        m_dev.sendJsonDescriptor(org_osvr_unifiedvideoinertial_json);

        /// Set up thread communication.
        setupBodyReporting();

        /// Set up the object that will run in the other thread, and spawn the
        /// thread.
        startTrackerThread();

        /// Register update callback
        m_dev.registerUpdateCallback(this);
    }

    ~UnifiedVideoInertialTracker() { stopTrackerThread(); }

    /// Create a "BodyReporting" interchange structure for each body we track.
    void setupBodyReporting() {
        m_bodyReportingVector.clear();
        auto n = m_trackingSystem->getNumBodies();
        for (size_type i = 0; i < n; ++i) {
            m_bodyReportingVector.emplace_back(
                osvr::vbtracker::BodyReporting::make());
        }
    }

    OSVR_ReturnCode update();

    void startTrackerThread() {
        if (m_trackerThreadFunctor) {
            throw std::logic_error("Trying to start the tracker thread when "
                                   "it's already started!");
        }
        std::cout << "Starting the tracker thread..." << std::endl;
        m_trackerThreadFunctor.reset(new TrackerThread(
            *m_trackingSystem, *m_source, m_bodyReportingVector,
            osvr::vbtracker::getHDKCameraParameters()));
        m_trackerThread = std::thread([&] { (*m_trackerThreadFunctor)(); });
    }
    void stopTrackerThread() {
        if (m_trackerThreadFunctor) {
            std::cout << "Shutting down the tracker thread..." << std::endl;
            m_trackerThreadFunctor->triggerStop();
            m_trackerThread.join();
            m_trackerThreadFunctor.reset();
            m_trackerThread = std::thread();
        }
    }

  private:
    osvr::pluginkit::DeviceToken m_dev;
    OSVR_ClientContext m_clientCtx;
    OSVR_ClientInterface m_clientInterface;
    OSVR_TrackerDeviceInterface m_tracker;
#if 0
    OSVR_AnalogDeviceInterface m_analog;
#endif
    osvr::vbtracker::ImageSourcePtr m_source;
    cv::Mat m_frame;
    cv::Mat m_imageGray;
    TrackingSystemPtr m_trackingSystem;
    std::vector<osvr::vbtracker::BodyReportingPtr> m_bodyReportingVector;
    std::unique_ptr<TrackerThread> m_trackerThreadFunctor;
    std::thread m_trackerThread;
};

inline OSVR_ReturnCode UnifiedVideoInertialTracker::update() {
    /// @todo use the m_bodyReportingVector to report stuff.

    return OSVR_RETURN_SUCCESS;
}

class ConfiguredDeviceConstructor {
  public:
    /// @brief This is the required signature for a device instantiation
    /// callback.
    OSVR_ReturnCode operator()(OSVR_PluginRegContext ctx, const char *params) {
        // Read the JSON data from parameters.
        Json::Value root;
        if (params) {
            Json::Reader r;
            if (!r.parse(params, root)) {
                std::cerr << "Could not parse parameters!" << std::endl;
            }
        }

        // Read these parameters from a "params" field in the device Json
        // configuration file.

        // This is in a separate function/header for sharing and for clarity.
        auto config = osvr::vbtracker::parseConfigParams(root);

#ifdef _WIN32
        auto cam = osvr::vbtracker::openHDKCameraDirectShow();
#else // !_WIN32
        /// @todo This is rather crude, as we can't select the exact camera we
        /// want, nor set the "50Hz" high-gain mode (and only works with HDK
        /// camera firmware v7 and up). Presumably eventually use libuvc on
        /// other platforms instead, at least for the HDK IR camera.

        auto cam = osvr::vbtracker::openOpenCVCamera(0);
#endif

        if (!cam || !cam->ok()) {
            std::cerr << "Could not access the tracking camera, skipping "
                         "video-based tracking!"
                      << std::endl;
            return OSVR_RETURN_FAILURE;
        }

        auto trackingSystem = osvr::vbtracker::makeHDKTrackingSystem(config);
        // OK, now that we have our parameters, create the device.
        osvr::pluginkit::PluginContext context(ctx);
        auto newTracker = osvr::pluginkit::registerObjectForDeletion(
            ctx, new UnifiedVideoInertialTracker(ctx, std::move(cam), config,
                                                 std::move(trackingSystem)));

        return OSVR_RETURN_SUCCESS;
    }
};

} // namespace

OSVR_PLUGIN(org_osvr_unifiedvideoinertial) {
    osvr::pluginkit::PluginContext context(ctx);

    /// Tell the core we're available to create a device object.
    osvr::pluginkit::registerDriverInstantiationCallback(
        ctx, DRIVER_NAME, new ConfiguredDeviceConstructor);

    return OSVR_RETURN_SUCCESS;
}
<|endoftext|>


<commit_before>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

#include <sys/stat.h>
#include <iostream>
#include <string>
using namespace std;

#include "config.h"

#include "osd/OSDMap.h"
#include "mon/MonMap.h"

void usage(const char *me)
{
  cout << me << " usage: [--print] [--createsimple <monmapfile> <numosd> [--clobber] [--pgbits <bitsperosd>]] <mapfilename>" << std::endl;
  cout << me << "   --export-crush <file>   write osdmap's crush map to <file>" << std::endl;
  cout << me << "   --import-crush <file>   replace osdmap's crush map with <file>" << std::endl;
  exit(1);
}

void printmap(const char *me, OSDMap *m)
{
  cout << me << ": osdmap: epoch " << m->get_epoch() << std::endl
       << me << ": osdmap: fsid " << m->get_fsid() << std::endl;
  /*for (unsigned i=0; i<m->mon_inst.size(); i++)
    cout << me << ": osdmap:  " //<< "mon" << i << " "
	 << m->mon_inst[i] << std::endl;
  */
}

int main(int argc, const char **argv)
{
  vector<const char*> args;
  argv_to_vec(argc, argv, args);
  parse_config_options(args);

  const char *me = argv[0];

  const char *fn = 0;
  bool print = false;
  bool createsimple = false;
  const char *monmapfn = 0;
  int num_osd = 0;
  int pg_bits = g_conf.osd_pg_bits;
  bool clobber = false;
  bool modified = false;
  const char *export_crush = 0;
  const char *import_crush = 0;
  list<entity_addr_t> add, rm;

  for (unsigned i=0; i<args.size(); i++) {
    if (strcmp(args[i], "--print") == 0)
      print = true;
    else if (strcmp(args[i], "--createsimple") == 0) {
      createsimple = true;
      monmapfn = args[++i];
      num_osd = atoi(args[++i]);
    } else if (strcmp(args[i], "--clobber") == 0)
      clobber = true;
    else if (strcmp(args[i], "--pgbits") == 0)
      pg_bits = atoi(args[++i]);
    else if (strcmp(args[i], "--export-crush") == 0)
      export_crush = args[++i];
    else if (strcmp(args[i], "--import-crush") == 0)
      import_crush = args[++i];
    else if (!fn)
      fn = args[i];
    else
      usage(me);
  }
  if (!fn) {
    cerr << me << ": must specify osdmap filename" << std::endl;
    usage(me);
  }

  OSDMap osdmap;
  bufferlist bl;

  cout << me << ": osdmap file '" << fn << "'" << std::endl;

  int r = 0;
  if (!(createsimple && clobber)) {
    r = bl.read_file(fn);
    osdmap.decode(bl);
  }
  if (!createsimple && r < 0) {
    cerr << me << ": couldn't open " << fn << ": " << strerror(errno) << std::endl;
    return -1;
  }
  else if (createsimple && !clobber && r == 0) {
    cerr << me << ": " << fn << " exists, --clobber to overwrite" << std::endl;
    return -1;
  }

  if (createsimple) {
    MonMap monmap;
    int r = monmap.read(monmapfn);
    if (r < 0) {
      cerr << me << ": can't read monmap from " << monmapfn << ": " << strerror(r) << std::endl;
      exit(1);
    }
    osdmap.build_simple(0, monmap.fsid, num_osd, pg_bits, 0);
    modified = true;
  }

  if (import_crush) {
    bufferlist cbl;
    r = cbl.read_file(import_crush);
    if (r < 0) {
      cerr << me << ": error reading crush map from " << import_crush << std::endl;
      exit(1);
    }
    // validate
    CrushWrapper cw;
    //cw._decode(cbl,    FIXME
    bufferlist::iterator p = cbl.begin();
    osdmap.crush.decode(p);
    cout << me << ": imported crush map from " << import_crush << std::endl;
    modified = true;
  }

  if (export_crush) {
    bufferlist cbl;
    osdmap.crush.encode(cbl);
    r = cbl.write_file(export_crush);
    if (r < 0) {
      cerr << me << ": error writing crush map to " << import_crush << std::endl;
      exit(1);
    }
    cout << me << ": exported crush map to " << export_crush << std::endl;
  }

  if (!print && !modified && !export_crush && !import_crush) {
    cerr << me << ": no action specified?" << std::endl;
    usage(me);
  }
  if (modified)
    osdmap.inc_epoch();

  if (print)
    printmap(me, &osdmap);

  if (modified) {
    osdmap.encode(bl);

    // write it out
    cout << me << ": writing epoch " << osdmap.get_epoch()
	 << " to " << fn
	 << std::endl;
    int r = bl.write_file(fn);
    assert(r >= 0);
  }

  return 0;
}
<commit_msg>osdmaptool: require num_osd > 0 when creating new osdmap<commit_after>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

#include <sys/stat.h>
#include <iostream>
#include <string>
using namespace std;

#include "config.h"

#include "osd/OSDMap.h"
#include "mon/MonMap.h"

void usage(const char *me)
{
  cout << me << " usage: [--print] [--createsimple <monmapfile> <numosd> [--clobber] [--pgbits <bitsperosd>]] <mapfilename>" << std::endl;
  cout << me << "   --export-crush <file>   write osdmap's crush map to <file>" << std::endl;
  cout << me << "   --import-crush <file>   replace osdmap's crush map with <file>" << std::endl;
  exit(1);
}

void printmap(const char *me, OSDMap *m)
{
  cout << me << ": osdmap: epoch " << m->get_epoch() << std::endl
       << me << ": osdmap: fsid " << m->get_fsid() << std::endl;
  /*for (unsigned i=0; i<m->mon_inst.size(); i++)
    cout << me << ": osdmap:  " //<< "mon" << i << " "
	 << m->mon_inst[i] << std::endl;
  */
}

int main(int argc, const char **argv)
{
  vector<const char*> args;
  argv_to_vec(argc, argv, args);
  parse_config_options(args);

  const char *me = argv[0];

  const char *fn = 0;
  bool print = false;
  bool createsimple = false;
  const char *monmapfn = 0;
  int num_osd = 0;
  int pg_bits = g_conf.osd_pg_bits;
  bool clobber = false;
  bool modified = false;
  const char *export_crush = 0;
  const char *import_crush = 0;
  list<entity_addr_t> add, rm;

  for (unsigned i=0; i<args.size(); i++) {
    if (strcmp(args[i], "--print") == 0)
      print = true;
    else if (strcmp(args[i], "--createsimple") == 0) {
      createsimple = true;
      monmapfn = args[++i];
      num_osd = atoi(args[++i]);
    } else if (strcmp(args[i], "--clobber") == 0)
      clobber = true;
    else if (strcmp(args[i], "--pgbits") == 0)
      pg_bits = atoi(args[++i]);
    else if (strcmp(args[i], "--export-crush") == 0)
      export_crush = args[++i];
    else if (strcmp(args[i], "--import-crush") == 0)
      import_crush = args[++i];
    else if (!fn)
      fn = args[i];
    else
      usage(me);
  }
  if (!fn) {
    cerr << me << ": must specify osdmap filename" << std::endl;
    usage(me);
  }

  OSDMap osdmap;
  bufferlist bl;

  cout << me << ": osdmap file '" << fn << "'" << std::endl;

  int r = 0;
  if (!(createsimple && clobber)) {
    r = bl.read_file(fn);
    osdmap.decode(bl);
  }
  if (!createsimple && r < 0) {
    cerr << me << ": couldn't open " << fn << ": " << strerror(errno) << std::endl;
    return -1;
  }
  else if (createsimple && !clobber && r == 0) {
    cerr << me << ": " << fn << " exists, --clobber to overwrite" << std::endl;
    return -1;
  }

  if (createsimple) {
    MonMap monmap;
    int r = monmap.read(monmapfn);
    if (r < 0) {
      cerr << me << ": can't read monmap from " << monmapfn << ": " << strerror(r) << std::endl;
      exit(1);
    }
    if (num_osd < 1) {
      cerr << me << ": osd count must be > 0" << std::endl;
      exit(1);
    }
    osdmap.build_simple(0, monmap.fsid, num_osd, pg_bits, 0);
    modified = true;
  }

  if (import_crush) {
    bufferlist cbl;
    r = cbl.read_file(import_crush);
    if (r < 0) {
      cerr << me << ": error reading crush map from " << import_crush << std::endl;
      exit(1);
    }
    // validate
    CrushWrapper cw;
    //cw._decode(cbl,    FIXME
    bufferlist::iterator p = cbl.begin();
    osdmap.crush.decode(p);
    cout << me << ": imported crush map from " << import_crush << std::endl;
    modified = true;
  }

  if (export_crush) {
    bufferlist cbl;
    osdmap.crush.encode(cbl);
    r = cbl.write_file(export_crush);
    if (r < 0) {
      cerr << me << ": error writing crush map to " << import_crush << std::endl;
      exit(1);
    }
    cout << me << ": exported crush map to " << export_crush << std::endl;
  }

  if (!print && !modified && !export_crush && !import_crush) {
    cerr << me << ": no action specified?" << std::endl;
    usage(me);
  }
  if (modified)
    osdmap.inc_epoch();

  if (print)
    printmap(me, &osdmap);

  if (modified) {
    osdmap.encode(bl);

    // write it out
    cout << me << ": writing epoch " << osdmap.get_epoch()
	 << " to " << fn
	 << std::endl;
    int r = bl.write_file(fn);
    assert(r >= 0);
  }

  return 0;
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2011 Kim Walisch, <kim.walisch@gmail.com>.
// All rights reserved.
//
// This file is part of primesieve.
// Homepage: http://primesieve.googlecode.com
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//   * Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above
//     copyright notice, this list of conditions and the following
//     disclaimer in the documentation and/or other materials provided
//     with the distribution.
//   * Neither the name of the author nor the names of its
//     contributors may be used to endorse or promote products derived
//     from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

#include "ParallelPrimeSieve.h"
#include "PrimeSieve.h"
#include "PrimeNumberFinder.h"
#include "defs.h"
#include "imath.h"

#if defined(_OPENMP)
  #include <omp.h>
#endif

#include <cstdlib>
#include <stdexcept>
#include <algorithm>

ParallelPrimeSieve::ParallelPrimeSieve() :
  numThreads_(USE_IDEAL_NUM_THREADS),
  shm_(NULL)
{
  // prevents prime k-tuplet gaps
  static_assert(defs::MIN_THREAD_INTERVAL >= 100,
               "defs::MIN_THREAD_INTERVAL >= 100");
}

/**
 * Used with the primesieve Qt application in ../qt-gui.
 * Initializes the ParallelPrimeSieve object with values from
 * a shared memory segment.
 */
void ParallelPrimeSieve::init(SharedMemory* shm) {
  if (shm == NULL)
    throw std::invalid_argument(
        "ParallelPrimeSieve: shared memory segment must not be NULL");
  shm_ = shm;
  this->setStartNumber(shm_->startNumber);
  this->setStopNumber(shm_->stopNumber);
  this->setSieveSize(shm_->sieveSize);
  this->setFlags(shm_->flags);
  this->setNumThreads(shm_->threads);
}

/**
 * Calculate the current status in percent of sieve().
 * @param processed  The size of the processed segment (interval)
 */
void ParallelPrimeSieve::doStatus(uint32_t processed) {
#if defined(_OPENMP)
  #pragma omp critical (doStatus)
#endif
  {
    PrimeSieve::doStatus(processed);
    // communicate the current status via shared memory
    // to the Qt GUI process
    if (shm_ != NULL)
      shm_->status = status_;
  }
}

int ParallelPrimeSieve::getMaxThreads() {
#if defined(_OPENMP)
  return omp_get_max_threads();
#else
  return 1;
#endif
}

/**
 * Get the current set number of threads for sieving.
 */
int ParallelPrimeSieve::getNumThreads() const {
  return (numThreads_ == USE_IDEAL_NUM_THREADS)
      ? this->getIdealNumThreads()
      : numThreads_;
}

/**
 * Set the number of threads for sieving.
 * If numThreads is invalid (numThreads < 1 or > getMaxThreads()) it
 * is set to numThreads = USE_IDEAL_NUM_THREADS.
 */
void ParallelPrimeSieve::setNumThreads(int numThreads) {
  numThreads_ = (numThreads < 1 && numThreads > this->getMaxThreads())
      ? USE_IDEAL_NUM_THREADS
      : numThreads;
}

/**
 * Get an ideal number of threads for the current set
 * startNumber_, stopNumber_ and flags_.
 */
int ParallelPrimeSieve::getIdealNumThreads() const {
  // 1 thread to print primes and k-tuplets in sequential order
  if (testFlags(PRINT_PRIMES | PRINT_KTUPLETS))
    return 1;

  // each thread sieves at least an interval of size sqrt(n) / 6
  // but not smaller than defs::MIN_THREAD_INTERVAL
  uint64_t threadThreshold = std::max<uint64_t>(
      defs::MIN_THREAD_INTERVAL,
      isqrt(stopNumber_) / 6);

  // use all threads if the sieve interval is sufficiently large
  int idealNumThreads = static_cast<int> (
      std::min<uint64_t>(
          this->getInterval() / threadThreshold,
          this->getMaxThreads()));

  return std::max<int>(1, idealNumThreads);
}

uint64_t ParallelPrimeSieve::getInterval() const {
  return stopNumber_ - startNumber_;
}

/**
 * Get an interval size that ensures a good load
 * balance among threads.
 */
uint64_t ParallelPrimeSieve::getIdealInterval() const {
  uint64_t threads  = this->getNumThreads();
  uint64_t interval = this->getInterval();
  if (threads == 1)
    return interval;

  // idealInterval = sqrt(n)*2000, 0.1 percent initialization
  uint64_t idealInterval = std::max<uint64_t>(
      defs::MIN_THREAD_INTERVAL,
      static_cast<uint64_t> (isqrt(stopNumber_)) * 2000);

  uint64_t maxThreadInterval = interval / threads;
  // correct the user's bad settings
  if (maxThreadInterval < interval &&
      maxThreadInterval < defs::MIN_THREAD_INTERVAL)
    maxThreadInterval = interval / this->getIdealNumThreads();

  return std::min<uint64_t>(idealInterval, maxThreadInterval);
}

/**
 * Sieve the primes and prime k-tuplets within [startNumber, stopNumber]
 * in parallel using OpenMP.
 */
void ParallelPrimeSieve::sieve() {
  if (stopNumber_ < startNumber_)
    throw std::invalid_argument("STOP must be >= START");

#if defined(_OPENMP)
  double t1 = omp_get_wtime();
  this->reset();
  uint64_t idealInterval = this->getIdealInterval();
   int64_t chunks        = (idealInterval > 0) ? this->getInterval() / idealInterval : 1;
  uint64_t maxOffset     = idealInterval * chunks;
  uint64_t maxStop       = startNumber_ + maxOffset + (32 - maxOffset % 30);
  if (maxStop < stopNumber_)
    chunks += 1;

  int threads = this->getNumThreads();

  // split the sieve interval [startNumber_, stopNumber_]
  // into 'chunks' sub-intervals that are processed in
  // parallel using OpenMP
  #pragma omp parallel for num_threads(threads) schedule(dynamic)
  for (int64_t i = 0; i < chunks; i++) {
    uint64_t start = startNumber_ + idealInterval * i;
    uint64_t stop  = startNumber_ + idealInterval * (i+1);
    // start/stop numbers must be chosen carefully
    // to prevent prime k-tuplets gaps
    if (i > 0)
      start += 32 - start % 30;
    stop += 32 - stop % 30;
    if (stop > stopNumber_)
      stop = stopNumber_;
    // sieve the primes within [start, stop]
    PrimeSieve ps(start, stop, this);
    ps.sieve();
    #pragma omp critical (counts)
    for (uint32_t j = 0; j < COUNTS_SIZE; j++)
      counts_[j] += ps.getCounts(j);
  }
  timeElapsed_ = omp_get_wtime() - t1;
#else
  PrimeSieve::sieve();
#endif
  // communicate the sieving results via shared memory
  // segment to the Qt GUI process
  if (shm_ != NULL) {
    for (uint32_t i = 0; i < COUNTS_SIZE; i++)
      shm_->counts[i] = counts_[i];
    shm_->timeElapsed = timeElapsed_;
  }
}
<commit_msg>minor update<commit_after>//
// Copyright (c) 2011 Kim Walisch, <kim.walisch@gmail.com>.
// All rights reserved.
//
// This file is part of primesieve.
// Homepage: http://primesieve.googlecode.com
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//   * Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above
//     copyright notice, this list of conditions and the following
//     disclaimer in the documentation and/or other materials provided
//     with the distribution.
//   * Neither the name of the author nor the names of its
//     contributors may be used to endorse or promote products derived
//     from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

#include "ParallelPrimeSieve.h"
#include "PrimeSieve.h"
#include "PrimeNumberFinder.h"
#include "defs.h"
#include "imath.h"

#if defined(_OPENMP)
  #include <omp.h>
#endif

#include <cstdlib>
#include <stdexcept>
#include <algorithm>

ParallelPrimeSieve::ParallelPrimeSieve() :
  numThreads_(USE_IDEAL_NUM_THREADS),
  shm_(NULL)
{
  // prevents prime k-tuplet gaps
  static_assert(defs::MIN_THREAD_INTERVAL >= 100,
               "defs::MIN_THREAD_INTERVAL >= 100");
}

/**
 * Used with the primesieve Qt application in ../qt-gui.
 * Initializes the ParallelPrimeSieve object with values from
 * a shared memory segment.
 */
void ParallelPrimeSieve::init(SharedMemory* shm) {
  if (shm == NULL)
    throw std::invalid_argument(
        "ParallelPrimeSieve: shared memory segment must not be NULL");
  shm_ = shm;
  this->setStartNumber(shm_->startNumber);
  this->setStopNumber(shm_->stopNumber);
  this->setSieveSize(shm_->sieveSize);
  this->setFlags(shm_->flags);
  this->setNumThreads(shm_->threads);
}

/**
 * Calculate the current status in percent of sieve().
 * @param processed  The size of the processed segment (interval)
 */
void ParallelPrimeSieve::doStatus(uint32_t processed) {
#if defined(_OPENMP)
  #pragma omp critical (doStatus)
#endif
  {
    PrimeSieve::doStatus(processed);
    // communicate the current status via shared memory
    // to the Qt GUI process
    if (shm_ != NULL)
      shm_->status = status_;
  }
}

int ParallelPrimeSieve::getMaxThreads() {
#if defined(_OPENMP)
  return omp_get_max_threads();
#else
  return 1;
#endif
}

/**
 * Get the current set number of threads for sieving.
 */
int ParallelPrimeSieve::getNumThreads() const {
  return (numThreads_ == USE_IDEAL_NUM_THREADS)
      ? this->getIdealNumThreads()
      : numThreads_;
}

/**
 * Set the number of threads for sieving.
 * If numThreads is invalid (numThreads < 1 or > getMaxThreads()) it
 * is set to numThreads = USE_IDEAL_NUM_THREADS.
 */
void ParallelPrimeSieve::setNumThreads(int numThreads) {
  numThreads_ = (numThreads < 1 && numThreads > this->getMaxThreads())
      ? USE_IDEAL_NUM_THREADS
      : numThreads;
}

/**
 * Get an ideal number of threads for the current set
 * startNumber_, stopNumber_ and flags_.
 */
int ParallelPrimeSieve::getIdealNumThreads() const {
  // 1 thread to generate primes and k-tuplets in sequential order
  if (testFlags(GENERATE_FLAGS))
    return 1;

  // each thread sieves at least an interval of size sqrt(n) / 6
  // but not smaller than defs::MIN_THREAD_INTERVAL
  uint64_t threadThreshold = std::max<uint64_t>(
      defs::MIN_THREAD_INTERVAL,
      isqrt(stopNumber_) / 6);

  // use all threads if the sieve interval is sufficiently large
  int idealNumThreads = static_cast<int> (
      std::min<uint64_t>(
          this->getInterval() / threadThreshold,
          this->getMaxThreads()));

  return std::max<int>(1, idealNumThreads);
}

uint64_t ParallelPrimeSieve::getInterval() const {
  return stopNumber_ - startNumber_;
}

/**
 * Get an interval size that ensures a good load
 * balance among threads.
 */
uint64_t ParallelPrimeSieve::getIdealInterval() const {
  uint64_t threads  = this->getNumThreads();
  uint64_t interval = this->getInterval();
  if (threads == 1)
    return interval;

  // idealInterval = sqrt(n)*2000, 0.1 percent initialization
  uint64_t idealInterval = std::max<uint64_t>(
      defs::MIN_THREAD_INTERVAL,
      static_cast<uint64_t> (isqrt(stopNumber_)) * 2000);

  uint64_t maxThreadInterval = interval / threads;
  // correct the user's bad settings
  if (maxThreadInterval < interval &&
      maxThreadInterval < defs::MIN_THREAD_INTERVAL)
    maxThreadInterval = interval / this->getIdealNumThreads();

  return std::min<uint64_t>(idealInterval, maxThreadInterval);
}

/**
 * Sieve the primes and prime k-tuplets within [startNumber, stopNumber]
 * in parallel using OpenMP.
 */
void ParallelPrimeSieve::sieve() {
  if (stopNumber_ < startNumber_)
    throw std::invalid_argument("STOP must be >= START");

#if defined(_OPENMP)
  double t1 = omp_get_wtime();
  this->reset();
  uint64_t idealInterval = this->getIdealInterval();
   int64_t chunks        = (idealInterval > 0) ? this->getInterval() / idealInterval : 1;
  uint64_t maxOffset     = idealInterval * chunks;
  uint64_t maxStop       = startNumber_ + maxOffset + (32 - maxOffset % 30);
  if (maxStop < stopNumber_)
    chunks += 1;

  int threads = this->getNumThreads();

  // split the sieve interval [startNumber_, stopNumber_]
  // into 'chunks' sub-intervals that are processed in
  // parallel using OpenMP
  #pragma omp parallel for num_threads(threads) schedule(dynamic)
  for (int64_t i = 0; i < chunks; i++) {
    uint64_t start = startNumber_ + idealInterval * i;
    uint64_t stop  = startNumber_ + idealInterval * (i+1);
    // start/stop numbers must be chosen carefully
    // to prevent prime k-tuplets gaps
    if (i > 0)
      start += 32 - start % 30;
    stop += 32 - stop % 30;
    if (stop > stopNumber_)
      stop = stopNumber_;
    // sieve the primes within [start, stop]
    PrimeSieve ps(start, stop, this);
    ps.sieve();
    #pragma omp critical (counts)
    for (uint32_t j = 0; j < COUNTS_SIZE; j++)
      counts_[j] += ps.getCounts(j);
  }
  timeElapsed_ = omp_get_wtime() - t1;
#else
  PrimeSieve::sieve();
#endif
  // communicate the sieving results via shared memory
  // segment to the Qt GUI process
  if (shm_ != NULL) {
    for (uint32_t i = 0; i < COUNTS_SIZE; i++)
      shm_->counts[i] = counts_[i];
    shm_->timeElapsed = timeElapsed_;
  }
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbImage.h"
#include "otbImageFileReader.h"
#include "otbStreamingImageFileWriter.h"
#include "otbFineRegistrationImageFilter.h"
#include "otbStandardWriterWatcher.h"
#include "otbCommandLineArgumentParser.h"
#include "otbVectorImage.h"
#include "otbImageList.h"
#include "otbImageListToVectorImageFilter.h"

#include "itkTimeProbe.h"
#include "itkFixedArray.h"
#include "itkNormalizedCorrelationImageToImageMetric.h"
#include "itkMeanReciprocalSquareDifferenceImageToImageMetric.h"
#include "itkMeanSquaresImageToImageMetric.h"
#include "itkMattesMutualInformationImageToImageMetric.h"
#include "itkDiscreteGaussianImageFilter.h"
#include "itkAbsImageFilter.h"
#include "itkVectorIndexSelectionCastImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"

int main(int argc, char * argv[])
{
  // Parse command line parameters
  typedef otb::CommandLineArgumentParser ParserType;
  ParserType::Pointer parser = ParserType::New();

  parser->SetProgramDescription("Estimate disparity map between two images. Output image contain x offset, y offset and metric value.");
  parser->AddOption("--Reference","The reference image","-ref", 1,true);
  parser->AddOption("--Secondary","The secondary image","-sec", 1,true);
  parser->AddOutputImage();
  parser->AddOption("--ExplorationRadius","Radius (in pixels) of the exploration window","-er",2,true);
  parser->AddOption("--MetricRadius","Radius (in pixels) of the metric computation window","-mr",2,true);
  parser->AddOption("--CoarseOffset","(optional) Coarse offset (in physical space) between the two images. Default is [0,0].","-co",2,false);
  parser->AddOption("--SubSamplingRate","(optional) Generate a result at a coarser resolution with a given sub-sampling rate in each direction (in pixels). Default is no sub-sampling","-ssr",2,false);
  parser->AddOption("--ReferenceGaussianSmoothing","(optional) Perform a gaussian smoothing of the reference image. Parameters are gaussian sigma (in pixels) in each direction. Default is no smoothing.","-rgs",2,false);
  parser->AddOption("--SecondaryGaussianSmoothing","(optional) Perform a gaussian smoothing of the secondary image. Parameters are gaussian sigma (in pixels) in each direction. Default is no smoothing.","-sgs",2,false);
  parser->AddOption("--Metric","(optional) Choose the metric used for block matching. Available metrics are cross-correlation (CC), cross-correlation with subtracted mean (CCSM), mean-square difference (MSD), mean reciprocal square difference (MRSD) and mutual information (MI). Default is cross-correlation","-m",1,false);
  parser->AddOption("--SubPixelAccuracy","(optional) Metric extrema location will be refined up to the given accuracy. Default is 0.01","-spa",1,false);
  parser->AddOption("--ValidityMask","(optional) Threshold to obtain a validity mask. Params are lowerThan or greaterThan and a threshold","-vm",2,true);

  typedef otb::CommandLineArgumentParseResult ParserResultType;
  ParserResultType::Pointer  parseResult = ParserResultType::New();

  try
  {
    parser->ParseCommandLine(argc,argv,parseResult);
  }
  catch ( itk::ExceptionObject & err )
  {
    std::string descriptionException = err.GetDescription();
    if (descriptionException.find("ParseCommandLine(): Help Parser") != std::string::npos)
      {
      return EXIT_SUCCESS;
      }
    if (descriptionException.find("ParseCommandLine(): Version Parser") != std::string::npos)
      {
      return EXIT_SUCCESS;
      }
    return EXIT_FAILURE;
  }

  const unsigned int Dimension = 2;
  typedef double     PixelType;

  typedef itk::FixedArray<PixelType,Dimension>                                 DeformationValueType;
  typedef otb::Image< PixelType,  Dimension >                                  ImageType;
  typedef otb::VectorImage<PixelType,Dimension>                                VectorImageType;
  typedef otb::ImageList<ImageType>                                            ImageListType;
  typedef otb::ImageListToVectorImageFilter<ImageListType,VectorImageType>     IL2VIFilterType;
  typedef otb::Image<DeformationValueType,Dimension>                           FieldImageType;
  typedef otb::ImageFileReader< ImageType >                                    ReaderType;
  typedef otb::StreamingImageFileWriter< VectorImageType >                     WriterType;
  typedef otb::FineRegistrationImageFilter<ImageType,ImageType,FieldImageType> RegistrationFilterType;
  typedef itk::DiscreteGaussianImageFilter<ImageType,ImageType>                GaussianFilterType;
  typedef itk::VectorIndexSelectionCastImageFilter<FieldImageType,ImageType>   VectorImageToImageFilterType;
  typedef itk::AbsImageFilter<ImageType,ImageType>                             AbsFilterType;
  typedef itk::BinaryThresholdImageFilter<ImageType,ImageType>                 BinaryThresholdImageFilterType;

  // Read reference image
  ReaderType::Pointer freader = ReaderType::New();
  freader->SetFileName(parseResult->GetParameterString("--Reference"));

  // Read secondary image
  ReaderType::Pointer mreader = ReaderType::New();
  mreader->SetFileName(parseResult->GetParameterString("--Secondary"));

  // Retrieve main registration parameters
  RegistrationFilterType::SizeType radius, sradius;
  ImageType::OffsetType ssrate;
  sradius[0] = parseResult->GetParameterULong("--ExplorationRadius",0);
  sradius[1] = parseResult->GetParameterULong("--ExplorationRadius",1);
  radius[0] = parseResult->GetParameterULong("--MetricRadius",0);
  radius[1] = parseResult->GetParameterULong("--MetricRadius",1);

  double accuracy = 0.01;
  if(parseResult->IsOptionPresent("--SubPixelAccuracy"))
    {
    accuracy = parseResult->GetParameterDouble("--SubPixelAccuracy");
    }
  ssrate.Fill(1);
  if(parseResult->IsOptionPresent("--SubSamplingRate"))
    {
    ssrate[0] = parseResult->GetParameterDouble("--SubSamplingRate",0);
    ssrate[1] = parseResult->GetParameterDouble("--SubSamplingRate",1);
    }
  RegistrationFilterType::SpacingType initialOffset;
  initialOffset.Fill(0);
  if(parseResult->IsOptionPresent("--CoarseOffset"))
    {
    initialOffset[0] = parseResult->GetParameterDouble("--CoarseOffset",0);
    initialOffset[1] = parseResult->GetParameterDouble("--CoarseOffset",1);
    }

  // Display info
  std::cout<<"Reference image   : "<<freader->GetFileName()<<std::endl;
  std::cout<<"Secondary image   : "<<mreader->GetFileName()<<std::endl;

  std::cout<<"Exploration radius: "<<sradius<<" (pixels)"<<std::endl;
  std::cout<<"Metric radius     : "<<radius<<" (pixels)"<<std::endl;
  std::cout<<"Sub-sampling rate : "<<ssrate<<" (pixels)"<<std::endl;
  std::cout<<"Coarse offset     : "<<initialOffset<<" (physical unit)"<<std::endl;
  std::cout<<"Accuracy          : "<<accuracy<<" (physical unit)"<<std::endl;

  RegistrationFilterType::Pointer registration = RegistrationFilterType::New();
  registration->SetRadius(radius);
  registration->SetSearchRadius(sradius);
  registration->SetSubPixelAccuracy(accuracy);
  registration->SetGridStep(ssrate);
  registration->SetInitialOffset(initialOffset);

  GaussianFilterType::Pointer refGaussianFilter,secGaussianFilter;

  if(parseResult->IsOptionPresent("--ReferenceGaussianSmoothing"))
    {
    refGaussianFilter = GaussianFilterType::New();
    refGaussianFilter->SetInput(freader->GetOutput());
    GaussianFilterType::ArrayType sigma;
    sigma[0] = parseResult->GetParameterDouble("--ReferenceGaussianSmoothing",0);
    sigma[1] = parseResult->GetParameterDouble("--ReferenceGaussianSmoothing",1);
    refGaussianFilter->SetVariance(sigma);
    refGaussianFilter->SetUseImageSpacingOff();
    std::cout<<"Reference image gaussian smoothing on."<<std::endl;
    std::cout<<"variance        : "<<sigma<<" (pixels)"<<std::endl;
    registration->SetFixedInput(refGaussianFilter->GetOutput());
    }
  else
    {
    std::cout<<"Reference image gaussian smoothing off."<<std::endl;
    registration->SetFixedInput(freader->GetOutput());
    }

  if(parseResult->IsOptionPresent("--SecondaryGaussianSmoothing"))
      {
      secGaussianFilter = GaussianFilterType::New();
      secGaussianFilter->SetInput(mreader->GetOutput());
      GaussianFilterType::ArrayType sigma;
      sigma[0] = parseResult->GetParameterDouble("--SecondaryGaussianSmoothing",0);
      sigma[1] = parseResult->GetParameterDouble("--SecondaryGaussianSmoothing",1);
      secGaussianFilter->SetVariance(sigma);
      secGaussianFilter->SetUseImageSpacingOff();
      std::cout<<"Secondary image gaussian smoothing on."<<std::endl;
      std::cout<<"variance        : "<<sigma<<" (pixels)"<<std::endl;
      registration->SetMovingInput(secGaussianFilter->GetOutput());
      }
    else
      {
      std::cout<<"Secondary image gaussian smoothing off."<<std::endl;
      registration->SetMovingInput(mreader->GetOutput());
      }

  // Retrieve metric name
  std::string metricId = "CC";
  if(parseResult->IsOptionPresent("--Metric"))
    {
    metricId = parseResult->GetParameterString("--Metric");
    }

  if(metricId == "CC")
    {
    std::cout<<"Metric            : Cross-correlation"<<std::endl;
    typedef itk::NormalizedCorrelationImageToImageMetric<ImageType,ImageType> NCCType;
    NCCType::Pointer metricPtr = NCCType::New();
    metricPtr->SubtractMeanOff();
    registration->SetMetric(metricPtr);
    registration->MinimizeOn();
    }
  else if(metricId == "CCSM")
    {
    std::cout<<"Metric            : Cross-correlation (mean subtracted)"<<std::endl;
    typedef itk::NormalizedCorrelationImageToImageMetric<ImageType,ImageType> NCCType;
    NCCType::Pointer metricPtr = NCCType::New();
    metricPtr->SubtractMeanOn();
    registration->SetMetric(metricPtr);
    registration->MinimizeOn();
    }
  else if(metricId == "MSD")
    {
    std::cout<<"Metric            : Mean square difference"<<std::endl;
    typedef itk::MeanSquaresImageToImageMetric<ImageType,ImageType> MeanSquareType;
    MeanSquareType::Pointer metricPtr = MeanSquareType::New();
    registration->SetMetric(metricPtr);
    registration->MinimizeOn();
    }
  else if(metricId == "MRSD")
    {
    std::cout<<"Metric            : Mean reciprocal square difference"<<std::endl;
    typedef itk::MeanReciprocalSquareDifferenceImageToImageMetric<ImageType,ImageType> MRSDType;
    MRSDType::Pointer metricPtr = MRSDType::New();
    registration->SetMetric(metricPtr);
    registration->MinimizeOff();
    }
  else if(metricId == "MI")
    {
    std::cout<<"Metric            : Mutual information"<<std::endl;
    typedef itk::MattesMutualInformationImageToImageMetric<ImageType,ImageType> MIType;
    MIType::Pointer metricPtr = MIType::New();
    registration->SetMetric(metricPtr);
    registration->MinimizeOn();
    }
  else
    {
    std::cerr<<"Metric "<<metricId<<" not recognized."<<std::endl;
    std::cerr<<"Possible choices are: CC, CCMS, MSD, MRSD, MI"<<std::endl;
    return EXIT_FAILURE;
    }
  VectorImageToImageFilterType::Pointer xExtractor = VectorImageToImageFilterType::New();
  xExtractor->SetInput(registration->GetOutputDeformationField());
  xExtractor->SetIndex(0);

  VectorImageToImageFilterType::Pointer yExtractor = VectorImageToImageFilterType::New();
  yExtractor->SetInput(registration->GetOutputDeformationField());
  yExtractor->SetIndex(1);

  ImageListType::Pointer il = ImageListType::New();
  il->PushBack(xExtractor->GetOutput());
  il->PushBack(yExtractor->GetOutput());

  AbsFilterType::Pointer absFilter;

  // Invert correlation to get classical rendering
  if(metricId == "CC" || metricId == "CCSM")
    {
    absFilter = AbsFilterType::New();
    absFilter->SetInput(registration->GetOutput());
    il->PushBack(absFilter->GetOutput());
    }
  else
    {
    il->PushBack(registration->GetOutput());
    }

  BinaryThresholdImageFilterType::Pointer threshold;
  if(parseResult->IsOptionPresent("--ValidityMask"))
    {
    threshold = BinaryThresholdImageFilterType::New();

    if(metricId == "CC" || metricId == "CCSM")
      {
      threshold->SetInput(absFilter->GetOutput());
      }
    else
      {
      threshold->SetInput(registration->GetOutput());
      }
    if(parseResult->GetParameterString("--ValidityMask",0)=="greaterThan")
      {
      threshold->SetLowerThreshold(parseResult->GetParameterDouble("--ValidityMask",1));
      }
    else if(parseResult->GetParameterString("--ValidityMask",0)=="lowerThan")
      {
      threshold->SetUpperThreshold(parseResult->GetParameterDouble("--ValidityMask",1));
      }
    else
      {
      std::cerr<<"Arguments of --ValidityMask option should begin with lowerThan or greaterThan"<<std::endl;
      return EXIT_FAILURE;
      }

    std::cout<<"A validity mask will be produced as the 4th band (valid pixels = 1.0, not valid = 0.0)."<<std::endl;
    std::cout<<"Pixels are considered valid if metric is "<<parseResult->GetParameterString("--ValidityMask",0)<<" ";
    std::cout<<parseResult->GetParameterDouble("--ValidityMask",1)<<std::endl;

    threshold->SetInsideValue(1.0);
    threshold->SetOutsideValue(0.);
    il->PushBack(threshold->GetOutput());
    }

  IL2VIFilterType::Pointer il2vi = IL2VIFilterType::New();
  il2vi->SetInput(il);

  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(parseResult->GetOutputImage());
  writer->SetInput(il2vi->GetOutput());

  std::cout<<std::endl;
  otb::StandardWriterWatcher watcher(writer,registration,"Fine Registration");

  writer->Update();

  return EXIT_SUCCESS;
}
<commit_msg>BUG: validity mask is optional<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbImage.h"
#include "otbImageFileReader.h"
#include "otbStreamingImageFileWriter.h"
#include "otbFineRegistrationImageFilter.h"
#include "otbStandardWriterWatcher.h"
#include "otbCommandLineArgumentParser.h"
#include "otbVectorImage.h"
#include "otbImageList.h"
#include "otbImageListToVectorImageFilter.h"

#include "itkTimeProbe.h"
#include "itkFixedArray.h"
#include "itkNormalizedCorrelationImageToImageMetric.h"
#include "itkMeanReciprocalSquareDifferenceImageToImageMetric.h"
#include "itkMeanSquaresImageToImageMetric.h"
#include "itkMattesMutualInformationImageToImageMetric.h"
#include "itkDiscreteGaussianImageFilter.h"
#include "itkAbsImageFilter.h"
#include "itkVectorIndexSelectionCastImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"

int main(int argc, char * argv[])
{
  // Parse command line parameters
  typedef otb::CommandLineArgumentParser ParserType;
  ParserType::Pointer parser = ParserType::New();

  parser->SetProgramDescription("Estimate disparity map between two images. Output image contain x offset, y offset and metric value.");
  parser->AddOption("--Reference","The reference image","-ref", 1,true);
  parser->AddOption("--Secondary","The secondary image","-sec", 1,true);
  parser->AddOutputImage();
  parser->AddOption("--ExplorationRadius","Radius (in pixels) of the exploration window","-er",2,true);
  parser->AddOption("--MetricRadius","Radius (in pixels) of the metric computation window","-mr",2,true);
  parser->AddOption("--CoarseOffset","(optional) Coarse offset (in physical space) between the two images. Default is [0,0].","-co",2,false);
  parser->AddOption("--SubSamplingRate","(optional) Generate a result at a coarser resolution with a given sub-sampling rate in each direction (in pixels). Default is no sub-sampling","-ssr",2,false);
  parser->AddOption("--ReferenceGaussianSmoothing","(optional) Perform a gaussian smoothing of the reference image. Parameters are gaussian sigma (in pixels) in each direction. Default is no smoothing.","-rgs",2,false);
  parser->AddOption("--SecondaryGaussianSmoothing","(optional) Perform a gaussian smoothing of the secondary image. Parameters are gaussian sigma (in pixels) in each direction. Default is no smoothing.","-sgs",2,false);
  parser->AddOption("--Metric","(optional) Choose the metric used for block matching. Available metrics are cross-correlation (CC), cross-correlation with subtracted mean (CCSM), mean-square difference (MSD), mean reciprocal square difference (MRSD) and mutual information (MI). Default is cross-correlation","-m",1,false);
  parser->AddOption("--SubPixelAccuracy","(optional) Metric extrema location will be refined up to the given accuracy. Default is 0.01","-spa",1,false);
  parser->AddOption("--ValidityMask","(optional) Threshold to obtain a validity mask. Params are lowerThan or greaterThan and a threshold","-vm",2,false);

  typedef otb::CommandLineArgumentParseResult ParserResultType;
  ParserResultType::Pointer  parseResult = ParserResultType::New();

  try
  {
    parser->ParseCommandLine(argc,argv,parseResult);
  }
  catch ( itk::ExceptionObject & err )
  {
    std::string descriptionException = err.GetDescription();
    if (descriptionException.find("ParseCommandLine(): Help Parser") != std::string::npos)
      {
      return EXIT_SUCCESS;
      }
    if (descriptionException.find("ParseCommandLine(): Version Parser") != std::string::npos)
      {
      return EXIT_SUCCESS;
      }
    return EXIT_FAILURE;
  }

  const unsigned int Dimension = 2;
  typedef double     PixelType;

  typedef itk::FixedArray<PixelType,Dimension>                                 DeformationValueType;
  typedef otb::Image< PixelType,  Dimension >                                  ImageType;
  typedef otb::VectorImage<PixelType,Dimension>                                VectorImageType;
  typedef otb::ImageList<ImageType>                                            ImageListType;
  typedef otb::ImageListToVectorImageFilter<ImageListType,VectorImageType>     IL2VIFilterType;
  typedef otb::Image<DeformationValueType,Dimension>                           FieldImageType;
  typedef otb::ImageFileReader< ImageType >                                    ReaderType;
  typedef otb::StreamingImageFileWriter< VectorImageType >                     WriterType;
  typedef otb::FineRegistrationImageFilter<ImageType,ImageType,FieldImageType> RegistrationFilterType;
  typedef itk::DiscreteGaussianImageFilter<ImageType,ImageType>                GaussianFilterType;
  typedef itk::VectorIndexSelectionCastImageFilter<FieldImageType,ImageType>   VectorImageToImageFilterType;
  typedef itk::AbsImageFilter<ImageType,ImageType>                             AbsFilterType;
  typedef itk::BinaryThresholdImageFilter<ImageType,ImageType>                 BinaryThresholdImageFilterType;

  // Read reference image
  ReaderType::Pointer freader = ReaderType::New();
  freader->SetFileName(parseResult->GetParameterString("--Reference"));

  // Read secondary image
  ReaderType::Pointer mreader = ReaderType::New();
  mreader->SetFileName(parseResult->GetParameterString("--Secondary"));

  // Retrieve main registration parameters
  RegistrationFilterType::SizeType radius, sradius;
  ImageType::OffsetType ssrate;
  sradius[0] = parseResult->GetParameterULong("--ExplorationRadius",0);
  sradius[1] = parseResult->GetParameterULong("--ExplorationRadius",1);
  radius[0] = parseResult->GetParameterULong("--MetricRadius",0);
  radius[1] = parseResult->GetParameterULong("--MetricRadius",1);

  double accuracy = 0.01;
  if(parseResult->IsOptionPresent("--SubPixelAccuracy"))
    {
    accuracy = parseResult->GetParameterDouble("--SubPixelAccuracy");
    }
  ssrate.Fill(1);
  if(parseResult->IsOptionPresent("--SubSamplingRate"))
    {
    ssrate[0] = parseResult->GetParameterDouble("--SubSamplingRate",0);
    ssrate[1] = parseResult->GetParameterDouble("--SubSamplingRate",1);
    }
  RegistrationFilterType::SpacingType initialOffset;
  initialOffset.Fill(0);
  if(parseResult->IsOptionPresent("--CoarseOffset"))
    {
    initialOffset[0] = parseResult->GetParameterDouble("--CoarseOffset",0);
    initialOffset[1] = parseResult->GetParameterDouble("--CoarseOffset",1);
    }

  // Display info
  std::cout<<"Reference image   : "<<freader->GetFileName()<<std::endl;
  std::cout<<"Secondary image   : "<<mreader->GetFileName()<<std::endl;

  std::cout<<"Exploration radius: "<<sradius<<" (pixels)"<<std::endl;
  std::cout<<"Metric radius     : "<<radius<<" (pixels)"<<std::endl;
  std::cout<<"Sub-sampling rate : "<<ssrate<<" (pixels)"<<std::endl;
  std::cout<<"Coarse offset     : "<<initialOffset<<" (physical unit)"<<std::endl;
  std::cout<<"Accuracy          : "<<accuracy<<" (physical unit)"<<std::endl;

  RegistrationFilterType::Pointer registration = RegistrationFilterType::New();
  registration->SetRadius(radius);
  registration->SetSearchRadius(sradius);
  registration->SetSubPixelAccuracy(accuracy);
  registration->SetGridStep(ssrate);
  registration->SetInitialOffset(initialOffset);

  GaussianFilterType::Pointer refGaussianFilter,secGaussianFilter;

  if(parseResult->IsOptionPresent("--ReferenceGaussianSmoothing"))
    {
    refGaussianFilter = GaussianFilterType::New();
    refGaussianFilter->SetInput(freader->GetOutput());
    GaussianFilterType::ArrayType sigma;
    sigma[0] = parseResult->GetParameterDouble("--ReferenceGaussianSmoothing",0);
    sigma[1] = parseResult->GetParameterDouble("--ReferenceGaussianSmoothing",1);
    refGaussianFilter->SetVariance(sigma);
    refGaussianFilter->SetUseImageSpacingOff();
    std::cout<<"Reference image gaussian smoothing on."<<std::endl;
    std::cout<<"variance        : "<<sigma<<" (pixels)"<<std::endl;
    registration->SetFixedInput(refGaussianFilter->GetOutput());
    }
  else
    {
    std::cout<<"Reference image gaussian smoothing off."<<std::endl;
    registration->SetFixedInput(freader->GetOutput());
    }

  if(parseResult->IsOptionPresent("--SecondaryGaussianSmoothing"))
      {
      secGaussianFilter = GaussianFilterType::New();
      secGaussianFilter->SetInput(mreader->GetOutput());
      GaussianFilterType::ArrayType sigma;
      sigma[0] = parseResult->GetParameterDouble("--SecondaryGaussianSmoothing",0);
      sigma[1] = parseResult->GetParameterDouble("--SecondaryGaussianSmoothing",1);
      secGaussianFilter->SetVariance(sigma);
      secGaussianFilter->SetUseImageSpacingOff();
      std::cout<<"Secondary image gaussian smoothing on."<<std::endl;
      std::cout<<"variance        : "<<sigma<<" (pixels)"<<std::endl;
      registration->SetMovingInput(secGaussianFilter->GetOutput());
      }
    else
      {
      std::cout<<"Secondary image gaussian smoothing off."<<std::endl;
      registration->SetMovingInput(mreader->GetOutput());
      }

  // Retrieve metric name
  std::string metricId = "CC";
  if(parseResult->IsOptionPresent("--Metric"))
    {
    metricId = parseResult->GetParameterString("--Metric");
    }

  if(metricId == "CC")
    {
    std::cout<<"Metric            : Cross-correlation"<<std::endl;
    typedef itk::NormalizedCorrelationImageToImageMetric<ImageType,ImageType> NCCType;
    NCCType::Pointer metricPtr = NCCType::New();
    metricPtr->SubtractMeanOff();
    registration->SetMetric(metricPtr);
    registration->MinimizeOn();
    }
  else if(metricId == "CCSM")
    {
    std::cout<<"Metric            : Cross-correlation (mean subtracted)"<<std::endl;
    typedef itk::NormalizedCorrelationImageToImageMetric<ImageType,ImageType> NCCType;
    NCCType::Pointer metricPtr = NCCType::New();
    metricPtr->SubtractMeanOn();
    registration->SetMetric(metricPtr);
    registration->MinimizeOn();
    }
  else if(metricId == "MSD")
    {
    std::cout<<"Metric            : Mean square difference"<<std::endl;
    typedef itk::MeanSquaresImageToImageMetric<ImageType,ImageType> MeanSquareType;
    MeanSquareType::Pointer metricPtr = MeanSquareType::New();
    registration->SetMetric(metricPtr);
    registration->MinimizeOn();
    }
  else if(metricId == "MRSD")
    {
    std::cout<<"Metric            : Mean reciprocal square difference"<<std::endl;
    typedef itk::MeanReciprocalSquareDifferenceImageToImageMetric<ImageType,ImageType> MRSDType;
    MRSDType::Pointer metricPtr = MRSDType::New();
    registration->SetMetric(metricPtr);
    registration->MinimizeOff();
    }
  else if(metricId == "MI")
    {
    std::cout<<"Metric            : Mutual information"<<std::endl;
    typedef itk::MattesMutualInformationImageToImageMetric<ImageType,ImageType> MIType;
    MIType::Pointer metricPtr = MIType::New();
    registration->SetMetric(metricPtr);
    registration->MinimizeOn();
    }
  else
    {
    std::cerr<<"Metric "<<metricId<<" not recognized."<<std::endl;
    std::cerr<<"Possible choices are: CC, CCMS, MSD, MRSD, MI"<<std::endl;
    return EXIT_FAILURE;
    }
  VectorImageToImageFilterType::Pointer xExtractor = VectorImageToImageFilterType::New();
  xExtractor->SetInput(registration->GetOutputDeformationField());
  xExtractor->SetIndex(0);

  VectorImageToImageFilterType::Pointer yExtractor = VectorImageToImageFilterType::New();
  yExtractor->SetInput(registration->GetOutputDeformationField());
  yExtractor->SetIndex(1);

  ImageListType::Pointer il = ImageListType::New();
  il->PushBack(xExtractor->GetOutput());
  il->PushBack(yExtractor->GetOutput());

  AbsFilterType::Pointer absFilter;

  // Invert correlation to get classical rendering
  if(metricId == "CC" || metricId == "CCSM")
    {
    absFilter = AbsFilterType::New();
    absFilter->SetInput(registration->GetOutput());
    il->PushBack(absFilter->GetOutput());
    }
  else
    {
    il->PushBack(registration->GetOutput());
    }

  BinaryThresholdImageFilterType::Pointer threshold;
  if(parseResult->IsOptionPresent("--ValidityMask"))
    {
    threshold = BinaryThresholdImageFilterType::New();

    if(metricId == "CC" || metricId == "CCSM")
      {
      threshold->SetInput(absFilter->GetOutput());
      }
    else
      {
      threshold->SetInput(registration->GetOutput());
      }
    if(parseResult->GetParameterString("--ValidityMask",0)=="greaterThan")
      {
      threshold->SetLowerThreshold(parseResult->GetParameterDouble("--ValidityMask",1));
      }
    else if(parseResult->GetParameterString("--ValidityMask",0)=="lowerThan")
      {
      threshold->SetUpperThreshold(parseResult->GetParameterDouble("--ValidityMask",1));
      }
    else
      {
      std::cerr<<"Arguments of --ValidityMask option should begin with lowerThan or greaterThan"<<std::endl;
      return EXIT_FAILURE;
      }

    std::cout<<"A validity mask will be produced as the 4th band (valid pixels = 1.0, not valid = 0.0)."<<std::endl;
    std::cout<<"Pixels are considered valid if metric is "<<parseResult->GetParameterString("--ValidityMask",0)<<" ";
    std::cout<<parseResult->GetParameterDouble("--ValidityMask",1)<<std::endl;

    threshold->SetInsideValue(1.0);
    threshold->SetOutsideValue(0.);
    il->PushBack(threshold->GetOutput());
    }

  IL2VIFilterType::Pointer il2vi = IL2VIFilterType::New();
  il2vi->SetInput(il);

  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(parseResult->GetOutputImage());
  writer->SetInput(il2vi->GetOutput());

  std::cout<<std::endl;
  otb::StandardWriterWatcher watcher(writer,registration,"Fine Registration");

  writer->Update();

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#ifndef HTTP_CLIENT_HH
#define HTTP_CLIENT_HH

#include "http/http_message.hh"
#include "shared_pool.hh"
#include "buffer.hh"

namespace ten {

class http_client {
private:
    std::shared_ptr<netsock> s;
    buffer buf;

    void ensure_connection() {
        if (s && s->valid()) return;
        s.reset(new netsock(AF_INET, SOCK_STREAM));
        if (s->dial(host.c_str(), port) != 0) {
            throw errorx("dial %s:%d failed", host.c_str(), port);
        }
    }

public:
    const std::string host;
    const uint16_t port;

    http_client(const std::string &host_, uint16_t port_=80)
        : buf(4*1024), host(host_), port(port_) {}

    http_response perform(const std::string &method, const std::string &path, const std::string &data="") {
        try {
            ensure_connection();
            uri u;
            u.scheme = "http";
            u.host = host;
            u.port = port;
            u.path = path;
            u.normalize();

            http_request r(method, u.compose(true));
            // HTTP/1.1 requires host header
            r.append("Host", u.host);
            r.append("Content-Length", data.size());

            std::string hdata = r.data();
            ssize_t nw = s->send(hdata.c_str(), hdata.size());
            nw = s->send(data.c_str(), data.size());

            http_parser parser;
            http_response resp;
            resp.parser_init(&parser);

            buf.clear();

            while (!resp.complete) {
                buf.reserve(4*1024);
                ssize_t nr = s->recv(buf.back(), buf.available());
                if (nr <= 0) { throw errorx("http get error"); }
                buf.commit(nr);
                size_t len = buf.size();
                resp.parse(&parser, buf.front(), len);
                buf.remove(len);
            }
            // should not be any data left over in buf
            CHECK(buf.size() == 0);

            return resp;
        } catch (errorx &e) {
            s.reset();
            throw;
        }
    }

    http_response get(const std::string &path) {
        return perform("GET", path);
    }

    http_response post(const std::string &path, const std::string &data) {
        return perform("POST", path, data);
    }

};

class http_pool : public shared_pool<http_client> {
public:
    http_pool(const std::string &host_, uint16_t port_, ssize_t max_conn)
        : shared_pool<http_client>("http://" + host_,
            std::bind(&http_pool::new_resource, this),
            max_conn
        ),
        host(host_), port(port_) {}

protected:
    std::string host;
    uint16_t port;

    std::shared_ptr<http_client> new_resource() {
        VLOG(3) << "new http_client resource " << host;
        return std::make_shared<http_client>(host, port);
    }
};

} // end namespace ten
#endif // HTTP_CLIENT_HH

<commit_msg>max_content_length<commit_after>#ifndef HTTP_CLIENT_HH
#define HTTP_CLIENT_HH

#include "http/http_message.hh"
#include "shared_pool.hh"
#include "buffer.hh"

namespace ten {

class http_client {
private:
    std::shared_ptr<netsock> s;
    buffer buf;

    void ensure_connection() {
        if (s && s->valid()) return;
        s.reset(new netsock(AF_INET, SOCK_STREAM));
        if (s->dial(host.c_str(), port) != 0) {
            throw errorx("dial %s:%d failed", host.c_str(), port);
        }
    }

public:
    const std::string host;
    const uint16_t port;
    size_t max_content_length;

    http_client(const std::string &host_, uint16_t port_=80)
        : buf(4*1024), host(host_), port(port_), max_content_length(-1) {}

    http_response perform(const std::string &method, const std::string &path, const std::string &data="") {
        try {
            ensure_connection();
            uri u;
            u.scheme = "http";
            u.host = host;
            u.port = port;
            u.path = path;
            u.normalize();

            http_request r(method, u.compose(true));
            // HTTP/1.1 requires host header
            r.append("Host", u.host);
            r.append("Content-Length", data.size());

            std::string hdata = r.data();
            ssize_t nw = s->send(hdata.c_str(), hdata.size());
            nw = s->send(data.c_str(), data.size());

            http_parser parser;
            http_response resp;
            resp.parser_init(&parser);

            buf.clear();

            while (!resp.complete) {
                buf.reserve(4*1024);
                ssize_t nr = s->recv(buf.back(), buf.available());
                if (nr <= 0) { throw errorx("http get error"); }
                buf.commit(nr);
                size_t len = buf.size();
                resp.parse(&parser, buf.front(), len);
                buf.remove(len);
                if (resp.body.size() >= max_content_length) {
                    s.reset(); // close this socket, we won't read anymore
                    return resp;
                }
            }
            // should not be any data left over in buf
            CHECK(buf.size() == 0);

            return resp;
        } catch (errorx &e) {
            s.reset();
            throw;
        }
    }

    http_response get(const std::string &path) {
        return perform("GET", path);
    }

    http_response post(const std::string &path, const std::string &data) {
        return perform("POST", path, data);
    }

};

class http_pool : public shared_pool<http_client> {
public:
    http_pool(const std::string &host_, uint16_t port_, ssize_t max_conn)
        : shared_pool<http_client>("http://" + host_,
            std::bind(&http_pool::new_resource, this),
            max_conn
        ),
        host(host_), port(port_) {}

protected:
    std::string host;
    uint16_t port;

    std::shared_ptr<http_client> new_resource() {
        VLOG(3) << "new http_client resource " << host;
        return std::make_shared<http_client>(host, port);
    }
};

} // end namespace ten
#endif // HTTP_CLIENT_HH

<|endoftext|>


<commit_before>// Copyright (c) 2014-2019 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAO_PEGTL_INTERNAL_FILE_MAPPER_WIN32_HPP
#define TAO_PEGTL_INTERNAL_FILE_MAPPER_WIN32_HPP

#if !defined( NOMINMAX )
#define NOMINMAX
#define TAO_PEGTL_NOMINMAX_WAS_DEFINED
#endif

#if !defined( WIN32_LEAN_AND_MEAN )
#define WIN32_LEAN_AND_MEAN
#define TAO_PEGTL_WIN32_LEAN_AND_MEAN_WAS_DEFINED
#endif

#include <windows.h>

#if defined( TAO_PEGTL_NOMINMAX_WAS_DEFINED )
#undef NOMINMAX
#undef TAO_PEGTL_NOMINMAX_WAS_DEFINED
#endif

#if defined( TAO_PEGTL_WIN32_LEAN_AND_MEAN_WAS_DEFINED )
#undef WIN32_LEAN_AND_MEAN
#undef TAO_PEGTL_WIN32_LEAN_AND_MEAN_WAS_DEFINED
#endif

#include <system_error>

#include "../config.hpp"

namespace tao
{
   namespace TAO_PEGTL_NAMESPACE
   {
      namespace internal
      {
         struct win32_file_opener
         {
            explicit win32_file_opener( const char* filename )
               : m_source( filename ),
                 m_handle( open() )
            {
            }

            win32_file_opener( const win32_file_opener& ) = delete;
            win32_file_opener( win32_file_opener&& ) = delete;

            ~win32_file_opener() noexcept
            {
               ::CloseHandle( m_handle );
            }

            void operator=( const win32_file_opener& ) = delete;
            void operator=( win32_file_opener&& ) = delete;

            [[nodiscard]] std::size_t size() const
            {
               LARGE_INTEGER size;
               if( !::GetFileSizeEx( m_handle, &size ) ) {
                  const auto ec = ::GetLastError();
                  throw std::system_error( ec, std::system_category(), std::string( "GetFileSizeEx(): " ) + m_source );
               }
               return std::size_t( size.QuadPart );
            }

            const char* const m_source;
            const HANDLE m_handle;

         private:
            [[nodiscard]] HANDLE open() const
            {
               SetLastError( 0 );
               std::wstring ws( m_source, m_source + strlen( m_source ) );
               const HANDLE handle = ::CreateFile2( ws.c_str(),
                                                    GENERIC_READ,
                                                    FILE_SHARE_READ,
                                                    OPEN_EXISTING,
                                                    nullptr );
               if( handle != INVALID_HANDLE_VALUE ) {
                  return handle;
               }
               const auto ec = ::GetLastError();
               throw std::system_error( ec, std::system_category(), std::string( "CreateFile2(): " ) + m_source );
            }
         };

         struct win32_file_mapper
         {
            explicit win32_file_mapper( const char* filename )
               : win32_file_mapper( win32_file_opener( filename ) )
            {
            }

            explicit win32_file_mapper( const win32_file_opener& reader )
               : m_size( reader.size() ),
                 m_handle( open( reader ) )
            {
            }

            win32_file_mapper( const win32_file_mapper& ) = delete;
            win32_file_mapper( win32_file_mapper&& ) = delete;

            ~win32_file_mapper() noexcept
            {
               ::CloseHandle( m_handle );
            }

            void operator=( const win32_file_mapper& ) = delete;
            void operator=( win32_file_mapper&& ) = delete;

            const size_t m_size;
            const HANDLE m_handle;

         private:
            [[nodiscard]] HANDLE open( const win32_file_opener& reader ) const
            {
               const uint64_t file_size = reader.size();
               SetLastError( 0 );
               // Use `CreateFileMappingW` because a) we're not specifying a
               // mapping name, so the character type is of no consequence, and
               // b) it's defined in `memoryapi.h`, unlike
               // `CreateFileMappingA`(?!)
               const HANDLE handle = ::CreateFileMappingW( reader.m_handle,
                                                           nullptr,
                                                           PAGE_READONLY,
                                                           DWORD( file_size >> 32 ),
                                                           DWORD( file_size & 0xffffffff ),
                                                           nullptr );
               if( handle != NULL || file_size == 0 ) {
                  return handle;
               }
               const auto ec = ::GetLastError();
               throw std::system_error( ec, std::system_category(), std::string( "CreateFileMappingW(): " ) + reader.m_source );
            }
         };

         class file_mapper
         {
         public:
            explicit file_mapper( const char* filename )
               : file_mapper( win32_file_mapper( filename ) )
            {
            }

            explicit file_mapper( const win32_file_mapper& mapper )
               : m_size( mapper.m_size ),
                 m_data( static_cast< const char* >( ::MapViewOfFile( mapper.m_handle,
                                                                      FILE_MAP_READ,
                                                                      0,
                                                                      0,
                                                                      0 ) ) )
            {
               if( ( m_size != 0 ) && ( intptr_t( m_data ) == 0 ) ) {
                  const auto ec = ::GetLastError();
                  throw std::system_error( ec, std::system_category(), "MapViewOfFile()" );
               }
            }

            file_mapper( const file_mapper& ) = delete;
            file_mapper( file_mapper&& ) = delete;

            ~file_mapper() noexcept
            {
               ::UnmapViewOfFile( LPCVOID( m_data ) );
            }

            void operator=( const file_mapper& ) = delete;
            void operator=( file_mapper&& ) = delete;

            [[nodiscard]] bool empty() const noexcept
            {
               return m_size == 0;
            }

            [[nodiscard]] std::size_t size() const noexcept
            {
               return m_size;
            }

            using iterator = const char*;
            using const_iterator = const char*;

            [[nodiscard]] iterator data() const noexcept
            {
               return m_data;
            }

            [[nodiscard]] iterator begin() const noexcept
            {
               return m_data;
            }

            [[nodiscard]] iterator end() const noexcept
            {
               return m_data + m_size;
            }

         private:
            const std::size_t m_size;
            const char* const m_data;
         };

      }  // namespace internal

   }  // namespace TAO_PEGTL_NAMESPACE

}  // namespace tao

#endif
<commit_msg>Fix #155<commit_after>// Copyright (c) 2014-2019 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/

#ifndef TAO_PEGTL_INTERNAL_FILE_MAPPER_WIN32_HPP
#define TAO_PEGTL_INTERNAL_FILE_MAPPER_WIN32_HPP

#if !defined( NOMINMAX )
#define NOMINMAX
#define TAO_PEGTL_NOMINMAX_WAS_DEFINED
#endif

#if !defined( WIN32_LEAN_AND_MEAN )
#define WIN32_LEAN_AND_MEAN
#define TAO_PEGTL_WIN32_LEAN_AND_MEAN_WAS_DEFINED
#endif

#include <windows.h>

#if defined( TAO_PEGTL_NOMINMAX_WAS_DEFINED )
#undef NOMINMAX
#undef TAO_PEGTL_NOMINMAX_WAS_DEFINED
#endif

#if defined( TAO_PEGTL_WIN32_LEAN_AND_MEAN_WAS_DEFINED )
#undef WIN32_LEAN_AND_MEAN
#undef TAO_PEGTL_WIN32_LEAN_AND_MEAN_WAS_DEFINED
#endif

#include <system_error>

#include "../config.hpp"

namespace tao
{
   namespace TAO_PEGTL_NAMESPACE
   {
      namespace internal
      {
         struct win32_file_opener
         {
            explicit win32_file_opener( const char* filename )
               : m_source( filename ),
                 m_handle( open() )
            {
            }

            win32_file_opener( const win32_file_opener& ) = delete;
            win32_file_opener( win32_file_opener&& ) = delete;

            ~win32_file_opener() noexcept
            {
               ::CloseHandle( m_handle );
            }

            void operator=( const win32_file_opener& ) = delete;
            void operator=( win32_file_opener&& ) = delete;

            [[nodiscard]] std::size_t size() const
            {
               LARGE_INTEGER size;
               if( !::GetFileSizeEx( m_handle, &size ) ) {
                  const auto ec = ::GetLastError();
                  throw std::system_error( ec, std::system_category(), std::string( "GetFileSizeEx(): " ) + m_source );
               }
               return std::size_t( size.QuadPart );
            }

            const char* const m_source;
            const HANDLE m_handle;

         private:
            [[nodiscard]] HANDLE open() const
            {
               SetLastError( 0 );
               std::wstring ws( m_source, m_source + strlen( m_source ) );

#if( _WIN32_WINNT >= 0x0602 )
               const HANDLE handle = ::CreateFile2( ws.c_str(),
                                                    GENERIC_READ,
                                                    FILE_SHARE_READ,
                                                    OPEN_EXISTING,
                                                    nullptr );
#else
               const HANDLE handle = ::CreateFileW( ws.c_str(),
                                                    GENERIC_READ,
                                                    FILE_SHARE_READ,
                                                    nullptr,
                                                    OPEN_EXISTING,
                                                    FILE_ATTRIBUTE_NORMAL,
                                                    nullptr );
#endif

               if( handle != INVALID_HANDLE_VALUE ) {
                  return handle;
               }
               const auto ec = ::GetLastError();
               throw std::system_error( ec, std::system_category(), std::string( "CreateFile2(): " ) + m_source );
            }
         };

         struct win32_file_mapper
         {
            explicit win32_file_mapper( const char* filename )
               : win32_file_mapper( win32_file_opener( filename ) )
            {
            }

            explicit win32_file_mapper( const win32_file_opener& reader )
               : m_size( reader.size() ),
                 m_handle( open( reader ) )
            {
            }

            win32_file_mapper( const win32_file_mapper& ) = delete;
            win32_file_mapper( win32_file_mapper&& ) = delete;

            ~win32_file_mapper() noexcept
            {
               ::CloseHandle( m_handle );
            }

            void operator=( const win32_file_mapper& ) = delete;
            void operator=( win32_file_mapper&& ) = delete;

            const size_t m_size;
            const HANDLE m_handle;

         private:
            [[nodiscard]] HANDLE open( const win32_file_opener& reader ) const
            {
               const uint64_t file_size = reader.size();
               SetLastError( 0 );
               // Use `CreateFileMappingW` because a) we're not specifying a
               // mapping name, so the character type is of no consequence, and
               // b) it's defined in `memoryapi.h`, unlike
               // `CreateFileMappingA`(?!)
               const HANDLE handle = ::CreateFileMappingW( reader.m_handle,
                                                           nullptr,
                                                           PAGE_READONLY,
                                                           DWORD( file_size >> 32 ),
                                                           DWORD( file_size & 0xffffffff ),
                                                           nullptr );
               if( handle != NULL || file_size == 0 ) {
                  return handle;
               }
               const auto ec = ::GetLastError();
               throw std::system_error( ec, std::system_category(), std::string( "CreateFileMappingW(): " ) + reader.m_source );
            }
         };

         class file_mapper
         {
         public:
            explicit file_mapper( const char* filename )
               : file_mapper( win32_file_mapper( filename ) )
            {
            }

            explicit file_mapper( const win32_file_mapper& mapper )
               : m_size( mapper.m_size ),
                 m_data( static_cast< const char* >( ::MapViewOfFile( mapper.m_handle,
                                                                      FILE_MAP_READ,
                                                                      0,
                                                                      0,
                                                                      0 ) ) )
            {
               if( ( m_size != 0 ) && ( intptr_t( m_data ) == 0 ) ) {
                  const auto ec = ::GetLastError();
                  throw std::system_error( ec, std::system_category(), "MapViewOfFile()" );
               }
            }

            file_mapper( const file_mapper& ) = delete;
            file_mapper( file_mapper&& ) = delete;

            ~file_mapper() noexcept
            {
               ::UnmapViewOfFile( LPCVOID( m_data ) );
            }

            void operator=( const file_mapper& ) = delete;
            void operator=( file_mapper&& ) = delete;

            [[nodiscard]] bool empty() const noexcept
            {
               return m_size == 0;
            }

            [[nodiscard]] std::size_t size() const noexcept
            {
               return m_size;
            }

            using iterator = const char*;
            using const_iterator = const char*;

            [[nodiscard]] iterator data() const noexcept
            {
               return m_data;
            }

            [[nodiscard]] iterator begin() const noexcept
            {
               return m_data;
            }

            [[nodiscard]] iterator end() const noexcept
            {
               return m_data + m_size;
            }

         private:
            const std::size_t m_size;
            const char* const m_data;
         };

      }  // namespace internal

   }  // namespace TAO_PEGTL_NAMESPACE

}  // namespace tao

#endif
<|endoftext|>