<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/
#ifndef itkImageToHistogramFilter_hxx
#define itkImageToHistogramFilter_hxx

#include "itkImageToHistogramFilter.h"
#include "itkImageRegionConstIterator.h"

namespace itk
{
namespace Statistics
{
template <typename TImage>
ImageToHistogramFilter<TImage>::ImageToHistogramFilter()
{
  this->SetNumberOfRequiredInputs(1);
  this->SetNumberOfRequiredOutputs(1);

  this->ProcessObject::SetNthOutput(0, this->MakeOutput(0));

  // same default values as in the HistogramGenerator

  this->Self::SetMarginalScale(100);

  if (typeid(ValueType) == typeid(signed char) || typeid(ValueType) == typeid(unsigned char))
  {
    this->Self::SetAutoMinimumMaximum(false);
  }
  else
  {
    this->Self::SetAutoMinimumMaximum(true);
  }
}

template <typename TImage>
DataObject::Pointer
ImageToHistogramFilter<TImage>::MakeOutput(DataObjectPointerArraySizeType itkNotUsed(idx))
{
  return HistogramType::New().GetPointer();
}

template <typename TImage>
const typename ImageToHistogramFilter<TImage>::HistogramType *
ImageToHistogramFilter<TImage>::GetOutput() const
{
  auto * output = itkDynamicCastInDebugMode<const HistogramType *>(this->ProcessObject::GetPrimaryOutput());

  return output;
}

template <typename TImage>
typename ImageToHistogramFilter<TImage>::HistogramType *
ImageToHistogramFilter<TImage>::GetOutput()
{

  auto * output = itkDynamicCastInDebugMode<HistogramType *>(this->ProcessObject::GetPrimaryOutput());

  return output;
}

template <typename TImage>
void
ImageToHistogramFilter<TImage>::GraftOutput(DataObject * graft)
{
  DataObject * output = const_cast<HistogramType *>(this->GetOutput());

  // Call Histogram to copy meta-information, and the container
  output->Graft(graft);
}

template <typename TImage>
unsigned int
ImageToHistogramFilter<TImage>::GetNumberOfInputRequestedRegions()
{
  // If we need to compute the minimum and maximum we don't stream
  if (this->GetAutoMinimumMaximumInput() && this->GetAutoMinimumMaximum())
  {
    return 1;
  }

  return Superclass::GetNumberOfInputRequestedRegions();
}

template <typename TImage>
void
ImageToHistogramFilter<TImage>::StreamedGenerateData(unsigned int inputRequestedRegionNumber)
{
  if (inputRequestedRegionNumber == 0)
  {
    this->InitializeOutputHistogram();
  }

  Superclass::StreamedGenerateData(inputRequestedRegionNumber);
}

template <typename TImage>
void
ImageToHistogramFilter<TImage>::InitializeOutputHistogram()
{
  const unsigned int nbOfComponents = this->GetInput()->GetNumberOfComponentsPerPixel();
  m_Minimum = HistogramMeasurementVectorType(nbOfComponents);
  m_Maximum = HistogramMeasurementVectorType(nbOfComponents);

  m_Minimum.Fill(NumericTraits<ValueType>::max());
  m_Maximum.Fill(NumericTraits<ValueType>::NonpositiveMin());

  m_MergeHistogram = nullptr;

  HistogramType * outputHistogram = this->GetOutput();
  outputHistogram->SetClipBinsAtEnds(true);

  // the parameter needed to initialize the histogram
  HistogramSizeType size(nbOfComponents);
  if (this->GetHistogramSizeInput())
  {
    // user provided value
    size = this->GetHistogramSize();
  }
  else
  {
    // use a default value, which must be computed at run time for the VectorImage
    size.Fill(256);
  }

  if (this->GetAutoMinimumMaximumInput() && this->GetAutoMinimumMaximum())
  {
    if (this->GetInput()->GetBufferedRegion() != this->GetInput()->GetLargestPossibleRegion())
    {
      itkExceptionMacro(<< "AutoMinimumMaximumInput is not supported with streaming.")
    }

    // we have to compute the minimum and maximum values
    this->GetMultiThreader()->template ParallelizeImageRegion<ImageType::ImageDimension>(
      this->GetInput()->GetBufferedRegion(),
      [this](const RegionType & inputRegionForThread) { this->ThreadedComputeMinimumAndMaximum(inputRegionForThread); },
      this);

    this->ApplyMarginalScale(m_Minimum, m_Maximum, size);
  }
  else
  {
    if (this->GetHistogramBinMinimumInput())
    {
      m_Minimum = this->GetHistogramBinMinimum();
    }
    else
    {
      m_Minimum.Fill(NumericTraits<ValueType>::NonpositiveMin() - 0.5);
    }
    if (this->GetHistogramBinMaximumInput())
    {
      m_Maximum = this->GetHistogramBinMaximum();
    }
    else
    {
      m_Maximum.Fill(NumericTraits<ValueType>::max() + 0.5);
    }
    // No marginal scaling is applied in this case
  }

  outputHistogram->SetMeasurementVectorSize(nbOfComponents);
  outputHistogram->Initialize(size, m_Minimum, m_Maximum);
}

template <typename TImage>
void
ImageToHistogramFilter<TImage>::AfterStreamedGenerateData()
{
  Superclass::AfterStreamedGenerateData();

  HistogramType * outputHistogram = this->GetOutput();
  outputHistogram->Graft(m_MergeHistogram);
  m_MergeHistogram = nullptr;
}

template <typename TImage>
void
ImageToHistogramFilter<TImage>::ThreadedComputeMinimumAndMaximum(const RegionType & inputRegionForThread)
{
  const unsigned int             nbOfComponents = this->GetInput()->GetNumberOfComponentsPerPixel();
  HistogramMeasurementVectorType min(nbOfComponents);
  HistogramMeasurementVectorType max(nbOfComponents);

  ImageRegionConstIterator<TImage> inputIt(this->GetInput(), inputRegionForThread);
  inputIt.GoToBegin();
  HistogramMeasurementVectorType m(nbOfComponents);

  min.Fill(NumericTraits<ValueType>::max());
  max.Fill(NumericTraits<ValueType>::NonpositiveMin());
  while (!inputIt.IsAtEnd())
  {
    const PixelType & p = inputIt.Get();
    NumericTraits<PixelType>::AssignToArray(p, m);
    for (unsigned int i = 0; i < nbOfComponents; i++)
    {
      min[i] = std::min(m[i], min[i]);
      max[i] = std::max(m[i], max[i]);
    }
    ++inputIt;
  }

  std::lock_guard<std::mutex> mutexHolder(m_Mutex);
  for (unsigned int i = 0; i < nbOfComponents; i++)
  {
    m_Minimum[i] = std::min(m_Minimum[i], min[i]);
    m_Maximum[i] = std::max(m_Maximum[i], max[i]);
  }
}

template <typename TImage>
void
ImageToHistogramFilter<TImage>::ThreadedStreamedGenerateData(const RegionType & inputRegionForThread)
{
  const unsigned int    nbOfComponents = this->GetInput()->GetNumberOfComponentsPerPixel();
  const HistogramType * outputHistogram = this->GetOutput();

  HistogramPointer histogram = HistogramType::New();
  histogram->SetClipBinsAtEnds(outputHistogram->GetClipBinsAtEnds());
  histogram->SetMeasurementVectorSize(nbOfComponents);
  histogram->Initialize(outputHistogram->GetSize(), m_Minimum, m_Maximum);

  ImageRegionConstIterator<TImage> inputIt(this->GetInput(), inputRegionForThread);
  inputIt.GoToBegin();
  HistogramMeasurementVectorType m(nbOfComponents);

  typename HistogramType::IndexType index;
  while (!inputIt.IsAtEnd())
  {
    const PixelType & p = inputIt.Get();
    NumericTraits<PixelType>::AssignToArray(p, m);
    histogram->GetIndex(m, index);
    histogram->IncreaseFrequencyOfIndex(index, 1);
    ++inputIt;
  }

  this->ThreadedMergeHistogram(std::move(histogram));
}

template <typename TImage>
void
ImageToHistogramFilter<TImage>::ThreadedMergeHistogram(HistogramPointer && histogram)
{
  while (true)
  {

    std::unique_lock<std::mutex> lock(m_Mutex);

    if (m_MergeHistogram.IsNull())
    {
      m_MergeHistogram = std::move(histogram);
      return;
    }
    else
    {

      // merge/reduce the local results with current values in m_MergeHistogram

      // take ownership locally
      HistogramPointer tomergeHistogram;
      swap(m_MergeHistogram, tomergeHistogram);

      // allow other threads to merge data
      lock.unlock();

      using HistogramIterator = typename HistogramType::ConstIterator;

      HistogramIterator hit = tomergeHistogram->Begin();
      HistogramIterator end = tomergeHistogram->End();

      typename HistogramType::IndexType index;

      while (hit != end)
      {
        histogram->GetIndex(hit.GetMeasurementVector(), index);
        histogram->IncreaseFrequencyOfIndex(index, hit.GetFrequency());
        ++hit;
      }
    }
  }
}

template <typename TImage>
void
ImageToHistogramFilter<TImage>::ApplyMarginalScale(HistogramMeasurementVectorType & min,
                                                   HistogramMeasurementVectorType & max,
                                                   HistogramSizeType &              size)
{
  const unsigned int nbOfComponents = this->GetInput()->GetNumberOfComponentsPerPixel();
  bool               clipHistograms = true;
  for (unsigned int i = 0; i < nbOfComponents; i++)
  {
    if (!NumericTraits<HistogramMeasurementType>::is_integer)
    {
      HistogramMeasurementType marginalScale = this->GetMarginalScale();
      const double             margin =
        (static_cast<HistogramMeasurementType>(max[i] - min[i]) / static_cast<HistogramMeasurementType>(size[i])) /
        static_cast<HistogramMeasurementType>(marginalScale);

      // Now we check if the max[i] value can be increased by
      // the margin value without saturating the capacity of the
      // HistogramMeasurementType
      if ((NumericTraits<HistogramMeasurementType>::max() - max[i]) > margin)
      {
        max[i] = static_cast<HistogramMeasurementType>(max[i] + margin);
      }
      else
      {
        // an overflow would occur if we add 'margin' to the max
        // therefore we just compromise in setting max = max.
        // Histogram measurement type would force the clipping the max
        // value.
        // Therefore we must call the following to include the max value:
        clipHistograms = false;
        // The above function is okay since here we are within the
        // autoMinMax
        // computation and clearly the user intended to include min and max.
      }
    }
    else
    {
      // max[i] = SafeAssign(max[i] + NumericTraits<MeasurementType>::OneValue());
      // if ( max[i] <= max[i] )
      if (max[i] < (static_cast<ValueType>(NumericTraits<HistogramMeasurementType>::max()) -
                    NumericTraits<ValueType>::OneValue()))
      {
        max[i] = static_cast<HistogramMeasurementType>(max[i] + NumericTraits<ValueType>::OneValue());
      }
      else
      {
        // an overflow would have occurred, therefore set max to max
        // Histogram measurement type would force the clipping the max
        // value.
        // Therefore we must call the following to include the max value:
        clipHistograms = false;
        // The above function is okay since here we are within the
        // autoMinMax
        // computation and clearly the user intended to include min and max.
      }
    }
  }
  if (clipHistograms == false)
  {
    this->GetOutput()->SetClipBinsAtEnds(false);
  }
}

template <typename TImage>
void
ImageToHistogramFilter<TImage>::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);
  // m_HistogramBinMinimum
  os << indent << "HistogramBinMinimum: " << this->GetHistogramBinMinimum() << std::endl;
  // m_HistogramBinMaximum
  os << indent << "HistogramBinMaximum: " << this->GetHistogramBinMaximum() << std::endl;
  // m_MarginalScale
  os << indent << "MarginalScale: " << this->GetMarginalScale() << std::endl;
  // m_AutoMinimumMaximum
  os << indent << "AutoMinimumMaximum: " << this->GetAutoMinimumMaximum() << std::endl;
  // m_HistogramSize
  os << indent << "HistogramSize: " << this->GetHistogramSize() << std::endl;
}
} // end of namespace Statistics
} // end of namespace itk

