<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "bucket.h"
#include <assert.h>
#include <map>
#include <vespa/vespalib/util/overload.h>
#include <vespa/vespalib/util/visit_ranges.h>

namespace vespalib {
namespace metrics {

namespace {

template<typename T>
std::vector<typename T::aggregator_type>
mergeFromSamples(const StableStore<typename T::sample_type> &source)
{
    using Aggregator = typename T::aggregator_type;
    using Sample = typename T::sample_type;
    using Key = std::pair<MetricId, Point>;
    using Map = std::map<Key, Aggregator>;
    using MapValue = typename Map::value_type;

    Map map;
    source.for_each([&map] (const Sample &sample) {
        Key id = sample.idx;
        auto iter_check = map.emplace(id, sample);
        if (!iter_check.second) {
            iter_check.first->second.merge(sample);
        }
    });
    std::vector<typename T::aggregator_type> result;
    for (const MapValue &entry : map) {
        result.push_back(entry.second);
    }
    return result;
}

template<typename T>
struct IdxComparator {
    bool operator() (const T& a, const T& b) { return a.idx < b.idx; }
};

template<typename T>
std::vector<T>
mergeVectors(const std::vector<T> &a,
             const std::vector<T> &b)
{
    std::vector<T> result;
    visit_ranges(overload
                 {
                     [&result](visit_ranges_either, const T& x) { result.push_back(x); },
                     [&result](visit_ranges_both, const T& x, const T& y) {
                         result.push_back(x);
                         result.back().merge(y);
                     }
                 }, a.begin(), a.end(), b.begin(), b.end(), IdxComparator<T>());
    return result;
}

template<typename T>
std::vector<T>
findMissing(const std::vector<T> &already,
            const std::vector<T> &complete)
{
    std::vector<T> result;
    visit_ranges(overload
                 {
                     // missing from "complete", should not happen:
                     [&result](visit_ranges_first, const T&) { },
                     // missing this:
                     [&result](visit_ranges_second, const T& x) { result.push_back(x); },
                     // already have this:
                     [&result](visit_ranges_both, const T&, const T&) { }
                 },
                 already.begin(), already.end(),
                 complete.begin(), complete.end(),
                 IdxComparator<T>());
    return result;
}

} // namespace <unnamed>

void Bucket::merge(const CurrentSamples &samples)
{
    counters = mergeFromSamples<Counter>(samples.counterIncrements);
    gauges = mergeFromSamples<Gauge>(samples.gaugeMeasurements);
}

void Bucket::merge(const Bucket &other)
{
    assert(genCnt < other.genCnt);
    genCnt = other.genCnt;
    startTime = std::min(startTime, other.startTime);
    endTime = std::max(endTime, other.endTime);

    std::vector<CounterAggregator> nextCounters = mergeVectors(counters, other.counters);
    counters = std::move(nextCounters);

    std::vector<GaugeAggregator> nextGauges = mergeVectors(gauges, other.gauges);
    gauges = std::move(nextGauges);
}

void Bucket::padMetrics(const Bucket &source)
{
    std::vector<CounterAggregator> missingC = findMissing(counters, source.counters);
    for (CounterAggregator aggr : missingC) {
        aggr.count = 0;
        counters.push_back(aggr);
    }
    std::vector<GaugeAggregator> missingG = findMissing(gauges, source.gauges);
    for (GaugeAggregator aggr : missingG) {
        aggr.observedCount = 0;
        aggr.sumValue = 0;
        aggr.minValue = 0;
        aggr.maxValue = 0;
        gauges.push_back(aggr);
    }
}

} // namespace vespalib::metrics
} // namespace vespalib
<commit_msg>Remove unused lambda capture in findMissing function.<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "bucket.h"
#include <assert.h>
#include <map>
#include <vespa/vespalib/util/overload.h>
#include <vespa/vespalib/util/visit_ranges.h>

namespace vespalib {
namespace metrics {

namespace {

template<typename T>
std::vector<typename T::aggregator_type>
mergeFromSamples(const StableStore<typename T::sample_type> &source)
{
    using Aggregator = typename T::aggregator_type;
    using Sample = typename T::sample_type;
    using Key = std::pair<MetricId, Point>;
    using Map = std::map<Key, Aggregator>;
    using MapValue = typename Map::value_type;

    Map map;
    source.for_each([&map] (const Sample &sample) {
        Key id = sample.idx;
        auto iter_check = map.emplace(id, sample);
        if (!iter_check.second) {
            iter_check.first->second.merge(sample);
        }
    });
    std::vector<typename T::aggregator_type> result;
    for (const MapValue &entry : map) {
        result.push_back(entry.second);
    }
    return result;
}

template<typename T>
struct IdxComparator {
    bool operator() (const T& a, const T& b) { return a.idx < b.idx; }
};

template<typename T>
std::vector<T>
mergeVectors(const std::vector<T> &a,
             const std::vector<T> &b)
{
    std::vector<T> result;
    visit_ranges(overload
                 {
                     [&result](visit_ranges_either, const T& x) { result.push_back(x); },
                     [&result](visit_ranges_both, const T& x, const T& y) {
                         result.push_back(x);
                         result.back().merge(y);
                     }
                 }, a.begin(), a.end(), b.begin(), b.end(), IdxComparator<T>());
    return result;
}

template<typename T>
std::vector<T>
findMissing(const std::vector<T> &already,
            const std::vector<T> &complete)
{
    std::vector<T> result;
    visit_ranges(overload
                 {
                     // missing from "complete", should not happen:
                     [](visit_ranges_first, const T&) { },
                     // missing this:
                     [&result](visit_ranges_second, const T& x) { result.push_back(x); },
                     // already have this:
                     [](visit_ranges_both, const T&, const T&) { }
                 },
                 already.begin(), already.end(),
                 complete.begin(), complete.end(),
                 IdxComparator<T>());
    return result;
}

} // namespace <unnamed>

void Bucket::merge(const CurrentSamples &samples)
{
    counters = mergeFromSamples<Counter>(samples.counterIncrements);
    gauges = mergeFromSamples<Gauge>(samples.gaugeMeasurements);
}

void Bucket::merge(const Bucket &other)
{
    assert(genCnt < other.genCnt);
    genCnt = other.genCnt;
    startTime = std::min(startTime, other.startTime);
    endTime = std::max(endTime, other.endTime);

    std::vector<CounterAggregator> nextCounters = mergeVectors(counters, other.counters);
    counters = std::move(nextCounters);

    std::vector<GaugeAggregator> nextGauges = mergeVectors(gauges, other.gauges);
    gauges = std::move(nextGauges);
}

void Bucket::padMetrics(const Bucket &source)
{
    std::vector<CounterAggregator> missingC = findMissing(counters, source.counters);
    for (CounterAggregator aggr : missingC) {
        aggr.count = 0;
        counters.push_back(aggr);
    }
    std::vector<GaugeAggregator> missingG = findMissing(gauges, source.gauges);
    for (GaugeAggregator aggr : missingG) {
        aggr.observedCount = 0;
        aggr.sumValue = 0;
        aggr.minValue = 0;
        aggr.maxValue = 0;
        gauges.push_back(aggr);
    }
}

} // namespace vespalib::metrics
} // namespace vespalib
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    TestCellDistanceSelector.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
// .SECTION Thanks
// This test was written by Philippe Pebay, Kitware SAS 2012

#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkExtractSelection.h"
#include "vtkIdTypeArray.h"
#include "vtkInformation.h"
#include "vtkCellDistanceSelector.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkPointData.h"
#include "vtkSelection.h"
#include "vtkSelectionNode.h"
#include "vtkSmartPointer.h"
#include "vtkTestUtilities.h"
#include "vtkUnstructuredGrid.h"
#include "vtkUnstructuredGridReader.h"
#include "vtkUnstructuredGridWriter.h"

#include <vtksys/ios/sstream>

// Reference values
vtkIdType cardCellDistanceSelection[] =
{
  54,
  54,
  108,
  45,
};

// ------------------------------------------------------------------------------------------------
static int CheckExtractedUGrid( vtkExtractSelection* extract,
                                const char* tag,
                                int testIdx,
                                bool writeGrid )
{
  // Output must be a multiblock dataset
  vtkMultiBlockDataSet* outputMB = vtkMultiBlockDataSet::SafeDownCast( extract->GetOutput() );
  if ( ! outputMB )
    {
    vtkGenericWarningMacro("Cannot downcast extracted selection to multiblock dataset.");

    return 1;
    }

  // First block must be an unstructured grid
  vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::SafeDownCast( outputMB->GetBlock( 0 ) );
  if ( ! ugrid )
    {
    vtkGenericWarningMacro("Cannot downcast extracted selection to unstructured grid.");

    return 1;
    }

  // Initialize test status
  int testStatus = 0;
  cerr << endl;

  // Verify selection cardinality
  vtkIdType nCells = ugrid->GetNumberOfCells();
  cout << tag
       << " contains "
       << nCells
       << " cells."
       << endl;

  if ( nCells != cardCellDistanceSelection[testIdx] )
    {
    vtkGenericWarningMacro( "Incorrect cardinality: "
                           << nCells
                           << " != "
                           << cardCellDistanceSelection[testIdx] );
    testStatus = 1;
    }

  // Verify selection cells
  cerr << "Original cell Ids (types): ";
  ugrid->GetCellData()->SetActiveScalars( "vtkOriginalCellIds" );
  vtkDataArray* oCellIds = ugrid->GetCellData()->GetScalars();
  for ( vtkIdType i = 0; i < oCellIds->GetNumberOfTuples(); ++ i )
    {
    cerr << oCellIds->GetTuple1( i )
         << " ";
    }
  cerr << endl;

  // If requested, write mesh
  if ( writeGrid )
    {
    vtksys_ios::ostringstream fileNameSS;
    fileNameSS << "./CellDistanceExtraction-"
               << testIdx
               << ".vtk";
    vtkSmartPointer<vtkUnstructuredGridWriter> writer = vtkSmartPointer<vtkUnstructuredGridWriter>::New();
    writer->SetFileName( fileNameSS.str().c_str() );
    writer->SetInputData( ugrid );
    writer->Write();
    cerr << "Wrote file "
         << fileNameSS.str()
         << endl;
    }

  return testStatus;
}

//----------------------------------------------------------------------------
int TestCellDistanceSelector( int argc, char * argv [] )
{
  // Initialize test value
  int testIntValue = 0;

  // Read 3D unstructured input mesh
  char* fileName = vtkTestUtilities::ExpandDataFileName( argc, argv, "Data/AngularSector.vtk");
  vtkSmartPointer<vtkUnstructuredGridReader> reader = vtkSmartPointer<vtkUnstructuredGridReader>::New();
  reader->SetFileName( fileName );
  reader->Update();
  delete [] fileName;

  // Create multi-block mesh for linear selector
  vtkSmartPointer<vtkMultiBlockDataSet> mesh = vtkSmartPointer<vtkMultiBlockDataSet>::New();
  mesh->SetNumberOfBlocks( 1 );
  mesh->GetMetaData( static_cast<unsigned>( 0 ) )->Set( vtkCompositeDataSet::NAME(), "Mesh" );
  mesh->SetBlock( 0, reader->GetOutput() );

  // *****************************************************************************
  // 0. Selection along inner segment with endpoints (0,0,0) and (.23, 04,.04)
  // *****************************************************************************

  // Create selection along one line segment
  vtkSmartPointer<vtkCellDistanceSelector> ls0 = vtkSmartPointer<vtkCellDistanceSelector>::New();
  ls0->SetInputData( mesh );

  // Extract selection from mesh
  vtkSmartPointer<vtkExtractSelection> es0 =  vtkSmartPointer<vtkExtractSelection>::New();
  es0->SetInputData( 0, mesh );
  es0->SetInputConnection( 1, ls0->GetOutputPort() );
  es0->Update();

  testIntValue += CheckExtractedUGrid( es0, "Selection (0,0,0)-(0.23,0.04,0.04)", 0, true );

  return testIntValue;
}
<commit_msg>A first test that corresponds to something real<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestCellDistanceSelector.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
// .SECTION Thanks
// This test was written by Philippe Pebay, Kitware SAS 2012

