<commit_before>#include "optimizers.h"

#include "common/io.h"
#include "tensors/tensor_operators.h"

namespace marian {

void Sgd::updateImpl(Tensor params, Tensor grads) {
  using namespace functional;
  Element(_1 -= (multiplyFactor_ * eta_) * _2, params, grads);

  params->getBackend()->synchronize();
}

// Aagrad

void Adagrad::updateImpl(Tensor params, Tensor grads) {
  if(!alloc_)
    alloc_ = New<TensorAllocator>(params->getBackend());

  if(!gt_) {
    int elements = (int)params->size();
    alloc_->reserveExact(params->memory()->size());
    alloc_->allocate(gt_, {1, elements});
    gt_->set(0.f);
  }

  using namespace functional;

  Element(_1 += (_2 * _2), gt_, grads);

  Element(_1 -= ((multiplyFactor_ * eta_) / (sqrt(_2) + eps_)) * _3,
          params,
          gt_,
          grads);

  params->getBackend()->synchronize();
}

void Adagrad::load(const std::string& name,
                   std::vector<Ptr<OptimizerBase>> opts,
                   std::vector<Ptr<Backend>> backends) {
  ABORT_IF(opts.size() != backends.size(), "opts and backends of different sizes??");

  if(!boost::filesystem::exists(name))
    return;

  LOG(info, "Loading Adagrad parameters from {}", name);

  std::vector<float> vGt;

  // @TODO: use new IO
  auto items = io::loadItems(name);
  for(auto item : items) {
    // get the size of gt_
    auto totalSize = item.shape.elements();

    // extract data into vectors
    if(item.name == "adagrad_gt") {
      vGt.resize(totalSize);
      std::copy(
          (float*)item.data(), (float*)item.data() + totalSize, vGt.begin());
    }
  }
  if(vGt.empty()) {
    LOG(warn, "[warn] Adagrad parameters not found in .npz file");
    return;
  }

  for(size_t id = 0; id < opts.size(); id++) {
    auto opt = std::dynamic_pointer_cast<Adagrad>(opts[id]);

    size_t totalSize = vGt.size();
    size_t shardSize = (size_t)(ceil(totalSize / (float)opts.size()));
    size_t shift = id * shardSize;
    size_t size = std::min(shardSize, totalSize-shift);

    if(!opt->alloc_)
      opt->alloc_ = New<TensorAllocator>(backends[id]);

    if(!opt->gt_) {
      opt->alloc_->reserveExact(sizeof(float) * size);
      opt->alloc_->allocate(opt->gt_, {1, (int)size});
    }

    std::vector<float> tmp(vGt.begin() + shift, vGt.begin() + shift + size);
    opt->gt_->set(tmp);
  }
}

void Adagrad::save(const std::string& name,
                   std::vector<Ptr<OptimizerBase>> opts,
                   size_t /*totalSize*/) {
  LOG(info, "Saving Adagrad parameters to {}", name);

  std::vector<float> vGt;

  for(auto optBase : opts) {
    auto opt = std::dynamic_pointer_cast<Adagrad>(optBase);
    std::vector<float> tmp;
    opt->gt_->get(tmp);
    vGt.insert(vGt.end(), tmp.begin(), tmp.end());
  }

  io::Item item;
  item.name = "adagrad_gt";
  item.shape = Shape({1, (int)vGt.size()});
  item.type = Type::float32;
  item.bytes.resize(vGt.size() * sizeOf(item.type));
  std::copy(
      (char*)vGt.data(), (char*)vGt.data() + vGt.size(), item.bytes.begin());

  io::saveItems(name, {item});
}

void Adagrad::resetStats() {
  if(gt_)
    gt_->set(0.f);
}

// Adam

void Adam::updateImpl(Tensor params, Tensor grads) {
  if(!alloc_)
    alloc_ = New<TensorAllocator>(params->getBackend());

  if(!mt_) {
    int elements = (int)params->size();
    alloc_->reserveExact(2 * params->memory()->size());
    alloc_->allocate(mt_, {1, elements});
    mt_->set(0.f);

    alloc_->allocate(vt_, {1, elements});
    vt_->set(0.f);
  }

  t_++;
  float denom1 = 1 - (float)std::pow(beta1_, t_);
  float denom2 = 1 - (float)std::pow(beta2_, t_);

  using namespace functional;

  Element(_1 = (beta1_ * _1) + ((1 - beta1_) * _2), mt_, grads);
  Element(_1 = (beta2_ * _1) + ((1 - beta2_) * (_2 * _2)), vt_, grads);

  Element(_1 -= (multiplyFactor_ * eta_) * (_2 / denom1)
                / (sqrt(_3 / denom2) + eps_),
          params,
          mt_,
          vt_);

  params->getBackend()->synchronize();
}

void Adam::load(const std::string& name,
                std::vector<Ptr<OptimizerBase>> opts,
                std::vector<Ptr<Backend>> backends) {
  ABORT_IF(opts.size() != backends.size(), "opts and backends of different sizes??");

  if(!boost::filesystem::exists(name))
    return;

  LOG(info, "Loading Adam parameters from {}", name);

  std::vector<float> vMt;
  std::vector<float> vVt;

  auto items = io::loadItems(name);
  for(auto item : items) {
    // get the size of mt_ and vt_, they are the same
    auto totalSize = item.shape.elements();

    // extract data into vectors
    if(item.name == "adam_mt") {
      vMt.resize(totalSize);
      std::copy(
          (float*)item.data(), (float*)item.data() + totalSize, vMt.begin());
    }
    if(item.name == "adam_vt") {
      vVt.resize(totalSize);
      std::copy(
          (float*)item.data(), (float*)item.data() + totalSize, vVt.begin());
    }
  }
  if(vMt.empty() || vVt.empty()) {
    LOG(warn, "[warn] Adam parameters not found in .npz file");
    return;
  }
  ABORT_IF(vMt.size() != vVt.size(), "mt and vt have different sizes??");

  for(size_t id = 0; id < opts.size(); id++) {
    auto opt = std::dynamic_pointer_cast<Adam>(opts[id]);

    size_t totalSize = vMt.size();
    size_t shardSize = (size_t)(ceil(totalSize / (float)opts.size()));
    size_t shift = id * shardSize;
    size_t size = std::min(shardSize, totalSize-shift);

    if(!opt->alloc_)
      opt->alloc_ = New<TensorAllocator>(backends[id]);

    if(!opt->mt_ || !opt->vt_) {
      opt->alloc_->reserveExact(2 * sizeof(float) * size);
      opt->alloc_->allocate(opt->mt_, {1, (int)size});
      opt->alloc_->allocate(opt->vt_, {1, (int)size});
    }

    std::vector<float> tmpMt(vMt.begin() + shift, vMt.begin() + shift + size);
    opt->mt_->set(tmpMt);
    std::vector<float> tmpVt(vVt.begin() + shift, vVt.begin() + shift + size);
    opt->vt_->set(tmpVt);
  }
}

void Adam::save(const std::string& name,
                std::vector<Ptr<OptimizerBase>> opts,
                size_t /*totalSize*/) {
  LOG(info, "Saving Adam parameters to {}", name);

  std::vector<float> vMt;
  std::vector<float> vVt;

  for(auto optBase : opts) {
    auto opt = std::dynamic_pointer_cast<Adam>(optBase);

    std::vector<float> tmp;
    opt->mt_->get(tmp);
    vMt.insert(vMt.end(), tmp.begin(), tmp.end());
    opt->vt_->get(tmp);
    vVt.insert(vVt.end(), tmp.begin(), tmp.end());
  }

  io::Item itemMt;
  itemMt.name = "adam_mt";
  itemMt.shape = Shape({1, (int)vMt.size()});
  itemMt.type = Type::float32;
  itemMt.bytes.resize(vMt.size() * sizeOf(itemMt.type));
  std::copy(
      (char*)vMt.data(), (char*)vMt.data() + vMt.size(), itemMt.bytes.begin());

  io::Item itemVt;
  itemVt.name = "adam_vt";
  itemVt.shape = Shape({1, (int)vVt.size()});
  itemVt.type = Type::float32;
  itemVt.bytes.resize(vVt.size() * sizeOf(itemVt.type));
  std::copy(
      (char*)vVt.data(), (char*)vVt.data() + vVt.size(), itemVt.bytes.begin());

  io::saveItems(name, {itemMt, itemVt});
}

void Adam::resetStats() {
  if(mt_)
    mt_->set(0.f);

  if(vt_)
    vt_->set(0.f);
}

Ptr<OptimizerBase> Optimizer(Ptr<Config> options) {
  float lrate = (float)options->get<double>("learn-rate"); // @TODO: should this be <float>?
  auto params = options->has("optimizer-params")
                    ? options->get<std::vector<float>>("optimizer-params")
                    : std::vector<float>({});

  Ptr<ClipperBase> clipper = nullptr;
  float clipNorm = (float)options->get<double>("clip-norm"); // @TODO: should this be <float>?
  if(clipNorm > 0)
    clipper = Clipper<Norm>(clipNorm);

  auto opt = options->get<std::string>("optimizer");

  if(opt == "sgd") {
    return Optimizer<Sgd>(lrate, clipper, params);
  } else if(opt == "adagrad") {
    return Optimizer<Adagrad>(lrate, clipper, params);
  } else if(opt == "adam") {
    return Optimizer<Adam>(lrate, clipper, params);
  } else {
    ABORT("Unknown optimizer: {}", opt);
  }
}
}  // namespace marian
<commit_msg>refactoring towards distributed saving of optimizer state<commit_after>#include "optimizers.h"

#include "common/io.h"
#include "tensors/tensor_operators.h"