#endif
<commit_msg>BUG: Fix ImageHistogram printing null inputs<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/
#ifndef itkImageToHistogramFilter_hxx
#define itkImageToHistogramFilter_hxx

#include "itkImageToHistogramFilter.h"
#include "itkImageRegionConstIterator.h"

namespace itk
{
namespace Statistics
{
template <typename TImage>
ImageToHistogramFilter<TImage>::ImageToHistogramFilter()
{
  this->SetNumberOfRequiredInputs(1);
  this->SetNumberOfRequiredOutputs(1);

  this->ProcessObject::SetNthOutput(0, this->MakeOutput(0));

  // same default values as in the HistogramGenerator

  this->Self::SetMarginalScale(100);

  if (typeid(ValueType) == typeid(signed char) || typeid(ValueType) == typeid(unsigned char))
  {
    this->Self::SetAutoMinimumMaximum(false);
  }
  else
  {
    this->Self::SetAutoMinimumMaximum(true);
  }
}

template <typename TImage>
DataObject::Pointer
ImageToHistogramFilter<TImage>::MakeOutput(DataObjectPointerArraySizeType itkNotUsed(idx))
{
  return HistogramType::New().GetPointer();
}

template <typename TImage>
const typename ImageToHistogramFilter<TImage>::HistogramType *
ImageToHistogramFilter<TImage>::GetOutput() const
{
  auto * output = itkDynamicCastInDebugMode<const HistogramType *>(this->ProcessObject::GetPrimaryOutput());

  return output;
}

template <typename TImage>
typename ImageToHistogramFilter<TImage>::HistogramType *
ImageToHistogramFilter<TImage>::GetOutput()
{

  auto * output = itkDynamicCastInDebugMode<HistogramType *>(this->ProcessObject::GetPrimaryOutput());

  return output;
}

template <typename TImage>
void
ImageToHistogramFilter<TImage>::GraftOutput(DataObject * graft)
{
  DataObject * output = const_cast<HistogramType *>(this->GetOutput());

  // Call Histogram to copy meta-information, and the container
  output->Graft(graft);
}

template <typename TImage>
unsigned int
ImageToHistogramFilter<TImage>::GetNumberOfInputRequestedRegions()
{
  // If we need to compute the minimum and maximum we don't stream
  if (this->GetAutoMinimumMaximumInput() && this->GetAutoMinimumMaximum())
  {
    return 1;
  }

  return Superclass::GetNumberOfInputRequestedRegions();
}

template <typename TImage>
void
ImageToHistogramFilter<TImage>::StreamedGenerateData(unsigned int inputRequestedRegionNumber)
{
  if (inputRequestedRegionNumber == 0)
  {
    this->InitializeOutputHistogram();
  }

  Superclass::StreamedGenerateData(inputRequestedRegionNumber);
}

template <typename TImage>
void
ImageToHistogramFilter<TImage>::InitializeOutputHistogram()
{
  const unsigned int nbOfComponents = this->GetInput()->GetNumberOfComponentsPerPixel();
  m_Minimum = HistogramMeasurementVectorType(nbOfComponents);
  m_Maximum = HistogramMeasurementVectorType(nbOfComponents);

  m_Minimum.Fill(NumericTraits<ValueType>::max());
  m_Maximum.Fill(NumericTraits<ValueType>::NonpositiveMin());

  m_MergeHistogram = nullptr;

  HistogramType * outputHistogram = this->GetOutput();
  outputHistogram->SetClipBinsAtEnds(true);

  // the parameter needed to initialize the histogram
  HistogramSizeType size(nbOfComponents);
  if (this->GetHistogramSizeInput())
  {
    // user provided value
    size = this->GetHistogramSize();
  }
  else
  {
    // use a default value, which must be computed at run time for the VectorImage
    size.Fill(256);
  }

  if (this->GetAutoMinimumMaximumInput() && this->GetAutoMinimumMaximum())
  {
    if (this->GetInput()->GetBufferedRegion() != this->GetInput()->GetLargestPossibleRegion())
    {
      itkExceptionMacro(<< "AutoMinimumMaximumInput is not supported with streaming.")
    }

    // we have to compute the minimum and maximum values
    this->GetMultiThreader()->template ParallelizeImageRegion<ImageType::ImageDimension>(
      this->GetInput()->GetBufferedRegion(),
      [this](const RegionType & inputRegionForThread) { this->ThreadedComputeMinimumAndMaximum(inputRegionForThread); },
      this);

    this->ApplyMarginalScale(m_Minimum, m_Maximum, size);
  }
  else
  {
    if (this->GetHistogramBinMinimumInput())
    {
      m_Minimum = this->GetHistogramBinMinimum();
    }
    else
    {
      m_Minimum.Fill(NumericTraits<ValueType>::NonpositiveMin() - 0.5);
    }
    if (this->GetHistogramBinMaximumInput())
    {
      m_Maximum = this->GetHistogramBinMaximum();
    }
    else
    {
      m_Maximum.Fill(NumericTraits<ValueType>::max() + 0.5);
    }
    // No marginal scaling is applied in this case
  }

  outputHistogram->SetMeasurementVectorSize(nbOfComponents);
  outputHistogram->Initialize(size, m_Minimum, m_Maximum);
}

template <typename TImage>
void
ImageToHistogramFilter<TImage>::AfterStreamedGenerateData()
{
  Superclass::AfterStreamedGenerateData();

  HistogramType * outputHistogram = this->GetOutput();
  outputHistogram->Graft(m_MergeHistogram);
  m_MergeHistogram = nullptr;
}

template <typename TImage>
void
ImageToHistogramFilter<TImage>::ThreadedComputeMinimumAndMaximum(const RegionType & inputRegionForThread)
{
  const unsigned int             nbOfComponents = this->GetInput()->GetNumberOfComponentsPerPixel();
  HistogramMeasurementVectorType min(nbOfComponents);
  HistogramMeasurementVectorType max(nbOfComponents);

  ImageRegionConstIterator<TImage> inputIt(this->GetInput(), inputRegionForThread);
  inputIt.GoToBegin();
  HistogramMeasurementVectorType m(nbOfComponents);

  min.Fill(NumericTraits<ValueType>::max());
  max.Fill(NumericTraits<ValueType>::NonpositiveMin());
  while (!inputIt.IsAtEnd())
  {
    const PixelType & p = inputIt.Get();
    NumericTraits<PixelType>::AssignToArray(p, m);
    for (unsigned int i = 0; i < nbOfComponents; i++)
    {
      min[i] = std::min(m[i], min[i]);
      max[i] = std::max(m[i], max[i]);
    }
    ++inputIt;
  }

  std::lock_guard<std::mutex> mutexHolder(m_Mutex);
  for (unsigned int i = 0; i < nbOfComponents; i++)
  {
    m_Minimum[i] = std::min(m_Minimum[i], min[i]);
    m_Maximum[i] = std::max(m_Maximum[i], max[i]);
  }
}

template <typename TImage>
void
ImageToHistogramFilter<TImage>::ThreadedStreamedGenerateData(const RegionType & inputRegionForThread)
{
  const unsigned int    nbOfComponents = this->GetInput()->GetNumberOfComponentsPerPixel();
  const HistogramType * outputHistogram = this->GetOutput();

  HistogramPointer histogram = HistogramType::New();
  histogram->SetClipBinsAtEnds(outputHistogram->GetClipBinsAtEnds());
  histogram->SetMeasurementVectorSize(nbOfComponents);
  histogram->Initialize(outputHistogram->GetSize(), m_Minimum, m_Maximum);

  ImageRegionConstIterator<TImage> inputIt(this->GetInput(), inputRegionForThread);
  inputIt.GoToBegin();
  HistogramMeasurementVectorType m(nbOfComponents);

  typename HistogramType::IndexType index;
  while (!inputIt.IsAtEnd())
  {
    const PixelType & p = inputIt.Get();
    NumericTraits<PixelType>::AssignToArray(p, m);
    histogram->GetIndex(m, index);
    histogram->IncreaseFrequencyOfIndex(index, 1);
    ++inputIt;
  }

  this->ThreadedMergeHistogram(std::move(histogram));
}

template <typename TImage>
void
ImageToHistogramFilter<TImage>::ThreadedMergeHistogram(HistogramPointer && histogram)
{
  while (true)
  {

    std::unique_lock<std::mutex> lock(m_Mutex);

    if (m_MergeHistogram.IsNull())
    {
      m_MergeHistogram = std::move(histogram);
      return;
    }
    else
    {

      // merge/reduce the local results with current values in m_MergeHistogram

      // take ownership locally
      HistogramPointer tomergeHistogram;
      swap(m_MergeHistogram, tomergeHistogram);

      // allow other threads to merge data
      lock.unlock();

      using HistogramIterator = typename HistogramType::ConstIterator;

      HistogramIterator hit = tomergeHistogram->Begin();
      HistogramIterator end = tomergeHistogram->End();

      typename HistogramType::IndexType index;

      while (hit != end)
      {
        histogram->GetIndex(hit.GetMeasurementVector(), index);
        histogram->IncreaseFrequencyOfIndex(index, hit.GetFrequency());
        ++hit;
      }
    }
  }
}

template <typename TImage>
void
ImageToHistogramFilter<TImage>::ApplyMarginalScale(HistogramMeasurementVectorType & min,
                                                   HistogramMeasurementVectorType & max,
                                                   HistogramSizeType &              size)
{
  const unsigned int nbOfComponents = this->GetInput()->GetNumberOfComponentsPerPixel();
  bool               clipHistograms = true;
  for (unsigned int i = 0; i < nbOfComponents; i++)
  {
    if (!NumericTraits<HistogramMeasurementType>::is_integer)
    {
      HistogramMeasurementType marginalScale = this->GetMarginalScale();
      const double             margin =
        (static_cast<HistogramMeasurementType>(max[i] - min[i]) / static_cast<HistogramMeasurementType>(size[i])) /
        static_cast<HistogramMeasurementType>(marginalScale);

      // Now we check if the max[i] value can be increased by
      // the margin value without saturating the capacity of the
      // HistogramMeasurementType
      if ((NumericTraits<HistogramMeasurementType>::max() - max[i]) > margin)
      {
        max[i] = static_cast<HistogramMeasurementType>(max[i] + margin);
      }
      else
      {
        // an overflow would occur if we add 'margin' to the max
        // therefore we just compromise in setting max = max.
        // Histogram measurement type would force the clipping the max
        // value.
        // Therefore we must call the following to include the max value:
        clipHistograms = false;
        // The above function is okay since here we are within the
        // autoMinMax
        // computation and clearly the user intended to include min and max.
      }
    }
    else
    {
      // max[i] = SafeAssign(max[i] + NumericTraits<MeasurementType>::OneValue());
      // if ( max[i] <= max[i] )
      if (max[i] < (static_cast<ValueType>(NumericTraits<HistogramMeasurementType>::max()) -
                    NumericTraits<ValueType>::OneValue()))
      {
        max[i] = static_cast<HistogramMeasurementType>(max[i] + NumericTraits<ValueType>::OneValue());
      }
      else
      {
        // an overflow would have occurred, therefore set max to max
        // Histogram measurement type would force the clipping the max
        // value.
        // Therefore we must call the following to include the max value:
        clipHistograms = false;
        // The above function is okay since here we are within the
        // autoMinMax
        // computation and clearly the user intended to include min and max.
      }
    }
  }
  if (clipHistograms == false)
  {
    this->GetOutput()->SetClipBinsAtEnds(false);
  }
}

template <typename TImage>
void
ImageToHistogramFilter<TImage>::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);
  if (this->GetHistogramBinMinimumInput())
  {
    os << indent << "HistogramBinMinimum: " << this->GetHistogramBinMinimum() << std::endl;
  }
  if (this->GetHistogramBinMaximumInput())
  {
    os << indent << "HistogramBinMaximum: " << this->GetHistogramBinMaximum() << std::endl;
  }
  os << indent << "MarginalScale: " << this->GetMarginalScale() << std::endl;
  os << indent << "AutoMinimumMaximum: " << this->GetAutoMinimumMaximum() << std::endl;
  if (this->GetHistogramSizeInput())
  {
    os << indent << "HistogramSize: " << this->GetHistogramSize() << std::endl;
  }
}
} // end of namespace Statistics
} // end of namespace itk