#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkExtractSelection.h"
#include "vtkIdTypeArray.h"
#include "vtkInformation.h"
#include "vtkCellDistanceSelector.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkPointData.h"
#include "vtkSelection.h"
#include "vtkSelectionNode.h"
#include "vtkSmartPointer.h"
#include "vtkTestUtilities.h"
#include "vtkUnstructuredGrid.h"
#include "vtkUnstructuredGridReader.h"
#include "vtkUnstructuredGridWriter.h"

#include <vtksys/ios/sstream>

// Reference values
vtkIdType cardCellDistanceSelection[] =
{
  125,
  54,
  108,
  45,
};

// ------------------------------------------------------------------------------------------------
static int CheckExtractedUGrid( vtkExtractSelection* extract,
                                const char* tag,
                                int testIdx,
                                bool writeGrid )
{
  // Output must be a multiblock dataset
  vtkMultiBlockDataSet* outputMB = vtkMultiBlockDataSet::SafeDownCast( extract->GetOutput() );
  if ( ! outputMB )
    {
    vtkGenericWarningMacro("Cannot downcast extracted selection to multiblock dataset.");

    return 1;
    }

  // First block must be an unstructured grid
  vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::SafeDownCast( outputMB->GetBlock( 0 ) );
  if ( ! ugrid )
    {
    vtkGenericWarningMacro("Cannot downcast extracted selection to unstructured grid.");

    return 1;
    }

  // Initialize test status
  int testStatus = 0;
  cerr << endl;

  // Verify selection cardinality
  vtkIdType nCells = ugrid->GetNumberOfCells();
  cout << tag
       << " contains "
       << nCells
       << " cells."
       << endl;

  if ( nCells != cardCellDistanceSelection[testIdx] )
    {
    vtkGenericWarningMacro( "Incorrect cardinality: "
                           << nCells
                           << " != "
                           << cardCellDistanceSelection[testIdx] );
    testStatus = 1;
    }

  // Verify selection cells
  cerr << "Original cell Ids (types): ";
  ugrid->GetCellData()->SetActiveScalars( "vtkOriginalCellIds" );
  vtkDataArray* oCellIds = ugrid->GetCellData()->GetScalars();
  for ( vtkIdType i = 0; i < oCellIds->GetNumberOfTuples(); ++ i )
    {
    cerr << oCellIds->GetTuple1( i )
         << " ";
    }
  cerr << endl;

  // If requested, write mesh
  if ( writeGrid )
    {
    vtksys_ios::ostringstream fileNameSS;
    fileNameSS << "./CellDistanceExtraction-"
               << testIdx
               << ".vtk";
    vtkSmartPointer<vtkUnstructuredGridWriter> writer = vtkSmartPointer<vtkUnstructuredGridWriter>::New();
    writer->SetFileName( fileNameSS.str().c_str() );
    writer->SetInputData( ugrid );
    writer->Write();
    cerr << "Wrote file "
         << fileNameSS.str()
         << endl;
    }

  return testStatus;
}

//----------------------------------------------------------------------------
int TestCellDistanceSelector( int argc, char * argv [] )
{
  // Initialize test value
  int testIntValue = 0;

  // Read 3D unstructured input mesh
  char* fileName = vtkTestUtilities::ExpandDataFileName( argc, argv, "Data/AngularSector.vtk");
  vtkSmartPointer<vtkUnstructuredGridReader> reader = vtkSmartPointer<vtkUnstructuredGridReader>::New();
  reader->SetFileName( fileName );
  reader->Update();
  delete [] fileName;

  // Create multi-block mesh for linear selector
  vtkSmartPointer<vtkMultiBlockDataSet> mesh = vtkSmartPointer<vtkMultiBlockDataSet>::New();
  mesh->SetNumberOfBlocks( 1 );
  mesh->GetMetaData( static_cast<unsigned>( 0 ) )->Set( vtkCompositeDataSet::NAME(), "Mesh" );
  mesh->SetBlock( 0, reader->GetOutput() );

  // *****************************************************************************
  // 0. Selection with distance of 2 from cell 7000
  // *****************************************************************************

  // Create a selection, sel0, of cell with index 7000
  vtkSmartPointer<vtkIdTypeArray> selArr0 = vtkSmartPointer<vtkIdTypeArray>::New();
  selArr0->InsertNextValue( 7000 );
  vtkSmartPointer<vtkSelectionNode> selNode0 = vtkSmartPointer<vtkSelectionNode>::New();
  selNode0->SetContentType( vtkSelectionNode::INDICES );
  selNode0->SetFieldType( vtkSelectionNode::CELL );
  selNode0->GetProperties()->Set( vtkSelectionNode::COMPOSITE_INDEX(), 1 );
  selNode0->SetSelectionList( selArr0 );
  vtkSmartPointer<vtkSelection> sel0 = vtkSmartPointer<vtkSelection>::New();
  sel0->AddNode( selNode0 );

  // Create selection up to topological distance of 2
  vtkSmartPointer<vtkCellDistanceSelector> ls0 = vtkSmartPointer<vtkCellDistanceSelector>::New();
  ls0->SetInputData( 0, sel0 );
  ls0->SetInputData( 1, mesh );
  ls0->SetDistance( 2 );

  // Extract selection from mesh
  vtkSmartPointer<vtkExtractSelection> es0 =  vtkSmartPointer<vtkExtractSelection>::New();
  es0->SetInputData( 0, mesh );
  es0->SetInputConnection( 1, ls0->GetOutputPort() );
  es0->Update();
  testIntValue += CheckExtractedUGrid( es0, "Selection d({7000})<3", 0, true );

  return testIntValue;
}
<|endoftext|>


<commit_before>/**
 *  Schulich Delta Hermes
 *  Copyright (C) 2015 University of Calgary Solar Car Team
 *
 *  This file is part of Schulich Delta Hermes
 *
 *  Schulich Delta Hermes is free software:
 *  you can redistribute it and/or modify it under the terms
 *  of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  Schulich Delta Hermes is distributed
 *  in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warranty of MERCHANTABILITY or
 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
 *  General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General
 *  Public License along with Schulich Delta Hermes.
 *  If not, see <http://www.gnu.org/licenses/>.
 *
 *  For further contact, email <software@calgarysolarcar.ca>
 */

#include "DriverControlDetails.h"
#include "MessageDecodingHelpers.h"
#include "MessageDefines.h"

using namespace MessageDecodingHelpers;

namespace
{
   const int motorVelocityIndex = 1;
   const int motorVoltageIndex = 5;
   const int motorCurrentRealIndex = 9;
   const int backEmfIndex = 13;
   const int dpsBoardTemperatureIndex = 17;
   const int dcBusAmpHoursIndex = 21;
   const int odometerIndex = 25;
}

DriverControlDetails::DriverControlDetails(
   const QByteArray& messageData)
: messageData_(messageData)
{
}

float DriverControlDetails::motorVelocity() const
{
   return getFloat(messageData_, motorVelocityIndex);
}

float DriverControlDetails::motorVoltage() const
{
   return getFloat(messageData_, motorVoltageIndex);
}

float DriverControlDetails::motorCurrentReal() const
{
   return getFloat(messageData_, motorCurrentRealIndex);
}

float DriverControlDetails::backEmf() const
{
   return getFloat(messageData_, backEmfIndex);
}

float DriverControlDetails::dpsBoardTemperature() const
{
   return getFloat(messageData_, dpsBoardTemperatureIndex);
}

float DriverControlDetails::dcBusAmpHours() const
{
   return getFloat(messageData_, dcBusAmpHoursIndex);
}

float DriverControlDetails::odometer() const
{
   return getFloat(messageData_, odometerIndex);
}

QString DriverControlDetails::toString() const
{
   QString messageString;
   messageString += QString::number(MessageDefines::DriverControlDetails) + ", ";
   messageString += QString::number(motorVelocity()) + ", ";
   messageString += QString::number(motorVoltage()) + ", ";
   messageString += QString::number(motorCurrentReal()) + ", ";
   messageString += QString::number(backEmf()) + ", ";
   messageString += QString::number(dpsBoardTemperature()) + ", ";
   messageString += QString::number(dcBusAmpHours()) + ", ";
   return messageString;
}
<commit_msg>renamed driver control details to follow naming conventions<commit_after>/**
 *  Schulich Delta Hermes
 *  Copyright (C) 2015 University of Calgary Solar Car Team
 *
 *  This file is part of Schulich Delta Hermes
 *
 *  Schulich Delta Hermes is free software:
 *  you can redistribute it and/or modify it under the terms
 *  of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  Schulich Delta Hermes is distributed
 *  in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warranty of MERCHANTABILITY or
 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
 *  General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General
 *  Public License along with Schulich Delta Hermes.
 *  If not, see <http://www.gnu.org/licenses/>.
 *
 *  For further contact, email <software@calgarysolarcar.ca>
 */

#include "DriverControlDetails.h"
#include "MessageDecodingHelpers.h"
#include "MessageDefines.h"

using namespace MessageDecodingHelpers;

namespace
{
   const int MOTOR_VELOCITY_INDEX = 1;
   const int MOTOR_VOLTAGE_INDEX = 5;
   const int MOTOR_CURRENT_REAL_INDEX = 9;
   const int BACK_EMF_INDEX = 13;
   const int DSP_BOARD_TEMPERATURE_INDEX = 17;
   const int DC_BUS_AMP_HOURS_INDEX = 21;
   const int ODOMETER_INDEX = 25;
}

DriverControlDetails::DriverControlDetails(
   const QByteArray& messageData)
: messageData_(messageData)
{
}

float DriverControlDetails::motorVelocity() const
{
   return getFloat(messageData_, MOTOR_VELOCITY_INDEX);
}

float DriverControlDetails::motorVoltage() const
{
   return getFloat(messageData_, MOTOR_VOLTAGE_INDEX);
}

float DriverControlDetails::motorCurrentReal() const
{
   return getFloat(messageData_, MOTOR_CURRENT_REAL_INDEX);
}

float DriverControlDetails::backEmf() const
{
   return getFloat(messageData_, BACK_EMF_INDEX);
}

float DriverControlDetails::dpsBoardTemperature() const
{
   return getFloat(messageData_, DSP_BOARD_TEMPERATURE_INDEX);
}

float DriverControlDetails::dcBusAmpHours() const
{
   return getFloat(messageData_, DC_BUS_AMP_HOURS_INDEX);
}

float DriverControlDetails::odometer() const
{
   return getFloat(messageData_, ODOMETER_INDEX);
}

QString DriverControlDetails::toString() const
{
   QString messageString;
   messageString += QString::number(MessageDefines::DriverControlDetails) + ", ";
   messageString += QString::number(motorVelocity()) + ", ";
   messageString += QString::number(motorVoltage()) + ", ";
   messageString += QString::number(motorCurrentReal()) + ", ";
   messageString += QString::number(backEmf()) + ", ";
   messageString += QString::number(dpsBoardTemperature()) + ", ";
   messageString += QString::number(dcBusAmpHours()) + ", ";
   return messageString;
}
<|endoftext|>