namespace marian {

void Sgd::updateImpl(Tensor params, Tensor grads) {
  using namespace functional;
  Element(_1 -= (multiplyFactor_ * eta_) * _2, params, grads);

  params->getBackend()->synchronize();
}

// Aagrad

void Adagrad::updateImpl(Tensor params, Tensor grads) {
  if(!alloc_)
    alloc_ = New<TensorAllocator>(params->getBackend());

  if(!gt_) {
    int elements = (int)params->size();
    alloc_->reserveExact(params->memory()->size());
    alloc_->allocate(gt_, {1, elements});
    gt_->set(0.f);
  }

  using namespace functional;

  Element(_1 += (_2 * _2), gt_, grads);

  Element(_1 -= ((multiplyFactor_ * eta_) / (sqrt(_2) + eps_)) * _3,
          params,
          gt_,
          grads);

  params->getBackend()->synchronize();
}

void Adagrad::load(const std::string& name,
                   std::vector<Ptr<OptimizerBase>> opts,
                   std::vector<Ptr<Backend>> backends) {
  ABORT_IF(opts.size() != backends.size(), "opts and backends of different sizes??");

  if(!boost::filesystem::exists(name))
    return;

  LOG(info, "Loading Adagrad parameters from {}", name);

  std::vector<float> vGt;

  // @TODO: use new IO
  auto items = io::loadItems(name);
  for(auto item : items) {
    // get the size of gt_
    auto totalSize = item.shape.elements();

    // extract data into vectors
    if(item.name == "adagrad_gt") {
      vGt.resize(totalSize);
      std::copy(
          (float*)item.data(), (float*)item.data() + totalSize, vGt.begin());
    }
  }
  if(vGt.empty()) {
    LOG(warn, "[warn] Adagrad parameters not found in .npz file");
    return;
  }

  for(size_t id = 0; id < opts.size(); id++) {
    auto opt = std::dynamic_pointer_cast<Adagrad>(opts[id]);

    size_t totalSize = vGt.size();
    size_t shardSize = (size_t)(ceil(totalSize / (float)opts.size()));
    size_t shift = id * shardSize;
    size_t size = std::min(shardSize, totalSize-shift);

    if(!opt->alloc_)
      opt->alloc_ = New<TensorAllocator>(backends[id]);

    if(!opt->gt_) {
      opt->alloc_->reserveExact(sizeof(float) * size);
      opt->alloc_->allocate(opt->gt_, {1, (int)size});
    }

    std::vector<float> tmp(vGt.begin() + shift, vGt.begin() + shift + size);
    opt->gt_->set(tmp);
  }
}

void Adagrad::save(const std::string& name,
                   std::vector<Ptr<OptimizerBase>> opts,
                   size_t /*totalSize*/) {
  LOG(info, "Saving Adagrad parameters to {}", name);

  // fetch and concatenate state vectors from shards into a CPU-side vector
  std::vector<float> vGt;
  for(auto optBase : opts) {
    auto opt = std::dynamic_pointer_cast<Adagrad>(optBase);
    std::vector<float> tmp;
    opt->gt_->get(tmp);
    vGt.insert(vGt.end(), tmp.begin(), tmp.end());
  }

  // save to file
  io::Item item;
  item.name = "adagrad_gt";
  item.shape = Shape({1, (int)vGt.size()});
  item.type = Type::float32;
  item.bytes.resize(vGt.size() * sizeOf(item.type));
  std::copy(
      (char*)vGt.data(), (char*)vGt.data() + vGt.size(), item.bytes.begin());

  io::saveItems(name, {item});
}

void Adagrad::resetStats() {
  if(gt_)
    gt_->set(0.f);
}

// Adam

void Adam::updateImpl(Tensor params, Tensor grads) {
  if(!alloc_)
    alloc_ = New<TensorAllocator>(params->getBackend());

  if(!mt_) {
    int elements = (int)params->size();
    alloc_->reserveExact(2 * params->memory()->size());
    alloc_->allocate(mt_, {1, elements});
    mt_->set(0.f);

    alloc_->allocate(vt_, {1, elements});
    vt_->set(0.f);
  }

  t_++;
  float denom1 = 1 - (float)std::pow(beta1_, t_);
  float denom2 = 1 - (float)std::pow(beta2_, t_);

  using namespace functional;

  Element(_1 = (beta1_ * _1) + ((1 - beta1_) * _2), mt_, grads);
  Element(_1 = (beta2_ * _1) + ((1 - beta2_) * (_2 * _2)), vt_, grads);

  Element(_1 -= (multiplyFactor_ * eta_) * (_2 / denom1)
                / (sqrt(_3 / denom2) + eps_),
          params,
          mt_,
          vt_);

  params->getBackend()->synchronize();
}

void Adam::load(const std::string& name,
                std::vector<Ptr<OptimizerBase>> opts,
                std::vector<Ptr<Backend>> backends) {
  ABORT_IF(opts.size() != backends.size(), "opts and backends of different sizes??");

  if(!boost::filesystem::exists(name))
    return;

  LOG(info, "Loading Adam parameters from {}", name);

  std::vector<float> vMt;
  std::vector<float> vVt;

  auto items = io::loadItems(name);
  for(auto item : items) {
    // get the size of mt_ and vt_, they are the same
    auto totalSize = item.shape.elements();

    // extract data into vectors
    if(item.name == "adam_mt") {
      vMt.resize(totalSize);
      std::copy(
          (float*)item.data(), (float*)item.data() + totalSize, vMt.begin());
    }
    if(item.name == "adam_vt") {
      vVt.resize(totalSize);
      std::copy(
          (float*)item.data(), (float*)item.data() + totalSize, vVt.begin());
    }
  }
  if(vMt.empty() || vVt.empty()) {
    LOG(warn, "[warn] Adam parameters not found in .npz file");
    return;
  }
  ABORT_IF(vMt.size() != vVt.size(), "mt and vt have different sizes??");

  for(size_t id = 0; id < opts.size(); id++) {
    auto opt = std::dynamic_pointer_cast<Adam>(opts[id]);

    size_t totalSize = vMt.size();
    size_t shardSize = (size_t)(ceil(totalSize / (float)opts.size()));
    size_t shift = id * shardSize;
    size_t size = std::min(shardSize, totalSize-shift);

    if(!opt->alloc_)
      opt->alloc_ = New<TensorAllocator>(backends[id]);

    if(!opt->mt_ || !opt->vt_) {
      opt->alloc_->reserveExact(2 * sizeof(float) * size);
      opt->alloc_->allocate(opt->mt_, {1, (int)size});
      opt->alloc_->allocate(opt->vt_, {1, (int)size});
    }

    std::vector<float> tmpMt(vMt.begin() + shift, vMt.begin() + shift + size);
    opt->mt_->set(tmpMt);
    std::vector<float> tmpVt(vVt.begin() + shift, vVt.begin() + shift + size);
    opt->vt_->set(tmpVt);
  }
}

void Adam::save(const std::string& name,
                std::vector<Ptr<OptimizerBase>> opts,
                size_t /*totalSize*/) {
  LOG(info, "Saving Adam parameters to {}", name);

  // fetch and concatenate state vectors from shards into a CPU-side vector
  std::vector<float> vMt;
  for(auto optBase : opts) {
    auto opt = std::dynamic_pointer_cast<Adam>(optBase);
    std::vector<float> tmp;
    opt->mt_->get(tmp);
    vMt.insert(vMt.end(), tmp.begin(), tmp.end());
  }
  std::vector<float> vVt;
  for(auto optBase : opts) {
    auto opt = std::dynamic_pointer_cast<Adam>(optBase);
    std::vector<float> tmp;
    opt->vt_->get(tmp);
    vVt.insert(vVt.end(), tmp.begin(), tmp.end());
  }

  // save to file
  io::Item itemMt;
  itemMt.name = "adam_mt";
  itemMt.shape = Shape({1, (int)vMt.size()});
  itemMt.type = Type::float32;
  itemMt.bytes.resize(vMt.size() * sizeOf(itemMt.type));
  std::copy(
      (char*)vMt.data(), (char*)vMt.data() + vMt.size(), itemMt.bytes.begin());

  io::Item itemVt;
  itemVt.name = "adam_vt";
  itemVt.shape = Shape({1, (int)vVt.size()});
  itemVt.type = Type::float32;
  itemVt.bytes.resize(vVt.size() * sizeOf(itemVt.type));
  std::copy(
      (char*)vVt.data(), (char*)vVt.data() + vVt.size(), itemVt.bytes.begin());

  io::saveItems(name, {itemMt, itemVt});
}

void Adam::resetStats() {
  if(mt_)
    mt_->set(0.f);

  if(vt_)
    vt_->set(0.f);
}

Ptr<OptimizerBase> Optimizer(Ptr<Config> options) {
  float lrate = (float)options->get<double>("learn-rate"); // @TODO: should this be <float>?
  auto params = options->has("optimizer-params")
                    ? options->get<std::vector<float>>("optimizer-params")
                    : std::vector<float>({});

  Ptr<ClipperBase> clipper = nullptr;
  float clipNorm = (float)options->get<double>("clip-norm"); // @TODO: should this be <float>?
  if(clipNorm > 0)
    clipper = Clipper<Norm>(clipNorm);

  auto opt = options->get<std::string>("optimizer");

  if(opt == "sgd") {
    return Optimizer<Sgd>(lrate, clipper, params);
  } else if(opt == "adagrad") {
    return Optimizer<Adagrad>(lrate, clipper, params);
  } else if(opt == "adam") {
    return Optimizer<Adam>(lrate, clipper, params);
  } else {
    ABORT("Unknown optimizer: {}", opt);
  }
}
}  // namespace marian
<|endoftext|>


<commit_before>/******************************************************************************
* Copyright (c) 2014, Howard Butler (howard@hobu.co)
*
* All rights reserved.
*
* 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 Hobu, Inc. or Flaxen Geo Consulting 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 <boost/test/unit_test.hpp>
#include <boost/cstdint.hpp>

#include <pdal/drivers/faux/Reader.hpp>
#include <pdal/filters/Reprojection.hpp>
#include <pdal/filters/Ferry.hpp>
#include <pdal/drivers/las/Reader.hpp>
#include <pdal/FileUtils.hpp>
#include <pdal/PointBuffer.hpp>
#include <pdal/PipelineManager.hpp>
#include <pdal/PipelineReader.hpp>
#include "Support.hpp"
#include "../StageTester.hpp"

using namespace pdal;

BOOST_AUTO_TEST_SUITE(FerryFilterTest)

BOOST_AUTO_TEST_CASE(test_ferry_copy)
{
    using namespace pdal;
    PipelineManager mgr;
    PipelineReader specReader(mgr);
    specReader.readPipeline(Support::datapath("filters/ferry.xml"));

    Stage *stage = mgr.getStage();
    mgr.execute();
    PointContext ctx = mgr.context();

    PointBufferSet pbSet = mgr.buffers();

    BOOST_CHECK_EQUAL(pbSet.size(), 1);
    PointBufferPtr buf = *pbSet.begin();
    BOOST_CHECK_EQUAL(buf->size(), 1065u);

    Dimension::Id::Enum state_plane_x = ctx.findDim("StatePlaneX");
    Dimension::Id::Enum state_plane_y = ctx.findDim("StatePlaneY");

    double lon = buf->getFieldAs<double>(Dimension::Id::X, 0);
    double lat = buf->getFieldAs<double>(Dimension::Id::Y, 0);

    double x = buf->getFieldAs<double>(state_plane_x, 0);
    double y = buf->getFieldAs<double>(state_plane_y, 0);

    BOOST_CHECK_CLOSE(-117.2501328350574, lon, 0.0001);
    BOOST_CHECK_CLOSE(49.341077824192915, lat, 0.0001);
    BOOST_CHECK_CLOSE(637012.24, x, 0.0001);
    BOOST_CHECK_CLOSE(849028.31, y, 0.0001);
}

BOOST_AUTO_TEST_CASE(test_ferry_invalid)
{
    using namespace pdal;

    Options ops1;
    ops1.add("filename", Support::datapath("las/1.2-with-color.las"));
    drivers::las::Reader reader(ops1);

    Options options;

    Option x("dimension", "X", "");
    Option toX("to","X", "");
    Options xO;
    xO.add(toX);
    x.setOptions(xO);
    options.add(x);

    filters::Ferry ferry(options);
    ferry.setInput(&reader);

    PointContext ctx;

    BOOST_CHECK_THROW(ferry.prepare(ctx), pdal::pdal_error );
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>turn off ferry reprojection test when there's no GDAL #435<commit_after>/******************************************************************************
* Copyright (c) 2014, Howard Butler (howard@hobu.co)
*
* All rights reserved.
*
* 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 Hobu, Inc. or Flaxen Geo Consulting 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 <boost/test/unit_test.hpp>
#include <boost/cstdint.hpp>

#include <pdal/drivers/faux/Reader.hpp>
#include <pdal/filters/Reprojection.hpp>
#include <pdal/filters/Ferry.hpp>
#include <pdal/drivers/las/Reader.hpp>
#include <pdal/FileUtils.hpp>
#include <pdal/PointBuffer.hpp>
#include <pdal/PipelineManager.hpp>
#include <pdal/PipelineReader.hpp>
#include "Support.hpp"
#include "../StageTester.hpp"

using namespace pdal;

BOOST_AUTO_TEST_SUITE(FerryFilterTest)

BOOST_AUTO_TEST_CASE(test_ferry_copy)
{
#ifdef PDAL_HAVE_GDAL
    using namespace pdal;
    PipelineManager mgr;
    PipelineReader specReader(mgr);
    specReader.readPipeline(Support::datapath("filters/ferry.xml"));

    Stage *stage = mgr.getStage();
    mgr.execute();
    PointContext ctx = mgr.context();

    PointBufferSet pbSet = mgr.buffers();

    BOOST_CHECK_EQUAL(pbSet.size(), 1);
    PointBufferPtr buf = *pbSet.begin();
    BOOST_CHECK_EQUAL(buf->size(), 1065u);

    Dimension::Id::Enum state_plane_x = ctx.findDim("StatePlaneX");
    Dimension::Id::Enum state_plane_y = ctx.findDim("StatePlaneY");

    double lon = buf->getFieldAs<double>(Dimension::Id::X, 0);
    double lat = buf->getFieldAs<double>(Dimension::Id::Y, 0);

    double x = buf->getFieldAs<double>(state_plane_x, 0);
    double y = buf->getFieldAs<double>(state_plane_y, 0);

    BOOST_CHECK_CLOSE(-117.2501328350574, lon, 0.0001);
    BOOST_CHECK_CLOSE(49.341077824192915, lat, 0.0001);
    BOOST_CHECK_CLOSE(637012.24, x, 0.0001);
    BOOST_CHECK_CLOSE(849028.31, y, 0.0001);
#endif
}

BOOST_AUTO_TEST_CASE(test_ferry_invalid)
{
    using namespace pdal;

    Options ops1;
    ops1.add("filename", Support::datapath("las/1.2-with-color.las"));
    drivers::las::Reader reader(ops1);

    Options options;

    Option x("dimension", "X", "");
    Option toX("to","X", "");
    Options xO;
    xO.add(toX);
    x.setOptions(xO);
    options.add(x);

    filters::Ferry ferry(options);
    ferry.setInput(&reader);

    PointContext ctx;

    BOOST_CHECK_THROW(ferry.prepare(ctx), pdal::pdal_error );
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/*
The Jinx library is distributed under the MIT License (MIT)
https://opensource.org/licenses/MIT
See LICENSE.TXT or Jinx.h for license details.
Copyright (c) 2016 James Boer
*/