#endif
<|endoftext|>


<commit_before>/*
 * Game: Pong Game.
 * Author: Rafael Campos Nunes.
 * License: Apache v2.
 *
 * Fell free to contact me on
 * Email: rafaelnunes737@hotmail.com
 * Github: https://github.com/rafaelcn
 *
 * Also you can contact me on IRC(freenode.net server) my nickname is: ranu.
 */

#ifndef DEBUG_HPP
#define DEBUG_HPP

#include <iostream>

/**
 * @brief The Debug class is where debug functions are defined.
 */
class Debug {
public:
    /**
     * @brief logf
     * @param filename
     * @param message
     * @return
     */
    static bool logf(const std::string& filename, const std::string& message);

    template<typename... Ts>
    static void log(const Ts&... args)
    {
        std::cout << "Debug::log: ";

        int expanded[] = { (std::cout << args << "", 0)... };
        (void)expanded;

        std::cout << std::endl;
    }

    template<typename... Ts>
    static void logerr(const Ts&... args)
    {
        std::cout << "Debug::logerr: ";

        int expanded[] = { (std::cout << args, 0)... };
        (void)expanded;

        std::cout << std::endl;
    }
};
#endif // DEBUG_H
<commit_msg>Added a warning debug option.<commit_after>/*
 * Game: Pong Game.
 * Author: Rafael Campos Nunes.
 * License: Apache v2.
 *
 * Fell free to contact me on
 * Email: rafaelnunes737@hotmail.com
 * Github: https://github.com/rafaelcn
 *
 * Also you can contact me on IRC(freenode.net server) my nickname is: ranu.
 */

#ifndef DEBUG_HPP
#define DEBUG_HPP

#include <iostream>

/**
 * @brief The Debug class is where debug functions are defined.
 */
class Debug {
public:
    /**
     * @brief logf
     * @param filename
     * @param message
     * @return
     */
    static bool logf(const std::string& filename, const std::string& message);

    template<typename... Ts>
    static void log(const Ts&... args)
    {
        std::cout << "Debug::log: ";

        int expanded[] = { (std::cout << args << "", 0)... };
        (void)expanded;

        std::cout << std::endl;
    }

    template<typename... Ts>
    static void logwarn(const Ts&... args)
    {
        std::cout << "Debug::logwarn: ";

        int expanded[] = { (std::cout << args, 0)... };
        (void)expanded;

        std::cout << std::endl;
    }

    template<typename... Ts>
    static void logerr(const Ts&... args)
    {
        std::cout << "Debug::logerr: ";

        int expanded[] = { (std::cout << args, 0)... };
        (void)expanded;

        std::cout << std::endl;
    }
};
#endif // DEBUG_H
<|endoftext|>


<commit_before>/*
  Copyright:        Copyright (C) 2003-2018 SIL International.
  Authors:          mcdurdin
*/
#include "pch.h"
#include <stdarg.h>

inline BOOL ShouldDebug() {
  return g_debug_KeymanLog;
}

#define TAB "\t"
#define NL  "\n"

#include <chrono>
#define _USE_WINDOWS

#ifdef _USE_WINDOWS
#define DECLSPEC_IMPORT __declspec(dllimport)
#define WINBASEAPI DECLSPEC_IMPORT
#define VOID void
#define WINAPI      __stdcall

extern "C"
__declspec(dllimport)
void
__stdcall
OutputDebugStringA(
  char *lpOutputString
);

#else
  #include <syslog.h>
#endif

// simulation of Windows GetTickCount()
unsigned long
GetTickCount()
{
  using namespace std::chrono;
  return (unsigned long) duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
}

int DebugLog_1(const char *file, int line, const char *function, const char *fmt, ...)
{
	char fmtbuf[256];

	va_list vars;
	va_start(vars, fmt);
	vsnprintf_s(fmtbuf, sizeof(fmtbuf) / sizeof(fmtbuf[0]), _TRUNCATE, fmt, vars);  // I2248   // I3547
	fmtbuf[255] = 0;
  va_end(vars);

	if(g_debug_KeymanLog) {
    if(g_debug_ToConsole) {   // I3951
      char windowinfo[1024];
      sprintf(windowinfo,
        "%d" TAB     //"TickCount" TAB
        "%s:%d" TAB  //"SourceFile" TAB
        "%s" TAB     //"Function"
        "%s" NL,     //"Message"

        GetTickCount(),   //"TickCount" TAB
        file, line,       //"SourceFile" TAB
        function,         //"Function" TAB
        fmtbuf);          //"Message"
#ifdef _USE_WINDOWS
      OutputDebugStringA(windowinfo);
#else
      syslog(LOG_DEBUG, "%s", windowinfo);
#endif
    }
	}

  return 0;
}

struct Debug_ModifierNames {
  char *name;
  UINT flag;
};

extern const char *VKeyNames[256];

const struct Debug_ModifierNames s_modifierNames[14] = {
  {" LCTRL", 0x0001},		// Left Control flag
  {" RCTRL", 0x0002},		// Right Control flag
  {" LALT", 0x0004},		// Left Alt flag
  {" RALT", 0x0008},		// Right Alt flag
  {" SHIFT", 0x0010},		// Either shift flag
  {" CTRL", 0x0020},		// Either ctrl flag -- don't use this for inputs
  {" ALT", 0x0040},		// Either alt flag -- don't use this for inputs
  {" CAPS", 0x0100},		// Caps lock on
  {" NCAPS", 0x0200},		// Caps lock NOT on
  {" NUMLOCK", 0x0400},		// Num lock on
  {" NNUMLOCK", 0x0800},		// Num lock NOT on
  {" SCROLL", 0x1000},		// Scroll lock on
  {" NSCROLL", 0x2000},		// Scroll lock NOT on
  {NULL, 0}
};

char *Debug_ModifierName(UINT modifiers) {
  __declspec(thread) static char buf[256];
  buf[0] = 0;
  for(int i = 0; s_modifierNames[i].name; i++)
    if (modifiers & s_modifierNames[i].flag) {
      strcat(buf, s_modifierNames[i].name);
    }

  if (*buf) return buf + 1;
  return "Unmodified";
}

char *Debug_VirtualKey(WORD vk) {
  __declspec(thread) static char buf[256];
  if (!ShouldDebug()) {
    return "";
  }

  if (vk < 256) {
    sprintf(buf, "['%s' 0x%x]", VKeyNames[vk], vk);
  }
  else {
    sprintf(buf, "[0x%x]", vk);
  }
  return buf;
}