<commit_before>
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// 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 Industrial Light & Magic 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.
//
///////////////////////////////////////////////////////////////////////////

//-----------------------------------------------------------------------------
//
//	Routines that generate pseudo-random numbers compatible
//	with the standard erand48(), nrand48(), etc. functions.
//
//-----------------------------------------------------------------------------

#include "ImathRandom.h"
#include "ImathLimits.h"

namespace Imath {

#if ULONG_MAX == 18446744073709551615LU
    typedef      long unsigned int Int64;
#else
    typedef long long unsigned int Int64;
#endif

namespace {

//
// Static state used by Imath::drand48(), Imath::lrand48() and Imath::srand48()
//

unsigned short staticState[3] = {0, 0, 0};

void
rand48Next (unsigned short state[3])
{
    //
    // drand48() and friends are all based
    // on a linear congruential sequence,
    //
    //   x[n+1] = (a * x[n] + c) % (m + 1),
    //
    // with a, c and m as specified below.
    //

    static const Int64 a = Int64 (0x5deece66dLL);
    static const Int64 c = Int64 (0xbLL);
    static const Int64 m = Int64 (0x0ffffffffffffLL);

    //
    // Assemble the 48-bit value x[n] from the
    // three 16-bit values stored in state.
    //

    Int64 x = (Int64 (state[2]) << 32) |
	      (Int64 (state[1]) << 16) |
	       Int64 (state[0]);

    //
    // Compute x[n+1]
    //

    x = (a * x + c) & m;

    //
    // Disassemble x[n+1] into three 16-bit values.
    // The code assumes that sizeof (unsigned short) == 2.
    //

    state[2] = x >> 32;
    state[1] = x >> 16;
    state[0] = x;
}

} // namespace

double
erand48 (unsigned short state[3])
{
    //
    // Generate a double-precision floating-point value between 0.0 and 1.0:
    //
    // The biased exponent for all doubles between 1.0 and 2.0 is 0x3ff.
    // The 48 most significant bits of the significand (mantissa) are
    // filled with pseudo-random bits generated by rand48Next().  The
    // remaining 4 bits are set to 0.  This results in a bit pattern
    // between 0x3ff0000000000000 and 0x3ffffffffffffff0, which corresponds
    // to a floating-point value between 1.0 and 1.9999999999999964.
    // Subtracting 1.0 from this value produces a number between 0.0 and
    // 0.9999999999999964.
    //

    rand48Next (state);

    union {double d; Int64 i;} u;

    u.i = (Int64 (0x3ff)    << 52) |	// sign and exponent
	  (Int64 (state[2]) << 36) |	// significand
	  (Int64 (state[1]) << 20) |
	  (Int64 (state[0]) <<  4);

    return u.d - 1;
}

double
drand48 ()
{
    return Imath::erand48 (staticState);
}

long int
nrand48 (unsigned short state[3])
{
    //
    // Generate an integer between 0 and 0x7fffffff.
    //

    rand48Next (state);

    return ((long int) (state[2]) << 15) |
	   ((long int) (state[1]) >>  1);
}

long int
lrand48 ()
{
    return Imath::nrand48 (staticState);
}

void
srand48 (long int seed)
{
    staticState[2] = seed >> 16;
    staticState[1] = seed;
    staticState[0] = 0x330e;
}

} // namespace Imath
<commit_msg>Fixed comments.<commit_after>
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// 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 Industrial Light & Magic 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.
//
///////////////////////////////////////////////////////////////////////////

//-----------------------------------------------------------------------------
//
//	Routines that generate pseudo-random numbers compatible
//	with the standard erand48(), nrand48(), etc. functions.
//
//-----------------------------------------------------------------------------

#include "ImathRandom.h"
#include "ImathLimits.h"

namespace Imath {

#if ULONG_MAX == 18446744073709551615LU
    typedef      long unsigned int Int64;
#else
    typedef long long unsigned int Int64;
#endif

namespace {

//
// Static state used by Imath::drand48(), Imath::lrand48() and Imath::srand48()
//

unsigned short staticState[3] = {0, 0, 0};

void
rand48Next (unsigned short state[3])
{
    //
    // drand48() and friends are all based
    // on a linear congruential sequence,
    //
    //   x[n+1] = (a * x[n] + c) % (m + 1),
    //
    // with a, c and m as specified below.
    //

    static const Int64 a = Int64 (0x5deece66dLL);
    static const Int64 c = Int64 (0xbLL);
    static const Int64 m = Int64 (0x0ffffffffffffLL);

    //
    // Assemble the 48-bit value x[n] from the
    // three 16-bit values stored in state.
    //

    Int64 x = (Int64 (state[2]) << 32) |
	      (Int64 (state[1]) << 16) |
	       Int64 (state[0]);

    //
    // Compute x[n+1]
    //

    x = (a * x + c) & m;

    //
    // Disassemble x[n+1] into three 16-bit values.
    // The code assumes that sizeof (unsigned short) == 2.
    //

    state[2] = x >> 32;
    state[1] = x >> 16;
    state[0] = x;
}

} // namespace

double
erand48 (unsigned short state[3])
{
    //
    // Generate double-precision floating-point values between 0.0 and 1.0:
    //
    // The biased exponent for all doubles between 1.0 and 2.0 is 0x3ff.
    // The 48 most significant bits of the significand (mantissa) are
    // filled with pseudo-random bits generated by rand48Next().
    // The remaining 4 bits are set to 0.  This results in bit patterns
    // between 0x3ff0000000000000 and 0x3ffffffffffffff0, which correspond
    // to uniformly distributed floating-point values between 1.0 and
    // 1.9999999999999964.  Subtracting 1.0 from those values produces
    // numbers between 0.0 and 0.9999999999999964.
    //

    rand48Next (state);

    union {double d; Int64 i;} u;

    u.i = (Int64 (0x3ff)    << 52) |	// sign and exponent
	  (Int64 (state[2]) << 36) |	// significand
	  (Int64 (state[1]) << 20) |
	  (Int64 (state[0]) <<  4);

    return u.d - 1;
}

double
drand48 ()
{
    return Imath::erand48 (staticState);
}

long int
nrand48 (unsigned short state[3])
{
    //
    // Generate uniformly distributed integers between 0 and 0x7fffffff.
    //

    rand48Next (state);

    return ((long int) (state[2]) << 15) |
	   ((long int) (state[1]) >>  1);
}

long int
lrand48 ()
{
    return Imath::nrand48 (staticState);
}

void
srand48 (long int seed)
{
    staticState[2] = seed >> 16;
    staticState[1] = seed;
    staticState[0] = 0x330e;
}

} // namespace Imath
<|endoftext|>


<commit_before>// RhoLaunch.cpp : Defines the entry point for the application.
//

#include "windows.h"
#include "RhoLaunch.h"

#define MAX_LOADSTRING 100
#define PB_WINDOW_RESTORE WM_USER + 10

// Global Functions:
int LaunchProcess( LPTSTR pFilePath, LPTSTR pCmdLine);

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPTSTR    lpCmdLine,
                   int       nCmdShow)
{

	COPYDATASTRUCT launchData;

	//validate the command line
	int iLen = wcslen(lpCmdLine);
	if(iLen < 3){
		return 1;
	}

	//LPWSTR pAppName = new WCHAR[iLen + 3];//allow space for the index
	LPWSTR pAppName,pTabName,pTemp;
	pAppName = pTemp= lpCmdLine;

	int iLoop;
	bool bStart,bTabStart,bAppName;
	bStart = bTabStart = bAppName= false;

	for(iLoop = 0;iLoop < iLen ;iLoop++)
	{
		if(lpCmdLine[iLoop] == L' '){

			if(bStart){
				if(!bAppName){
					*pTemp = NULL;//terminate the app name
					pTemp++;
					bAppName = true;
					pTabName = pTemp;

				}
				else if(bTabStart){
					*pTemp = NULL;//terminate the tab name
					break;//finished so exit loop
				}

			}
			continue;//ignore spaces

		}

		if(lpCmdLine[iLoop] == L'/'){
			if(!bStart){
				bStart = !bStart;
				continue;

			}

			if(!bAppName){
				*pTemp= NULL;
				bAppName = !bAppName;
				bTabStart = true;
			}

			if(!bTabStart){
				bTabStart = true;
				continue;
			}

		}
		*pTemp= lpCmdLine[iLoop];
		pTemp++;

	}
	*pTemp = NULL;

	HWND hwndRunningRE = FindWindow(NULL, pAppName);

	if (hwndRunningRE){
		//  Found the running instance

		//rhode expects a MultiByte string so convert
		int ilen = wcslen(pTabName);
		char *pTabNameMB = new char[ilen+1];
		wcstombs(pTabNameMB, pTabName,ilen);

		launchData.lpData = pTabNameMB;
		launchData.cbData = (ilen+1);

		ShowWindow(hwndRunningRE, SW_RESTORE);

		SendMessage(hwndRunningRE,PB_WINDOW_RESTORE,(WPARAM) NULL,(LPARAM)TRUE);

		//send a message to inform Rho of the requested index
		SendMessage(hwndRunningRE,WM_COPYDATA,(WPARAM)NULL,(LPARAM) (LPVOID) &launchData );

		delete [] pTabNameMB;

		//  switch to it

		SetForegroundWindow(hwndRunningRE);

	}
	else{
		//no window handle, so try to start the app
		//will only work if RhoLaunch is in the same directory as the app

		//build the Rho app name
		WCHAR pApp[MAX_PATH + 1];
		int iIndex,iLen;

		if(!(iLen = GetModuleFileName(NULL,pApp,MAX_PATH))){
			return 1;//error could not find the path
		}

		//remove 'RhoLaunch' from the path
		for(iIndex = iLen - 1;pApp[iIndex]!=L'\\';iIndex--);
		pApp[iIndex+ 1] = NULL;

		//LPWSTR pApp = new WCHAR[wcslen(pAppName)+10];
		wcscat(pApp,pAppName);
		wcscat(pApp,L".exe");

		LPWSTR pTabCommand = new WCHAR[wcslen(pTabName)+20];
		wsprintf(pTabCommand,L"/tabname=\"%s\"",pTabName);

		LaunchProcess(pApp,pTabCommand);

		delete [] pTabCommand;
	}

	return 0;
}

int LaunchProcess( LPTSTR pFilePath, LPTSTR pCmdLine)
{

	STARTUPINFO				StartInfo;
	PROCESS_INFORMATION		ProcessInfo;
	BOOL					bOk;

	//	Reset the contents of the 'Process Information' and 'Start Up' structures.

	memset( &ProcessInfo, 0, sizeof( PROCESS_INFORMATION));
	memset( &StartInfo, 0, sizeof( STARTUPINFO));
	StartInfo.cb = sizeof( STARTUPINFO);

	//	Create the 'browser' in a seperate process.

	bOk = CreateProcess( pFilePath,		//	LPCTSTR lpApplicationName,//L"\\program files\\Neon\\BIN\\SVC_Controls.exe",
						 pCmdLine,		//	LPTSTR lpCommandLine,
						 NULL,			//	LPSECURITY_ATTRIBUTES lpProcessAttributes,
						 NULL,			//	LPSECURITY_ATTRIBUTES lpThreadAttributes,
						 FALSE,			//	BOOL bInheritHandles,
						 0,				//	DWORD dwCreationFlags,
						 NULL,			//	LPVOID lpEnvironment,
						 NULL,			//	LPCTSTR lpCurrentDirectory,
						 &StartInfo,	//	LPSTARTUPINFO lpStartupInfo,
						 &ProcessInfo);	//	LPPROCESS_INFORMATION lpProcessInformation
	//m_dwProcessID = ProcessInfo.dwProcessId;

	//	If all is Ok, then return '0' else return the last error code.

	return bOk ? 0 : GetLastError();
}<commit_msg>Modifying RhoLaunch to look for Window's ClassName<commit_after>// RhoLaunch.cpp : Defines the entry point for the application.
//