#include <chrono>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#ifdef _WINDOWS
#include <conio.h>
#endif

#include "../../../Source/Jinx.h"

using namespace Jinx;

#define REQUIRE assert

Jinx::RuntimePtr TestCreateRuntime()
{
	return Jinx::CreateRuntime();
}

Jinx::ScriptPtr TestCreateScript(const char * scriptText, Jinx::RuntimePtr runtime = nullptr)
{
	if (!runtime)
		runtime = CreateRuntime();

	// Compile the text to bytecode
	auto bytecode = runtime->Compile(scriptText, "Test Script", { "core" });
	if (!bytecode)
		return nullptr;

	// Create a runtime script with the given bytecode
	return runtime->CreateScript(bytecode);
}

Jinx::ScriptPtr TestExecuteScript(const char * scriptText, Jinx::RuntimePtr runtime = nullptr)
{
	// Create a runtime script
	auto script = TestCreateScript(scriptText, runtime);
	if (!script)
		return nullptr;

	// Execute script until finished
	do
	{
		if (!script->Execute())
			return nullptr;
	}
	while (!script->IsFinished());

	return script;
}

int main(int argc, char ** argv)
{
	printf("Jinx version: %s\n", Jinx::VersionString);

	// Add scope block to ensure all objects are destroyed for shutdown test
	{
		GlobalParams globalParams;
		globalParams.logSymbols = true;
		globalParams.logBytecode = true;
        globalParams.maxInstructions = 5000;
		globalParams.allocBlockSize = 1024 * 256;
		globalParams.allocFn = [](size_t size) { return malloc(size); };
		globalParams.reallocFn = [](void * p, size_t size) { return realloc(p, size); };
		globalParams.freeFn = [](void * p) { free(p); };
		Jinx::Initialize(globalParams);

		static const char * scriptText =
			u8R"(

			function (opt/optional) (blah) {num} stuff
				-- do nothing
			end

			--optional 123 stuff
			opt 456 stuff
			--789 stuff
			--blah 000 stuff
			--opt blah 111 stuff

			)";

		auto script = TestExecuteScript(scriptText);
		REQUIRE(script);
	}

	Jinx::ShutDown();

	auto stats = GetMemoryStats();
	REQUIRE(stats.currentAllocatedMemory == 0);
	REQUIRE(stats.currentUsedMemory == 0);

#ifdef _WINDOWS
	printf("Press any key to continue...");
	_getch();
#endif

    return 0;
}<commit_msg>Test chained functions<commit_after>/*
The Jinx library is distributed under the MIT License (MIT)
https://opensource.org/licenses/MIT
See LICENSE.TXT or Jinx.h for license details.
Copyright (c) 2016 James Boer
*/

#include <chrono>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#ifdef _WINDOWS
#include <conio.h>
#endif

#include "../../../Source/Jinx.h"

using namespace Jinx;

#define REQUIRE assert

Jinx::RuntimePtr TestCreateRuntime()
{
	return Jinx::CreateRuntime();
}

Jinx::ScriptPtr TestCreateScript(const char * scriptText, Jinx::RuntimePtr runtime = nullptr)
{
	if (!runtime)
		runtime = CreateRuntime();

	// Compile the text to bytecode
	auto bytecode = runtime->Compile(scriptText, "Test Script", { "core" });
	if (!bytecode)
		return nullptr;

	// Create a runtime script with the given bytecode
	return runtime->CreateScript(bytecode);
}

Jinx::ScriptPtr TestExecuteScript(const char * scriptText, Jinx::RuntimePtr runtime = nullptr)
{
	// Create a runtime script
	auto script = TestCreateScript(scriptText, runtime);
	if (!script)
		return nullptr;

	// Execute script until finished
	do
	{
		if (!script->Execute())
			return nullptr;
	}
	while (!script->IsFinished());

	return script;
}

int main(int argc, char ** argv)
{
	printf("Jinx version: %s\n", Jinx::VersionString);

	// Add scope block to ensure all objects are destroyed for shutdown test
	{
		GlobalParams globalParams;
		globalParams.logSymbols = true;
		globalParams.logBytecode = true;
        globalParams.maxInstructions = 5000;
		globalParams.allocBlockSize = 1024 * 256;
		globalParams.allocFn = [](size_t size) { return malloc(size); };
		globalParams.reallocFn = [](void * p, size_t size) { return realloc(p, size); };
		globalParams.freeFn = [](void * p) { free(p); };
		Jinx::Initialize(globalParams);

		static const char * scriptText =
			u8R"(

			function {a} minus {b}
				return a - b
			end

			set a to 5 minus 3 minus 1

			)";

		auto script = TestExecuteScript(scriptText);
		REQUIRE(script);
		REQUIRE(script->GetVariable("a") == 1);
	}

	Jinx::ShutDown();

	auto stats = GetMemoryStats();
	REQUIRE(stats.currentAllocatedMemory == 0);
	REQUIRE(stats.currentUsedMemory == 0);

#ifdef _WINDOWS
	printf("Press any key to continue...");
	_getch();
#endif

    return 0;
}<|endoftext|>


<commit_before>/*
   Copyright (c) 2012-2016 Alex Zhondin <lexxmark.dev@gmail.com>

   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.
*/

#include "PropertyWidget.h"
#include <QSplitter>
#include <QMouseEvent>

class QtnSplitterEventsHandler: public QObject
{
public:
    QtnSplitterEventsHandler(QObject* parent)
        : QObject(parent)
    {
    }

protected:
    bool eventFilter(QObject* obj, QEvent* event) override
    {
        // check input
        if (event->type() != QEvent::MouseButtonDblClick)
            return false;

         QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
         if (mouseEvent->button() != Qt::LeftButton)
             return false;

        QSplitterHandle* splitterHandle = qobject_cast<QSplitterHandle*>(obj);
        if (!splitterHandle)
            return false;

        QSplitter* splitter = splitterHandle->splitter();
        if (!splitter || splitter->count() < 2)
            return false;

        // change splitter sizes to make description panel occupy ideal height
        QWidget* bottomWidget = splitter->widget(1);
        QList<int> sizes = splitter->sizes();
        if (sizes.size() != 2)
            return false;

        sizes[0] += sizes[1];
        sizes[1] = bottomWidget->heightForWidth(bottomWidget->size().width());
        sizes[0] -= qMax(sizes[1], 0);

        splitter->setSizes(sizes);

        return true;
    }
};

// It's safe to call this function on any platform.
// It will only have an effect on the Mac.
void set_smaller_text_osx(QWidget *w)
{
    Q_ASSERT(w != 0);

    // By default, none of these size attributes are set.
    // If any has been set explicitly, we'll leave the widget alone.
    if (!w->testAttribute(Qt::WA_MacMiniSize) &&
        !w->testAttribute(Qt::WA_MacSmallSize) &&
        !w->testAttribute(Qt::WA_MacNormalSize) &&
        !w->testAttribute(Qt::WA_MacVariableSize))
    {
      // make the text the 'normal' size
      w->setAttribute(Qt::WA_MacSmallSize);
    }
}

QtnPropertyWidget::QtnPropertyWidget(QWidget* parent)
    : QWidget(parent),
      m_parts(QtnPropertyWidgetPartsDescriptionPanel),
      m_layout(new QVBoxLayout(this)),
      m_toolbar(0),
      m_propertyView(new QtnPropertyView(this)),
      m_descriptionSplitter(0),
      m_descriptionPanel(0)
{
  set_smaller_text_osx(this);

  m_layout->addWidget(m_propertyView);

  QObject::connect(m_propertyView, &QtnPropertyView::activePropertyChanged, this, &QtnPropertyWidget::setActiveProperty);
  updateParts();
}

QtnPropertyWidget::QtnPropertyWidget(QtnPropertyView *propertyView, QWidget* parent)
    : QWidget(parent),
      m_parts(QtnPropertyWidgetPartsDescriptionPanel),
      m_layout(new QVBoxLayout(this)),
      m_toolbar(0),
      m_propertyView(propertyView),
      m_descriptionSplitter(0),
      m_descriptionPanel(0)
{
    Q_ASSERT(propertyView);
    propertyView->setParent(this);

    set_smaller_text_osx(this);

    m_layout->addWidget(m_propertyView);

    QObject::connect(m_propertyView, &QtnPropertyView::activePropertyChanged, this, &QtnPropertyWidget::setActiveProperty);
    updateParts();
}

QtnPropertyWidget::~QtnPropertyWidget()
{

}

void QtnPropertyWidget::setParts(QtnPropertyWidgetParts newParts)
{
    if (m_parts == newParts)
        return;

    m_parts = newParts;
    updateParts();
}

void QtnPropertyWidget::updateParts()
{
    // clear layout
    while (!m_layout->isEmpty())
        m_layout->takeAt(0);

    // check toolbar

    // check description panel
    if (m_parts & QtnPropertyWidgetPartsDescriptionPanel)
    {
        if (!m_descriptionSplitter)
        {
            // create splitter
            Q_ASSERT(!m_descriptionPanel);
            QSplitter* splitter = new QSplitter(Qt::Vertical, this);

            // add property view
            splitter->addWidget(m_propertyView);

            // create description panel
            m_descriptionPanel = new QLabel(splitter);
            m_descriptionPanel->setTextFormat(Qt::RichText);
            m_descriptionPanel->setAlignment(Qt::AlignTop);
            m_descriptionPanel->setWordWrap(true);
            m_descriptionPanel->setFrameStyle(QFrame::Box | QFrame::Sunken);
            m_descriptionPanel->setMinimumSize(0,  5 * QFontMetrics(font()).height() / 2);
            QSizePolicy p = m_descriptionPanel->sizePolicy();
            p.setVerticalPolicy(QSizePolicy::Ignored);
            p.setHorizontalPolicy(QSizePolicy::Ignored);
            m_descriptionPanel->setSizePolicy(p);

            // setup DblClick handler
            splitter->handle(1)->installEventFilter(new QtnSplitterEventsHandler(splitter));

            m_descriptionSplitter = splitter;
        }

        m_layout->addWidget(m_descriptionSplitter);
    }
    else
    {
        if (m_descriptionSplitter)
        {
            delete m_descriptionSplitter;
            m_descriptionSplitter = nullptr;
            m_descriptionPanel = nullptr;
        }

        m_layout->addWidget(m_propertyView);
    }
}