char *Debug_UnicodeString(PWSTR s, int x) {
  if (!ShouldDebug()) {
    return "";
  }
  __declspec(thread) static char bufout[2][128 * 7];
  WCHAR *p;
  char *q;
  bufout[x][0] = 0;
  for (p = s, q = bufout[x]; *p && (p - s < 128); p++)
  {
    sprintf(q, "U+%4.4X ", *p); q = strchr(q, 0);
  }
  //WideCharToMultiByte(CP_ACP, 0, buf, -1, bufout, 128, NULL, NULL);
  return bufout[x];
}

char *Debug_UnicodeString(std::u16string s, int x) {
  if (!ShouldDebug()) {
    return "";
  }
  __declspec(thread) static char bufout[2][128 * 7];
  auto p = s.begin();
  char *q;
  bufout[x][0] = 0;
  for (p, q = bufout[x]; p != s.end(); p++)
  {
    sprintf(q, "U+%4.4X ", *p); q = strchr(q, 0);
  }
  //WideCharToMultiByte(CP_ACP, 0, buf, -1, bufout, 128, NULL, NULL);
  return bufout[x];
}

void write_console(BOOL error, const wchar_t *fmt, ...) {
  if (!g_silent || error) {
    va_list vars;
    va_start(vars, fmt);
    vwprintf(fmt, vars);
    va_end(vars);
  }
}
<commit_msg>[Common] debug functions thread safety removal for cross-platform<commit_after>/*
  Copyright:        Copyright (C) 2003-2018 SIL International.
  Authors:          mcdurdin
*/
#include "pch.h"
#include <stdarg.h>

inline BOOL ShouldDebug() {
  return g_debug_KeymanLog;
}

#define TAB "\t"
#define NL  "\n"

#include <chrono>

#ifdef _MSC_VER
#define _USE_WINDOWS
#endif

#ifdef _USE_WINDOWS
#define DECLSPEC_IMPORT __declspec(dllimport)
#define WINBASEAPI DECLSPEC_IMPORT
#define VOID void
#define WINAPI      __stdcall

extern "C"
__declspec(dllimport)
void
__stdcall
OutputDebugStringA(
  char *lpOutputString
);

#else
  #include <syslog.h>
#endif

// simulation of Windows GetTickCount()
unsigned long
GetTickCount()
{
  using namespace std::chrono;
  return (unsigned long) duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
}

int DebugLog_1(const char *file, int line, const char *function, const char *fmt, ...)
{
	char fmtbuf[256];

	va_list vars;
	va_start(vars, fmt);
	vsnprintf_s(fmtbuf, sizeof(fmtbuf) / sizeof(fmtbuf[0]), _TRUNCATE, fmt, vars);  // I2248   // I3547
	fmtbuf[255] = 0;
  va_end(vars);

	if(g_debug_KeymanLog) {
    if(g_debug_ToConsole) {   // I3951
      char windowinfo[1024];
      sprintf(windowinfo,
        "%d" TAB     //"TickCount" TAB
        "%s:%d" TAB  //"SourceFile" TAB
        "%s" TAB     //"Function"
        "%s" NL,     //"Message"

        GetTickCount(),   //"TickCount" TAB
        file, line,       //"SourceFile" TAB
        function,         //"Function" TAB
        fmtbuf);          //"Message"
#ifdef _USE_WINDOWS
      OutputDebugStringA(windowinfo);
#else
      syslog(LOG_DEBUG, "%s", windowinfo);
#endif
    }
	}

  return 0;
}

struct Debug_ModifierNames {
  char *name;
  UINT flag;
};

extern const char *VKeyNames[256];

const struct Debug_ModifierNames s_modifierNames[14] = {
  {" LCTRL", 0x0001},		// Left Control flag
  {" RCTRL", 0x0002},		// Right Control flag
  {" LALT", 0x0004},		// Left Alt flag
  {" RALT", 0x0008},		// Right Alt flag
  {" SHIFT", 0x0010},		// Either shift flag
  {" CTRL", 0x0020},		// Either ctrl flag -- don't use this for inputs
  {" ALT", 0x0040},		// Either alt flag -- don't use this for inputs
  {" CAPS", 0x0100},		// Caps lock on
  {" NCAPS", 0x0200},		// Caps lock NOT on
  {" NUMLOCK", 0x0400},		// Num lock on
  {" NNUMLOCK", 0x0800},		// Num lock NOT on
  {" SCROLL", 0x1000},		// Scroll lock on
  {" NSCROLL", 0x2000},		// Scroll lock NOT on
  {NULL, 0}
};

char *Debug_ModifierName(UINT modifiers) {
#ifdef _MSC_VER
  __declspec(thread)
#endif
  static char buf[256];
  buf[0] = 0;
  for(int i = 0; s_modifierNames[i].name; i++)
    if (modifiers & s_modifierNames[i].flag) {
      strcat(buf, s_modifierNames[i].name);
    }

  if (*buf) return buf + 1;
  return "Unmodified";
}

char *Debug_VirtualKey(WORD vk) {
#ifdef _MSC_VER
  __declspec(thread)
#endif
  static char buf[256];
  if (!ShouldDebug()) {
    return "";
  }

  if (vk < 256) {
    sprintf(buf, "['%s' 0x%x]", VKeyNames[vk], vk);
  }
  else {
    sprintf(buf, "[0x%x]", vk);
  }
  return buf;
}

char *Debug_UnicodeString(PWSTR s, int x) {
  if (!ShouldDebug()) {
    return "";
  }
#ifdef _MSC_VER
  __declspec(thread)
#endif
  static char bufout[2][128 * 7];
  WCHAR *p;
  char *q;
  bufout[x][0] = 0;
  for (p = s, q = bufout[x]; *p && (p - s < 128); p++)
  {
    sprintf(q, "U+%4.4X ", *p); q = strchr(q, 0);
  }
  //WideCharToMultiByte(CP_ACP, 0, buf, -1, bufout, 128, NULL, NULL);
  return bufout[x];
}

char *Debug_UnicodeString(std::u16string s, int x) {
  if (!ShouldDebug()) {
    return "";
  }
#ifdef _MSC_VER
  __declspec(thread)
#endif
  static char bufout[2][128 * 7];
  auto p = s.begin();
  char *q;
  bufout[x][0] = 0;
  for (p, q = bufout[x]; p != s.end(); p++)
  {
    sprintf(q, "U+%4.4X ", *p); q = strchr(q, 0);
  }
  //WideCharToMultiByte(CP_ACP, 0, buf, -1, bufout, 128, NULL, NULL);
  return bufout[x];
}

void write_console(BOOL error, const wchar_t *fmt, ...) {
  if (!g_silent || error) {
    va_list vars;
    va_start(vars, fmt);
    vwprintf(fmt, vars);
    va_end(vars);
  }
}
<|endoftext|>


<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2013-2019 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. 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.
 *
 * 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 <modules/basegl/processors/imageprocessing/imagechannelcombine.h>
#include <modules/opengl/texture/textureunit.h>
#include <modules/opengl/texture/textureutils.h>
#include <modules/opengl/shader/shaderutils.h>

namespace inviwo {

const ProcessorInfo ImageChannelCombine::processorInfo_{
    "org.inviwo.ImageChannelCombine",  // Class identifier
    "Image Channel Combine",           // Display name
    "Image Operation",                 // Category
    CodeState::Experimental,           // Code state
    Tags::GL,                          // Tags
};
const ProcessorInfo ImageChannelCombine::getProcessorInfo() const { return processorInfo_; }

ImageChannelCombine::ImageChannelCombine()
    : Processor()
    , inport0_("inport0", true)
    , inport1_("inport1", true)
    , inport2_("inport2", true)
    , inport3_("inport3", true)
    , outport_("outport", false)
    , rChannelSrc_("redChannel", "Red Channel",
                   {{"r", "Red", 0}, {"g", "Green", 1}, {"b", "Blue", 2}, {"a", "Alpha", 3}})
    , gChannelSrc_("greenChannel", "Green Channel",
                   {{"r", "Red", 0}, {"g", "Green", 1}, {"b", "Blue", 2}, {"a", "Alpha", 3}})
    , bChannelSrc_("blueChannel", "Blue Channel",
                   {{"r", "Red", 0}, {"g", "Green", 1}, {"b", "Blue", 2}, {"a", "Alpha", 3}})
    , aChannelSrc_("alphaChannel", "Alpha Channel",
                   {{"r", "Red", 0}, {"g", "Green", 1}, {"b", "Blue", 2}, {"a", "Alpha", 3}})
    , alpha_("alpha", "Alpha", 1.0f, 0.0f, 1.0f, 0.001f)
    , shader_("img_channel_combine.frag") {
    shader_.onReload([this]() { invalidate(InvalidationLevel::InvalidResources); });

    addPort(inport0_);
    addPort(inport1_);
    addPort(inport2_);
    inport3_.setOptional(true);
    addPort(inport3_);

    addPort(outport_);

    addProperties(rChannelSrc_, gChannelSrc_, bChannelSrc_, aChannelSrc_, alpha_);
}

void ImageChannelCombine::process() {
    auto isSame = [](auto a, auto b, auto c) {
        if (a != b) return false;
        if (a != c) return false;
        if (b != c) return false;
        return true;
    };
    auto img0 = inport0_.getData();
    auto img1 = inport1_.getData();
    auto img2 = inport2_.getData();
    auto img3 = inport3_.getData();

    if (isSame(img0->getDimensions(), img1->getDimensions(), img2->getDimensions()) &&
        (inport3_.isConnected() && img3 && img3->getDimensions() != img0->getDimensions())) {
        throw Exception("The image dimensions of all inports needs to be the same", IVW_CONTEXT);
    }

    if (inport0_.isChanged() || inport1_.isChanged() || inport2_.isChanged()) {
        const auto dimensions = inport0_.getData()->getDimensions();
        auto t1 = inport0_.getData()->getDataFormat()->getNumericType();
        auto t2 = inport1_.getData()->getDataFormat()->getNumericType();
        auto t3 = inport2_.getData()->getDataFormat()->getNumericType();
        NumericType type;
        if (t1 == t2 && t1 == t3) {
            // All have the same numType
            type = t1;
        } else if (t1 == NumericType::Float || t2 == NumericType::Float ||
                   t2 == NumericType::Float) {
            // At least one is a float type
            type = NumericType::Float;
        } else {
            // At least one are signed, and at least one are unsigned
            type = NumericType::Float;
        }

        auto p0 = inport0_.getData()->getDataFormat()->getPrecision();
        auto p1 = inport1_.getData()->getDataFormat()->getPrecision();
        auto p2 = inport2_.getData()->getDataFormat()->getPrecision();
        DataFormatBase::get(type, 4, std::max({p0, p1, p2}));

        auto img = std::make_shared<Image>(dimensions, DataVec4UInt8::get());
        outport_.setData(img);
    }

    utilgl::activateAndClearTarget(outport_);
    shader_.activate();
    TextureUnitContainer units;
    utilgl::bindAndSetUniforms(shader_, units, inport0_, ImageType::ColorOnly);
    utilgl::bindAndSetUniforms(shader_, units, inport1_, ImageType::ColorOnly);
    utilgl::bindAndSetUniforms(shader_, units, inport2_, ImageType::ColorOnly);
    if (inport3_.hasData()) {
        utilgl::bindAndSetUniforms(shader_, units, inport3_, ImageType::ColorOnly);
    }
    utilgl::setUniforms(shader_, outport_, rChannelSrc_, gChannelSrc_, bChannelSrc_, aChannelSrc_,
                        alpha_);
    shader_.setUniform("use_alpha_texture", inport3_.hasData());
    utilgl::setUniforms(shader_, outport_);
    utilgl::singleDrawImagePlaneRect();
    shader_.deactivate();
    utilgl::deactivateCurrentTarget();
}

}  // namespace inviwo
<commit_msg>BaseGL: minor optimization<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2013-2019 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. 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.
 *
 * 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 <modules/basegl/processors/imageprocessing/imagechannelcombine.h>