#include "windows.h"
#include "RhoLaunch.h"

#define MAX_LOADSTRING 100
#define PB_WINDOW_RESTORE WM_USER + 10

// Global Functions:
int LaunchProcess( LPTSTR pFilePath, LPTSTR pCmdLine);

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPTSTR    lpCmdLine,
                   int       nCmdShow)
{

	COPYDATASTRUCT launchData;

	//validate the command line
	int iLen = wcslen(lpCmdLine);
	if(iLen < 3){
		return 1;
	}

	//LPWSTR pAppName = new WCHAR[iLen + 3];//allow space for the index
	LPWSTR pAppName,pTabName,pTemp;
	pAppName = pTemp= lpCmdLine;

	int iLoop;
	bool bStart,bTabStart,bAppName;
	bStart = bTabStart = bAppName= false;

	for(iLoop = 0;iLoop < iLen ;iLoop++)
	{
		if(lpCmdLine[iLoop] == L' '){

			if(bStart){
				if(!bAppName){
					*pTemp = NULL;//terminate the app name
					pTemp++;
					bAppName = true;
					pTabName = pTemp;

				}
				else if(bTabStart){
					*pTemp = NULL;//terminate the tab name
					break;//finished so exit loop
				}

			}
			continue;//ignore spaces

		}

		if(lpCmdLine[iLoop] == L'/'){
			if(!bStart){
				bStart = !bStart;
				continue;

			}

			if(!bAppName){
				*pTemp= NULL;
				bAppName = !bAppName;
				bTabStart = true;
			}

			if(!bTabStart){
				bTabStart = true;
				continue;
			}

		}
		*pTemp= lpCmdLine[iLoop];
		pTemp++;

	}
	*pTemp = NULL;

//	HWND hwndRunningRE = FindWindow(NULL, pAppName);
	//  DCC Main Window now has Classname <pAppName>.MainWindow
	WCHAR* szClassName = new WCHAR[wcslen(pAppName) + wcslen(L".MainWindow") + 1];
	wcscpy(szClassName, pAppName);
	wcscat(szClassName, L".MainWindow");
	HWND hwndRunningRE = FindWindow(szClassName, NULL);
	delete[] szClassName;

	if (hwndRunningRE){
		//  Found the running instance

		//rhode expects a MultiByte string so convert
		int ilen = wcslen(pTabName);
		char *pTabNameMB = new char[ilen+1];
		wcstombs(pTabNameMB, pTabName,ilen);

		launchData.lpData = pTabNameMB;
		launchData.cbData = (ilen+1);

		ShowWindow(hwndRunningRE, SW_RESTORE);

		SendMessage(hwndRunningRE,PB_WINDOW_RESTORE,(WPARAM) NULL,(LPARAM)TRUE);

		//send a message to inform Rho of the requested index
		SendMessage(hwndRunningRE,WM_COPYDATA,(WPARAM)NULL,(LPARAM) (LPVOID) &launchData );

		delete [] pTabNameMB;

		//  switch to it

		SetForegroundWindow(hwndRunningRE);

	}
	else{
		//no window handle, so try to start the app
		//will only work if RhoLaunch is in the same directory as the app

		//build the Rho app name
		WCHAR pApp[MAX_PATH + 1];
		int iIndex,iLen;

		if(!(iLen = GetModuleFileName(NULL,pApp,MAX_PATH))){
			return 1;//error could not find the path
		}

		//remove 'RhoLaunch' from the path
		for(iIndex = iLen - 1;pApp[iIndex]!=L'\\';iIndex--);
		pApp[iIndex+ 1] = NULL;

		//LPWSTR pApp = new WCHAR[wcslen(pAppName)+10];
		wcscat(pApp,pAppName);
		wcscat(pApp,L".exe");

		LPWSTR pTabCommand = new WCHAR[wcslen(pTabName)+20];
		wsprintf(pTabCommand,L"/tabname=\"%s\"",pTabName);

		LaunchProcess(pApp,pTabCommand);

		delete [] pTabCommand;
	}

	return 0;
}

int LaunchProcess( LPTSTR pFilePath, LPTSTR pCmdLine)
{

	STARTUPINFO				StartInfo;
	PROCESS_INFORMATION		ProcessInfo;
	BOOL					bOk;

	//	Reset the contents of the 'Process Information' and 'Start Up' structures.

	memset( &ProcessInfo, 0, sizeof( PROCESS_INFORMATION));
	memset( &StartInfo, 0, sizeof( STARTUPINFO));
	StartInfo.cb = sizeof( STARTUPINFO);

	//	Create the 'browser' in a seperate process.

	bOk = CreateProcess( pFilePath,		//	LPCTSTR lpApplicationName,//L"\\program files\\Neon\\BIN\\SVC_Controls.exe",
						 pCmdLine,		//	LPTSTR lpCommandLine,
						 NULL,			//	LPSECURITY_ATTRIBUTES lpProcessAttributes,
						 NULL,			//	LPSECURITY_ATTRIBUTES lpThreadAttributes,
						 FALSE,			//	BOOL bInheritHandles,
						 0,				//	DWORD dwCreationFlags,
						 NULL,			//	LPVOID lpEnvironment,
						 NULL,			//	LPCTSTR lpCurrentDirectory,
						 &StartInfo,	//	LPSTARTUPINFO lpStartupInfo,
						 &ProcessInfo);	//	LPPROCESS_INFORMATION lpProcessInformation
	//m_dwProcessID = ProcessInfo.dwProcessId;

	//	If all is Ok, then return '0' else return the last error code.

	return bOk ? 0 : GetLastError();
}<|endoftext|>


<commit_before>/*
  Steering macro for the Detector/<action> trending

  //
  // code to check consitency
  //
  gSystem->SetIncludePath("-I$ROOTSYS/include -I$ALICE_ROOT/ -I$ALICE_ROOT/include -I$ALICE_ROOT/install/include -I$ALICE_ROOT/STEER\
   -I$ALICE_ROOT/TPC -I$ALICE_ROOT/ITS -I$ALICE_ROOT/TRD -I$ALICE_ROOT/TOF -I$ALICE_ROOT/RAW  -I$ALICE_ROOT/STAT -I$ALICE_ROOT/TPC/TPCBase  -I$ALICE_ROOT/TPC/TPCRec -I$ALICE_ROOT/TPC/TPCCalib -I$ALICE_PHYSICS/../src/PWGPP/TPC/");
  .L $ALICE_PHYSICS/../src/PWGPP/QA/scripts/qaTrending.C+
  period="LHC15o";
  pass="cpass1_pass1";
  detector="T0";
  referenceDet="ITS;TPC;TRD;TOF";

  treeQADet=InitTrees(detector,referenceDet);
  treeQADet->SetAlias("tagID","run");
  InitSummaryTrending(treeQADet);

*/

#include "TTree.h"
#include "TString.h"
#include "TStatToolkit.h"
#include "AliExternalInfo.h"
#include "TStyle.h"
#include "TROOT.h"
#include "TMultiGraph.h"
#include "TMath.h"
#include "TLegend.h"

TTree * InitTrees(const char * detector,   const char * referenceDet);    // load QA trees and Sttering tree <det>   QA.<Det>, Logbook, Lo
void    InitSummaryTrending(TTree * tree);                     // can be generic ?
void    SetDrawStyle();                                        // setting Defaul draw style
TObjArray * GetTexDescription(TLatex *latex);                  // should go to base code
void    logbookConfig(TTree * tree);                              // should go to base code

//
// Macro global variables:
//
char * year=0, *period=0, *pass=0;
TTree * treeQADet=0;
std::map<std::string,TTree*> qaMap;
TCanvas *canvasQA=0;          // central canvas for QA plots
TObjArray * descriptionQA=0;  // descriptionQA of process  (time/aliroot/root/pariod/pass/user)
TObjArray*   oaMultGr=0;      // status bar multigraph
TString      statusDescription[3];   // status bra description

//
//
// Drawing configuration can be changed
//
// colors & markers:
Int_t colPosA=kGreen+2; //kRed;
Int_t colPosC=kMagenta+1; //kAzure-4;
Int_t colNegA=kRed; //kRed;//kOrange;
Int_t colNegC=kAzure-4; //kAzure-4;//kGreen;
Int_t colSum=kBlack;
Int_t marA1=21;
Int_t marA2=24;
Int_t marC1=20;
Int_t marC2=25;
Int_t marSum=34;//full cross
Int_t marCorr=31;//snowflake
Float_t markerSize=0.9;
const char * defColors="1;2;4;3;856;616";
const char * defMarkers="21;22;25;26;27;28";
const char * bandColors="1;400;400;632;632;416;416"; // kBlack;kYellow;kYellow;kRed; kRed; kGreeen; kGreen
// shifting of graphs within one run for better visibility:
Float_t sh_gr0=-0.3;
Float_t sh_gr1=-0.1;
Float_t sh_gr2=+0.1;
Float_t sh_gr3=+0.3;
// maximal canvas width
Int_t kMaxCanvasWidth=2500;
// status bar height
Float_t statPadHeight=0.30; //fraction of canvas height (was 0.25 until Aug 2014)
Float_t statPadBotMar=0.40; //bottom margin of pad for run numbers
Int_t   padRightMargin=0.07;

void qaTrending(){
}