void QtnPropertyWidget::setActiveProperty(const QtnPropertyBase* activeProperty)
{
    if (m_descriptionPanel)
    {
        if (!activeProperty)
        {
            m_descriptionPanel->setText("");
        }
        else
        {
            m_descriptionPanel->setText(QString("%1
%2").arg(activeProperty->displayName(), activeProperty->description()));
        }
    }
}
<commit_msg>Fix crash with QtnPropertyWidgetPartsNone flag<commit_after>/*
   Copyright (c) 2012-2016 Alex Zhondin <lexxmark.dev@gmail.com>

   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.
*/

#include "PropertyWidget.h"
#include <QSplitter>
#include <QMouseEvent>

class QtnSplitterEventsHandler: public QObject
{
public:
    QtnSplitterEventsHandler(QObject* parent)
        : QObject(parent)
    {
    }

protected:
    bool eventFilter(QObject* obj, QEvent* event) override
    {
        // check input
        if (event->type() != QEvent::MouseButtonDblClick)
            return false;

         QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
         if (mouseEvent->button() != Qt::LeftButton)
             return false;

        QSplitterHandle* splitterHandle = qobject_cast<QSplitterHandle*>(obj);
        if (!splitterHandle)
            return false;

        QSplitter* splitter = splitterHandle->splitter();
        if (!splitter || splitter->count() < 2)
            return false;

        // change splitter sizes to make description panel occupy ideal height
        QWidget* bottomWidget = splitter->widget(1);
        QList<int> sizes = splitter->sizes();
        if (sizes.size() != 2)
            return false;

        sizes[0] += sizes[1];
        sizes[1] = bottomWidget->heightForWidth(bottomWidget->size().width());
        sizes[0] -= qMax(sizes[1], 0);

        splitter->setSizes(sizes);

        return true;
    }
};

// It's safe to call this function on any platform.
// It will only have an effect on the Mac.
void set_smaller_text_osx(QWidget *w)
{
    Q_ASSERT(w != 0);

    // By default, none of these size attributes are set.
    // If any has been set explicitly, we'll leave the widget alone.
    if (!w->testAttribute(Qt::WA_MacMiniSize) &&
        !w->testAttribute(Qt::WA_MacSmallSize) &&
        !w->testAttribute(Qt::WA_MacNormalSize) &&
        !w->testAttribute(Qt::WA_MacVariableSize))
    {
      // make the text the 'normal' size
      w->setAttribute(Qt::WA_MacSmallSize);
    }
}

QtnPropertyWidget::QtnPropertyWidget(QWidget* parent)
    : QWidget(parent),
      m_parts(QtnPropertyWidgetPartsDescriptionPanel),
      m_layout(new QVBoxLayout(this)),
      m_toolbar(0),
      m_propertyView(new QtnPropertyView(this)),
      m_descriptionSplitter(0),
      m_descriptionPanel(0)
{
  set_smaller_text_osx(this);

  m_layout->addWidget(m_propertyView);

  QObject::connect(m_propertyView, &QtnPropertyView::activePropertyChanged, this, &QtnPropertyWidget::setActiveProperty);
  updateParts();
}

QtnPropertyWidget::QtnPropertyWidget(QtnPropertyView *propertyView, QWidget* parent)
    : QWidget(parent),
      m_parts(QtnPropertyWidgetPartsDescriptionPanel),
      m_layout(new QVBoxLayout(this)),
      m_toolbar(0),
      m_propertyView(propertyView),
      m_descriptionSplitter(0),
      m_descriptionPanel(0)
{
    Q_ASSERT(propertyView);
    propertyView->setParent(this);

    set_smaller_text_osx(this);

    m_layout->addWidget(m_propertyView);

    QObject::connect(m_propertyView, &QtnPropertyView::activePropertyChanged, this, &QtnPropertyWidget::setActiveProperty);
    updateParts();
}

QtnPropertyWidget::~QtnPropertyWidget()
{

}

void QtnPropertyWidget::setParts(QtnPropertyWidgetParts newParts)
{
    if (m_parts == newParts)
        return;

    m_parts = newParts;
    updateParts();
}

void QtnPropertyWidget::updateParts()
{
    // clear layout
    while (!m_layout->isEmpty())
        m_layout->takeAt(0);

    // check toolbar

    // check description panel
    if (m_parts & QtnPropertyWidgetPartsDescriptionPanel)
    {
        if (!m_descriptionSplitter)
        {
            // create splitter
            Q_ASSERT(!m_descriptionPanel);
            QSplitter* splitter = new QSplitter(Qt::Vertical, this);

            // add property view
            splitter->addWidget(m_propertyView);

            // create description panel
            m_descriptionPanel = new QLabel(splitter);
            m_descriptionPanel->setTextFormat(Qt::RichText);
            m_descriptionPanel->setAlignment(Qt::AlignTop);
            m_descriptionPanel->setWordWrap(true);
            m_descriptionPanel->setFrameStyle(QFrame::Box | QFrame::Sunken);
            m_descriptionPanel->setMinimumSize(0,  5 * QFontMetrics(font()).height() / 2);
            QSizePolicy p = m_descriptionPanel->sizePolicy();
            p.setVerticalPolicy(QSizePolicy::Ignored);
            p.setHorizontalPolicy(QSizePolicy::Ignored);
            m_descriptionPanel->setSizePolicy(p);

            // setup DblClick handler
            splitter->handle(1)->installEventFilter(new QtnSplitterEventsHandler(splitter));

            m_descriptionSplitter = splitter;
        }

        m_layout->addWidget(m_descriptionSplitter);
    }
    else
    {
        m_layout->addWidget(m_propertyView);

        if (m_descriptionSplitter)
        {
            delete m_descriptionSplitter;
            m_descriptionSplitter = nullptr;
            m_descriptionPanel = nullptr;
        }
    }
}

void QtnPropertyWidget::setActiveProperty(const QtnPropertyBase* activeProperty)
{
    if (m_descriptionPanel)
    {
        if (!activeProperty)
        {
            m_descriptionPanel->setText("");
        }
        else
        {
            m_descriptionPanel->setText(QString("%1
%2").arg(activeProperty->displayName(), activeProperty->description()));
        }
    }
}
<|endoftext|>


<commit_before>// @(#)root/base:$Name:  $:$Id: TPluginManager.cxx,v 1.35 2007/02/13 14:26:58 rdm Exp $
// Author: Fons Rademakers   26/1/2002

/*************************************************************************
 * Copyright (C) 1995-2002, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TPluginManager                                                       //
//                                                                      //
// This class implements a plugin library manager. It keeps track of    //
// a list of plugin handlers. A plugin handler knows which plugin       //
// library to load to get a specific class that is used to extend the   //
// functionality of a specific base class and how to create an object   //
// of this class. For example, to extend the base class TFile to be     //
// able to read RFIO files one needs to load the plugin library         //
// libRFIO.so which defines the TRFIOFile class. This loading should    //
// be triggered when a given URI contains a regular expression defined  //
// by the handler. Handlers can be defined for example as resources     //
// in the .rootrc file, e.g.:                                           //
//                                                                      //
//   Plugin.TFile:       ^rfio:   TRFIOFile    RFIO   "<constructor>"   //
//   Plugin.TSQLServer:  ^mysql:  TMySQLServer MySQL  "<constructor>"   //
//   +Plugin.TSQLServer: ^pgsql:  TPgSQLServer PgSQL  "<constructor>"   //
//   Plugin.TVirtualFitter: *     TFitter      Minuit "TFitter(Int_t)"  //
//                                                                      //
// Where the + in front of Plugin.TSQLServer says that it extends the   //
// existing definition of TSQLServer, usefull when there is more than   //
// one plugin that can extend the same base class. The "<constructor>"  //
// should be the constructor or a static method that generates an       //
// instance of the specified class. Global methods should start with    //
// "::" in their name, like "::CreateFitter()".                         //
// Instead of being a shared library a plugin can also be a CINT        //
// script, so instead of libDialog.so one can have Dialog.C.            //
// The * is a placeholder in case there is no need for a URI to         //
// differentiate between different plugins for the same base class.     //
// For the default plugins see $ROOTSYS/etc/system.rootrc.              //
//                                                                      //
// Plugin handlers can also be registered at run time, e.g.:            //
//                                                                      //
//   gROOT->GetPluginManager()->AddHandler("TSQLServer", "^sapdb:",     //
//                                         "TSapDBServer", "SapDB",     //
//             "TSapDBServer(const char*,const char*, const char*)");   //
//                                                                      //
// A list of currently defined handlers can be printed using:           //
//                                                                      //
//   gROOT->GetPluginManager()->Print(); // use option="a" to see ctors //
//                                                                      //
// The use of the plugin library manager removes all textual references //
// to hard-coded class and library names and the resulting dependencies //
// in the base classes. The plugin manager is used to extend a.o.       //
// TFile, TSQLServer, TGrid, etc. functionality.                        //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TPluginManager.h"
#include "Varargs.h"
#include "TEnv.h"
#include "TRegexp.h"
#include "TROOT.h"
#include "THashList.h"
#include "TOrdCollection.h"
#include "Varargs.h"
#include "TClass.h"
#include "TCint.h"
#include "TMethod.h"
#include "TMethodArg.h"
#include "TDataType.h"
#include "TMethodCall.h"
#include "TVirtualMutex.h"

ClassImp(TPluginHandler)

//______________________________________________________________________________
TPluginHandler::TPluginHandler(const char *base, const char *regexp,
                               const char *className, const char *pluginName,
                               const char *ctor)
{
   // Create a plugin handler. Called by TPluginManager.

   fBase     = base;
   fRegexp   = regexp;
   fClass    = className;
   fPlugin   = pluginName;
   fCtor     = ctor;
   fCallEnv  = 0;
   fCanCall  = 0;
   fIsMacro  = kFALSE;
   fIsGlobal = kFALSE;

   if (gROOT->LoadMacro(pluginName, 0, kTRUE) == 0)
      fIsMacro = kTRUE;

   if (fCtor.Contains("::")) {
      fIsGlobal = kTRUE;
      fCtor = fCtor.Strip(TString::kLeading, ':');
   }
}

//______________________________________________________________________________
TPluginHandler::~TPluginHandler()
{
   // Cleanup plugin handler object.

   delete fCallEnv;
}

//______________________________________________________________________________
Bool_t TPluginHandler::CanHandle(const char *base, const char *uri)
{
   // Check if regular expression appears in the URI, if so return kTRUE.
   // If URI = 0 always return kTRUE.

   if (fBase != base)
      return kFALSE;

   if (!uri || fRegexp == "*")
      return kTRUE;

   Bool_t wildcard = kFALSE;
   if (!fRegexp.MaybeRegexp())
      wildcard = kTRUE;

   TRegexp re(fRegexp, wildcard);
   TString ruri = uri;

   if (ruri.Index(re) != kNPOS)
      return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
void TPluginHandler::SetupCallEnv()
{
   // Setup ctor or static method call environment.

   fCanCall = -1;

   // check if class exists
   TClass *cl = TClass::GetClass(fClass);
   if (!cl && !fIsGlobal) {
      Error("SetupCallEnv", "class %s not found in plugin %s", fClass.Data(),
            fPlugin.Data());
      return;
   }

   // split method and prototype strings
   TString method = fCtor(0, fCtor.Index("("));
   TString proto  = fCtor(fCtor.Index("(")+1, fCtor.Index(")")-fCtor.Index("(")-1);

   if (fIsGlobal) {
      cl = 0;
      fMethod = gROOT->GetGlobalFunctionWithPrototype(method, proto, kTRUE);
   } else {
      fMethod = cl->GetMethodWithPrototype(method, proto);
   }

   if (!fMethod) {
      if (fIsGlobal)
         Error("SetupCallEnv", "global function %s not found", method.Data());
      else
         Error("SetupCallEnv", "method %s not found in class %s", method.Data(),
               fClass.Data());
      return;
   }

   if (!fIsGlobal && !(fMethod->Property() & kIsPublic)) {
      Error("SetupCallEnv", "method %s is not public", method.Data());
      return;
   }

   fCallEnv = new TMethodCall;
   fCallEnv->InitWithPrototype(cl, method, proto);

   fCanCall = 1;

   return;
}

//______________________________________________________________________________
Int_t TPluginHandler::CheckPlugin()
{
   // Check if the plugin library for this handler exits. Returns 0
   // when it exists and -1 in case the plugin does not exist.

   if (fIsMacro) {
      if (TClass::GetClass(fClass)) return 0;
      return gROOT->LoadMacro(fPlugin, 0, kTRUE);
   } else
      return gROOT->LoadClass(fClass, fPlugin, kTRUE);
}

//______________________________________________________________________________
Int_t TPluginHandler::LoadPlugin()
{
   // Load the plugin library for this handler. Returns 0 on successful loading
   // and -1 in case the library does not exist or in case of error.

   if (fIsMacro) {
      if (TClass::GetClass(fClass)) return 0;
      return gROOT->LoadMacro(fPlugin);
   } else {
      // first call also loads dependent libraries declared via the rootmap file
      if (gROOT->LoadClass(fClass)) return 0;
      return gROOT->LoadClass(fClass, fPlugin);
   }
}

//______________________________________________________________________________
Long_t TPluginHandler::ExecPlugin(Int_t va_(nargs), ...)
{
   // Execute ctor for this plugin and return pointer to object of specific
   // class. User must cast the returned long to the correct class.
   // This method accepts a variable number of arguments to be passed
   // to the ctor, where nargs is the number of arguments, followed
   // by nargs arguments. Returns 0 in case of error.

   if (fCtor.IsNull()) {
      Error("ExecPlugin", "no ctor specified for this handler %s", fClass.Data());
      return 0;
   }

   if (!fCallEnv && !fCanCall)
      SetupCallEnv();

   if (fCanCall == -1)
      return 0;

   if (nargs < fMethod->GetNargs() - fMethod->GetNargsOpt() ||
       nargs > fMethod->GetNargs()) {
      Error("ExecPlugin", "nargs (%d) not consistent with expected number of arguments ([%d-%d])",
            nargs, fMethod->GetNargs() - fMethod->GetNargsOpt(),
            fMethod->GetNargs());
      return 0;
   }

   R__LOCKGUARD2(gCINTMutex);

   fCallEnv->ResetParam();

   if (nargs > 0) {
      TIter next(fMethod->GetListOfMethodArgs());
      TMethodArg *arg;

      va_list ap;
      va_start(ap, va_(nargs));

      for (int i = 0; i < nargs; i++) {
         arg = (TMethodArg*) next();
         TString type = arg->GetFullTypeName();
         TDataType *dt = gROOT->GetType(type);
         if (dt)
            type = dt->GetFullTypeName();
         if (arg->Property() & (kIsPointer | kIsArray | kIsReference))
            fCallEnv->SetParam((Long_t) va_arg(ap, void*));
         else if (type == "bool")
            fCallEnv->SetParam((Long_t) va_arg(ap, int));  // bool is promoted to int
         else if (type == "char" || type == "unsigned char")
            fCallEnv->SetParam((Long_t) va_arg(ap, int));  // char is promoted to int
         else if (type == "short" || type == "unsigned short")
            fCallEnv->SetParam((Long_t) va_arg(ap, int));  // short is promoted to int
         else if (type == "int" || type == "unsigned int")
            fCallEnv->SetParam((Long_t) va_arg(ap, int));
         else if (type == "long" || type == "unsigned long")
            fCallEnv->SetParam((Long_t) va_arg(ap, long));
         else if (type == "long long")
            fCallEnv->SetParam((Long64_t) va_arg(ap, Long64_t));
         else if (type == "unsigned long long")
            fCallEnv->SetParam((ULong64_t) va_arg(ap, ULong64_t));
         else if (type == "float")
            fCallEnv->SetParam((Double_t) va_arg(ap, double));  // float is promoted to double
         else if (type == "double")
            fCallEnv->SetParam((Double_t) va_arg(ap, double));
      }

      va_end(ap);
   }

   Long_t ret;
   fCallEnv->Execute(ret);

   return ret;
}

ClassImp(TPluginManager)

//______________________________________________________________________________
TPluginManager::~TPluginManager()
{
   // Clean up the plugin manager.

   delete fHandlers;
}

//______________________________________________________________________________
void TPluginManager::LoadHandlersFromEnv(TEnv *env)
{
   // Load plugin handlers specified in config file, like:
   //    Plugin.TFile:       ^rfio:    TRFIOFile      RFIO  "TRFIOFile(...)"
   //    Plugin.TSQLServer:  ^mysql:   TMySQLServer   MySQL "TMySQLServer(...)"
   //    +Plugin.TSQLServer: ^pgsql:   TPgSQLServer   PgSQL "TPgSQLServer(...)"
   // The + allows the extension of an already defined resource (see TEnv).

   if (!env) return;

   TIter next(env->GetTable());
   TEnvRec *er;

   while ((er = (TEnvRec*) next())) {
      const char *s;
      if ((s = strstr(er->GetName(), "Plugin."))) {
         // use s, i.e. skip possible OS and application prefix to Plugin.
         // so that GetValue() takes properly care of returning the value
         // for the specified OS and/or application
         const char *val = env->GetValue(s, (const char*)0);
         if (val) {
            Int_t cnt = 0;
            char *v = StrDup(val);
            s += 7;
            while (1) {
               TString regexp = strtok(!cnt ? v : 0, "; ");
               if (regexp.IsNull()) break;
               TString clss   = strtok(0, "; ");
               if (clss.IsNull()) break;
               TString plugin = strtok(0, "; ");
               if (plugin.IsNull()) break;
               TString ctor = strtok(0, ";\"");
               if (!ctor.Contains("("))
                  ctor = strtok(0, ";\"");
               AddHandler(s, regexp, clss, plugin, ctor);
               cnt++;
            }
            delete [] v;
         }
      }
   }
}

//______________________________________________________________________________
void TPluginManager::AddHandler(const char *base, const char *regexp,
                                const char *className, const char *pluginName,
                                const char *ctor)
{
   // Add plugin handler to the list of handlers. If there is already a
   // handler defined for the same base and regexp it will be replaced.

   if (!fHandlers) {
      fHandlers = new TList;
      fHandlers->IsOwner();
   }

   // make sure there is no previous handler for the same case
   RemoveHandler(base, regexp);

   TPluginHandler *h = new TPluginHandler(base, regexp, className,
                                          pluginName, ctor);
   fHandlers->Add(h);
}

//______________________________________________________________________________
void TPluginManager::RemoveHandler(const char *base, const char *regexp)
{
   // Remove handler for the specified base class and the specified
   // regexp. If regexp=0 remove all handlers for the specified base.

   if (!fHandlers) return;

   TIter next(fHandlers);
   TPluginHandler *h;

   while ((h = (TPluginHandler*) next())) {
      if (h->fBase == base) {
         if (!regexp || h->fRegexp == regexp) {
            fHandlers->Remove(h);
            delete h;
         }
      }
   }
}

//______________________________________________________________________________
TPluginHandler *TPluginManager::FindHandler(const char *base, const char *uri)
{
   // Returns the handler if there exists a handler for the specified URI.
   // The uri can be 0 in which case the first matching plugin handler
   // will be returned. Returns 0 in case handler is not found.

   if (!fHandlers) return 0;

   TIter next(fHandlers);
   TPluginHandler *h;

   while ((h = (TPluginHandler*) next())) {
      if (h->CanHandle(base, uri)) {
         if (gDebug > 0)
            Info("FindHandler", "found plugin for %s", h->GetClass());
         return h;
      }
   }

   if (gDebug > 0) {
      if (uri)
         Info("FindHandler", "did not find plugin for class %s and uri %s", base, uri);
      else
         Info("FindHandler", "did not find plugin for class %s", base);
   }

   return 0;
}

//______________________________________________________________________________
void TPluginManager::Print(Option_t *opt) const
{
   // Print list of registered plugin handlers. If option is "a" print
   // also the ctor's that will be used.

   if (!fHandlers) return;

   TIter next(fHandlers);
   TPluginHandler *h;

   Printf("=====================================================================");
   Printf("Base                 Regexp        Class              Plugin");
   Printf("=====================================================================");

   while ((h = (TPluginHandler*) next())) {
      const char *exist = "";
      if (h->CheckPlugin() == -1)
         exist = " [*]";
      Printf("%-20s %-13s %-18s %s%s", h->fBase.Data(), h->fRegexp.Data(),
             h->fClass.Data(), h->fPlugin.Data(), exist);
      if (strchr(opt, 'a'))
         Printf("  [Ctor: %s]", h->fCtor.Data());
   }
   Printf("=====================================================================");
   Printf("[*] plugin not available");
   Printf("=====================================================================\n");
}
<commit_msg>increase in FindHandler() the debug level in case no plugin is found to > 2.<commit_after>// @(#)root/base:$Name:  $:$Id: TPluginManager.cxx,v 1.36 2007/02/14 18:08:36 rdm Exp $
// Author: Fons Rademakers   26/1/2002

/*************************************************************************
 * Copyright (C) 1995-2002, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TPluginManager                                                       //
//                                                                      //
// This class implements a plugin library manager. It keeps track of    //
// a list of plugin handlers. A plugin handler knows which plugin       //
// library to load to get a specific class that is used to extend the   //
// functionality of a specific base class and how to create an object   //
// of this class. For example, to extend the base class TFile to be     //
// able to read RFIO files one needs to load the plugin library         //
// libRFIO.so which defines the TRFIOFile class. This loading should    //
// be triggered when a given URI contains a regular expression defined  //
// by the handler. Handlers can be defined for example as resources     //
// in the .rootrc file, e.g.:                                           //
//                                                                      //
//   Plugin.TFile:       ^rfio:   TRFIOFile    RFIO   "<constructor>"   //
//   Plugin.TSQLServer:  ^mysql:  TMySQLServer MySQL  "<constructor>"   //
//   +Plugin.TSQLServer: ^pgsql:  TPgSQLServer PgSQL  "<constructor>"   //
//   Plugin.TVirtualFitter: *     TFitter      Minuit "TFitter(Int_t)"  //
//                                                                      //
// Where the + in front of Plugin.TSQLServer says that it extends the   //
// existing definition of TSQLServer, usefull when there is more than   //
// one plugin that can extend the same base class. The "<constructor>"  //
// should be the constructor or a static method that generates an       //
// instance of the specified class. Global methods should start with    //
// "::" in their name, like "::CreateFitter()".                         //
// Instead of being a shared library a plugin can also be a CINT        //
// script, so instead of libDialog.so one can have Dialog.C.            //
// The * is a placeholder in case there is no need for a URI to         //
// differentiate between different plugins for the same base class.     //
// For the default plugins see $ROOTSYS/etc/system.rootrc.              //
//                                                                      //
// Plugin handlers can also be registered at run time, e.g.:            //
//                                                                      //
//   gROOT->GetPluginManager()->AddHandler("TSQLServer", "^sapdb:",     //
//                                         "TSapDBServer", "SapDB",     //
//             "TSapDBServer(const char*,const char*, const char*)");   //
//                                                                      //
// A list of currently defined handlers can be printed using:           //
//                                                                      //
//   gROOT->GetPluginManager()->Print(); // use option="a" to see ctors //
//                                                                      //
// The use of the plugin library manager removes all textual references //
// to hard-coded class and library names and the resulting dependencies //
// in the base classes. The plugin manager is used to extend a.o.       //
// TFile, TSQLServer, TGrid, etc. functionality.                        //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TPluginManager.h"
#include "Varargs.h"
#include "TEnv.h"
#include "TRegexp.h"
#include "TROOT.h"
#include "THashList.h"
#include "TOrdCollection.h"
#include "Varargs.h"
#include "TClass.h"
#include "TCint.h"
#include "TMethod.h"
#include "TMethodArg.h"
#include "TDataType.h"
#include "TMethodCall.h"
#include "TVirtualMutex.h"

ClassImp(TPluginHandler)

//______________________________________________________________________________
TPluginHandler::TPluginHandler(const char *base, const char *regexp,
                               const char *className, const char *pluginName,
                               const char *ctor)
{
   // Create a plugin handler. Called by TPluginManager.

   fBase     = base;
   fRegexp   = regexp;
   fClass    = className;
   fPlugin   = pluginName;
   fCtor     = ctor;
   fCallEnv  = 0;
   fCanCall  = 0;
   fIsMacro  = kFALSE;
   fIsGlobal = kFALSE;

   if (gROOT->LoadMacro(pluginName, 0, kTRUE) == 0)
      fIsMacro = kTRUE;

   if (fCtor.Contains("::")) {
      fIsGlobal = kTRUE;
      fCtor = fCtor.Strip(TString::kLeading, ':');
   }
}

//______________________________________________________________________________
TPluginHandler::~TPluginHandler()
{
   // Cleanup plugin handler object.

   delete fCallEnv;
}

//______________________________________________________________________________
Bool_t TPluginHandler::CanHandle(const char *base, const char *uri)
{
   // Check if regular expression appears in the URI, if so return kTRUE.
   // If URI = 0 always return kTRUE.

   if (fBase != base)
      return kFALSE;

   if (!uri || fRegexp == "*")
      return kTRUE;

   Bool_t wildcard = kFALSE;
   if (!fRegexp.MaybeRegexp())
      wildcard = kTRUE;

   TRegexp re(fRegexp, wildcard);
   TString ruri = uri;

   if (ruri.Index(re) != kNPOS)
      return kTRUE;
   return kFALSE;
}

//______________________________________________________________________________
void TPluginHandler::SetupCallEnv()
{
   // Setup ctor or static method call environment.

   fCanCall = -1;

   // check if class exists
   TClass *cl = TClass::GetClass(fClass);
   if (!cl && !fIsGlobal) {
      Error("SetupCallEnv", "class %s not found in plugin %s", fClass.Data(),
            fPlugin.Data());
      return;
   }

   // split method and prototype strings
   TString method = fCtor(0, fCtor.Index("("));
   TString proto  = fCtor(fCtor.Index("(")+1, fCtor.Index(")")-fCtor.Index("(")-1);

   if (fIsGlobal) {
      cl = 0;
      fMethod = gROOT->GetGlobalFunctionWithPrototype(method, proto, kTRUE);
   } else {
      fMethod = cl->GetMethodWithPrototype(method, proto);
   }

   if (!fMethod) {
      if (fIsGlobal)
         Error("SetupCallEnv", "global function %s not found", method.Data());
      else
         Error("SetupCallEnv", "method %s not found in class %s", method.Data(),
               fClass.Data());
      return;
   }

   if (!fIsGlobal && !(fMethod->Property() & kIsPublic)) {
      Error("SetupCallEnv", "method %s is not public", method.Data());
      return;
   }

   fCallEnv = new TMethodCall;
   fCallEnv->InitWithPrototype(cl, method, proto);

   fCanCall = 1;

   return;
}

//______________________________________________________________________________
Int_t TPluginHandler::CheckPlugin()
{
   // Check if the plugin library for this handler exits. Returns 0
   // when it exists and -1 in case the plugin does not exist.

   if (fIsMacro) {
      if (TClass::GetClass(fClass)) return 0;
      return gROOT->LoadMacro(fPlugin, 0, kTRUE);
   } else
      return gROOT->LoadClass(fClass, fPlugin, kTRUE);
}

//______________________________________________________________________________
Int_t TPluginHandler::LoadPlugin()
{
   // Load the plugin library for this handler. Returns 0 on successful loading
   // and -1 in case the library does not exist or in case of error.

   if (fIsMacro) {
      if (TClass::GetClass(fClass)) return 0;
      return gROOT->LoadMacro(fPlugin);
   } else {
      // first call also loads dependent libraries declared via the rootmap file
      if (gROOT->LoadClass(fClass)) return 0;
      return gROOT->LoadClass(fClass, fPlugin);
   }
}

//______________________________________________________________________________
Long_t TPluginHandler::ExecPlugin(Int_t va_(nargs), ...)
{
   // Execute ctor for this plugin and return pointer to object of specific
   // class. User must cast the returned long to the correct class.
   // This method accepts a variable number of arguments to be passed
   // to the ctor, where nargs is the number of arguments, followed
   // by nargs arguments. Returns 0 in case of error.

   if (fCtor.IsNull()) {
      Error("ExecPlugin", "no ctor specified for this handler %s", fClass.Data());
      return 0;
   }

   if (!fCallEnv && !fCanCall)
      SetupCallEnv();

   if (fCanCall == -1)
      return 0;

   if (nargs < fMethod->GetNargs() - fMethod->GetNargsOpt() ||
       nargs > fMethod->GetNargs()) {
      Error("ExecPlugin", "nargs (%d) not consistent with expected number of arguments ([%d-%d])",
            nargs, fMethod->GetNargs() - fMethod->GetNargsOpt(),
            fMethod->GetNargs());
      return 0;
   }

   R__LOCKGUARD2(gCINTMutex);

   fCallEnv->ResetParam();

   if (nargs > 0) {
      TIter next(fMethod->GetListOfMethodArgs());
      TMethodArg *arg;

      va_list ap;
      va_start(ap, va_(nargs));

      for (int i = 0; i < nargs; i++) {
         arg = (TMethodArg*) next();
         TString type = arg->GetFullTypeName();
         TDataType *dt = gROOT->GetType(type);
         if (dt)
            type = dt->GetFullTypeName();
         if (arg->Property() & (kIsPointer | kIsArray | kIsReference))
            fCallEnv->SetParam((Long_t) va_arg(ap, void*));
         else if (type == "bool")
            fCallEnv->SetParam((Long_t) va_arg(ap, int));  // bool is promoted to int
         else if (type == "char" || type == "unsigned char")
            fCallEnv->SetParam((Long_t) va_arg(ap, int));  // char is promoted to int
         else if (type == "short" || type == "unsigned short")
            fCallEnv->SetParam((Long_t) va_arg(ap, int));  // short is promoted to int
         else if (type == "int" || type == "unsigned int")
            fCallEnv->SetParam((Long_t) va_arg(ap, int));
         else if (type == "long" || type == "unsigned long")
            fCallEnv->SetParam((Long_t) va_arg(ap, long));
         else if (type == "long long")
            fCallEnv->SetParam((Long64_t) va_arg(ap, Long64_t));
         else if (type == "unsigned long long")
            fCallEnv->SetParam((ULong64_t) va_arg(ap, ULong64_t));
         else if (type == "float")
            fCallEnv->SetParam((Double_t) va_arg(ap, double));  // float is promoted to double
         else if (type == "double")
            fCallEnv->SetParam((Double_t) va_arg(ap, double));
      }

      va_end(ap);
   }

   Long_t ret;
   fCallEnv->Execute(ret);

   return ret;
}

ClassImp(TPluginManager)

//______________________________________________________________________________
TPluginManager::~TPluginManager()
{
   // Clean up the plugin manager.

   delete fHandlers;
}

//______________________________________________________________________________
void TPluginManager::LoadHandlersFromEnv(TEnv *env)
{
   // Load plugin handlers specified in config file, like:
   //    Plugin.TFile:       ^rfio:    TRFIOFile      RFIO  "TRFIOFile(...)"
   //    Plugin.TSQLServer:  ^mysql:   TMySQLServer   MySQL "TMySQLServer(...)"
   //    +Plugin.TSQLServer: ^pgsql:   TPgSQLServer   PgSQL "TPgSQLServer(...)"
   // The + allows the extension of an already defined resource (see TEnv).

   if (!env) return;

   TIter next(env->GetTable());
   TEnvRec *er;

   while ((er = (TEnvRec*) next())) {
      const char *s;
      if ((s = strstr(er->GetName(), "Plugin."))) {
         // use s, i.e. skip possible OS and application prefix to Plugin.
         // so that GetValue() takes properly care of returning the value
         // for the specified OS and/or application
         const char *val = env->GetValue(s, (const char*)0);
         if (val) {
            Int_t cnt = 0;
            char *v = StrDup(val);
            s += 7;
            while (1) {
               TString regexp = strtok(!cnt ? v : 0, "; ");
               if (regexp.IsNull()) break;
               TString clss   = strtok(0, "; ");
               if (clss.IsNull()) break;
               TString plugin = strtok(0, "; ");
               if (plugin.IsNull()) break;
               TString ctor = strtok(0, ";\"");
               if (!ctor.Contains("("))
                  ctor = strtok(0, ";\"");
               AddHandler(s, regexp, clss, plugin, ctor);
               cnt++;
            }
            delete [] v;
         }
      }
   }
}

//______________________________________________________________________________
void TPluginManager::AddHandler(const char *base, const char *regexp,
                                const char *className, const char *pluginName,
                                const char *ctor)
{
   // Add plugin handler to the list of handlers. If there is already a
   // handler defined for the same base and regexp it will be replaced.

   if (!fHandlers) {
      fHandlers = new TList;
      fHandlers->IsOwner();
   }

   // make sure there is no previous handler for the same case
   RemoveHandler(base, regexp);

   TPluginHandler *h = new TPluginHandler(base, regexp, className,
                                          pluginName, ctor);
   fHandlers->Add(h);
}

//______________________________________________________________________________
void TPluginManager::RemoveHandler(const char *base, const char *regexp)
{
   // Remove handler for the specified base class and the specified
   // regexp. If regexp=0 remove all handlers for the specified base.

   if (!fHandlers) return;

   TIter next(fHandlers);
   TPluginHandler *h;

   while ((h = (TPluginHandler*) next())) {
      if (h->fBase == base) {
         if (!regexp || h->fRegexp == regexp) {
            fHandlers->Remove(h);
            delete h;
         }
      }
   }
}

//______________________________________________________________________________
TPluginHandler *TPluginManager::FindHandler(const char *base, const char *uri)
{
   // Returns the handler if there exists a handler for the specified URI.
   // The uri can be 0 in which case the first matching plugin handler
   // will be returned. Returns 0 in case handler is not found.

   if (!fHandlers) return 0;

   TIter next(fHandlers);
   TPluginHandler *h;

   while ((h = (TPluginHandler*) next())) {
      if (h->CanHandle(base, uri)) {
         if (gDebug > 0)
            Info("FindHandler", "found plugin for %s", h->GetClass());
         return h;
      }
   }

   if (gDebug > 2) {
      if (uri)
         Info("FindHandler", "did not find plugin for class %s and uri %s", base, uri);
      else
         Info("FindHandler", "did not find plugin for class %s", base);
   }

   return 0;
}

//______________________________________________________________________________
void TPluginManager::Print(Option_t *opt) const
{
   // Print list of registered plugin handlers. If option is "a" print
   // also the ctor's that will be used.

   if (!fHandlers) return;

   TIter next(fHandlers);
   TPluginHandler *h;

   Printf("=====================================================================");
   Printf("Base                 Regexp        Class              Plugin");
   Printf("=====================================================================");

   while ((h = (TPluginHandler*) next())) {
      const char *exist = "";
      if (h->CheckPlugin() == -1)
         exist = " [*]";
      Printf("%-20s %-13s %-18s %s%s", h->fBase.Data(), h->fRegexp.Data(),
             h->fClass.Data(), h->fPlugin.Data(), exist);
      if (strchr(opt, 'a'))
         Printf("  [Ctor: %s]", h->fCtor.Data());
   }
   Printf("=====================================================================");
   Printf("[*] plugin not available");
   Printf("=====================================================================\n");
}
<|endoftext|>


<commit_before>/***************************************************************************
              fbellini@cern.ch - last modified on 28/11/2013
//
//Lauches KStar analysis with rsn mini package
//Allows basic configuration of pile-up check and event cuts
//
****************************************************************************/
enum pairYCutSet { kPairDefault,
		   kNegative,
		   kCentral
                 };

enum eventCutSet { kOld = -1,
		   kEvtDefault, //=0
		   kNoPileUpCut, //=1
		   kPileUpMV, //=2
		   kPileUpSPD3, //=3
		   kDefaultVtx8, //=4
		   kDefaultVtx5, //=5
		   kMCEvtDefault //=6
};

enum eventMixConfig { kDisabled = -1,
		      kMixDefault,//=0 //10 events, Dvz = 1cm, DC = 10
		      k5Evts, //=1 //5 events, Dvz = 1cm, DC = 10
		      k5Cent,  //=2 //10 events, Dvz = 1cm, DC = 5
                    };

AliRsnMiniAnalysisTask * AddTaskKStarPPB
(
 Bool_t      isMC = kFALSE,
 Bool_t      isPP = kFALSE,
 TString     outNameSuffix = "tof2s",
 Int_t       evtCutSetID = 0,
 Int_t       pairCutSetID = 0,
 Int_t       mixingConfigID = 0,
 Int_t       aodFilterBit = 5,
 Int_t       customQualityCutsID = -1,
 AliRsnCutSetDaughterParticle::ERsnDaughterCutSet cutPiCandidate = AliRsnCutSetDaughterParticle::kTOFpidKstarPPB2011,
 AliRsnCutSetDaughterParticle::ERsnDaughterCutSet cutKaCandidate = AliRsnCutSetDaughterParticle::kTOFpidKstarPPB2011,
 Float_t     nsigmaPi = 2.0,
 Float_t     nsigmaKa = 2.0,
 Bool_t      enableMonitor = kTRUE,
 Bool_t      IsMcTrueOnly = kFALSE,
 TString     monitorOpt = "NoSIGN",
 Bool_t      useMixLS = 0,
 Bool_t      checkReflex = 0,
 AliRsnMiniValue::EType yaxisvar = AliRsnMiniValue::kPt
)
{

  //-------------------------------------------
  // event cuts
  //-------------------------------------------
  UInt_t      triggerMask = AliVEvent::kINT7;
  Bool_t      rmFirstEvtChunk = kTRUE; //needed for pA 2013
  Bool_t      rejectPileUp = kTRUE; //best if used, for pA 2013
  Int_t       MinPlpContribSPD = 5; //default value if used
  Bool_t      useMVPileUpSelection = kFALSE; //
  Int_t       MinPlpContribMV = 5; //default value if used
  Bool_t      useVtxCut2013pA = kTRUE; //default use recommended 2013 pA vtx selection
  Double_t    vtxZcut = 10.0; //cm, default cut on vtx z

  if (evtCutSetID==eventCutSet::kOld) {
    triggerMask = AliVEvent::kAnyINT;
    rmFirstEvtChunk = kFALSE;
    rejectPileUp = kFALSE;
    useVtxCut2013pA = kFALSE;
  }

  if (evtCutSetID==eventCutSet::kNoPileUpCut) {
    rmFirstEvtChunk = kTRUE;
    rejectPileUp = kFALSE;
  }

  if (evtCutSetID==eventCutSet::kPileUpMV) {
    useMVPileUpSelection = kTRUE;
    MinPlpContribSPD = 3;
    //MinPlpContribMV = 5; //already set as default
  }

  if (evtCutSetID==eventCutSet::kPileUpSPD3) {
    MinPlpContribSPD = 3;
  }

  if (evtCutSetID==eventCutSet::kDefaultVtx8){
    vtxZcut = 8.0; //cm
  }

  if (evtCutSetID==eventCutSet::kDefaultVtx5){
    vtxZcut = 5.0; //cm
  }

  if (evtCutSetID==eventCutSet::kMCEvtDefault) {
    rmFirstEvtChunk = kFALSE;
    rejectPileUp = kFALSE;
  }

  //-------------------------------------------
  //pair cuts
  //-------------------------------------------
  Double_t    minYlab =  -0.465;
  Double_t    maxYlab =  0.035;

  if (pairCutSetID==pairYCutSet::kNegative) { //-0.5<y_cm<0.0
    minYlab = -0.965;    maxYlab = -0.465;
  }

  if (pairCutSetID==pairYCutSet::kCentral) { //|y_cm|<0.3
    minYlab = -0.765;    maxYlab = -0.165;
  }

  //-------------------------------------------
  //mixing settings
  //-------------------------------------------
  Int_t       nmix = 0;
  Float_t     maxDiffVzMix = 1.0;
  Float_t     maxDiffMultMix = 10.0;

  if (mixingConfigID == eventMixConfig::kMixDefault) {
    nmix = 10;
  }

  if (mixingConfigID == eventMixConfig::k5Evts) {
    nmix = 5;
  }

  if (mixingConfigID == eventMixConfig::k5Cent) {
    maxDiffMultMix = 5;
  }

  //
  // -- INITIALIZATION ----------------------------------------------------------------------------
  // retrieve analysis manager
  //
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
   if (!mgr) {
      ::Error("AddAnalysisTaskTOFKStar", "No analysis manager to connect to.");
      return NULL;
   }

   // create the task and configure
   TString taskName = Form("TOFKStar%s%s_%i%i", (isPP? "pp" : "PbPb"), (isMC ? "MC" : "Data"), (Int_t)cutPiCandidate,(Int_t)cutKaCandidate );
   AliRsnMiniAnalysisTask *task = new AliRsnMiniAnalysisTask(taskName.Data(), isMC);
   //task->UseESDTriggerMask(triggerMask); //ESD
   task->SelectCollisionCandidates(triggerMask); //AOD

   if (isPP)
     task->UseMultiplicity("QUALITY");
   else
     task->UseCentrality("V0A");
   // set event mixing options
   task->UseContinuousMix();
   //task->UseBinnedMix();
   task->SetNMix(nmix);
   task->SetMaxDiffVz(maxDiffVzMix);
   task->SetMaxDiffMult(maxDiffMultMix);
   ::Info("AddAnalysisTaskTOFKStar", Form("Event mixing configuration: \n events to mix = %i \n max diff. vtxZ = cm %5.3f \n max diff multi = %5.3f", nmix, maxDiffVzMix, maxDiffMultMix));

   mgr->AddTask(task);

   //
   // -- EVENT CUTS (same for all configs) ---------------------------------------------------------
   //
   // cut on primary vertex:
   // - 2nd argument --> |Vz| range
   // - 3rd argument --> minimum required number of contributors to vtx
   // - 4th argument --> tells if TPC stand-alone vertexes must be accepted
   AliRsnCutPrimaryVertex *cutVertex = new AliRsnCutPrimaryVertex("cutVertex", vtxZcut, 0, kFALSE);
   //if (isPP) cutVertex->SetCheckPileUp(kTRUE);   // set the check for pileup
   //set check for pileup in 2013
   AliRsnCutEventUtils *cutEventUtils = new AliRsnCutEventUtils("cutEventUtils", rmFirstEvtChunk, rejectPileUp);
   cutEventUtils->SetUseVertexSelection2013pA(useVtxCut2013pA);
   ::Info("AddAnalysisTaskTOFKStar", Form(":::::::::::::::::: Vertex cut as pA 2013: %s", (useVtxCut2013pA?"ON":"OFF")));
   if (useMVPileUpSelection){
     cutEventUtils->SetUseMVPlpSelection(useMVPileUpSelection);
     cutEventUtils->SetMinPlpContribMV(MinPlpContribMV);
     cutEventUtils->SetMinPlpContribSPD(MinPlpContribSPD);
     ::Info("AddAnalysisTaskTOFKStar", Form("Multiple-vtx Pile-up rejection settings: MinPlpContribMV = %i, MinPlpContribSPD = %i", MinPlpContribMV, MinPlpContribSPD));
   } else {
     cutEventUtils->SetMinPlpContribSPD(MinPlpContribSPD);
     ::Info("AddAnalysisTaskTOFKStar", Form("SPD Pile-up rejection settings: MinPlpContribSPD = %i", MinPlpContribSPD));
   }
   ::Info("AddAnalysisTaskTOFKStar", Form(":::::::::::::::::: Pile-up rejection mode: %s", (rejectPileUp?"ON":"OFF")));
   ::Info("AddAnalysisTaskTOFKStar", Form("::::::::::::: Remove first event in chunk: %s", (rmFirstEvtChunk?"ON":"OFF")));

   // define and fill cut set for event cut
   AliRsnCutSet *eventCuts = new AliRsnCutSet("eventCuts", AliRsnTarget::kEvent);
   eventCuts->AddCut(cutEventUtils);
   eventCuts->AddCut(cutVertex);
   eventCuts->SetCutScheme(Form("%s&%s", cutEventUtils->GetName(), cutVertex->GetName()));
   // set cuts in task
   task->SetEventCuts(eventCuts);

   //
   // -- EVENT-ONLY COMPUTATIONS -------------------------------------------------------------------
   //
   //vertex
   Int_t vtxID = task->CreateValue(AliRsnMiniValue::kVz, kFALSE);
   AliRsnMiniOutput *outVtx = task->CreateOutput("eventVtx", "HIST", "EVENT");
   outVtx->AddAxis(vtxID, 240, -12.0, 12.0);

   //multiplicity or centrality
   Int_t multID = task->CreateValue(AliRsnMiniValue::kMult, kFALSE);
   AliRsnMiniOutput *outMult = task->CreateOutput("eventMult", "HIST", "EVENT");
   if (isPP)
     outMult->AddAxis(multID, 400, 0.0, 400.0);
   else
     outMult->AddAxis(multID, 100, 0.0, 100.0);

   TH2F* hvz=new TH2F("hVzVsCent","", 100, 0., 100., 240, -12.0, 12.0);
   task->SetEventQAHist("vz",hvz);//plugs this histogram into the fHAEventVz data member

   TH2F* hmc=new TH2F("MultiVsCent","", 100, 0., 100., 400, 0., 400.);
   hmc->GetYaxis()->SetTitle("QUALITY");
   task->SetEventQAHist("multicent",hmc);//plugs this histogram into the fHAEventMultiCent data member

   //
   // -- PAIR CUTS (common to all resonances) ------------------------------------------------------
   //
   AliRsnCutMiniPair *cutY = new AliRsnCutMiniPair("cutRapidity", AliRsnCutMiniPair::kRapidityRange);
   cutY->SetRangeD(minYlab, maxYlab);

   AliRsnCutSet *cutsPair = new AliRsnCutSet("pairCuts", AliRsnTarget::kMother);
   cutsPair->AddCut(cutY);
   cutsPair->SetCutScheme(cutY->GetName());

   //
   // -- CONFIG ANALYSIS --------------------------------------------------------------------------
   //
   gROOT->LoadMacro("$ALICE_PHYSICS/PWGLF/RESONANCES/macros/mini/ConfigKStarPPb.C");
   if (!ConfigKStarPPb(task, isMC, isPP, "", cutsPair, aodFilterBit, customQualityCutsID, cutPiCandidate, cutKaCandidate, nsigmaPi, nsigmaKa, enableMonitor, isMC&IsMcTrueOnly,  monitorOpt.Data(), useMixLS, isMC&checkReflex, yaxisvar)) return 0x0;

   //
   // -- CONTAINERS --------------------------------------------------------------------------------
   //
   TString outputFileName = AliAnalysisManager::GetCommonFileName();
   //  outputFileName += ":Rsn";
   Printf("AddAnalysisTaskTOFKStar - Set OutputFileName : \n %s\n", outputFileName.Data() );

   AliAnalysisDataContainer *output = mgr->CreateContainer(Form("RsnOut_%s",outNameSuffix.Data()),
							   TList::Class(),
							   AliAnalysisManager::kOutputContainer,
							   outputFileName);
   mgr->ConnectInput(task, 0, mgr->GetCommonInputContainer());
   mgr->ConnectOutput(task, 1, output);

   return task;
}
<commit_msg>Modified macro to enable more event selection options. Now we can cross-check the p-Pb normalization and signal loss correction due to vertexing inefficiency and vertex selection.<commit_after>/***************************************************************************
              fbellini@cern.ch - last modified on 28/11/2013
//
//Lauches KStar analysis with rsn mini package
//Allows basic configuration of pile-up check and event cuts
//
****************************************************************************/
enum pairYCutSet { kPairDefault,
		   kNegative,
		   kCentral
                 };

enum eventCutSet { kOld = -1,
		   kEvtDefault, //=0
		   kNoPileUpCut, //=1
		   kPileUpMV, //=2
		   kPileUpSPD3, //=3
		   kDefaultVtx8, //=4
		   kDefaultVtx5, //=5
		   kMCEvtINELonly,//=6
		   kMCEvtCutpA2013only,//=7
		   kMCEvtDefault //=8
};

enum eventMixConfig { kDisabled = -1,
		      kMixDefault,//=0 //10 events, Dvz = 1cm, DC = 10
		      k5Evts, //=1 //5 events, Dvz = 1cm, DC = 10
		      k5Cent,  //=2 //10 events, Dvz = 1cm, DC = 5
                    };

AliRsnMiniAnalysisTask * AddTaskKStarPPB
(
 Bool_t      isMC = kFALSE,
 Bool_t      isPP = kFALSE,
 TString     outNameSuffix = "tof2s",
 Int_t       evtCutSetID = 0,
 Int_t       pairCutSetID = 0,
 Int_t       mixingConfigID = 0,
 Int_t       aodFilterBit = 5,
 Int_t       customQualityCutsID = -1,
 AliRsnCutSetDaughterParticle::ERsnDaughterCutSet cutPiCandidate = AliRsnCutSetDaughterParticle::kTOFpidKstarPPB2011,
 AliRsnCutSetDaughterParticle::ERsnDaughterCutSet cutKaCandidate = AliRsnCutSetDaughterParticle::kTOFpidKstarPPB2011,
 Float_t     nsigmaPi = 2.0,
 Float_t     nsigmaKa = 2.0,
 Bool_t      enableMonitor = kTRUE,
 Bool_t      IsMcTrueOnly = kFALSE,
 TString     monitorOpt = "NoSIGN",
 Bool_t      useMixLS = 0,
 Bool_t      checkReflex = 0,
 AliRsnMiniValue::EType yaxisvar = AliRsnMiniValue::kPt
)
{

  //-------------------------------------------
  // event cuts
  //-------------------------------------------
  UInt_t      triggerMask = AliVEvent::kINT7;
  Bool_t      rmFirstEvtChunk = kTRUE; //needed for pA 2013
  Bool_t      rejectPileUp = kTRUE; //best if used, for pA 2013
  Int_t       MinPlpContribSPD = 5; //default value if used
  Bool_t      useMVPileUpSelection = kFALSE; //
  Int_t       MinPlpContribMV = 5; //default value if used
  Bool_t      useVtxCut2013pA = kTRUE; //default use recommended 2013 pA vtx selection
  Double_t    vtxZcut = 10.0; //cm, default cut on vtx z

  if (evtCutSetID==eventCutSet::kOld) {
    triggerMask = AliVEvent::kAnyINT;
    rmFirstEvtChunk = kFALSE;
    rejectPileUp = kFALSE;
    useVtxCut2013pA = kFALSE;
  }

  if (evtCutSetID==eventCutSet::kNoPileUpCut) {
    rmFirstEvtChunk = kTRUE;
    rejectPileUp = kFALSE;
  }

  if (evtCutSetID==eventCutSet::kPileUpMV) {
    useMVPileUpSelection = kTRUE;
    MinPlpContribSPD = 3;
    //MinPlpContribMV = 5; //already set as default
  }

  if (evtCutSetID==eventCutSet::kPileUpSPD3) {
    MinPlpContribSPD = 3;
  }

  if (evtCutSetID==eventCutSet::kDefaultVtx8){
    vtxZcut = 8.0; //cm
  }

  if (evtCutSetID==eventCutSet::kDefaultVtx5){
    vtxZcut = 5.0; //cm
  }

  if (evtCutSetID==eventCutSet::kMCEvtINELonly) {
    rmFirstEvtChunk = kFALSE;
    rejectPileUp = kFALSE;
    useVtxCut2013pA = kFALSE;
    vtxZcut = 1.0e3; //cm
  }

  if (evtCutSetID==eventCutSet::kMCEvtCutpA2013only) {
    rmFirstEvtChunk = kFALSE;
    rejectPileUp = kFALSE;
    useVtxCut2013pA = kTRUE;
    vtxZcut = 1.0e3; //cm
  }

  if (evtCutSetID==eventCutSet::kMCEvtDefault) {
    rmFirstEvtChunk = kFALSE;
    rejectPileUp = kFALSE;
    useVtxCut2013pA = kTRUE;
    vtxZcut = 10.0; //cm
  }

  //-------------------------------------------
  //pair cuts
  //-------------------------------------------
  Double_t    minYlab =  -0.465;
  Double_t    maxYlab =  0.035;

  if (pairCutSetID==pairYCutSet::kNegative) { //-0.5<y_cm<0.0
    minYlab = -0.965;    maxYlab = -0.465;
  }

  if (pairCutSetID==pairYCutSet::kCentral) { //|y_cm|<0.3
    minYlab = -0.765;    maxYlab = -0.165;
  }

  //-------------------------------------------
  //mixing settings
  //-------------------------------------------
  Int_t       nmix = 0;
  Float_t     maxDiffVzMix = 1.0;
  Float_t     maxDiffMultMix = 10.0;

  if (mixingConfigID == eventMixConfig::kMixDefault) {
    nmix = 10;
  }

  if (mixingConfigID == eventMixConfig::k5Evts) {
    nmix = 5;
  }

  if (mixingConfigID == eventMixConfig::k5Cent) {
    maxDiffMultMix = 5;
  }

  //
  // -- INITIALIZATION ----------------------------------------------------------------------------
  // retrieve analysis manager
  //
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
   if (!mgr) {
      ::Error("AddAnalysisTaskTOFKStar", "No analysis manager to connect to.");
      return NULL;
   }

   // create the task and configure
   TString taskName = Form("TOFKStar%s%s_%i%i", (isPP? "pp" : "PbPb"), (isMC ? "MC" : "Data"), (Int_t)cutPiCandidate,(Int_t)cutKaCandidate );
   AliRsnMiniAnalysisTask *task = new AliRsnMiniAnalysisTask(taskName.Data(), isMC);
   //task->UseESDTriggerMask(triggerMask); //ESD
   task->SelectCollisionCandidates(triggerMask); //AOD

   if (isPP)
     task->UseMultiplicity("QUALITY");
   else
     task->UseCentrality("V0A");
   // set event mixing options
   task->UseContinuousMix();
   task->SetNMix(nmix);
   task->SetMaxDiffVz(maxDiffVzMix);
   task->SetMaxDiffMult(maxDiffMultMix);
   ::Info("AddAnalysisTaskTOFKStar", Form("Event mixing configuration: \n events to mix = %i \n max diff. vtxZ = cm %5.3f \n max diff multi = %5.3f", nmix, maxDiffVzMix, maxDiffMultMix));

   mgr->AddTask(task);

   //
   // -- EVENT CUTS (same for all configs) ---------------------------------------------------------
   //
   // cut on primary vertex:
   // - 2nd argument --> |Vz| range
   // - 3rd argument --> minimum required number of contributors to vtx
   // - 4th argument --> tells if TPC stand-alone vertexes must be accepted
   AliRsnCutPrimaryVertex *cutVertex = new AliRsnCutPrimaryVertex("cutVertex", vtxZcut, 0, kFALSE);
   //if (isPP) cutVertex->SetCheckPileUp(kTRUE);   // set the check for pileup
   //set check for pileup in 2013
   AliRsnCutEventUtils *cutEventUtils = new AliRsnCutEventUtils("cutEventUtils", rmFirstEvtChunk, rejectPileUp);
   cutEventUtils->SetUseVertexSelection2013pA(useVtxCut2013pA, vtxZcut);
   ::Info("AddAnalysisTaskTOFKStar", Form(":::::::::::::::::: Vertex cut as pA 2013 (max Vz = %4.2f cm): %s", vtxZcut, (useVtxCut2013pA?"ON":"OFF")));
   if (useMVPileUpSelection){
     cutEventUtils->SetUseMVPlpSelection(useMVPileUpSelection);
     cutEventUtils->SetMinPlpContribMV(MinPlpContribMV);
     cutEventUtils->SetMinPlpContribSPD(MinPlpContribSPD);
     ::Info("AddAnalysisTaskTOFKStar", Form("Multiple-vtx Pile-up rejection settings: MinPlpContribMV = %i, MinPlpContribSPD = %i", MinPlpContribMV, MinPlpContribSPD));
   } else {
     cutEventUtils->SetMinPlpContribSPD(MinPlpContribSPD);
     ::Info("AddAnalysisTaskTOFKStar", Form("SPD Pile-up rejection settings: MinPlpContribSPD = %i", MinPlpContribSPD));
   }
   ::Info("AddAnalysisTaskTOFKStar", Form(":::::::::::::::::: Pile-up rejection mode: %s", (rejectPileUp?"ON":"OFF")));
   ::Info("AddAnalysisTaskTOFKStar", Form("::::::::::::: Remove first event in chunk: %s", (rmFirstEvtChunk?"ON":"OFF")));

   // define and fill cut set for event cut
   AliRsnCutSet *eventCuts = new AliRsnCutSet("eventCuts", AliRsnTarget::kEvent);
   eventCuts->AddCut(cutEventUtils);
   eventCuts->AddCut(cutVertex);
   eventCuts->SetCutScheme(Form("%s&%s", cutEventUtils->GetName(), cutVertex->GetName()));
   // set cuts in task
   task->SetEventCuts(eventCuts);

   //
   // -- EVENT-ONLY COMPUTATIONS -------------------------------------------------------------------
   //
   //vertex
   Int_t vtxID = task->CreateValue(AliRsnMiniValue::kVz, kFALSE);
   //multiplicity or centrality
   Int_t multID = task->CreateValue(AliRsnMiniValue::kMult, kFALSE);
   //reference multiplicity (default with global tracks with good quality, if not available uses tracklets)
   Int_t multRefID = task->CreateValue(AliRsnMiniValue::kRefMult, kFALSE);

   AliRsnMiniOutput *outVtx = task->CreateOutput("eventVtx", "HIST", "EVENT");
   outVtx->AddAxis(vtxID, 500, -50.0, 50.0);

   AliRsnMiniOutput *outMult = task->CreateOutput("eventMult", "HIST", "EVENT");
   if (isPP)
     outMult->AddAxis(multID, 400, 0.0, 400.0);
   else
     outMult->AddAxis(multID, 101, 0.0, 101.0);

   AliRsnMiniOutput *outRefMult = task->CreateOutput("eventRefMult", "HIST", "EVENT");
   outRefMult->AddAxis(multRefID, 400, 0.0, 400.0);

   TH2F* hvz = new TH2F("hVzVsCent",Form("Vertex position vs centrality"), 101, 0., 101., 500, -50.0, 50.0);
   hvz->GetXaxis()->SetTitle("V0A");
   hvz->GetYaxis()->SetTitle("z_{vtx} (cm)");
   task->SetEventQAHist("vz", hvz);//plugs this histogram into the fHAEventVz data member

   TH2F* hRefMultiVsCent = new TH2F("hRefMultiVsCent",Form("Reference multiplicity vs centrality"), 101, 0., 101., 400, 0., 400.);
   hRefMultiVsCent->GetXaxis()->SetTitle("V0A");
   hRefMultiVsCent->GetYaxis()->SetTitle("GLOBAL");
   task->SetEventQAHist("refmulti",hRefMultiVsCent);//plugs this histogram into the fHAEventRefMultiCent data member

   TH2F* hMultiVsCent = new TH2F("hMultiVsCent",Form("Multiplicity vs centrality"), 101, 0., 101., 400, 0., 400.);
   hMultiVsCent->GetXaxis()->SetTitle("V0A");
   hMultiVsCent->GetYaxis()->SetTitle("QUALITY");
   task->SetEventQAHist("multicent",hMultiVsCent);//plugs this histogram into the fHAEventMultiCent data member
   //
   // -- PAIR CUTS (common to all resonances) ------------------------------------------------------
   //
   AliRsnCutMiniPair *cutY = new AliRsnCutMiniPair("cutRapidity", AliRsnCutMiniPair::kRapidityRange);
   cutY->SetRangeD(minYlab, maxYlab);

   AliRsnCutSet *cutsPair = new AliRsnCutSet("pairCuts", AliRsnTarget::kMother);
   cutsPair->AddCut(cutY);
   cutsPair->SetCutScheme(cutY->GetName());

   //
   // -- CONFIG ANALYSIS --------------------------------------------------------------------------
   //
   gROOT->LoadMacro("$ALICE_PHYSICS/PWGLF/RESONANCES/macros/mini/ConfigKStarPPb.C");
   if (!ConfigKStarPPb(task, isMC, isPP, "", cutsPair, aodFilterBit, customQualityCutsID, cutPiCandidate, cutKaCandidate, nsigmaPi, nsigmaKa, enableMonitor, isMC&IsMcTrueOnly,  monitorOpt.Data(), useMixLS, isMC&checkReflex, yaxisvar)) return 0x0;

   //
   // -- CONTAINERS --------------------------------------------------------------------------------
   //
   TString outputFileName = AliAnalysisManager::GetCommonFileName();
   //  outputFileName += ":Rsn";
   Printf("AddAnalysisTaskTOFKStar - Set OutputFileName : \n %s\n", outputFileName.Data() );

   AliAnalysisDataContainer *output = mgr->CreateContainer(Form("RsnOut_%s",outNameSuffix.Data()),
							   TList::Class(),
							   AliAnalysisManager::kOutputContainer,
							   outputFileName);
   mgr->ConnectInput(task, 0, mgr->GetCommonInputContainer());
   mgr->ConnectOutput(task, 1, output);

   return task;
}
<|endoftext|>