#include <modules/opengl/texture/textureunit.h>
#include <modules/opengl/texture/textureutils.h>
#include <modules/opengl/shader/shaderutils.h>

namespace inviwo {

const ProcessorInfo ImageChannelCombine::processorInfo_{
    "org.inviwo.ImageChannelCombine",  // Class identifier
    "Image Channel Combine",           // Display name
    "Image Operation",                 // Category
    CodeState::Experimental,           // Code state
    Tags::GL,                          // Tags
};
const ProcessorInfo ImageChannelCombine::getProcessorInfo() const { return processorInfo_; }

ImageChannelCombine::ImageChannelCombine()
    : Processor()
    , inport0_("inport0", true)
    , inport1_("inport1", true)
    , inport2_("inport2", true)
    , inport3_("inport3", true)
    , outport_("outport", false)
    , rChannelSrc_("redChannel", "Red Channel",
                   {{"r", "Red", 0}, {"g", "Green", 1}, {"b", "Blue", 2}, {"a", "Alpha", 3}})
    , gChannelSrc_("greenChannel", "Green Channel",
                   {{"r", "Red", 0}, {"g", "Green", 1}, {"b", "Blue", 2}, {"a", "Alpha", 3}})
    , bChannelSrc_("blueChannel", "Blue Channel",
                   {{"r", "Red", 0}, {"g", "Green", 1}, {"b", "Blue", 2}, {"a", "Alpha", 3}})
    , aChannelSrc_("alphaChannel", "Alpha Channel",
                   {{"r", "Red", 0}, {"g", "Green", 1}, {"b", "Blue", 2}, {"a", "Alpha", 3}})
    , alpha_("alpha", "Alpha", 1.0f, 0.0f, 1.0f, 0.001f)
    , shader_("img_channel_combine.frag") {
    shader_.onReload([this]() { invalidate(InvalidationLevel::InvalidResources); });

    addPort(inport0_);
    addPort(inport1_);
    addPort(inport2_);
    inport3_.setOptional(true);
    addPort(inport3_);

    addPort(outport_);

    addProperties(rChannelSrc_, gChannelSrc_, bChannelSrc_, aChannelSrc_, alpha_);
}

void ImageChannelCombine::process() {
    auto isSame = [](auto a, auto b, auto c) {
        if (a != b) return false;
        if (a != c) return false;
        return true;
    };
    auto img0 = inport0_.getData();
    auto img1 = inport1_.getData();
    auto img2 = inport2_.getData();
    auto img3 = inport3_.getData();

    if (isSame(img0->getDimensions(), img1->getDimensions(), img2->getDimensions()) &&
        (inport3_.isConnected() && img3 && img3->getDimensions() != img0->getDimensions())) {
        throw Exception("The image dimensions of all inports needs to be the same", IVW_CONTEXT);
    }

    if (inport0_.isChanged() || inport1_.isChanged() || inport2_.isChanged()) {
        const auto dimensions = inport0_.getData()->getDimensions();
        auto t1 = inport0_.getData()->getDataFormat()->getNumericType();
        auto t2 = inport1_.getData()->getDataFormat()->getNumericType();
        auto t3 = inport2_.getData()->getDataFormat()->getNumericType();
        NumericType type;
        if (t1 == t2 && t1 == t3) {
            // All have the same numType
            type = t1;
        } else if (t1 == NumericType::Float || t2 == NumericType::Float ||
                   t2 == NumericType::Float) {
            // At least one is a float type
            type = NumericType::Float;
        } else {
            // At least one are signed, and at least one are unsigned
            type = NumericType::Float;
        }

        auto p0 = inport0_.getData()->getDataFormat()->getPrecision();
        auto p1 = inport1_.getData()->getDataFormat()->getPrecision();
        auto p2 = inport2_.getData()->getDataFormat()->getPrecision();
        DataFormatBase::get(type, 4, std::max({p0, p1, p2}));

        auto img = std::make_shared<Image>(dimensions, DataVec4UInt8::get());
        outport_.setData(img);
    }

    utilgl::activateAndClearTarget(outport_);
    shader_.activate();
    TextureUnitContainer units;
    utilgl::bindAndSetUniforms(shader_, units, inport0_, ImageType::ColorOnly);
    utilgl::bindAndSetUniforms(shader_, units, inport1_, ImageType::ColorOnly);
    utilgl::bindAndSetUniforms(shader_, units, inport2_, ImageType::ColorOnly);
    if (inport3_.hasData()) {
        utilgl::bindAndSetUniforms(shader_, units, inport3_, ImageType::ColorOnly);
    }
    utilgl::setUniforms(shader_, outport_, rChannelSrc_, gChannelSrc_, bChannelSrc_, aChannelSrc_,
                        alpha_);
    shader_.setUniform("use_alpha_texture", inport3_.hasData());
    utilgl::setUniforms(shader_, outport_);
    utilgl::singleDrawImagePlaneRect();
    shader_.deactivate();
    utilgl::deactivateCurrentTarget();
}

}  // namespace inviwo
<|endoftext|>


<commit_before>/*
  This is a tool shipped by 'Aleph - A Library for Exploring Persistent
  Homology'.

  Its purpose is to analyse the persistent homology of connectivity
  matrices. The tool bears some semblance to the *network analysis*
  tools, but focuses specifically on data sets whose weights are an
  interpretable correlation measure.
*/

#include <aleph/persistenceDiagrams/Entropy.hh>
#include <aleph/persistenceDiagrams/Norms.hh>

#include <aleph/persistenceDiagrams/io/JSON.hh>

#include <aleph/persistentHomology/Calculation.hh>

#include <aleph/topology/io/AdjacencyMatrix.hh>

#include <aleph/topology/Simplex.hh>
#include <aleph/topology/SimplicialComplex.hh>

#include <aleph/utilities/Filesystem.hh>

#include <iostream>
#include <map>
#include <string>
#include <vector>

#include <getopt.h>

void usage()
{
  std::cerr << "Usage: connectivity_matrix_analysis [--dimension DIMENSION] FILENAMES\n"
            << "\n"
            << "Analyses a set of connectivity matrices. The matrices are optionally\n"
            << "expanded to a pre-defined dimension. By default, only information of\n"
            << "the zeroth persistent homology group will be shown.\n"
            << "\n"
            << "Flags:\n"
            << "  -k: keep & report unpaired simplices (infinite values)\n"
            << "\n";
}

int main( int argc, char** argv )
{
  static option commandLineOptions[] =
  {
    { "dimension"     , required_argument, nullptr, 'd' },
    { "keep-unpaired" , no_argument      , nullptr, 'k' },
    { nullptr         , 0                , nullptr,  0  }
  };

  unsigned dimension = 0;
  bool keepUnpaired  = false;

  {
    int option = 0;

    while( ( option = getopt_long( argc, argv, "d:k", commandLineOptions, nullptr ) ) != -1 )
    {
      switch( option )
      {
      case 'd':
        dimension = static_cast<unsigned>( std::stoul(optarg) );
        break;
      case 'k':
        keepUnpaired = false;
        break;
      }
    }
  }

  if( (argc - optind) < 1 )
  {
    usage();
    return -1;
  }

  bool verbose            = false;

  using DataType          = double;
  using VertexType        = unsigned short;
  using Simplex           = aleph::topology::Simplex<DataType, VertexType>;
  using SimplicialComplex = aleph::topology::SimplicialComplex<Simplex>;

  std::vector<std::string> filenames;

  for( int i = optind; i < argc; i++ )
    filenames.push_back( argv[i] );

  aleph::topology::io::AdjacencyMatrixReader reader;
  reader.setIgnoreNaNs();
  reader.setIgnoreZeroWeights();

  // Whew, is there *really* no better way of specifying this strategy
  // here as a qualified name?
  reader.setVertexWeightAssignmentStrategy(
      aleph::topology::io::AdjacencyMatrixReader::VertexWeightAssignmentStrategy::AssignZero
  );

  std::cout << "{\n"
            << "\"diagrams\": [\n";

  for( auto&& filename : filenames )
  {
    if( verbose )
      std::cerr << "* Processing " << filename << "...";

    SimplicialComplex K;
    reader( filename, K );

    K.sort();

    bool dualize                    = true;
    bool includeAllUnpairedCreators = keepUnpaired;

    auto diagrams
      = aleph::calculatePersistenceDiagrams( K,
                                             dualize,
                                             includeAllUnpairedCreators );

    if( verbose )
      std::cerr << "finished\n";

    auto basename
      = aleph::utilities::basename( filename );

    for( auto&& diagram : diagrams )
    {
      // Stores additional data about each persistence diagram in order
      // to make it easier to keep track of information.
      std::map<std::string, std::string> kvs;

      kvs["total_persistence_1"] = std::to_string( aleph::totalPersistence( diagram, 1.0 ) );
      kvs["total_persistence_2"] = std::to_string( aleph::totalPersistence( diagram, 2.0 ) );

      kvs["persistent_entropy"]  = std::to_string( aleph::persistentEntropy( diagram ) );

      aleph::io::writeJSON( std::cout, diagram, basename, kvs );
    }
  }

  std::cout << "\n"
            << "]\n"
            << "}\n";
}
<commit_msg>Added option to replace infinite values in the persistence diagram<commit_after>/*
  This is a tool shipped by 'Aleph - A Library for Exploring Persistent
  Homology'.

  Its purpose is to analyse the persistent homology of connectivity
  matrices. The tool bears some semblance to the *network analysis*
  tools, but focuses specifically on data sets whose weights are an
  interpretable correlation measure.
*/