TTree * InitTrees(const char * detector,  const char *referenceDet){
  //
  // Init tree for given period
  //  all  trees stored in qaMap
  //  FriendTree added to the master treeQADet
  // Currentrly in the code we assume ID="run";
  // Bug in root tree ?  - in case more than one friend tree set - indeces looks corrupted
  //    0.) QA tree per detector Raw+MC (if exist)
  //    1.) QA trees per refernce detectors specified by string refDet e.g "TPC;TRD;TOF"
  //    2.) Logbook tree per run
  //    3.) Logbook tree per run/detector
  //    3.) RCT table
  //    4.) CPass table
  //
  //  tree is created with addition of friend trees which can be used in queries
  //  queries as analog to the SQL statement

  /*
    period="LHC15o"; pass="cpass1_pass1"
  */
  ::Info("qaTrending::InitTrees::Begin","Detector %s, RefDet=%s",detector, referenceDet);
  AliExternalInfo info;
  Int_t treeCounter=0;
  // Load trees
  TObjArray * detArray=TString(referenceDet).Tokenize(";");
  Int_t nrefDets=detArray->GetEntries();
  TVectorF runCounter(5+nrefDets*2);  // <QADet>, <Logbook>, <Logbook.Det>, <MonAlisa>, <CPass>, <QA.RefDet>xnrefDets, <Logbook.RefDet>xnrefDets
  //
  ::Info("qaTrending::InitTrees::End","Laoding trees");
  treeQADet = info.GetTreeDataQA(detector,period, pass);
  if (!treeQADet){
    ::Error("qaTrending.InitTrees", "Input QA tree %s not available", detector);
    return 0;
  }
  runCounter[treeCounter++]=treeQADet->Draw("run","1","goff");
  qaMap[TString::Format("QA.%s",detector).Data()]=treeQADet;
  //
  qaMap["Logbook"]=info.GetTree("Logbook",period,"");
  qaMap["Logbook"]->AddFriend(treeQADet,"QADet");
  treeQADet->AddFriend(qaMap["Logbook"],"Logbook");
  runCounter[treeCounter++]=treeQADet->Draw("run","1","goff");
  //
  qaMap["MonALISA.RCT"]=info.GetTree("MonALISA.RCT",period,pass);
  qaMap["MonALISA.RCT"]->AddFriend(treeQADet,"QADet");
  treeQADet->AddFriend(qaMap["MonALISA.RCT"],"MonALISA.RCT");
  runCounter[treeCounter++]=treeQADet->Draw("run","1","goff");
  //
  TTree *treeLogbookDetector =info.GetTree("Logbook.detector",period,"");
  if (treeLogbookDetector){
    if (detArray->GetEntries()>0){
      for (Int_t idet=0; idet<detArray->GetEntries(); idet++){
	// Load Logbook.RefDet
	const char *detName=detArray->At(idet)->GetName();
	TTree * treeLog =treeLogbookDetector->CopyTree(TString::Format("detector==\"%s\"",detName).Data());
	if (treeLog->GetEntries()<=0){
	  ::Error("qaTrending.InitTrees","Missing Tree Logbook. %s - check the syntax",detName);
	}else{
	  treeLog->BuildIndex("run");
	  qaMap[TString::Format("Logbook.%s",detName).Data()]=treeLog;
	  treeLog->AddFriend(treeQADet, "QADet");
	  treeQADet->AddFriend(treeLog,  TString::Format("Logbook.%s",detName).Data());
	  runCounter[treeCounter++]=treeQADet->Draw("run","1","goff");
	}
	// Load QA.RefDet
	TTree * treeQARefDet = info.GetTreeDataQA(detName,period, pass);
	if (treeQARefDet){
	  qaMap[TString::Format("QA.%s",detName).Data()]=treeQARefDet;
	  treeQARefDet->AddFriend(treeQADet, "QADet");
	  treeQADet->AddFriend(treeQARefDet,  TString::Format("QA.%s",detName).Data());
	  runCounter[treeCounter++]=treeQADet->Draw("run","1","goff");
	}else{
	  ::Error("qaTrending.InitTrees","Missing Tree QA.%s - check the syntax",detName);
	}
      }
    }
  }
  //
  // Check consistency of data
  //
  ::Info("qaTrending::InitTrees::End","Checking trees");
  TList *arrFriends = treeQADet->GetListOfFriends();
  for (Int_t ifriend=0; ifriend<arrFriends->GetEntries(); ifriend++){
    Int_t entries = treeQADet->Draw(TString::Format("run-%s.run", arrFriends->At(ifriend)->GetName()).Data(),"1","goff");
    Double_t mean=0;
    if (entries>0) {
      mean=TMath::Mean(entries, treeQADet->GetV1());
    }
    if (mean==0){
      ::Info("qaTrending::InitTrees", "Friend:\t%s\t%d\t%f", arrFriends->At(ifriend)->GetName(), entries,mean);
    }else{
      ::Error("qaTrending::InitTrees", "Friend:\t%s\t%d\t%f", arrFriends->At(ifriend)->GetName(), entries,mean);
    }
  }
  delete detArray;
  ::Info("qaTrending::InitTrees::End","Detector %s, RefDet=%s",detector, referenceDet);

  return treeQADet;
}

void SetDrawStyle(){
  //
  // Standard drawing style
  //
  gROOT->SetStyle("Plain");
  gStyle->SetPalette(1);
  gStyle->SetLabelSize(0.04,"x");
  gStyle->SetPadTickX(1);
  gStyle->SetPadTickY(1);
}

TObjArray * GetTexDescription(TLatex *latex){
  //
  //
  //
  TObjArray * description= new TObjArray();
  TString sTimestamp  = TString::Format("Creation time:%s",gSystem->GetFromPipe("date").Data());
  TString sUser=TString::Format("User:%s",gSystem->GetFromPipe("echo $USER").Data());
  TString sPeriod=TString::Format("period:%s",period);
  TString sPass=TString::Format("pass:%s",pass);
  TString sAlirootVer;
  TString sAliphysicsVer;
  //TString runStat=
  if (gSystem->GetFromPipe("echo $ALICE_VER") == "master" || gSystem->GetFromPipe("echo $ALICE_VER") == ""){
    sAlirootVer = "AliRoot: " + gSystem->GetFromPipe("wdir=`pwd`; cd $ALICE_ROOT/../src; git describe; cd $wdir;");
  }else {
    sAlirootVer = "AliRoot: " + gSystem->GetFromPipe("echo $ALIROOT_VERSION");
  }
  if (gSystem->GetFromPipe("echo $ALIPHYSICS_VER") == "master" || gSystem->GetFromPipe("echo $ALIPHYSICS_VER") == ""){
    sAliphysicsVer = "AliPhysics: " + gSystem->GetFromPipe("wdir=`pwd`; cd $ALICE_PHYSICS/../src; git describe; cd $wdir;");
  }else {
    sAliphysicsVer = "AliPhysics: " + gSystem->GetFromPipe("echo $ALIPHYSICS_VERSION");
  }
  //
  description->AddLast(latex->DrawLatexNDC(latex->GetX(), latex->GetY(),sTimestamp.Data()));
  description->AddLast(latex->DrawLatexNDC(latex->GetX(), latex->GetY()-1.1*latex->GetTextSize(),sUser.Data()));
  description->AddLast(latex->DrawLatexNDC(latex->GetX(), latex->GetY()-2.2*latex->GetTextSize(),sPeriod.Data()));
  description->AddLast(latex->DrawLatexNDC(latex->GetX(), latex->GetY()-3.3*latex->GetTextSize(),sPass.Data()));
  description->AddLast(latex->DrawLatexNDC(latex->GetX(), latex->GetY()-4.4*latex->GetTextSize(),sAlirootVer.Data()));
  description->AddLast(latex->DrawLatexNDC(latex->GetX(), latex->GetY()-5.5*latex->GetTextSize(),sAliphysicsVer.Data()));
  return description;
}

void logbookConfig(TTree * tree){
  //
  //
  //
  TStatToolkit::AddMetadata(tree,"totalEvents.Title","N_{events}");
  TStatToolkit::AddMetadata(tree,"totalEvents.AxisTitle","N_{events}");
  TStatToolkit::AddMetadata(tree,"totalEvents.Legend","logbook - N_{events}");
  TStatToolkit::AddMetadata(tree,"totalEventsPhysics.Title","N_{phys.ev.}");
  TStatToolkit::AddMetadata(tree,"totalEventsPhysics.AxisTitle","N_{phys.ev.}");
  TStatToolkit::AddMetadata(tree,"totalEventsPhysics.Legend","logbook - N_{phys.ev.}");
  //
  TStatToolkit::AddMetadata(tree,"LogbookDet.eventCountPhysics.Title","T0 - N_{events}");
  TStatToolkit::AddMetadata(tree,"LogbookT0.eventCountPhysics.AxisTitle","T0 - N_{events}");
  TStatToolkit::AddMetadata(tree,"LogbookT0.eventCountPhysics.Legend","T0 - N_{events}");
  TStatToolkit::AddMetadata(tree,"LogbookTPC.eventCountPhysics.Title","TPC - N_{events}");
  TStatToolkit::AddMetadata(tree,"LogbookTPC.eventCountPhysics.AxisTitle","TPC - N_{events}");
  TStatToolkit::AddMetadata(tree,"LogbookTPC.eventCountPhysics.Legend","TPC - N_{events}");
}

void InitSummaryTrending(TTree * tree){
  //
  // Init drawing for the <detector> QA
  // Detector specific qaConfig() has to be called before invoking this function
  //    0.) Make descriptor
  //    1.) Make default canvas - addopt canvas width to the number of entries to draw
  //    3.) compute detector  status graphs

  //
  //   0.) Make descriptor
  //
  TLatex *latex= new TLatex;
  latex->SetX(0.11);
  latex->SetY(0.8);
  latex->SetTextSize(0.03);
  descriptionQA = GetTexDescription(latex);
  //
  //   1.) Make default canvas - addopt canvas width to the number of entries to draw
  //
  TGraphErrors *gr = (TGraphErrors*) TStatToolkit::MakeGraphSparse(tree,"resolution:tagID","");
  Int_t numberOfTags = gr->GetN();
  cout<<"number of graph entries: "<<numberOfTags<<endl;
  double SpaceForLegend = 0.;
  Int_t canvas_width  = SpaceForLegend + (numberOfTags+5)*30;
  Int_t canvas_height = 600;
  if ( canvas_width>kMaxCanvasWidth)   canvas_width=kMaxCanvasWidth;
  canvasQA = new TCanvas("canvasQA","canvasQA",canvas_width,canvas_height);
  canvasQA->SetGrid(3);
  canvasQA->cd();
  gPad->SetTicks(1,2);
  // canvasQA->SetRightMargin(SpaceForLegend/canvas_width);
  double leftlegend  = 1 - 180./canvasQA->GetWw();
  double rightlegend = 1 - 10./canvasQA->GetWw();
  //
  // 2.) process config file qaConfig.C to initialize status aliases (outliers etc.), status bar criteria, status lines, ...
  //
  TString sStatusbarVars  = statusDescription[0];
  TString sStatusbarNames = statusDescription[1];
  TString sCriteria       = statusDescription[2];
  cout << "sStatusbarVars = " << sStatusbarVars.Data() << endl;
  cout << "sCriteria      = " << sCriteria.Data() << endl;
  //
  // 3.) compute detector status graphs
  //
  TObjArray* oaStatusbarVars = sStatusbarVars.Tokenize(";");
  TObjArray* oaStatusbarNames = sStatusbarNames.Tokenize(";");
  oaMultGr = new TObjArray();
  int igr=0;
  for (Int_t vari=oaStatusbarVars->GetEntriesFast()-1; vari>=0; vari--){ // invert the order of the status graphs
    TString sVar = Form("%s:tagID", oaStatusbarVars->At(vari)->GetName()); //e.g. -> dcar:run
    oaMultGr->Add( TStatToolkit::MakeStatusMultGr(tree, sVar.Data(),  "", sCriteria.Data(), igr) );
    TString sYtitle = oaStatusbarNames->At(vari)->GetName(); // set better name for y axis of statuspad
    ((TMultiGraph*) oaMultGr->At(igr))->SetTitle(sYtitle.Data());
    igr++;
  }
}
<commit_msg> ATO-360 - removing metdata part. Defined in another macro<commit_after>/*
  Steering macro for the Detector/<action> trending

  //
  // code to check consitency
  //
  gSystem->SetIncludePath("-I$ROOTSYS/include -I$ALICE_ROOT/ -I$ALICE_ROOT/include -I$ALICE_ROOT/install/include -I$ALICE_ROOT/STEER\
   -I$ALICE_ROOT/TPC -I$ALICE_ROOT/ITS -I$ALICE_ROOT/TRD -I$ALICE_ROOT/TOF -I$ALICE_ROOT/RAW  -I$ALICE_ROOT/STAT -I$ALICE_ROOT/TPC/TPCBase  -I$ALICE_ROOT/TPC/TPCRec -I$ALICE_ROOT/TPC/TPCCalib -I$ALICE_PHYSICS/../src/PWGPP/TPC/");
  .L $ALICE_PHYSICS/../src/PWGPP/QA/scripts/qaTrending.C+
  period="LHC15o";
  pass="cpass1_pass1";
  detector="T0";
  referenceDet="ITS;TPC;TRD;TOF";

  treeQADet=InitTrees(detector,referenceDet);
  treeQADet->SetAlias("tagID","run");
  InitSummaryTrending(treeQADet);

*/