#include <aleph/persistenceDiagrams/Entropy.hh>
#include <aleph/persistenceDiagrams/Norms.hh>

#include <aleph/persistenceDiagrams/io/JSON.hh>

#include <aleph/persistentHomology/Calculation.hh>

#include <aleph/topology/io/AdjacencyMatrix.hh>

#include <aleph/topology/Simplex.hh>
#include <aleph/topology/SimplicialComplex.hh>

#include <aleph/utilities/Filesystem.hh>

#include <cmath>

#include <algorithm>
#include <iostream>
#include <limits>
#include <map>
#include <string>
#include <vector>

#include <getopt.h>

void usage()
{
  std::cerr << "Usage: connectivity_matrix_analysis [--dimension DIMENSION] [--infinity INF] FILENAMES\n"
            << "\n"
            << "Analyses a set of connectivity matrices. The matrices are optionally\n"
            << "expanded to a pre-defined dimension. By default, only information of\n"
            << "the zeroth persistent homology group will be shown.\n"
            << "\n"
            << "The value INF will be used to replace infinite values in the diagram\n"
            << "in order to facilitate the subsequent analysis.\n"
            << "\n"
            << "Flags:\n"
            << "  -k: keep & report unpaired simplices (infinite values)\n"
            << "  -v: verbose output\n"
            << "\n";
}

int main( int argc, char** argv )
{
  static option commandLineOptions[] =
  {
    { "dimension"     , required_argument, nullptr, 'd' },
    { "infinity"      , required_argument, nullptr, 'i' },
    { "keep-unpaired" , no_argument      , nullptr, 'k' },
    { "verbose"       , no_argument      , nullptr, 'v' },
    { nullptr         , 0                , nullptr,  0  }
  };

  unsigned dimension = 0;
  double infinity    = std::numeric_limits<double>::infinity();
  bool keepUnpaired  = false;
  bool verbose       = false;

  {
    int option = 0;

    while( ( option = getopt_long( argc, argv, "d:i:kv", commandLineOptions, nullptr ) ) != -1 )
    {
      switch( option )
      {
      case 'd':
        dimension = static_cast<unsigned>( std::stoul(optarg) );
        break;
      case 'i':
        infinity = static_cast<double>( std::stod(optarg) );
        break;
      case 'k':
        keepUnpaired = false;
        break;
      }
    }
  }

  if( (argc - optind) < 1 )
  {
    usage();
    return -1;
  }

  using DataType           = double;
  using VertexType         = unsigned short;
  using Simplex            = aleph::topology::Simplex<DataType, VertexType>;
  using SimplicialComplex  = aleph::topology::SimplicialComplex<Simplex>;
  using PersistenceDiagram = aleph::PersistenceDiagram<DataType>;
  using Point              = typename PersistenceDiagram::Point;

  std::vector<std::string> filenames;

  for( int i = optind; i < argc; i++ )
    filenames.push_back( argv[i] );

  aleph::topology::io::AdjacencyMatrixReader reader;
  reader.setIgnoreNaNs();
  reader.setIgnoreZeroWeights();

  // Whew, is there *really* no better way of specifying this strategy
  // here as a qualified name?
  reader.setVertexWeightAssignmentStrategy(
      aleph::topology::io::AdjacencyMatrixReader::VertexWeightAssignmentStrategy::AssignZero
  );

  std::cout << "{\n"
            << "\"diagrams\": [\n";

  for( auto&& filename : filenames )
  {
    if( verbose )
      std::cerr << "* Processing " << filename << "...";

    SimplicialComplex K;
    reader( filename, K );

    K.sort();

    bool dualize                    = true;
    bool includeAllUnpairedCreators = keepUnpaired;

    auto diagrams
      = aleph::calculatePersistenceDiagrams( K,
                                             dualize,
                                             includeAllUnpairedCreators );

    if( verbose )
      std::cerr << "finished\n";

    auto basename
      = aleph::utilities::basename( filename );

    for( auto&& diagram : diagrams )
    {
      if( std::isfinite( infinity ) )
      {
        std::transform( diagram.begin(), diagram.end(), diagram.begin(),
            [&infinity] ( const Point& p )
            {
              if( p.isUnpaired() )
                return Point( p.x(), infinity );
              else
                return Point( p.x(), p.y() );
            }
        );
      }

      // Stores additional data about each persistence diagram in order
      // to make it easier to keep track of information.
      std::map<std::string, std::string> kvs;

      kvs["total_persistence_1"] = std::to_string( aleph::totalPersistence( diagram, 1.0 ) );
      kvs["total_persistence_2"] = std::to_string( aleph::totalPersistence( diagram, 2.0 ) );

      kvs["persistent_entropy"]  = std::to_string( aleph::persistentEntropy( diagram ) );

      aleph::io::writeJSON( std::cout, diagram, basename, kvs );
    }
  }

  std::cout << "\n"
            << "]\n"
            << "}\n";
}
<|endoftext|>


<commit_before>#include "drawer.hh"

#include <cmath>
#include <cstring>
#include <deque>
#include <iostream>
#include <fstream>
#include <stdexcept>

namespace
{

const std::string svg_preambule(
    "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
    "<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>\n"
    );

struct svg_shape
{
    svg_shape() = default;
    svg_shape(const svg_shape &) = delete;
    svg_shape & operator=(const svg_shape &) = delete;

    virtual void flush(std::ostream & out) = 0;

    virtual ~svg_shape()
    {
    }
};

struct svg_circle
    : public svg_shape
{
    OutputCoord pos;
    double radius;
    std::string fill;
    double stroke_width;
    std::string stroke;

    svg_circle(const OutputCoord & pos, double radius, const std::string & fill,
               double stroke_width, const std::string & stroke)
        : pos(pos), radius(radius), fill(fill),
          stroke_width(stroke_width), stroke(stroke)
    {
    }

    virtual void flush(std::ostream & out)
    {
        out << "<circle cx='" << pos.x << "' cy='" << pos.y << "' r='" << radius << "' fill='" << fill << "' "
            "stroke='" << stroke << "' stroke-width='" << stroke_width << "' />\n";
    }
};

struct svg_rect
    : public svg_shape
{
    OutputCoord start, size;
    std::string fill;

    svg_rect(const OutputCoord & start, const OutputCoord & size, const std::string & fill)
        : start(start), size(size), fill(fill)
    {
    }

    virtual void flush(std::ostream & out)
    {
        out << "<rect x='" << start.x << "' y='" << start.y << "' "
            "width='" << size.x << "' height='" << size.y << "' fill='" << fill << "' />\n";
    }
};

struct svg_cbezier
    : public svg_shape
{
    std::vector<OutputCoord> path;
    std::string stroke;
    double width;

    svg_cbezier(std::vector<OutputCoord> && path, const std::string & stroke, double width)
        : path(std::move(path)), stroke(stroke), width(width)
    {
    }

    virtual void flush(std::ostream & out)
    {
        if (! path.empty())
        {
            out << "<path fill='none' stroke='" << stroke << "' stroke-width='" << width << "' "
                "d='M";
            auto i(path.begin()), i_end(path.end());
            out << i->x << ',' << i->y << ' ';
            ++i;
            while (i != i_end)
            {
                out << "L" << i->x << ',' << i->y << ' ';
                ++i;
            }

            out << "' />\n";
        }
    }
};

struct svg_text
    : public svg_shape
{
    std::string body;
    OutputCoord pos;
    double size;

    svg_text(const std::string & body, const OutputCoord & pos, double size)
        : body(body), pos(pos), size(size)
    {
    }

    virtual void flush(std::ostream & out)
    {
        out << "<text x='" << pos.x << "' y='" << pos.y << "' font-size='" << size << "' font-family='sans-serif'>\n"
            << body << "\n</text>\n";
    }
};

}

struct Drawer::Impl
{
    std::shared_ptr<Projection> projection_;
    const OutputCoord canvas_;
    std::deque<std::shared_ptr<svg_shape>> shapes_;

    Impl(const OutputCoord & canvas)
        : canvas_(canvas)
    {
    }
};

Drawer::Drawer(const OutputCoord & canvas)
    : imp_(new Impl(canvas))
{
    std::string background_color("white");
    double hx(imp_->canvas_.x / 2.), hy(imp_->canvas_.y / 2.);
    imp_->shapes_.push_back(
        std::make_shared<svg_rect>(OutputCoord(-hx, -hy), OutputCoord(imp_->canvas_.x, imp_->canvas_.y), background_color));
}

Drawer::~Drawer()
{
    delete imp_;
}

void Drawer::set_projection(const std::shared_ptr<Projection> & projection)
{
    imp_->projection_ = projection;
}

void Drawer::store(const char * file) const
{
    std::ofstream of(file);
    if (! of)
        throw std::runtime_error("Can't open file '" + std::string(file) + "' for writing " + std::strerror(errno));

    of << svg_preambule;

    double hx(imp_->canvas_.x / 2.), hy(imp_->canvas_.y / 2.);
    of << "<svg width='" << imp_->canvas_.x << "mm' height='" << imp_->canvas_.y << "mm' "
        "viewBox='" << -hx << ' ' << -hy << ' ' << imp_->canvas_.x << ' ' << imp_->canvas_.y << "' "
        "xmlns='http://www.w3.org/2000/svg' version='1.1'>\n";

    for (auto shape(imp_->shapes_.begin()), shape_end(imp_->shapes_.end());
         shape != shape_end; ++shape)
        (*shape)->flush(of);

    of << "</svg>\n";
}

void Drawer::draw(const Star & star)
{
    static std::string black("black");
    static std::string white("white");
    static const double e(exp(1));

    double s(2. * exp(-star.vmag_ / e));
    OutputCoord coord(imp_->projection_->project(star.pos_));
    auto c(std::make_shared<svg_circle>(coord, s, black, .5 * s, white));
    imp_->shapes_.push_back(c);

//    if (star.vmag_ < 4. && ! star.common_name_.empty())
//        imp_->board << Lb::Text(-star.pos_.ra + s, star.pos_.dec, star.common_name_, Lb::Fonts::Helvetica, 3.);
}

void Drawer::draw(const std::vector<ln_equ_posn> & path)
{
    std::vector<OutputCoord> ret;
    double min(0), max(0);
    for (auto i(path.begin()), i_end(path.end());
         i != i_end; ++i)
    {
        auto p(imp_->projection_->project(*i));
        if (p.y > max)
            max = p.y;
        else if (p.y < min)
            min = p.y;

        ret.push_back(p);
    }
    std::cout << max << ' ' << min << '\n';
    imp_->shapes_.push_back(std::make_shared<svg_cbezier>(std::move(ret), "#888888", 0.1));
}

void Drawer::draw(const std::string & body, const ln_equ_posn & pos)
{
    imp_->shapes_.push_back(std::make_shared<svg_text>(body, imp_->projection_->project(pos), 4.));
}
<commit_msg>clean up junk<commit_after>#include "drawer.hh"

#include <cmath>
#include <cstring>
#include <deque>
#include <fstream>
#include <stdexcept>

namespace
{

const std::string svg_preambule(
    "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
    "<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>\n"
    );

struct svg_shape
{
    svg_shape() = default;
    svg_shape(const svg_shape &) = delete;
    svg_shape & operator=(const svg_shape &) = delete;

    virtual void flush(std::ostream & out) = 0;

    virtual ~svg_shape()
    {
    }
};

struct svg_circle
    : public svg_shape
{
    OutputCoord pos;
    double radius;
    std::string fill;
    double stroke_width;
    std::string stroke;

    svg_circle(const OutputCoord & pos, double radius, const std::string & fill,
               double stroke_width, const std::string & stroke)
        : pos(pos), radius(radius), fill(fill),
          stroke_width(stroke_width), stroke(stroke)
    {
    }

    virtual void flush(std::ostream & out)
    {
        out << "<circle cx='" << pos.x << "' cy='" << pos.y << "' r='" << radius << "' fill='" << fill << "' "
            "stroke='" << stroke << "' stroke-width='" << stroke_width << "' />\n";
    }
};

struct svg_rect
    : public svg_shape
{
    OutputCoord start, size;
    std::string fill;

    svg_rect(const OutputCoord & start, const OutputCoord & size, const std::string & fill)
        : start(start), size(size), fill(fill)
    {
    }

    virtual void flush(std::ostream & out)
    {
        out << "<rect x='" << start.x << "' y='" << start.y << "' "
            "width='" << size.x << "' height='" << size.y << "' fill='" << fill << "' />\n";
    }
};

struct svg_cbezier
    : public svg_shape
{
    std::vector<OutputCoord> path;
    std::string stroke;
    double width;

    svg_cbezier(std::vector<OutputCoord> && path, const std::string & stroke, double width)
        : path(std::move(path)), stroke(stroke), width(width)
    {
    }

    virtual void flush(std::ostream & out)
    {
        if (! path.empty())
        {
            out << "<path fill='none' stroke='" << stroke << "' stroke-width='" << width << "' "
                "d='M";
            auto i(path.begin()), i_end(path.end());
            out << i->x << ',' << i->y << ' ';
            ++i;
            while (i != i_end)
            {
                out << "L" << i->x << ',' << i->y << ' ';
                ++i;
            }

            out << "' />\n";
        }
    }
};

struct svg_text
    : public svg_shape
{
    std::string body;
    OutputCoord pos;
    double size;

    svg_text(const std::string & body, const OutputCoord & pos, double size)
        : body(body), pos(pos), size(size)
    {
    }

    virtual void flush(std::ostream & out)
    {
        out << "<text x='" << pos.x << "' y='" << pos.y << "' font-size='" << size << "' font-family='sans-serif'>\n"
            << body << "\n</text>\n";
    }
};

}

struct Drawer::Impl
{
    std::shared_ptr<Projection> projection_;
    const OutputCoord canvas_;
    std::deque<std::shared_ptr<svg_shape>> shapes_;

    Impl(const OutputCoord & canvas)
        : canvas_(canvas)
    {
    }
};

Drawer::Drawer(const OutputCoord & canvas)
    : imp_(new Impl(canvas))
{
    std::string background_color("white");
    double hx(imp_->canvas_.x / 2.), hy(imp_->canvas_.y / 2.);
    imp_->shapes_.push_back(
        std::make_shared<svg_rect>(OutputCoord(-hx, -hy), OutputCoord(imp_->canvas_.x, imp_->canvas_.y), background_color));
}

Drawer::~Drawer()
{
    delete imp_;
}

void Drawer::set_projection(const std::shared_ptr<Projection> & projection)
{
    imp_->projection_ = projection;
}

void Drawer::store(const char * file) const
{
    std::ofstream of(file);
    if (! of)
        throw std::runtime_error("Can't open file '" + std::string(file) + "' for writing " + std::strerror(errno));

    of << svg_preambule;

    double hx(imp_->canvas_.x / 2.), hy(imp_->canvas_.y / 2.);
    of << "<svg width='" << imp_->canvas_.x << "mm' height='" << imp_->canvas_.y << "mm' "
        "viewBox='" << -hx << ' ' << -hy << ' ' << imp_->canvas_.x << ' ' << imp_->canvas_.y << "' "
        "xmlns='http://www.w3.org/2000/svg' version='1.1'>\n";

    for (auto shape(imp_->shapes_.begin()), shape_end(imp_->shapes_.end());
         shape != shape_end; ++shape)
        (*shape)->flush(of);

    of << "</svg>\n";
}

void Drawer::draw(const Star & star)
{
    static std::string black("black");
    static std::string white("white");
    static const double e(exp(1));

    double s(2. * exp(-star.vmag_ / e));
    OutputCoord coord(imp_->projection_->project(star.pos_));
    auto c(std::make_shared<svg_circle>(coord, s, black, .5 * s, white));
    imp_->shapes_.push_back(c);

//    if (star.vmag_ < 4. && ! star.common_name_.empty())
//        imp_->board << Lb::Text(-star.pos_.ra + s, star.pos_.dec, star.common_name_, Lb::Fonts::Helvetica, 3.);
}

void Drawer::draw(const std::vector<ln_equ_posn> & path)
{
    std::vector<OutputCoord> ret;
    for (auto i(path.begin()), i_end(path.end());
         i != i_end; ++i)
        ret.push_back(imp_->projection_->project(*i));
    imp_->shapes_.push_back(std::make_shared<svg_cbezier>(std::move(ret), "#888888", 0.1));
}

void Drawer::draw(const std::string & body, const ln_equ_posn & pos)
{
    imp_->shapes_.push_back(std::make_shared<svg_text>(body, imp_->projection_->project(pos), 4.));
}
<|endoftext|>


<commit_before>/*

   Copyright 2016  Amazon.com, Inc. or its affiliates. All Rights Reserved.

   Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at

   http://aws.amazon.com/apache2.0/

   or in the "license" file accompanying this file. This file 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 <iostream>
#include <sstream>
#include <algorithm>
#include <fstream>
#include <sys/stat.h>
#include <dirent.h>
#include <cstring>

#include "Utils.h"

using std::stringstream;
using std::ifstream;

void CWMetric::updateMetrics(string metric, string value)
{
//Plugin to Plot Cloudwatch Metrics from the EC2 Instance so that as you cans see the training Progress
 /*
    static const string executable = "/usr/bin/cw_monitoring.py";
    ifstream f(executable.c_str());
    if ( f.good())
    {
        stringstream command ;
        command <<"python "<< executable << " --metric  "<< metric << " --value "<< value;
        std::cout << "Executing "<< command.str()<< std::endl;
        system(command.str().c_str());
    }
*/
}

void CWMetric::updateMetrics(string metric, int value)
{
    stringstream sValue;
    sValue << value;
    return CWMetric::updateMetrics(metric, sValue.str());

}

void CWMetric::updateMetrics(string metric, unsigned int value)
{
    stringstream sValue;
    sValue << value;
    return CWMetric::updateMetrics(metric, sValue.str());

}

void CWMetric::updateMetrics(string metric, double value)
{
    stringstream sValue;
    sValue << value;
    return CWMetric::updateMetrics(metric, sValue.str());
}

void CWMetric::updateMetrics(string metric, size_t value)
{
    stringstream sValue;
    sValue << value;
    return CWMetric::updateMetrics(metric, sValue.str());
}

char* getCmdOption(char ** begin, char ** end, const std::string & option)
{
    char ** itr = std::find(begin, end, option);
    if (itr != end && ++itr != end)
    {
        return *itr;
    }
    return 0;
}

bool cmdOptionExists(char** begin, char** end, const std::string& option)
{
    return find(begin, end, option) != end;
}

/**
 * Helper function to return the value of a given argument. If it isn't supplied, errors out.
 */
string getRequiredArgValue(int argc, char** argv, string flag, string message, void (*usage)())
{
    if(!cmdOptionExists(argv, argv+argc, flag))
    {
        std::cout << "Error: Missing required argument: " << flag << ": " << message << std::endl;
        usage();
        exit(1);
    }
    else
    {
        return string(getCmdOption(argv, argv + argc, flag));
    }
}

/**
 * Helper function to return the value of a given argument. If it isn't supplied, return the defaultValue.
 */
string getOptionalArgValue(int argc, char** argv, string flag, string defaultValue)
{
    if(!cmdOptionExists(argv, argv+argc, flag))
    {
        return defaultValue;
    }
    else
    {
        return string(getCmdOption(argv, argv + argc, flag));
    }
}

/**
 * Returns true if the argument flag is defined/set.
 */
bool isArgSet(int argc, char** argv, string flag) {
    return cmdOptionExists(argv, argv+argc, flag);
}

/*
This is an utility function which checks the file actually exist
*/
bool fileExists(const std::string& fileName)
{
    ifstream stream(fileName);
    if(stream.good()) {
        return true;
    } else {
        return false;
    }
}