#include "TTree.h"
#include "TString.h"
#include "TStatToolkit.h"
#include "AliExternalInfo.h"
#include "TStyle.h"
#include "TROOT.h"
#include "TMultiGraph.h"
#include "TMath.h"
#include "TLegend.h"

TTree * InitTrees(const char * detector,   const char * referenceDet);    // load QA trees and Sttering tree <det>   QA.<Det>, Logbook, Lo
void    InitSummaryTrending(TTree * tree);                     // can be generic ?
void    SetDrawStyle();                                        // setting Default draw style
TObjArray * GetTexDescription(TLatex *latex);                  // should go to base code

//
// Macro global variables:
//
char * year=0, *period=0, *pass=0;
TTree * treeQADet=0;
std::map<std::string,TTree*> qaMap;
TCanvas *canvasQA=0;          // central canvas for QA plots
TObjArray * descriptionQA=0;  // descriptionQA of process  (time/aliroot/root/pariod/pass/user)
TObjArray*   oaMultGr=0;      // status bar multigraph
TString      statusDescription[3];   // status bar description

//
//
// Drawing configuration can be changed
//
// colors & markers:
Int_t colPosA=kGreen+2; //kRed;
Int_t colPosC=kMagenta+1; //kAzure-4;
Int_t colNegA=kRed; //kRed;//kOrange;
Int_t colNegC=kAzure-4; //kAzure-4;//kGreen;
Int_t colSum=kBlack;
Int_t marA1=21;
Int_t marA2=24;
Int_t marC1=20;
Int_t marC2=25;
Int_t marSum=34;//full cross
Int_t marCorr=31;//snowflake
Float_t markerSize=0.9;
const char * defColors="1;2;4;3;856;616";
const char * defMarkers="21;22;25;26;27;28";
const char * bandColors="1;400;400;632;632;416;416"; // kBlack;kYellow;kYellow;kRed; kRed; kGreeen; kGreen
// shifting of graphs within one run for better visibility:
Float_t sh_gr0=-0.3;
Float_t sh_gr1=-0.1;
Float_t sh_gr2=+0.1;
Float_t sh_gr3=+0.3;
// maximal canvas width
Int_t kMaxCanvasWidth=2500;
// status bar height
Float_t statPadHeight=0.30; //fraction of canvas height (was 0.25 until Aug 2014)
Float_t statPadBotMar=0.40; //bottom margin of pad for run numbers
Int_t   padRightMargin=0.07;

void qaTrending(){
}

TTree * InitTrees(const char * detector,  const char *referenceDet){
  //
  // Init tree for given period
  //  all  trees stored in qaMap
  //  FriendTree added to the master treeQADet
  // Currentrly in the code we assume ID="run";
  // Bug in root tree ?  - in case more than one friend tree set - indeces looks corrupted
  //    0.) QA tree per detector Raw+MC (if exist)
  //    1.) QA trees per refernce detectors specified by string refDet e.g "TPC;TRD;TOF"
  //    2.) Logbook tree per run
  //    3.) Logbook tree per run/detector
  //    3.) RCT table
  //    4.) CPass table
  //
  //  tree is created with addition of friend trees which can be used in queries
  //  queries as analog to the SQL statement

  /*
    period="LHC15o"; pass="cpass1_pass1"
  */
  ::Info("qaTrending::InitTrees::Begin","Detector %s, RefDet=%s",detector, referenceDet);
  AliExternalInfo info;
  Int_t treeCounter=0;
  // Load trees
  TObjArray * detArray=TString(referenceDet).Tokenize(";");
  Int_t nrefDets=detArray->GetEntries();
  TVectorF runCounter(5+nrefDets*2);  // <QADet>, <Logbook>, <Logbook.Det>, <MonAlisa>, <CPass>, <QA.RefDet>xnrefDets, <Logbook.RefDet>xnrefDets
  //
  ::Info("qaTrending::InitTrees::End","Laoding trees");
  treeQADet = info.GetTreeDataQA(detector,period, pass);
  if (!treeQADet){
    ::Error("qaTrending.InitTrees", "Input QA tree %s not available", detector);
    return 0;
  }
  runCounter[treeCounter++]=treeQADet->Draw("run","1","goff");
  qaMap[TString::Format("QA.%s",detector).Data()]=treeQADet;
  //
  qaMap["Logbook"]=info.GetTree("Logbook",period,"");
  qaMap["Logbook"]->AddFriend(treeQADet,"QADet");
  treeQADet->AddFriend(qaMap["Logbook"],"Logbook");
  runCounter[treeCounter++]=treeQADet->Draw("run","1","goff");
  //
  qaMap["MonALISA.RCT"]=info.GetTree("MonALISA.RCT",period,pass);
  qaMap["MonALISA.RCT"]->AddFriend(treeQADet,"QADet");
  treeQADet->AddFriend(qaMap["MonALISA.RCT"],"MonALISA.RCT");
  runCounter[treeCounter++]=treeQADet->Draw("run","1","goff");
  //
  TTree *treeLogbookDetector =info.GetTree("Logbook.detector",period,"");
  if (treeLogbookDetector){
    if (detArray->GetEntries()>0){
      for (Int_t idet=0; idet<detArray->GetEntries(); idet++){
	// Load Logbook.RefDet
	const char *detName=detArray->At(idet)->GetName();
	TTree * treeLog =treeLogbookDetector->CopyTree(TString::Format("detector==\"%s\"",detName).Data());
	if (treeLog->GetEntries()<=0){
	  ::Error("qaTrending.InitTrees","Missing Tree Logbook. %s - check the syntax",detName);
	}else{
	  treeLog->BuildIndex("run");
	  qaMap[TString::Format("Logbook.%s",detName).Data()]=treeLog;
	  treeLog->AddFriend(treeQADet, "QADet");
	  treeQADet->AddFriend(treeLog,  TString::Format("Logbook.%s",detName).Data());
	  runCounter[treeCounter++]=treeQADet->Draw("run","1","goff");
	}
	// Load QA.RefDet
	TTree * treeQARefDet = info.GetTreeDataQA(detName,period, pass);
	if (treeQARefDet){
	  qaMap[TString::Format("QA.%s",detName).Data()]=treeQARefDet;
	  treeQARefDet->AddFriend(treeQADet, "QADet");
	  treeQADet->AddFriend(treeQARefDet,  TString::Format("QA.%s",detName).Data());
	  runCounter[treeCounter++]=treeQADet->Draw("run","1","goff");
	}else{
	  ::Error("qaTrending.InitTrees","Missing Tree QA.%s - check the syntax",detName);
	}
      }
    }
  }
  //
  // Check consistency of data
  //
  ::Info("qaTrending::InitTrees::End","Checking trees");
  TList *arrFriends = treeQADet->GetListOfFriends();
  for (Int_t ifriend=0; ifriend<arrFriends->GetEntries(); ifriend++){
    Int_t entries = treeQADet->Draw(TString::Format("run-%s.run", arrFriends->At(ifriend)->GetName()).Data(),"1","goff");
    Double_t mean=0;
    if (entries>0) {
      mean=TMath::Mean(entries, treeQADet->GetV1());
    }
    if (mean==0){
      ::Info("qaTrending::InitTrees", "Friend:\t%s\t%d\t%f", arrFriends->At(ifriend)->GetName(), entries,mean);
    }else{
      ::Error("qaTrending::InitTrees", "Friend:\t%s\t%d\t%f", arrFriends->At(ifriend)->GetName(), entries,mean);
    }
  }
  delete detArray;
  ::Info("qaTrending::InitTrees::End","Detector %s, RefDet=%s",detector, referenceDet);

  return treeQADet;
}

void SetDrawStyle(){
  //
  // Standard drawing style
  //
  gROOT->SetStyle("Plain");
  gStyle->SetPalette(1);
  gStyle->SetLabelSize(0.04,"x");
  gStyle->SetPadTickX(1);
  gStyle->SetPadTickY(1);
}

TObjArray * GetTexDescription(TLatex *latex){
  //
  //
  //
  TObjArray * description= new TObjArray();
  TString sTimestamp  = TString::Format("Creation time:%s",gSystem->GetFromPipe("date").Data());
  TString sUser=TString::Format("User:%s",gSystem->GetFromPipe("echo $USER").Data());
  TString sPeriod=TString::Format("period:%s",period);
  TString sPass=TString::Format("pass:%s",pass);
  TString sAlirootVer;
  TString sAliphysicsVer;
  //TString runStat=
  if (gSystem->GetFromPipe("echo $ALICE_VER") == "master" || gSystem->GetFromPipe("echo $ALICE_VER") == ""){
    sAlirootVer = "AliRoot: " + gSystem->GetFromPipe("wdir=`pwd`; cd $ALICE_ROOT/../src; git describe; cd $wdir;");
  }else {
    sAlirootVer = "AliRoot: " + gSystem->GetFromPipe("echo $ALIROOT_VERSION");
  }
  if (gSystem->GetFromPipe("echo $ALIPHYSICS_VER") == "master" || gSystem->GetFromPipe("echo $ALIPHYSICS_VER") == ""){
    sAliphysicsVer = "AliPhysics: " + gSystem->GetFromPipe("wdir=`pwd`; cd $ALICE_PHYSICS/../src; git describe; cd $wdir;");
  }else {
    sAliphysicsVer = "AliPhysics: " + gSystem->GetFromPipe("echo $ALIPHYSICS_VERSION");
  }
  //
  description->AddLast(latex->DrawLatexNDC(latex->GetX(), latex->GetY(),sTimestamp.Data()));
  description->AddLast(latex->DrawLatexNDC(latex->GetX(), latex->GetY()-1.1*latex->GetTextSize(),sUser.Data()));
  description->AddLast(latex->DrawLatexNDC(latex->GetX(), latex->GetY()-2.2*latex->GetTextSize(),sPeriod.Data()));
  description->AddLast(latex->DrawLatexNDC(latex->GetX(), latex->GetY()-3.3*latex->GetTextSize(),sPass.Data()));
  description->AddLast(latex->DrawLatexNDC(latex->GetX(), latex->GetY()-4.4*latex->GetTextSize(),sAlirootVer.Data()));
  description->AddLast(latex->DrawLatexNDC(latex->GetX(), latex->GetY()-5.5*latex->GetTextSize(),sAliphysicsVer.Data()));
  return description;
}