/**
 * Currently we simply use the file extension. Ideally we should use something like the unix
 * file command to determine specific file type.
 */
bool isNetCDFfile(const string &filename)
{
    size_t extIndex = filename.find_last_of(".");
    if (extIndex == string::npos) {
        return false;
    }

    string ext = filename.substr(extIndex);
    return (ext.compare(NETCDF_FILE_EXTENTION) == 0);
}

/*
This is the splitter which is used to split a  string
which is used majorly for splitting our data sets
*/
std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems)
{
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim))
    {
        elems.push_back(item);
    }
    return elems;
}

std::vector<std::string> split(const std::string &s, char delim)
{
    std::vector<std::string> elems;
    split(s, delim, elems);
    return elems;
}

void forceClearVector(vector<unsigned int> &vectorToClear)
{
    vectorToClear.clear();
    vector<unsigned int>(vectorToClear).swap(vectorToClear);
}

void forceClearVector(vector<float> &vectorToClear)
{
    vectorToClear.clear();
    vector<float>(vectorToClear).swap(vectorToClear);
}

double elapsed_time(timeval x, timeval y)
{
    const int uSecondsInSeconds = 1000000;

    timeval result;
    /* Perform the carry for the later subtraction by updating y. */
    if (x.tv_usec < y.tv_usec) {
        int nsec = (y.tv_usec - x.tv_usec) / uSecondsInSeconds + 1;
        y.tv_usec -= uSecondsInSeconds * nsec;
        y.tv_sec += nsec;
    }
    if (x.tv_usec - y.tv_usec > uSecondsInSeconds) {
        int nsec = (x.tv_usec - y.tv_usec) / uSecondsInSeconds;
        y.tv_usec += uSecondsInSeconds * nsec;
        y.tv_sec -= nsec;
    }

    /* Compute the time remaining to wait.
       tv_usec is certainly positive. */
    result.tv_sec = x.tv_sec - y.tv_sec;
    result.tv_usec = x.tv_usec - y.tv_usec;
    return (double) result.tv_sec + ((double) result.tv_usec / (double) uSecondsInSeconds);
}

bool isDirectory(const string &dirname) {
    struct stat buf;
    stat(dirname.c_str(), &buf);
    return S_ISDIR(buf.st_mode);
}

bool isFile(const string &filename) {
    struct stat buf;
    stat(filename.c_str(), &buf);
    return S_ISREG(buf.st_mode);
}

int listFiles(const string &dirname, const bool recursive, vector<string> &files) {
    if (isFile(dirname)) {
        files.push_back(dirname);
    } else if (isDirectory(dirname)) {
        DIR *dp;
        struct dirent *dirp;

        if ((dp = opendir(dirname.data())) != NULL) {
            string normalizedDirname = (dirname[dirname.length() - 1] != '/') ? dirname + "/" : dirname;

            while ((dirp = readdir(dp)) != NULL) {
                char *relativeChildFilePath = dirp->d_name;
                if (strcmp(relativeChildFilePath, ".") == 0 || strcmp(relativeChildFilePath, "..") == 0) {
                    continue;
                }
                string absoluteChildFilePath = normalizedDirname + relativeChildFilePath;

                if (recursive && isDirectory(absoluteChildFilePath)) {
                    listFiles(absoluteChildFilePath, recursive, files);
                } else {
                    files.push_back(absoluteChildFilePath);
                }
            }
        } else {
            std::cerr << "Error(" << errno << ") opening " << dirname << std::endl;
            return errno;
        }
    } else {
        return 1;
    }
    std::sort(files.begin(), files.end());
    return 0;
}
<commit_msg>Fixed resource leak in listFiles(). There was a missing closedir() call.<commit_after>/*

   Copyright 2016  Amazon.com, Inc. or its affiliates. All Rights Reserved.

   Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at

   http://aws.amazon.com/apache2.0/

   or in the "license" file accompanying this file. This file 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 <iostream>
#include <sstream>
#include <algorithm>
#include <fstream>
#include <sys/stat.h>
#include <dirent.h>
#include <cstring>

#include "Utils.h"

using std::stringstream;
using std::ifstream;

void CWMetric::updateMetrics(string metric, string value)
{
//Plugin to Plot Cloudwatch Metrics from the EC2 Instance so that as you cans see the training Progress
 /*
    static const string executable = "/usr/bin/cw_monitoring.py";
    ifstream f(executable.c_str());
    if ( f.good())
    {
        stringstream command ;
        command <<"python "<< executable << " --metric  "<< metric << " --value "<< value;
        std::cout << "Executing "<< command.str()<< std::endl;
        system(command.str().c_str());
    }
*/
}

void CWMetric::updateMetrics(string metric, int value)
{
    stringstream sValue;
    sValue << value;
    return CWMetric::updateMetrics(metric, sValue.str());

}

void CWMetric::updateMetrics(string metric, unsigned int value)
{
    stringstream sValue;
    sValue << value;
    return CWMetric::updateMetrics(metric, sValue.str());

}

void CWMetric::updateMetrics(string metric, double value)
{
    stringstream sValue;
    sValue << value;
    return CWMetric::updateMetrics(metric, sValue.str());
}

void CWMetric::updateMetrics(string metric, size_t value)
{
    stringstream sValue;
    sValue << value;
    return CWMetric::updateMetrics(metric, sValue.str());
}

char* getCmdOption(char ** begin, char ** end, const std::string & option)
{
    char ** itr = std::find(begin, end, option);
    if (itr != end && ++itr != end)
    {
        return *itr;
    }
    return 0;
}

bool cmdOptionExists(char** begin, char** end, const std::string& option)
{
    return find(begin, end, option) != end;
}

/**
 * Helper function to return the value of a given argument. If it isn't supplied, errors out.
 */
string getRequiredArgValue(int argc, char** argv, string flag, string message, void (*usage)())
{
    if(!cmdOptionExists(argv, argv+argc, flag))
    {
        std::cout << "Error: Missing required argument: " << flag << ": " << message << std::endl;
        usage();
        exit(1);
    }
    else
    {
        return string(getCmdOption(argv, argv + argc, flag));
    }
}

/**
 * Helper function to return the value of a given argument. If it isn't supplied, return the defaultValue.
 */
string getOptionalArgValue(int argc, char** argv, string flag, string defaultValue)
{
    if(!cmdOptionExists(argv, argv+argc, flag))
    {
        return defaultValue;
    }
    else
    {
        return string(getCmdOption(argv, argv + argc, flag));
    }
}

/**
 * Returns true if the argument flag is defined/set.
 */
bool isArgSet(int argc, char** argv, string flag) {
    return cmdOptionExists(argv, argv+argc, flag);
}

/*
This is an utility function which checks the file actually exist
*/
bool fileExists(const std::string& fileName)
{
    ifstream stream(fileName);
    if(stream.good()) {
        return true;
    } else {
        return false;
    }
}

/**
 * Currently we simply use the file extension. Ideally we should use something like the unix
 * file command to determine specific file type.
 */
bool isNetCDFfile(const string &filename)
{
    size_t extIndex = filename.find_last_of(".");
    if (extIndex == string::npos) {
        return false;
    }

    string ext = filename.substr(extIndex);
    return (ext.compare(NETCDF_FILE_EXTENTION) == 0);
}

/*
This is the splitter which is used to split a  string
which is used majorly for splitting our data sets
*/
std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems)
{
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim))
    {
        elems.push_back(item);
    }
    return elems;
}

std::vector<std::string> split(const std::string &s, char delim)
{
    std::vector<std::string> elems;
    split(s, delim, elems);
    return elems;
}

void forceClearVector(vector<unsigned int> &vectorToClear)
{
    vectorToClear.clear();
    vector<unsigned int>(vectorToClear).swap(vectorToClear);
}

void forceClearVector(vector<float> &vectorToClear)
{
    vectorToClear.clear();
    vector<float>(vectorToClear).swap(vectorToClear);
}

double elapsed_time(timeval x, timeval y)
{
    const int uSecondsInSeconds = 1000000;

    timeval result;
    /* Perform the carry for the later subtraction by updating y. */
    if (x.tv_usec < y.tv_usec) {
        int nsec = (y.tv_usec - x.tv_usec) / uSecondsInSeconds + 1;
        y.tv_usec -= uSecondsInSeconds * nsec;
        y.tv_sec += nsec;
    }
    if (x.tv_usec - y.tv_usec > uSecondsInSeconds) {
        int nsec = (x.tv_usec - y.tv_usec) / uSecondsInSeconds;
        y.tv_usec += uSecondsInSeconds * nsec;
        y.tv_sec -= nsec;
    }

    /* Compute the time remaining to wait.
       tv_usec is certainly positive. */
    result.tv_sec = x.tv_sec - y.tv_sec;
    result.tv_usec = x.tv_usec - y.tv_usec;
    return (double) result.tv_sec + ((double) result.tv_usec / (double) uSecondsInSeconds);
}

bool isDirectory(const string &dirname) {
    struct stat buf;
    stat(dirname.c_str(), &buf);
    return S_ISDIR(buf.st_mode);
}

bool isFile(const string &filename) {
    struct stat buf;
    stat(filename.c_str(), &buf);
    return S_ISREG(buf.st_mode);
}

int listFiles(const string &dirname, const bool recursive, vector<string> &files) {
    if (isFile(dirname)) {
        files.push_back(dirname);
    } else if (isDirectory(dirname)) {
        DIR *dp;
        struct dirent *dirp;

        if ((dp = opendir(dirname.data())) != NULL) {
            string normalizedDirname = (dirname[dirname.length() - 1] != '/') ? dirname + "/" : dirname;

            while ((dirp = readdir(dp)) != NULL) {
                char *relativeChildFilePath = dirp->d_name;
                if (strcmp(relativeChildFilePath, ".") == 0 || strcmp(relativeChildFilePath, "..") == 0) {
                    continue;
                }
                string absoluteChildFilePath = normalizedDirname + relativeChildFilePath;

                if (recursive && isDirectory(absoluteChildFilePath)) {
                    listFiles(absoluteChildFilePath, recursive, files);
                } else {
                    files.push_back(absoluteChildFilePath);
                }
            }
	    closedir(dp);
        } else {
            std::cerr << "Error(" << errno << ") opening " << dirname << std::endl;
            return errno;
        }
    } else {
        return 1;
    }
    std::sort(files.begin(), files.end());
    return 0;
}
<|endoftext|>