void InitSummaryTrending(TTree * tree){
  //
  // Init drawing for the <detector> QA
  // Detector specific qaConfig() has to be called before invoking this function
  //    0.) Make descriptor
  //    1.) Make default canvas - addopt canvas width to the number of entries to draw
  //    3.) compute detector  status graphs

  //
  //   0.) Make descriptor
  //
  TLatex *latex= new TLatex;
  latex->SetX(0.11);
  latex->SetY(0.8);
  latex->SetTextSize(0.03);
  descriptionQA = GetTexDescription(latex);
  //
  //   1.) Make default canvas - addopt canvas width to the number of entries to draw
  //
  TGraphErrors *gr = (TGraphErrors*) TStatToolkit::MakeGraphSparse(tree,"resolution:tagID","");
  Int_t numberOfTags = gr->GetN();
  cout<<"number of graph entries: "<<numberOfTags<<endl;
  double SpaceForLegend = 0.;
  Int_t canvas_width  = SpaceForLegend + (numberOfTags+5)*30;
  Int_t canvas_height = 600;
  if ( canvas_width>kMaxCanvasWidth)   canvas_width=kMaxCanvasWidth;
  canvasQA = new TCanvas("canvasQA","canvasQA",canvas_width,canvas_height);
  canvasQA->SetGrid(3);
  canvasQA->cd();
  gPad->SetTicks(1,2);
  // canvasQA->SetRightMargin(SpaceForLegend/canvas_width);
  double leftlegend  = 1 - 180./canvasQA->GetWw();
  double rightlegend = 1 - 10./canvasQA->GetWw();
  //
  // 2.) process config file qaConfig.C to initialize status aliases (outliers etc.), status bar criteria, status lines, ...
  //
  TString sStatusbarVars  = statusDescription[0];
  TString sStatusbarNames = statusDescription[1];
  TString sCriteria       = statusDescription[2];
  cout << "sStatusbarVars = " << sStatusbarVars.Data() << endl;
  cout << "sCriteria      = " << sCriteria.Data() << endl;
  //
  // 3.) compute detector status graphs
  //
  TObjArray* oaStatusbarVars = sStatusbarVars.Tokenize(";");
  TObjArray* oaStatusbarNames = sStatusbarNames.Tokenize(";");
  oaMultGr = new TObjArray();
  int igr=0;
  for (Int_t vari=oaStatusbarVars->GetEntriesFast()-1; vari>=0; vari--){ // invert the order of the status graphs
    TString sVar = Form("%s:tagID", oaStatusbarVars->At(vari)->GetName()); //e.g. -> dcar:run
    oaMultGr->Add( TStatToolkit::MakeStatusMultGr(tree, sVar.Data(),  "", sCriteria.Data(), igr) );
    TString sYtitle = oaStatusbarNames->At(vari)->GetName(); // set better name for y axis of statuspad
    ((TMultiGraph*) oaMultGr->At(igr))->SetTitle(sYtitle.Data());
    igr++;
  }
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011, Alexandru-Eugen Ichim
 *                      Willow Garage, Inc
 *  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 Willow Garage, Inc. 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.
 *
 *  $Id$
 */

#ifndef PCL_FEATURES_IMPL_MULTISCALE_FEATURE_PERSISTENCE_H_
#define PCL_FEATURES_IMPL_MULTISCALE_FEATURE_PERSISTENCE_H_

#include "pcl/features/multiscale_feature_persistence.h"

template <typename PointSource, typename PointFeature>
pcl::MultiscaleFeaturePersistence<PointSource, PointFeature>::MultiscaleFeaturePersistence ()
  : distance_metric_ (MANHATTAN),
    feature_estimator_ ()
{
  feature_representation_.reset (new DefaultPointRepresentation<PointFeature>);
  // No input is needed, hack around the initCompute () check from PCLBase
  input_.reset (new PointCloud<PointSource> ());
};

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointSource, typename PointFeature> bool
pcl::MultiscaleFeaturePersistence<PointSource, PointFeature>::initCompute ()
{
  if (!PCLBase<PointSource>::initCompute ())
  {
    PCL_ERROR ("[pcl::MultiscaleFeaturePersistence::initCompute] PCLBase::initCompute () failed - no input cloud was given.\n");
    return false;
  }
  if (!feature_estimator_)
  {
    PCL_ERROR ("[pcl::MultiscaleFeaturePersistence::initCompute] No feature estimator was set\n");
    return false;
  }
  if (scale_values_.empty ())
  {
    PCL_ERROR ("[pcl::MultiscaleFeaturePersistence::initCompute] No scale values were given\n");
    return false;
  }

  mean_feature.resize (feature_representation_->getNumberOfDimensions ());

  return true;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointSource, typename PointFeature> void
pcl::MultiscaleFeaturePersistence<PointSource, PointFeature>::computeFeaturesAtAllScales ()
{
  features_at_scale.resize (scale_values_.size ());
  features_at_scale_vectorized.resize (scale_values_.size ());
  for (size_t scale_i = 0; scale_i < scale_values_.size (); ++scale_i)
  {
    FeatureCloudPtr feature_cloud (new FeatureCloud ());
    computeFeatureAtScale (scale_values_[scale_i], feature_cloud);
    features_at_scale[scale_i] = feature_cloud;

    // Vectorize each feature and insert it into the vectorized feature storage
    std::vector<std::vector<float> > feature_cloud_vectorized (feature_cloud->points.size ());
    for (size_t feature_i = 0; feature_i < feature_cloud->points.size (); ++feature_i)
    {
      std::vector<float> feature_vectorized (feature_representation_->getNumberOfDimensions ());
      feature_representation_->vectorize (feature_cloud->points[feature_i], feature_vectorized);
      feature_cloud_vectorized[feature_i] = feature_vectorized;
    }
    features_at_scale_vectorized[scale_i] = feature_cloud_vectorized;
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointSource, typename PointFeature> void
pcl::MultiscaleFeaturePersistence<PointSource, PointFeature>::computeFeatureAtScale (float &scale,
                                                                                FeatureCloudPtr &features)
{
   feature_estimator_->setRadiusSearch (scale);
   feature_estimator_->compute (*features);
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointSource, typename PointFeature> float
pcl::MultiscaleFeaturePersistence<PointSource, PointFeature>::distanceBetweenFeatures (const std::vector<float> &a,
                                                                                const std::vector<float> &b)
{
  float dist = 0.0f;

  switch (distance_metric_)
  {
    case (MANHATTAN):
    {
      for (size_t i = 0; i < a.size (); ++i)
        dist += fabs (a[i] - b[i]);
      break;
    }

    case (EUCLIDEAN):
    {
      for (size_t i = 0; i < a.size (); ++i)
        dist += (a[i] - b[i]) * (a[i] - b[i]);
      dist = sqrt (dist);
      break;
    }

    case (JEFFRIES_MATUSITA):
    {
      for (size_t i = 0; i < a.size (); ++i)
        dist += (sqrt ( fabs (a[i])) - sqrt ( fabs (b[i]))) * (sqrt (fabs (a[i])) - sqrt ( fabs (b[i])));
      dist = sqrt (dist);
      break;
    }

    case (BHATTACHARYYA):
    {
      for (size_t i = 0; i < a.size (); ++i)
        dist += sqrt (fabs (a[i] - b[i]));
      dist = -log (dist);
      break;
    }

    case (CHI_SQUARE):
    {
      for (size_t i = 0; i < a.size (); ++i)
        dist += (a[i] - b[i]) * (a[i] - b[i]) / (a[i] + b[i]);
      break;
    }

    case (KL_DIVERGENCE):
    {
      for (size_t i = 0; i < a.size (); ++i)
        dist += (a[i] - b[i]) * log (a[i] / b[i]);
      break;
    }
  }

  return dist;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointSource, typename PointFeature> void
pcl::MultiscaleFeaturePersistence<PointSource, PointFeature>::calculateMeanFeature ()
{
  // Reset mean feature
  for (int i = 0; i < feature_representation_->getNumberOfDimensions (); ++i)
    mean_feature[i] = 0.0f;

  float normalization_factor = 0.0f;
  for (std::vector<std::vector<std::vector<float> > >::iterator scale_it = features_at_scale_vectorized.begin (); scale_it != features_at_scale_vectorized.end(); ++scale_it) {
    normalization_factor += scale_it->size ();
    for (std::vector<std::vector<float> >::iterator feature_it = scale_it->begin (); feature_it != scale_it->end (); ++feature_it)
      for (int dim_i = 0; dim_i < feature_representation_->getNumberOfDimensions (); ++dim_i)
        mean_feature[dim_i] += (*feature_it)[dim_i];
  }

  for (int dim_i = 0; dim_i < feature_representation_->getNumberOfDimensions (); ++dim_i)
    mean_feature[dim_i] /= normalization_factor;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointSource, typename PointFeature> void
pcl::MultiscaleFeaturePersistence<PointSource, PointFeature>::extractUniqueFeatures ()
{
  unique_features_indices.resize (scale_values_.size ());
  unique_features_table.resize (scale_values_.size ());
  for (size_t scale_i = 0; scale_i < features_at_scale_vectorized.size (); ++scale_i)
  {
    // Calculate standard deviation within the scale
    float standard_dev = 0.0;
    std::vector<float> diff_vector (features_at_scale_vectorized[scale_i].size ());
    for (size_t point_i = 0; point_i < features_at_scale_vectorized[scale_i].size (); ++point_i)
    {
      float diff = distanceBetweenFeatures (features_at_scale_vectorized[scale_i][point_i], mean_feature);
      standard_dev += diff * diff;
      diff_vector[point_i] = diff;
    }
    standard_dev = sqrt (standard_dev / features_at_scale_vectorized[scale_i].size ());
    PCL_INFO("Standard deviation for scale %f is %f\n", scale_values_[scale_i], standard_dev);

    // Select only points outside (mean +/- alpha * standard_dev)
    std::list<size_t> indices_per_scale;
    std::vector<bool> indices_table_per_scale (features_at_scale[scale_i]->points.size (), false);
    for (size_t point_i = 0; point_i < features_at_scale[scale_i]->points.size (); ++point_i)
    {
      if (diff_vector[point_i] > alpha_ * standard_dev)
      {
        indices_per_scale.push_back (point_i);
        indices_table_per_scale[point_i] = true;
      }
    }
    unique_features_indices[scale_i] = indices_per_scale;
    unique_features_table[scale_i] = indices_table_per_scale;
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointSource, typename PointFeature> void
pcl::MultiscaleFeaturePersistence<PointSource, PointFeature>::determinePersistentFeatures (FeatureCloud &output_features,
                                                                                boost::shared_ptr<std::vector<int> > &output_indices)
{
  if (!initCompute ())
    return;

  // Compute the features for all scales with the given feature estimator
  computeFeaturesAtAllScales ();

  // Compute mean feature
  calculateMeanFeature ();

  // Get the 'unique' features at each scale
  extractUniqueFeatures ();

  // Determine persistent features between scales

/*
  // Method 1: a feature is considered persistent if it is 'unique' in at least 2 different scales
  for (size_t scale_i = 0; scale_i < features_at_scale_vectorized.size () - 1; ++scale_i)
    for (std::list<size_t>::iterator feature_it = unique_features_indices[scale_i].begin (); feature_it != unique_features_indices[scale_i].end (); ++feature_it)
    {
      if (unique_features_table[scale_i][*feature_it] == true)
      {
        output_features.points.push_back (features_at_scale[scale_i]->points[*feature_it]);
        output_indices->push_back (*feature_it);
      }
    }
*/
  // Method 2: a feature is considered persistent if it is 'unique' in all the scales
  for (std::list<size_t>::iterator feature_it = unique_features_indices.front ().begin (); feature_it != unique_features_indices.front ().end (); ++feature_it)
  {
    bool present_in_all = true;
    for (size_t scale_i = 0; scale_i < features_at_scale.size (); ++scale_i)
      present_in_all = present_in_all && unique_features_table[scale_i][*feature_it];

    if (present_in_all)
    {
      output_features.points.push_back (features_at_scale.front ()->points[*feature_it]);
      output_indices->push_back (*feature_it);
    }
  }

  // Consider that output cloud is unorganized
  output_features.header = feature_estimator_->getInputCloud ()->header;
  output_features.is_dense = feature_estimator_->getInputCloud ()->is_dense;
  output_features.width = output_features.points.size ();
  output_features.height = 1;
}

#define PCL_INSTANTIATE_MultiscaleFeaturePersistence(InT, Feature) template class PCL_EXPORTS pcl::MultiscaleFeaturePersistence<InT, Feature>;

#endif /* PCL_FEATURES_IMPL_MULTISCALE_FEATURE_PERSISTENCE_H_ */
<commit_msg>MSVC fix(?)<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011, Alexandru-Eugen Ichim
 *                      Willow Garage, Inc
 *  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 Willow Garage, Inc. 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.
 *
 *  $Id$
 */

#ifndef PCL_FEATURES_IMPL_MULTISCALE_FEATURE_PERSISTENCE_H_
#define PCL_FEATURES_IMPL_MULTISCALE_FEATURE_PERSISTENCE_H_

#include "pcl/features/multiscale_feature_persistence.h"

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointSource, typename PointFeature>
pcl::MultiscaleFeaturePersistence<PointSource, PointFeature>::MultiscaleFeaturePersistence ()
  : distance_metric_ (MANHATTAN),
    feature_estimator_ ()
{
  feature_representation_.reset (new DefaultPointRepresentation<PointFeature>);
  // No input is needed, hack around the initCompute () check from PCLBase
  input_.reset (new pcl::PointCloud<PointSource> ());
};

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointSource, typename PointFeature> bool
pcl::MultiscaleFeaturePersistence<PointSource, PointFeature>::initCompute ()
{
  if (!PCLBase<PointSource>::initCompute ())
  {
    PCL_ERROR ("[pcl::MultiscaleFeaturePersistence::initCompute] PCLBase::initCompute () failed - no input cloud was given.\n");
    return false;
  }
  if (!feature_estimator_)
  {
    PCL_ERROR ("[pcl::MultiscaleFeaturePersistence::initCompute] No feature estimator was set\n");
    return false;
  }
  if (scale_values_.empty ())
  {
    PCL_ERROR ("[pcl::MultiscaleFeaturePersistence::initCompute] No scale values were given\n");
    return false;
  }

  mean_feature.resize (feature_representation_->getNumberOfDimensions ());

  return true;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointSource, typename PointFeature> void
pcl::MultiscaleFeaturePersistence<PointSource, PointFeature>::computeFeaturesAtAllScales ()
{
  features_at_scale.resize (scale_values_.size ());
  features_at_scale_vectorized.resize (scale_values_.size ());
  for (size_t scale_i = 0; scale_i < scale_values_.size (); ++scale_i)
  {
    FeatureCloudPtr feature_cloud (new FeatureCloud ());
    computeFeatureAtScale (scale_values_[scale_i], feature_cloud);
    features_at_scale[scale_i] = feature_cloud;

    // Vectorize each feature and insert it into the vectorized feature storage
    std::vector<std::vector<float> > feature_cloud_vectorized (feature_cloud->points.size ());
    for (size_t feature_i = 0; feature_i < feature_cloud->points.size (); ++feature_i)
    {
      std::vector<float> feature_vectorized (feature_representation_->getNumberOfDimensions ());
      feature_representation_->vectorize (feature_cloud->points[feature_i], feature_vectorized);
      feature_cloud_vectorized[feature_i] = feature_vectorized;
    }
    features_at_scale_vectorized[scale_i] = feature_cloud_vectorized;
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointSource, typename PointFeature> void
pcl::MultiscaleFeaturePersistence<PointSource, PointFeature>::computeFeatureAtScale (float &scale,
                                                                                FeatureCloudPtr &features)
{
   feature_estimator_->setRadiusSearch (scale);
   feature_estimator_->compute (*features);
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointSource, typename PointFeature> float
pcl::MultiscaleFeaturePersistence<PointSource, PointFeature>::distanceBetweenFeatures (const std::vector<float> &a,
                                                                                const std::vector<float> &b)
{
  float dist = 0.0f;

  switch (distance_metric_)
  {
    case (MANHATTAN):
    {
      for (size_t i = 0; i < a.size (); ++i)
        dist += fabs (a[i] - b[i]);
      break;
    }

    case (EUCLIDEAN):
    {
      for (size_t i = 0; i < a.size (); ++i)
        dist += (a[i] - b[i]) * (a[i] - b[i]);
      dist = sqrt (dist);
      break;
    }

    case (JEFFRIES_MATUSITA):
    {
      for (size_t i = 0; i < a.size (); ++i)
        dist += (sqrt ( fabs (a[i])) - sqrt ( fabs (b[i]))) * (sqrt (fabs (a[i])) - sqrt ( fabs (b[i])));
      dist = sqrt (dist);
      break;
    }

    case (BHATTACHARYYA):
    {
      for (size_t i = 0; i < a.size (); ++i)
        dist += sqrt (fabs (a[i] - b[i]));
      dist = -log (dist);
      break;
    }

    case (CHI_SQUARE):
    {
      for (size_t i = 0; i < a.size (); ++i)
        dist += (a[i] - b[i]) * (a[i] - b[i]) / (a[i] + b[i]);
      break;
    }

    case (KL_DIVERGENCE):
    {
      for (size_t i = 0; i < a.size (); ++i)
        dist += (a[i] - b[i]) * log (a[i] / b[i]);
      break;
    }
  }

  return dist;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointSource, typename PointFeature> void
pcl::MultiscaleFeaturePersistence<PointSource, PointFeature>::calculateMeanFeature ()
{
  // Reset mean feature
  for (int i = 0; i < feature_representation_->getNumberOfDimensions (); ++i)
    mean_feature[i] = 0.0f;

  float normalization_factor = 0.0f;
  for (std::vector<std::vector<std::vector<float> > >::iterator scale_it = features_at_scale_vectorized.begin (); scale_it != features_at_scale_vectorized.end(); ++scale_it) {
    normalization_factor += scale_it->size ();
    for (std::vector<std::vector<float> >::iterator feature_it = scale_it->begin (); feature_it != scale_it->end (); ++feature_it)
      for (int dim_i = 0; dim_i < feature_representation_->getNumberOfDimensions (); ++dim_i)
        mean_feature[dim_i] += (*feature_it)[dim_i];
  }

  for (int dim_i = 0; dim_i < feature_representation_->getNumberOfDimensions (); ++dim_i)
    mean_feature[dim_i] /= normalization_factor;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointSource, typename PointFeature> void
pcl::MultiscaleFeaturePersistence<PointSource, PointFeature>::extractUniqueFeatures ()
{
  unique_features_indices.resize (scale_values_.size ());
  unique_features_table.resize (scale_values_.size ());
  for (size_t scale_i = 0; scale_i < features_at_scale_vectorized.size (); ++scale_i)
  {
    // Calculate standard deviation within the scale
    float standard_dev = 0.0;
    std::vector<float> diff_vector (features_at_scale_vectorized[scale_i].size ());
    for (size_t point_i = 0; point_i < features_at_scale_vectorized[scale_i].size (); ++point_i)
    {
      float diff = distanceBetweenFeatures (features_at_scale_vectorized[scale_i][point_i], mean_feature);
      standard_dev += diff * diff;
      diff_vector[point_i] = diff;
    }
    standard_dev = sqrt (standard_dev / features_at_scale_vectorized[scale_i].size ());
    PCL_INFO("Standard deviation for scale %f is %f\n", scale_values_[scale_i], standard_dev);

    // Select only points outside (mean +/- alpha * standard_dev)
    std::list<size_t> indices_per_scale;
    std::vector<bool> indices_table_per_scale (features_at_scale[scale_i]->points.size (), false);
    for (size_t point_i = 0; point_i < features_at_scale[scale_i]->points.size (); ++point_i)
    {
      if (diff_vector[point_i] > alpha_ * standard_dev)
      {
        indices_per_scale.push_back (point_i);
        indices_table_per_scale[point_i] = true;
      }
    }
    unique_features_indices[scale_i] = indices_per_scale;
    unique_features_table[scale_i] = indices_table_per_scale;
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointSource, typename PointFeature> void
pcl::MultiscaleFeaturePersistence<PointSource, PointFeature>::determinePersistentFeatures (FeatureCloud &output_features,
                                                                                boost::shared_ptr<std::vector<int> > &output_indices)
{
  if (!initCompute ())
    return;

  // Compute the features for all scales with the given feature estimator
  computeFeaturesAtAllScales ();

  // Compute mean feature
  calculateMeanFeature ();

  // Get the 'unique' features at each scale
  extractUniqueFeatures ();

  // Determine persistent features between scales

/*
  // Method 1: a feature is considered persistent if it is 'unique' in at least 2 different scales
  for (size_t scale_i = 0; scale_i < features_at_scale_vectorized.size () - 1; ++scale_i)
    for (std::list<size_t>::iterator feature_it = unique_features_indices[scale_i].begin (); feature_it != unique_features_indices[scale_i].end (); ++feature_it)
    {
      if (unique_features_table[scale_i][*feature_it] == true)
      {
        output_features.points.push_back (features_at_scale[scale_i]->points[*feature_it]);
        output_indices->push_back (*feature_it);
      }
    }
*/
  // Method 2: a feature is considered persistent if it is 'unique' in all the scales
  for (std::list<size_t>::iterator feature_it = unique_features_indices.front ().begin (); feature_it != unique_features_indices.front ().end (); ++feature_it)
  {
    bool present_in_all = true;
    for (size_t scale_i = 0; scale_i < features_at_scale.size (); ++scale_i)
      present_in_all = present_in_all && unique_features_table[scale_i][*feature_it];

    if (present_in_all)
    {
      output_features.points.push_back (features_at_scale.front ()->points[*feature_it]);
      output_indices->push_back (*feature_it);
    }
  }

  // Consider that output cloud is unorganized
  output_features.header = feature_estimator_->getInputCloud ()->header;
  output_features.is_dense = feature_estimator_->getInputCloud ()->is_dense;
  output_features.width = output_features.points.size ();
  output_features.height = 1;
}

#define PCL_INSTANTIATE_MultiscaleFeaturePersistence(InT, Feature) template class PCL_EXPORTS pcl::MultiscaleFeaturePersistence<InT, Feature>;

#endif /* PCL_FEATURES_IMPL_MULTISCALE_FEATURE_PERSISTENCE_H_ */
<|endoftext|>


<commit_before>#include "systemGenerator.h"

#include <generatorBase/generatorCustomizer.h>

using namespace trik::simple;
using namespace generatorBase::simple;

SystemGenerator::SystemGenerator(qrRepo::RepoApi const &repo
		, generatorBase::GeneratorCustomizer &customizer
		, qReal::Id const &id
		, QObject *parent)
	: BindingGenerator(repo, customizer, id
			, repo.property(id, "Code").toBool() ? "system.t" : "nativeCode.t"
			, QList<Binding *>()
					<< Binding::createDirect("@@COMMAND@@", "Command")
			, parent)
{
}
<commit_msg>Fixed inverted "Code" value in System Call block<commit_after>#include "systemGenerator.h"

#include <generatorBase/generatorCustomizer.h>

using namespace trik::simple;
using namespace generatorBase::simple;

SystemGenerator::SystemGenerator(qrRepo::RepoApi const &repo
		, generatorBase::GeneratorCustomizer &customizer
		, qReal::Id const &id
		, QObject *parent)
	: BindingGenerator(repo, customizer, id
			, repo.property(id, "Code").toBool() ? "nativeCode.t" : "system.t"
			, QList<Binding *>()
					<< Binding::createDirect("@@COMMAND@@", "Command")
			, parent)
{
}
<|endoftext|>