<commit_before>/*
 * Factory.cpp
 *
 *  Created on: Jan 20, 2016
 *      Author: pschultz
 */

#include "Factory.hpp"
#include "include/pv_common.h"

#include "columns/HyPerCol.hpp"

#include "layers/ANNErrorLayer.hpp"
#include "layers/ANNLayer.hpp"
#include "layers/ANNSquaredLayer.hpp"
#include "layers/ANNWhitenedLayer.hpp"
#include "layers/BackgroundLayer.hpp"
#include "layers/BinningLayer.hpp"
#include "layers/CloneVLayer.hpp"
#include "layers/ConstantLayer.hpp"
#include "layers/DropoutLayer.hpp"
#include "layers/FilenameParsingGroundTruthLayer.hpp"
#include "layers/GapLayer.hpp"
#include "layers/HyPerLCALayer.hpp"
#include "layers/HyPerLayer.hpp"
#include "layers/ISTALayer.hpp"
#include "layers/ImageFromMemoryBuffer.hpp"
#include "layers/ImageLayer.hpp"
#include "layers/KmeansLayer.hpp"
#include "layers/LCALIFLayer.hpp"
#include "layers/LIF.hpp"
#include "layers/LIFGap.hpp"
#include "layers/LabelErrorLayer.hpp"
#include "layers/LeakyIntegrator.hpp"
#include "layers/MaskLayer.hpp"
#include "layers/MomentumLCALayer.hpp"
#include "layers/PoolingIndexLayer.hpp"
#include "layers/PtwiseProductLayer.hpp"
#include "layers/PtwiseQuotientLayer.hpp"
#include "layers/PvpLayer.hpp"
#include "layers/RescaleLayer.hpp"
#include "layers/Retina.hpp"
#include "layers/RunningAverageLayer.hpp"
#include "layers/ShuffleLayer.hpp"
#include "layers/SigmoidLayer.hpp"
#include "layers/WTALayer.hpp"

#include "connections/CloneConn.hpp"
#include "connections/CloneKernelConn.hpp"
#include "connections/CopyConn.hpp"
#include "connections/FeedbackConn.hpp"
#include "connections/GapConn.hpp"
#include "connections/HyPerConn.hpp"
#include "connections/IdentConn.hpp"
#include "connections/ImprintConn.hpp"
#include "connections/KernelConn.hpp"
#include "connections/MomentumConn.hpp"
#include "connections/PlasticCloneConn.hpp"
#include "connections/PoolingConn.hpp"
#include "connections/RescaleConn.hpp"
#include "connections/TransposeConn.hpp"
#include "connections/TransposePoolingConn.hpp"

#include "probes/AdaptiveTimeScaleProbe.hpp"
#include "probes/ColumnEnergyProbe.hpp"
#include "probes/FirmThresholdCostFnLCAProbe.hpp"
#include "probes/FirmThresholdCostFnProbe.hpp"
#include "probes/KernelProbe.hpp"
#include "probes/KneeTimeScaleProbe.hpp"
#include "probes/L0NormLCAProbe.hpp"
#include "probes/L0NormProbe.hpp"
#include "probes/L1NormLCAProbe.hpp"
#include "probes/L1NormProbe.hpp"
#include "probes/L2NormProbe.hpp"
#include "probes/LogTimeScaleProbe.hpp"
#include "probes/PointLIFProbe.hpp"
#include "probes/PointProbe.hpp"
#include "probes/QuotientColProbe.hpp"
#include "probes/RequireAllZeroActivityProbe.hpp"
#include "probes/StatsProbe.hpp"

#include "initv/ConstantV.hpp"
#include "initv/GaussianRandomV.hpp"
#include "initv/InitVFromFile.hpp"
#include "initv/UniformRandomV.hpp"
#include "initv/ZeroV.hpp"

#include "weightinit/InitCocircWeights.hpp"
#include "weightinit/InitGauss2DWeights.hpp"
#include "weightinit/InitGaussianRandomWeights.hpp"
#include "weightinit/InitIdentWeights.hpp"
#include "weightinit/InitMaxPoolingWeights.hpp"
#include "weightinit/InitOneToOneWeights.hpp"
#include "weightinit/InitOneToOneWeightsWithDelays.hpp"
#include "weightinit/InitSmartWeights.hpp"
#include "weightinit/InitSpreadOverArborsWeights.hpp"
#include "weightinit/InitUniformRandomWeights.hpp"
#include "weightinit/InitUniformWeights.hpp"
#include "weightinit/InitWeights.hpp"

#include "normalizers/NormalizeContrastZeroMean.hpp"
#include "normalizers/NormalizeGroup.hpp"
#include "normalizers/NormalizeL2.hpp"
#include "normalizers/NormalizeMax.hpp"
#include "normalizers/NormalizeSum.hpp"

namespace PV {

Factory::Factory() { registerCoreKeywords(); }

int Factory::registerCoreKeywords() {
   keywordHandlerList = std::vector<KeywordHandler *>();

   registerKeyword("Image", Factory::create<BaseInputDeprecatedError>);
   registerKeyword("Movie", Factory::create<BaseInputDeprecatedError>);
   registerKeyword("ImagePvp", Factory::create<BaseInputDeprecatedError>);
   registerKeyword("MoviePvp", Factory::create<BaseInputDeprecatedError>);

   registerKeyword("ANNErrorLayer", Factory::create<ANNErrorLayer>);
   registerKeyword("ANNLayer", Factory::create<ANNLayer>);
   registerKeyword("ANNSquaredLayer", Factory::create<ANNSquaredLayer>);
   registerKeyword("ANNWhitenedLayer", Factory::create<ANNWhitenedLayer>);
   registerKeyword("BackgroundLayer", Factory::create<BackgroundLayer>);
   registerKeyword("BinningLayer", Factory::create<BinningLayer>);
   registerKeyword("CloneVLayer", Factory::create<CloneVLayer>);
   registerKeyword("ConstantLayer", Factory::create<ConstantLayer>);
   registerKeyword("DropoutLayer", Factory::create<DropoutLayer>);
   registerKeyword(
         "FilenameParsingGroundTruthLayer", Factory::create<FilenameParsingGroundTruthLayer>);
   registerKeyword("GapLayer", Factory::create<GapLayer>);
   registerKeyword("HyPerLayer", Factory::create<HyPerLayer>);
   registerKeyword("HyPerLCALayer", Factory::create<HyPerLCALayer>);
   registerKeyword("ISTALayer", Factory::create<ISTALayer>);

   registerKeyword("ImageLayer", Factory::create<ImageLayer>);
   registerKeyword("PvpLayer", Factory::create<PvpLayer>);
   registerKeyword("ImageFromMemoryBuffer", Factory::create<ImageFromMemoryBuffer>);
   registerKeyword("KmeansLayer", Factory::create<KmeansLayer>);
   registerKeyword("LCALIFLayer", Factory::create<LCALIFLayer>);
   registerKeyword("LIF", Factory::create<LIF>);
   registerKeyword("LIFGap", Factory::create<LIFGap>);
   registerKeyword("LabelErrorLayer", Factory::create<LabelErrorLayer>);
   registerKeyword("LeakyIntegrator", Factory::create<LeakyIntegrator>);
   registerKeyword("MaskLayer", Factory::create<MaskLayer>);
   registerKeyword("MomentumLCALayer", Factory::create<MomentumLCALayer>);
   registerKeyword("PoolingIndexLayer", Factory::create<PoolingIndexLayer>);
   registerKeyword("PtwiseProductLayer", Factory::create<PtwiseProductLayer>);
   registerKeyword("PtwiseQuotientLayer", Factory::create<PtwiseQuotientLayer>);
   registerKeyword("RescaleLayer", Factory::create<RescaleLayer>);
   registerKeyword("RunningAverageLayer", Factory::create<RunningAverageLayer>);
   registerKeyword("Retina", Factory::create<Retina>);
   registerKeyword("ShuffleLayer", Factory::create<ShuffleLayer>);
   registerKeyword("SigmoidLayer", Factory::create<SigmoidLayer>);
   registerKeyword("WTALayer", Factory::create<WTALayer>);

   registerKeyword("HyPerConn", Factory::create<HyPerConn>);
   registerKeyword("CloneConn", Factory::create<CloneConn>);
   registerKeyword("CloneKernelConn", Factory::create<CloneKernelConn>);
   registerKeyword("CopyConn", Factory::create<CopyConn>);
   registerKeyword("FeedbackConn", Factory::create<FeedbackConn>);
   registerKeyword("GapConn", Factory::create<GapConn>);
   registerKeyword("IdentConn", Factory::create<IdentConn>);
   registerKeyword("ImprintConn", Factory::create<ImprintConn>);
   registerKeyword("KernelConn", Factory::create<KernelConn>);
   registerKeyword("MomentumConn", Factory::create<MomentumConn>);
   registerKeyword("PlasticCloneConn", Factory::create<PlasticCloneConn>);
   registerKeyword("PoolingConn", Factory::create<PoolingConn>);
   registerKeyword("RescaleConn", Factory::create<RescaleConn>);
   registerKeyword("TransposeConn", Factory::create<TransposeConn>);
   registerKeyword("TransposePoolingConn", Factory::create<TransposePoolingConn>);
   registerKeyword("AdaptiveTimeScaleProbe", Factory::create<AdaptiveTimeScaleProbe>);
   registerKeyword("KneeTimeScaleProbe", Factory::create<KneeTimeScaleProbe>);
   registerKeyword("LogTimeScaleProbe", Factory::create<LogTimeScaleProbe>);
   registerKeyword("ColumnEnergyProbe", Factory::create<ColumnEnergyProbe>);
   registerKeyword("FirmThresholdCostFnLCAProbe", Factory::create<FirmThresholdCostFnLCAProbe>);
   registerKeyword("FirmThresholdCostFnProbe", Factory::create<FirmThresholdCostFnProbe>);
   registerKeyword("KernelProbe", Factory::create<KernelProbe>);
   registerKeyword("L0NormLCAProbe", Factory::create<L0NormLCAProbe>);
   registerKeyword("L0NormProbe", Factory::create<L0NormProbe>);
   registerKeyword("L1NormLCAProbe", Factory::create<L1NormLCAProbe>);
   registerKeyword("L1NormProbe", Factory::create<L1NormProbe>);
   registerKeyword("L2NormProbe", Factory::create<L2NormProbe>);
   registerKeyword("PointLIFProbe", Factory::create<PointLIFProbe>);
   registerKeyword("PointProbe", Factory::create<PointProbe>);
   registerKeyword("QuotientColProbe", Factory::create<QuotientColProbe>);
   registerKeyword("RequireAllZeroActivityProbe", Factory::create<RequireAllZeroActivityProbe>);
   registerKeyword("StatsProbe", Factory::create<StatsProbe>);

   registerKeyword("ConstantV", Factory::create<ConstantV>);
   registerKeyword("GaussianRandomV", Factory::create<GaussianRandomV>);
   registerKeyword("InitVFromFile", Factory::create<InitVFromFile>);
   registerKeyword("UniformRandomV", Factory::create<UniformRandomV>);
   registerKeyword("ZeroV", Factory::create<ZeroV>);

   registerKeyword("Gauss2DWeight", Factory::create<InitGauss2DWeights>);
   registerKeyword("CoCircWeight", Factory::create<InitCocircWeights>);
   registerKeyword("UniformWeight", Factory::create<InitUniformWeights>);
   registerKeyword("SmartWeight", Factory::create<InitSmartWeights>);
   registerKeyword("UniformRandomWeight", Factory::create<InitUniformRandomWeights>);
   registerKeyword("GaussianRandomWeight", Factory::create<InitGaussianRandomWeights>);
   registerKeyword("IdentWeight", Factory::create<InitIdentWeights>);
   registerKeyword("OneToOneWeights", Factory::create<InitOneToOneWeights>);
   registerKeyword("OneToOneWeightsWithDelays", Factory::create<InitOneToOneWeightsWithDelays>);
   registerKeyword("SpreadOverArborsWeight", Factory::create<InitSpreadOverArborsWeights>);
   registerKeyword("MaxPoolingWeight", Factory::create<InitMaxPoolingWeights>);
   registerKeyword("FileWeight", Factory::create<InitWeights>);

   registerKeyword("normalizeContrastZeroMean", Factory::create<NormalizeContrastZeroMean>);
   registerKeyword("normalizeL2", Factory::create<NormalizeL2>);
   registerKeyword("normalizeMax", Factory::create<NormalizeMax>);
   registerKeyword("normalizeSum", Factory::create<NormalizeSum>);
   registerKeyword("normalizeGroup", Factory::create<NormalizeGroup>);

   return PV_SUCCESS;
}

int Factory::copyKeywordHandlerList(std::vector<KeywordHandler *> const &orig) {
   for (auto &kh : orig) {
      registerKeyword(kh->getKeyword(), kh->getCreator());
   }
   return PV_SUCCESS;
}

int Factory::registerKeyword(char const *keyword, ObjectCreateFn creator) {
   KeywordHandler const *keywordHandler = getKeywordHandler(keyword);
   if (keywordHandler != nullptr) {
      return PV_FAILURE;
   }
   KeywordHandler *newKeyword = new KeywordHandler(keyword, creator);
   keywordHandlerList.push_back(newKeyword);
   return PV_SUCCESS;
}

BaseObject *Factory::createByKeyword(char const *keyword, char const *name, HyPerCol *hc) const {
   // Sep 21, 2016: PtwiseLinearTransferLayer marked obsolete.
   if (!strcmp(keyword, "PtwiseLinearTransferLayer")) {
      Fatal() << keyword << " \"" << name
              << "\": PtwiseLinearTransferLayer is obsolete. Use ANNLayer instead.\n";
   }
   KeywordHandler const *keywordHandler = getKeywordHandler(keyword);
   if (keywordHandler == nullptr) {
      auto errorString = std::string("Unrecognized keyword ").append(keyword);
      throw std::invalid_argument(errorString);
   }
   return keywordHandler ? keywordHandler->create(name, hc) : nullptr;
}

KeywordHandler const *Factory::getKeywordHandler(char const *keyword) const {
   for (auto &typeCreator : keywordHandlerList) {
      if (!strcmp(typeCreator->getKeyword(), keyword)) {
         return typeCreator;
      }
   }
   return nullptr;
}

int Factory::clearKeywordHandlerList() {
   for (auto &kh : keywordHandlerList) {
      delete kh;
   }
   keywordHandlerList.clear();
   return PV_SUCCESS;
}

Factory::~Factory() { clearKeywordHandlerList(); }

} /* namespace PV */
<commit_msg>Removed error for long-obsolete PtwiseLinearTransferLayer<commit_after>/*
 * Factory.cpp
 *
 *  Created on: Jan 20, 2016
 *      Author: pschultz
 */

#include "Factory.hpp"
#include "include/pv_common.h"

#include "columns/HyPerCol.hpp"

#include "layers/ANNErrorLayer.hpp"
#include "layers/ANNLayer.hpp"
#include "layers/ANNSquaredLayer.hpp"
#include "layers/ANNWhitenedLayer.hpp"
#include "layers/BackgroundLayer.hpp"
#include "layers/BinningLayer.hpp"
#include "layers/CloneVLayer.hpp"
#include "layers/ConstantLayer.hpp"
#include "layers/DropoutLayer.hpp"
#include "layers/FilenameParsingGroundTruthLayer.hpp"
#include "layers/GapLayer.hpp"
#include "layers/HyPerLCALayer.hpp"
#include "layers/HyPerLayer.hpp"
#include "layers/ISTALayer.hpp"
#include "layers/ImageFromMemoryBuffer.hpp"
#include "layers/ImageLayer.hpp"
#include "layers/KmeansLayer.hpp"
#include "layers/LCALIFLayer.hpp"
#include "layers/LIF.hpp"
#include "layers/LIFGap.hpp"
#include "layers/LabelErrorLayer.hpp"
#include "layers/LeakyIntegrator.hpp"
#include "layers/MaskLayer.hpp"
#include "layers/MomentumLCALayer.hpp"
#include "layers/PoolingIndexLayer.hpp"
#include "layers/PtwiseProductLayer.hpp"
#include "layers/PtwiseQuotientLayer.hpp"
#include "layers/PvpLayer.hpp"
#include "layers/RescaleLayer.hpp"
#include "layers/Retina.hpp"
#include "layers/RunningAverageLayer.hpp"
#include "layers/ShuffleLayer.hpp"
#include "layers/SigmoidLayer.hpp"
#include "layers/WTALayer.hpp"

#include "connections/CloneConn.hpp"
#include "connections/CloneKernelConn.hpp"
#include "connections/CopyConn.hpp"
#include "connections/FeedbackConn.hpp"
#include "connections/GapConn.hpp"
#include "connections/HyPerConn.hpp"
#include "connections/IdentConn.hpp"
#include "connections/ImprintConn.hpp"
#include "connections/KernelConn.hpp"
#include "connections/MomentumConn.hpp"
#include "connections/PlasticCloneConn.hpp"
#include "connections/PoolingConn.hpp"
#include "connections/RescaleConn.hpp"
#include "connections/TransposeConn.hpp"
#include "connections/TransposePoolingConn.hpp"

#include "probes/AdaptiveTimeScaleProbe.hpp"
#include "probes/ColumnEnergyProbe.hpp"
#include "probes/FirmThresholdCostFnLCAProbe.hpp"
#include "probes/FirmThresholdCostFnProbe.hpp"
#include "probes/KernelProbe.hpp"
#include "probes/KneeTimeScaleProbe.hpp"
#include "probes/L0NormLCAProbe.hpp"
#include "probes/L0NormProbe.hpp"
#include "probes/L1NormLCAProbe.hpp"
#include "probes/L1NormProbe.hpp"
#include "probes/L2NormProbe.hpp"
#include "probes/LogTimeScaleProbe.hpp"
#include "probes/PointLIFProbe.hpp"
#include "probes/PointProbe.hpp"
#include "probes/QuotientColProbe.hpp"
#include "probes/RequireAllZeroActivityProbe.hpp"
#include "probes/StatsProbe.hpp"

#include "initv/ConstantV.hpp"
#include "initv/GaussianRandomV.hpp"
#include "initv/InitVFromFile.hpp"
#include "initv/UniformRandomV.hpp"
#include "initv/ZeroV.hpp"

#include "weightinit/InitCocircWeights.hpp"
#include "weightinit/InitGauss2DWeights.hpp"
#include "weightinit/InitGaussianRandomWeights.hpp"
#include "weightinit/InitIdentWeights.hpp"
#include "weightinit/InitMaxPoolingWeights.hpp"
#include "weightinit/InitOneToOneWeights.hpp"
#include "weightinit/InitOneToOneWeightsWithDelays.hpp"
#include "weightinit/InitSmartWeights.hpp"
#include "weightinit/InitSpreadOverArborsWeights.hpp"
#include "weightinit/InitUniformRandomWeights.hpp"
#include "weightinit/InitUniformWeights.hpp"
#include "weightinit/InitWeights.hpp"

#include "normalizers/NormalizeContrastZeroMean.hpp"
#include "normalizers/NormalizeGroup.hpp"
#include "normalizers/NormalizeL2.hpp"
#include "normalizers/NormalizeMax.hpp"
#include "normalizers/NormalizeSum.hpp"

namespace PV {

Factory::Factory() { registerCoreKeywords(); }

int Factory::registerCoreKeywords() {
   keywordHandlerList = std::vector<KeywordHandler *>();

   registerKeyword("Image", Factory::create<BaseInputDeprecatedError>);
   registerKeyword("Movie", Factory::create<BaseInputDeprecatedError>);
   registerKeyword("ImagePvp", Factory::create<BaseInputDeprecatedError>);
   registerKeyword("MoviePvp", Factory::create<BaseInputDeprecatedError>);

   registerKeyword("ANNErrorLayer", Factory::create<ANNErrorLayer>);
   registerKeyword("ANNLayer", Factory::create<ANNLayer>);
   registerKeyword("ANNSquaredLayer", Factory::create<ANNSquaredLayer>);
   registerKeyword("ANNWhitenedLayer", Factory::create<ANNWhitenedLayer>);
   registerKeyword("BackgroundLayer", Factory::create<BackgroundLayer>);
   registerKeyword("BinningLayer", Factory::create<BinningLayer>);
   registerKeyword("CloneVLayer", Factory::create<CloneVLayer>);
   registerKeyword("ConstantLayer", Factory::create<ConstantLayer>);
   registerKeyword("DropoutLayer", Factory::create<DropoutLayer>);
   registerKeyword(
         "FilenameParsingGroundTruthLayer", Factory::create<FilenameParsingGroundTruthLayer>);
   registerKeyword("GapLayer", Factory::create<GapLayer>);
   registerKeyword("HyPerLayer", Factory::create<HyPerLayer>);
   registerKeyword("HyPerLCALayer", Factory::create<HyPerLCALayer>);
   registerKeyword("ISTALayer", Factory::create<ISTALayer>);

   registerKeyword("ImageLayer", Factory::create<ImageLayer>);
   registerKeyword("PvpLayer", Factory::create<PvpLayer>);
   registerKeyword("ImageFromMemoryBuffer", Factory::create<ImageFromMemoryBuffer>);
   registerKeyword("KmeansLayer", Factory::create<KmeansLayer>);
   registerKeyword("LCALIFLayer", Factory::create<LCALIFLayer>);
   registerKeyword("LIF", Factory::create<LIF>);
   registerKeyword("LIFGap", Factory::create<LIFGap>);
   registerKeyword("LabelErrorLayer", Factory::create<LabelErrorLayer>);
   registerKeyword("LeakyIntegrator", Factory::create<LeakyIntegrator>);
   registerKeyword("MaskLayer", Factory::create<MaskLayer>);
   registerKeyword("MomentumLCALayer", Factory::create<MomentumLCALayer>);
   registerKeyword("PoolingIndexLayer", Factory::create<PoolingIndexLayer>);
   registerKeyword("PtwiseProductLayer", Factory::create<PtwiseProductLayer>);
   registerKeyword("PtwiseQuotientLayer", Factory::create<PtwiseQuotientLayer>);
   registerKeyword("RescaleLayer", Factory::create<RescaleLayer>);
   registerKeyword("RunningAverageLayer", Factory::create<RunningAverageLayer>);
   registerKeyword("Retina", Factory::create<Retina>);
   registerKeyword("ShuffleLayer", Factory::create<ShuffleLayer>);
   registerKeyword("SigmoidLayer", Factory::create<SigmoidLayer>);
   registerKeyword("WTALayer", Factory::create<WTALayer>);

   registerKeyword("HyPerConn", Factory::create<HyPerConn>);
   registerKeyword("CloneConn", Factory::create<CloneConn>);
   registerKeyword("CloneKernelConn", Factory::create<CloneKernelConn>);
   registerKeyword("CopyConn", Factory::create<CopyConn>);
   registerKeyword("FeedbackConn", Factory::create<FeedbackConn>);
   registerKeyword("GapConn", Factory::create<GapConn>);
   registerKeyword("IdentConn", Factory::create<IdentConn>);
   registerKeyword("ImprintConn", Factory::create<ImprintConn>);
   registerKeyword("KernelConn", Factory::create<KernelConn>);
   registerKeyword("MomentumConn", Factory::create<MomentumConn>);
   registerKeyword("PlasticCloneConn", Factory::create<PlasticCloneConn>);
   registerKeyword("PoolingConn", Factory::create<PoolingConn>);
   registerKeyword("RescaleConn", Factory::create<RescaleConn>);
   registerKeyword("TransposeConn", Factory::create<TransposeConn>);
   registerKeyword("TransposePoolingConn", Factory::create<TransposePoolingConn>);
   registerKeyword("AdaptiveTimeScaleProbe", Factory::create<AdaptiveTimeScaleProbe>);
   registerKeyword("KneeTimeScaleProbe", Factory::create<KneeTimeScaleProbe>);
   registerKeyword("LogTimeScaleProbe", Factory::create<LogTimeScaleProbe>);
   registerKeyword("ColumnEnergyProbe", Factory::create<ColumnEnergyProbe>);
   registerKeyword("FirmThresholdCostFnLCAProbe", Factory::create<FirmThresholdCostFnLCAProbe>);
   registerKeyword("FirmThresholdCostFnProbe", Factory::create<FirmThresholdCostFnProbe>);
   registerKeyword("KernelProbe", Factory::create<KernelProbe>);
   registerKeyword("L0NormLCAProbe", Factory::create<L0NormLCAProbe>);
   registerKeyword("L0NormProbe", Factory::create<L0NormProbe>);
   registerKeyword("L1NormLCAProbe", Factory::create<L1NormLCAProbe>);
   registerKeyword("L1NormProbe", Factory::create<L1NormProbe>);
   registerKeyword("L2NormProbe", Factory::create<L2NormProbe>);
   registerKeyword("PointLIFProbe", Factory::create<PointLIFProbe>);
   registerKeyword("PointProbe", Factory::create<PointProbe>);
   registerKeyword("QuotientColProbe", Factory::create<QuotientColProbe>);
   registerKeyword("RequireAllZeroActivityProbe", Factory::create<RequireAllZeroActivityProbe>);
   registerKeyword("StatsProbe", Factory::create<StatsProbe>);

   registerKeyword("ConstantV", Factory::create<ConstantV>);
   registerKeyword("GaussianRandomV", Factory::create<GaussianRandomV>);
   registerKeyword("InitVFromFile", Factory::create<InitVFromFile>);
   registerKeyword("UniformRandomV", Factory::create<UniformRandomV>);
   registerKeyword("ZeroV", Factory::create<ZeroV>);

   registerKeyword("Gauss2DWeight", Factory::create<InitGauss2DWeights>);
   registerKeyword("CoCircWeight", Factory::create<InitCocircWeights>);
   registerKeyword("UniformWeight", Factory::create<InitUniformWeights>);
   registerKeyword("SmartWeight", Factory::create<InitSmartWeights>);
   registerKeyword("UniformRandomWeight", Factory::create<InitUniformRandomWeights>);
   registerKeyword("GaussianRandomWeight", Factory::create<InitGaussianRandomWeights>);
   registerKeyword("IdentWeight", Factory::create<InitIdentWeights>);
   registerKeyword("OneToOneWeights", Factory::create<InitOneToOneWeights>);
   registerKeyword("OneToOneWeightsWithDelays", Factory::create<InitOneToOneWeightsWithDelays>);
   registerKeyword("SpreadOverArborsWeight", Factory::create<InitSpreadOverArborsWeights>);
   registerKeyword("MaxPoolingWeight", Factory::create<InitMaxPoolingWeights>);
   registerKeyword("FileWeight", Factory::create<InitWeights>);

   registerKeyword("normalizeContrastZeroMean", Factory::create<NormalizeContrastZeroMean>);
   registerKeyword("normalizeL2", Factory::create<NormalizeL2>);
   registerKeyword("normalizeMax", Factory::create<NormalizeMax>);
   registerKeyword("normalizeSum", Factory::create<NormalizeSum>);
   registerKeyword("normalizeGroup", Factory::create<NormalizeGroup>);

   return PV_SUCCESS;
}

int Factory::copyKeywordHandlerList(std::vector<KeywordHandler *> const &orig) {
   for (auto &kh : orig) {
      registerKeyword(kh->getKeyword(), kh->getCreator());
   }
   return PV_SUCCESS;
}

int Factory::registerKeyword(char const *keyword, ObjectCreateFn creator) {
   KeywordHandler const *keywordHandler = getKeywordHandler(keyword);
   if (keywordHandler != nullptr) {
      return PV_FAILURE;
   }
   KeywordHandler *newKeyword = new KeywordHandler(keyword, creator);
   keywordHandlerList.push_back(newKeyword);
   return PV_SUCCESS;
}

BaseObject *Factory::createByKeyword(char const *keyword, char const *name, HyPerCol *hc) const {
   KeywordHandler const *keywordHandler = getKeywordHandler(keyword);
   if (keywordHandler == nullptr) {
      auto errorString = std::string("Unrecognized keyword ").append(keyword);
      throw std::invalid_argument(errorString);
   }
   return keywordHandler ? keywordHandler->create(name, hc) : nullptr;
}

KeywordHandler const *Factory::getKeywordHandler(char const *keyword) const {
   for (auto &typeCreator : keywordHandlerList) {
      if (!strcmp(typeCreator->getKeyword(), keyword)) {
         return typeCreator;
      }
   }
   return nullptr;
}

int Factory::clearKeywordHandlerList() {
   for (auto &kh : keywordHandlerList) {
      delete kh;
   }
   keywordHandlerList.clear();
   return PV_SUCCESS;
}

Factory::~Factory() { clearKeywordHandlerList(); }

} /* namespace PV */
<|endoftext|>


<commit_before>/*
 * PV_Init.cpp
 *
 *  Created on: Jul 31, 2015
 *      Author: slundquist
 */
#include <csignal>
#include <cMakeHeader.h>
#ifdef PV_USE_OPENMP_THREADS
#include <omp.h>
#endif // PV_USE_OPENMP_THREADS
#include "PV_Init.hpp"
#include "utils/PVLog.hpp"
#include "columns/HyPerCol.hpp"

namespace PV {

PV_Init::PV_Init(int* argc, char ** argv[], bool allowUnrecognizedArguments){
   //Initialize MPI
   initSignalHandler();
   commInit(argc, argv);
   initMaxThreads();
   params = nullptr;
   mCommunicator = nullptr;
   arguments = new PV_Arguments(*argc, *argv, allowUnrecognizedArguments);
   initLogFile(false/*appendFlag*/);
   initialize(); // must follow initialization of arguments data member.
}

PV_Init::~PV_Init(){
   delete params;
   delete mCommunicator;
   delete arguments;
   commFinalize();
}

int PV_Init::initSignalHandler()
{
   // Block SIGUSR1.  root process checks for SIGUSR1 during advanceTime() and broadcasts sends to all processes,
   // which saves the result in the checkpointSignal member variable.
   // When run() checks whether to call checkpointWrite, it looks at checkpointSignal, and writes a
   // checkpoint if checkpointWriteFlag is true, regardless of whether the next scheduled checkpoint time has arrived.
   //
   // This routine must be called before MPI_Initialize; otherwise a thread created by MPI will not get the signal handler
   // but will get the signal and the job will terminate.
   sigset_t blockusr1;
   sigemptyset(&blockusr1);
   sigaddset(&blockusr1, SIGUSR1);
   sigprocmask(SIG_BLOCK, &blockusr1, NULL);
   return 0;
}

int PV_Init::initialize() {
   delete mCommunicator;
   mCommunicator = new Communicator(arguments);
   int status = PV_SUCCESS;
   // It is okay to initialize without there being a params file.
   // setParams() can be called later.
   delete params; params = NULL;
   if (arguments->getParamsFile()) {
      status = createParams();
   }
   printInitMessage();
   return status;
}

int PV_Init::initMaxThreads() {
#ifdef PV_USE_OPENMP_THREADS
   maxThreads = omp_get_max_threads();
#else // PV_USE_OPENMP_THREADS
   maxThreads = 1;
#endif // PV_USE_OPENMP_THREADS
   return PV_SUCCESS;
}

int PV_Init::commInit(int* argc, char*** argv)
{
   int mpiInit;
   // If MPI wasn't initialized, initialize it.
   // Remember if it was initialized on entry; the destructor will only finalize if the constructor init'ed.
   // This way, you can do several simulations sequentially by initializing MPI before creating
   // the first HyPerCol; after running the first simulation the MPI environment will still exist and you
   // can run the second simulation, etc.
   MPI_Initialized(&mpiInit);
   if( !mpiInit) {
      pvAssert((*argv)[*argc]==NULL); // Open MPI 1.7 assumes this.
      MPI_Init(argc, argv);
   }
   else{
      pvError() << "PV_Init communicator already initialized\n";
   }

   return 0;
}

void PV_Init::initLogFile(bool appendFlag) {
   // TODO: Under MPI, non-root processes should send messages to root process.
   // Currently, if logFile is directory/filename.txt, the root process writes to that path,
   // and nonroot processes write to directory/filename_<rank>.txt, where <rank> is replaced with the global rank.
   // If filename does not have an extension, _<rank> is appended.
   // Note that the global rank zero process does not insert _<rank>.  This is deliberate, as the nonzero ranks
   // should be MPI-ing the data to the zero rank.
   char const * logFile = arguments->getLogFile();
   int const globalRootProcess = 0;
   int globalRank;
   MPI_Comm_rank(MPI_COMM_WORLD, &globalRank);
   std::ios_base::openmode mode = appendFlag ? std::ios_base::out | std::ios_base::app : std::ios_base::out;
   if (logFile && globalRank != globalRootProcess) {
      // To prevent collisions caused by multiple processes opening the same file for logging,
      // processes with global rank other than zero append the rank to the log filename.
      // If the logfile has an extension (e.g. ".log", ".txt"), the rank is appended before the
      // period separating the extension.
      std::string logFileString(logFile);
      size_t finalSlash = logFileString.rfind('/');
      size_t finalDot = logFileString.rfind('.');
      size_t insertionPoint;
      if (finalDot == std::string::npos || (finalSlash!=std::string::npos && finalDot < finalSlash) ) {
         insertionPoint = logFileString.length();
      }
      else {
         insertionPoint = finalDot;
      }
      logFileString.insert(finalDot, std::to_string(globalRank)).insert(finalDot, "_");
      PV::setLogFile(logFileString.c_str(), mode);
   }
   else {
      PV::setLogFile(logFile, mode);
   }
}

int PV_Init::setParams(char const * params_file) {
   if (params_file == NULL) { return PV_FAILURE; }
   char const * newParamsFile = arguments->setParamsFile(params_file);
   if (newParamsFile==NULL) {
      pvErrorNoExit().printf("PV_Init unable to set new params file: %s\n", strerror(errno));
      return PV_FAILURE;
   }
   initialize();
   return createParams();
}

int PV_Init::createParams() {
   char const * params_file = arguments->getParamsFile();
   if (params_file) {
      delete params;
      params = new PVParams(params_file, 2*(INITIAL_LAYER_ARRAY_SIZE+INITIAL_CONNECTION_ARRAY_SIZE), mCommunicator);
      return PV_SUCCESS;
   }
   else {
      return PV_FAILURE;
   }
}

int PV_Init::setLogFile(char const * log_file, bool appendFlag) {
   arguments->setLogFile(log_file);
   initLogFile(appendFlag);
   printInitMessage();
}

int PV_Init::setMPIConfiguration(int rows, int columns, int batchWidth) {
   if (rows >= 0) { arguments->setNumRows(rows); }
   if (columns >= 0) { arguments->setNumColumns(columns); }
   if (batchWidth >= 0) { arguments->setBatchWidth(batchWidth); }
   initialize();
   return PV_SUCCESS;
}

void PV_Init::printInitMessage() {
   time_t currentTime = time(nullptr);
   pvInfo() << "PetaVision initialized at " << ctime(&currentTime); // string returned by ctime contains a trailing \n.
   pvInfo() << "Command line arguments are:\n";
   printState();
}

int PV_Init::resetState() {
   return arguments->resetState();
}

int PV_Init::registerKeyword(char const * keyword, ObjectCreateFn creator) {
   int status = Factory::instance()->registerKeyword(keyword, creator);
   if (status != PV_SUCCESS) {
      if (getWorldRank()==0) {
         pvErrorNoExit().printf("PV_Init: keyword \"%s\" has already been registered.\n", keyword);
      }
   }
   return status;
}

#ifdef OBSOLETE // Marked obsolete Jul 19, 2016.  Use hc=createHyPerCol(pv_init_ptr) instead of hc=pv_init_ptr->build().
HyPerCol * PV_Init::build() {
   HyPerCol * hc = new HyPerCol("column", this);
   if( hc == NULL ) {
      pvErrorNoExit().printf("Unable to create HyPerCol\n");
      return NULL;
   }
   PVParams * hcparams = hc->parameters();
   int numGroups = hcparams->numberOfGroups();

   // Make sure first group defines a column
   if( strcmp(hcparams->groupKeywordFromIndex(0), "HyPerCol") ) {
      pvErrorNoExit().printf("First group in the params file did not define a HyPerCol.\n");
      delete hc;
      return NULL;
   }

   for (int k=0; k<numGroups; k++) {
      const char * kw = hcparams->groupKeywordFromIndex(k);
      const char * name = hcparams->groupNameFromIndex(k);
      if (!strcmp(kw, "HyPerCol")) {
         if (k==0) { continue; }
         else {
            if (hc->columnId()==0) {
               pvErrorNoExit().printf("Group %d in params file (\"%s\") is a HyPerCol; the HyPerCol must be the first group.\n",
                       k+1, name);
            }
            delete hc;
            return NULL;
         }
      }
      else {
         BaseObject * addedObject = factory->create(kw, name, hc);
         if (addedObject==NULL) {
            if (hc->globalRank()==0) {
               pvErrorNoExit().printf("Unable to create %s \"%s\".\n", kw, name);
            }
            delete hc;
            return NULL;
         }
      }
   }

   if( hc->numberOfLayers() == 0 ) {
      pvErrorNoExit().printf("HyPerCol \"%s\" does not have any layers.\n", hc->getName());
      delete hc;
      return NULL;
   }
   return hc;
}
#endif // OBSOLETE // Marked obsolete Jul 19, 2016.  Use hc=createHyPerCol(pv_init_ptr) instead of hc=pv_init_ptr->build().

int PV_Init::commFinalize()
{
   MPI_Finalize();
   return 0;
}

} // namespace PV

<commit_msg>Bugfix for filename of logfiles on non-root processes<commit_after>/*
 * PV_Init.cpp
 *
 *  Created on: Jul 31, 2015
 *      Author: slundquist
 */
#include <csignal>
#include <cMakeHeader.h>
#ifdef PV_USE_OPENMP_THREADS
#include <omp.h>
#endif // PV_USE_OPENMP_THREADS
#include "PV_Init.hpp"
#include "utils/PVLog.hpp"
#include "columns/HyPerCol.hpp"

namespace PV {

PV_Init::PV_Init(int* argc, char ** argv[], bool allowUnrecognizedArguments){
   //Initialize MPI
   initSignalHandler();
   commInit(argc, argv);
   initMaxThreads();
   params = nullptr;
   mCommunicator = nullptr;
   arguments = new PV_Arguments(*argc, *argv, allowUnrecognizedArguments);
   initLogFile(false/*appendFlag*/);
   initialize(); // must follow initialization of arguments data member.
}

PV_Init::~PV_Init(){
   delete params;
   delete mCommunicator;
   delete arguments;
   commFinalize();
}

int PV_Init::initSignalHandler()
{
   // Block SIGUSR1.  root process checks for SIGUSR1 during advanceTime() and broadcasts sends to all processes,
   // which saves the result in the checkpointSignal member variable.
   // When run() checks whether to call checkpointWrite, it looks at checkpointSignal, and writes a
   // checkpoint if checkpointWriteFlag is true, regardless of whether the next scheduled checkpoint time has arrived.
   //
   // This routine must be called before MPI_Initialize; otherwise a thread created by MPI will not get the signal handler
   // but will get the signal and the job will terminate.
   sigset_t blockusr1;
   sigemptyset(&blockusr1);
   sigaddset(&blockusr1, SIGUSR1);
   sigprocmask(SIG_BLOCK, &blockusr1, NULL);
   return 0;
}

int PV_Init::initialize() {
   delete mCommunicator;
   mCommunicator = new Communicator(arguments);
   int status = PV_SUCCESS;
   // It is okay to initialize without there being a params file.
   // setParams() can be called later.
   delete params; params = NULL;
   if (arguments->getParamsFile()) {
      status = createParams();
   }
   printInitMessage();
   return status;
}

int PV_Init::initMaxThreads() {
#ifdef PV_USE_OPENMP_THREADS
   maxThreads = omp_get_max_threads();
#else // PV_USE_OPENMP_THREADS
   maxThreads = 1;
#endif // PV_USE_OPENMP_THREADS
   return PV_SUCCESS;
}

int PV_Init::commInit(int* argc, char*** argv)
{
   int mpiInit;
   // If MPI wasn't initialized, initialize it.
   // Remember if it was initialized on entry; the destructor will only finalize if the constructor init'ed.
   // This way, you can do several simulations sequentially by initializing MPI before creating
   // the first HyPerCol; after running the first simulation the MPI environment will still exist and you
   // can run the second simulation, etc.
   MPI_Initialized(&mpiInit);
   if( !mpiInit) {
      pvAssert((*argv)[*argc]==NULL); // Open MPI 1.7 assumes this.
      MPI_Init(argc, argv);
   }
   else{
      pvError() << "PV_Init communicator already initialized\n";
   }

   return 0;
}

void PV_Init::initLogFile(bool appendFlag) {
   // TODO: Under MPI, non-root processes should send messages to root process.
   // Currently, if logFile is directory/filename.txt, the root process writes to that path,
   // and nonroot processes write to directory/filename_<rank>.txt, where <rank> is replaced with the global rank.
   // If filename does not have an extension, _<rank> is appended.
   // Note that the global rank zero process does not insert _<rank>.  This is deliberate, as the nonzero ranks
   // should be MPI-ing the data to the zero rank.
   char const * logFile = arguments->getLogFile();
   int const globalRootProcess = 0;
   int globalRank;
   MPI_Comm_rank(MPI_COMM_WORLD, &globalRank);
   std::ios_base::openmode mode = appendFlag ? std::ios_base::out | std::ios_base::app : std::ios_base::out;
   if (logFile && globalRank != globalRootProcess) {
      // To prevent collisions caused by multiple processes opening the same file for logging,
      // processes with global rank other than zero append the rank to the log filename.
      // If the logfile has an extension (e.g. ".log", ".txt"), the rank is appended before the
      // period separating the extension.
      std::string logFileString(logFile);
      size_t finalSlash = logFileString.rfind('/');
      size_t finalDot = logFileString.rfind('.');
      size_t insertionPoint;
      if (finalDot == std::string::npos || (finalSlash!=std::string::npos && finalDot < finalSlash) ) {
         insertionPoint = logFileString.length();
      }
      else {
         insertionPoint = finalDot;
      }
      std::string insertion("_");
      insertion.append(std::to_string(globalRank));
      logFileString.insert(insertionPoint, insertion);
      PV::setLogFile(logFileString.c_str(), mode);
   }
   else {
      PV::setLogFile(logFile, mode);
   }
}

int PV_Init::setParams(char const * params_file) {
   if (params_file == NULL) { return PV_FAILURE; }
   char const * newParamsFile = arguments->setParamsFile(params_file);
   if (newParamsFile==NULL) {
      pvErrorNoExit().printf("PV_Init unable to set new params file: %s\n", strerror(errno));
      return PV_FAILURE;
   }
   initialize();
   return createParams();
}

int PV_Init::createParams() {
   char const * params_file = arguments->getParamsFile();
   if (params_file) {
      delete params;
      params = new PVParams(params_file, 2*(INITIAL_LAYER_ARRAY_SIZE+INITIAL_CONNECTION_ARRAY_SIZE), mCommunicator);
      return PV_SUCCESS;
   }
   else {
      return PV_FAILURE;
   }
}

int PV_Init::setLogFile(char const * log_file, bool appendFlag) {
   arguments->setLogFile(log_file);
   initLogFile(appendFlag);
   printInitMessage();
}

int PV_Init::setMPIConfiguration(int rows, int columns, int batchWidth) {
   if (rows >= 0) { arguments->setNumRows(rows); }
   if (columns >= 0) { arguments->setNumColumns(columns); }
   if (batchWidth >= 0) { arguments->setBatchWidth(batchWidth); }
   initialize();
   return PV_SUCCESS;
}

void PV_Init::printInitMessage() {
   time_t currentTime = time(nullptr);
   pvInfo() << "PetaVision initialized at " << ctime(&currentTime); // string returned by ctime contains a trailing \n.
   pvInfo() << "Command line arguments are:\n";
   printState();
}

int PV_Init::resetState() {
   return arguments->resetState();
}

int PV_Init::registerKeyword(char const * keyword, ObjectCreateFn creator) {
   int status = Factory::instance()->registerKeyword(keyword, creator);
   if (status != PV_SUCCESS) {
      if (getWorldRank()==0) {
         pvErrorNoExit().printf("PV_Init: keyword \"%s\" has already been registered.\n", keyword);
      }
   }
   return status;
}

#ifdef OBSOLETE // Marked obsolete Jul 19, 2016.  Use hc=createHyPerCol(pv_init_ptr) instead of hc=pv_init_ptr->build().
HyPerCol * PV_Init::build() {
   HyPerCol * hc = new HyPerCol("column", this);
   if( hc == NULL ) {
      pvErrorNoExit().printf("Unable to create HyPerCol\n");
      return NULL;
   }
   PVParams * hcparams = hc->parameters();
   int numGroups = hcparams->numberOfGroups();

   // Make sure first group defines a column
   if( strcmp(hcparams->groupKeywordFromIndex(0), "HyPerCol") ) {
      pvErrorNoExit().printf("First group in the params file did not define a HyPerCol.\n");
      delete hc;
      return NULL;
   }

   for (int k=0; k<numGroups; k++) {
      const char * kw = hcparams->groupKeywordFromIndex(k);
      const char * name = hcparams->groupNameFromIndex(k);
      if (!strcmp(kw, "HyPerCol")) {
         if (k==0) { continue; }
         else {
            if (hc->columnId()==0) {
               pvErrorNoExit().printf("Group %d in params file (\"%s\") is a HyPerCol; the HyPerCol must be the first group.\n",
                       k+1, name);
            }
            delete hc;
            return NULL;
         }
      }
      else {
         BaseObject * addedObject = factory->create(kw, name, hc);
         if (addedObject==NULL) {
            if (hc->globalRank()==0) {
               pvErrorNoExit().printf("Unable to create %s \"%s\".\n", kw, name);
            }
            delete hc;
            return NULL;
         }
      }
   }

   if( hc->numberOfLayers() == 0 ) {
      pvErrorNoExit().printf("HyPerCol \"%s\" does not have any layers.\n", hc->getName());
      delete hc;
      return NULL;
   }
   return hc;
}
#endif // OBSOLETE // Marked obsolete Jul 19, 2016.  Use hc=createHyPerCol(pv_init_ptr) instead of hc=pv_init_ptr->build().

int PV_Init::commFinalize()
{
   MPI_Finalize();
   return 0;
}

} // namespace PV

<|endoftext|>


<commit_before>//
// Copyright (C) 2018 University of Amsterdam
//
// This program 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.
//
// This program 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 this program.  If not, see
// <http://www.gnu.org/licenses/>.
//

#include "computer.h"
#include <QDir>
#include "gui/messageforwarder.h"

Computer::Computer(QObject *parent): FileMenuObject(parent)
{
	setListModel(new ComputerListModel(this));
}

FileEvent *Computer::browseOpen(const QString &path)
{
	QString browsePath;
	if (path == "")
		browsePath = _computerListModel->getMostRecent();
	else
		browsePath = path;

	QString filter = "Data Sets (*.csv *.txt *.sav *.ods *.dta *.por *.sas7bdat *.sas7bcat *.xpt)";
	if (_mode == FileEvent::FileSyncData)
		filter = "Data Sets (*.csv *.txt *.sav *.ods)";

	QString finalPath = MessageForwarder::browseOpenFile("Open", browsePath, filter);

	FileEvent *event = new FileEvent(this, _mode);

	if (finalPath != "")
	{
		event->setPath(finalPath);
		emit dataSetIORequest(event);
	}
	else
	{
		event->setComplete(false);
	}

	return event;
}

FileEvent *Computer::browseSave(const QString &path, FileEvent::FileMode mode)
{
	QString caption = "Save";
	QString filter = "JASP Files (*.jasp)";

	QString browsePath = path;
	if (path == "")
		browsePath = _computerListModel->getMostRecent();

	if (_hasFileName)
		browsePath += QDir::separator() + _fileName;

	switch(mode)
	{
	case FileEvent::FileExportResults:
		caption = "Export Result as HTML";
#ifdef JASP_DEBUG
		// In debug mode enable pdf export
		filter = "HTML Files (*.html *.pdf)";
#else
		// For future use of pdf export switch to line above
		filter = "HTML Files (*.html)";
#endif
		break;

	case FileEvent::FileGenerateData:
	case FileEvent::FileExportData:
		caption	= "Export Data as CSV";
		filter	= "CSV Files (*.csv *.txt)";
		break;

	case FileEvent::FileSyncData:
		caption = "Sync Data";
		filter = "Data Files (*.csv *.txt *.sav *.ods)";
		break;

	case FileEvent::FileSave:
		break;

	default:
		throw std::runtime_error("Wrong FileEvent type for saving!");
	}

	QString finalPath = MessageForwarder::browseSaveFile(caption, browsePath, filter);
	FileEvent *event = new FileEvent(this, mode);

	if (finalPath != "")
	{
		// Default file extensions if not specified
		if		(mode == FileEvent::FileSave			&&	!finalPath.endsWith(".jasp", Qt::CaseInsensitive))
			finalPath.append(QString(".jasp"));
		else if	(mode == FileEvent::FileExportResults	&&	(!finalPath.endsWith(".html", Qt::CaseInsensitive) &&
															!finalPath.endsWith(".pdf", Qt::CaseInsensitive)))
			finalPath.append(QString(".html"));
		else if	(mode == FileEvent::FileExportData		&&	(!finalPath.endsWith(".csv", Qt::CaseInsensitive) &&
															!finalPath.endsWith(".txt", Qt::CaseInsensitive)))

			finalPath.append(QString(".csv"));

		event->setPath(finalPath);
		emit dataSetIORequest(event);
	}
	else
		event->setComplete(false);

	return event;

}

void Computer::addRecentFolder(const QString &path)
{
    _computerListModel->addRecentFolder(path);
}

void Computer::analysesExportResults()
{
    _mode = FileEvent::FileExportResults;
    browseMostRecent();
}

void Computer::setFileName(const QString &filename)
{
	_fileName = filename;
	_hasFileName = true;
}

void Computer::clearFileName()
{
	_fileName = "";
	_hasFileName = false;
}

//Slots
void Computer::browsePath(QString path)
{
	if (_mode == FileEvent::FileOpen || _mode == FileEvent::FileSyncData)
		browseOpen(path);
	else
		browseSave(path, _mode);
}

void Computer::browseMostRecent()
{
	QString mostrecent = _computerListModel->getMostRecent();
	browsePath(mostrecent);
}

void Computer::setListModel(ComputerListModel * listModel)
{
	if (_computerListModel == listModel)
		return;

	_computerListModel = listModel;

	connect(_computerListModel, &ComputerListModel::browsePath, this, &Computer::browsePath);

	emit listModelChanged(_computerListModel);
}
<commit_msg>JASP should be able to open .jasp files through browsing<commit_after>//
// Copyright (C) 2018 University of Amsterdam
//
// This program 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.
//
// This program 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 this program.  If not, see
// <http://www.gnu.org/licenses/>.
//

#include "computer.h"
#include <QDir>
#include "gui/messageforwarder.h"

Computer::Computer(QObject *parent): FileMenuObject(parent)
{
	setListModel(new ComputerListModel(this));
}

FileEvent *Computer::browseOpen(const QString &path)
{
	QString browsePath;
	if (path == "")
		browsePath = _computerListModel->getMostRecent();
	else
		browsePath = path;

	QString filter = "Data Sets (*.jasp *.csv *.txt *.sav *.ods *.dta *.por *.sas7bdat *.sas7bcat *.xpt)";
	if (_mode == FileEvent::FileSyncData)
		filter = "Data Sets (*.csv *.txt *.sav *.ods)";

	QString finalPath = MessageForwarder::browseOpenFile("Open", browsePath, filter);

	FileEvent *event = new FileEvent(this, _mode);

	if (finalPath != "")
	{
		event->setPath(finalPath);
		emit dataSetIORequest(event);
	}
	else
	{
		event->setComplete(false);
	}

	return event;
}

FileEvent *Computer::browseSave(const QString &path, FileEvent::FileMode mode)
{
	QString caption = "Save";
	QString filter = "JASP Files (*.jasp)";

	QString browsePath = path;
	if (path == "")
		browsePath = _computerListModel->getMostRecent();

	if (_hasFileName)
		browsePath += QDir::separator() + _fileName;

	switch(mode)
	{
	case FileEvent::FileExportResults:
		caption = "Export Result as HTML";
#ifdef JASP_DEBUG
		// In debug mode enable pdf export
		filter = "HTML Files (*.html *.pdf)";
#else
		// For future use of pdf export switch to line above
		filter = "HTML Files (*.html)";
#endif
		break;

	case FileEvent::FileGenerateData:
	case FileEvent::FileExportData:
		caption	= "Export Data as CSV";
		filter	= "CSV Files (*.csv *.txt)";
		break;

	case FileEvent::FileSyncData:
		caption = "Sync Data";
		filter = "Data Files (*.csv *.txt *.sav *.ods)";
		break;

	case FileEvent::FileSave:
		break;

	default:
		throw std::runtime_error("Wrong FileEvent type for saving!");
	}

	QString finalPath = MessageForwarder::browseSaveFile(caption, browsePath, filter);
	FileEvent *event = new FileEvent(this, mode);

	if (finalPath != "")
	{
		// Default file extensions if not specified
		if		(mode == FileEvent::FileSave			&&	!finalPath.endsWith(".jasp", Qt::CaseInsensitive))
			finalPath.append(QString(".jasp"));
		else if	(mode == FileEvent::FileExportResults	&&	(!finalPath.endsWith(".html", Qt::CaseInsensitive) &&
															!finalPath.endsWith(".pdf", Qt::CaseInsensitive)))
			finalPath.append(QString(".html"));
		else if	(mode == FileEvent::FileExportData		&&	(!finalPath.endsWith(".csv", Qt::CaseInsensitive) &&
															!finalPath.endsWith(".txt", Qt::CaseInsensitive)))

			finalPath.append(QString(".csv"));

		event->setPath(finalPath);
		emit dataSetIORequest(event);
	}
	else
		event->setComplete(false);

	return event;

}

void Computer::addRecentFolder(const QString &path)
{
    _computerListModel->addRecentFolder(path);
}

void Computer::analysesExportResults()
{
    _mode = FileEvent::FileExportResults;
    browseMostRecent();
}

void Computer::setFileName(const QString &filename)
{
	_fileName = filename;
	_hasFileName = true;
}

void Computer::clearFileName()
{
	_fileName = "";
	_hasFileName = false;
}

//Slots
void Computer::browsePath(QString path)
{
	if (_mode == FileEvent::FileOpen || _mode == FileEvent::FileSyncData)
		browseOpen(path);
	else
		browseSave(path, _mode);
}

void Computer::browseMostRecent()
{
	QString mostrecent = _computerListModel->getMostRecent();
	browsePath(mostrecent);
}

void Computer::setListModel(ComputerListModel * listModel)
{
	if (_computerListModel == listModel)
		return;

	_computerListModel = listModel;

	connect(_computerListModel, &ComputerListModel::browsePath, this, &Computer::browsePath);

	emit listModelChanged(_computerListModel);
}
<|endoftext|>


<commit_before>#include "../../log/logger.h"
#include "traceroute.h"

#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
#include <arpa/inet.h>
#elif defined(Q_OS_WIN)
#include <winsock2.h>
#endif

LOGGER("Traceroute");

Traceroute::Traceroute(QObject *parent)
: Measurement(parent)
, currentStatus(Unknown)
, m_ping()
, endOfRoute(false)
, ttl(0)
{
    setResultHeader(QStringList() << "results");
}

Traceroute::~Traceroute()
{
}

Measurement::Status Traceroute::status() const
{
    return currentStatus;
}

void Traceroute::setStatus(Status status)
{
    if (currentStatus != status)
    {
        currentStatus = status;
        emit statusChanged(status);
    }
}

bool Traceroute::prepare(NetworkManager *networkManager,
                         const MeasurementDefinitionPtr &measurementDefinition)
{
    Q_UNUSED(networkManager);
    definition = measurementDefinition.dynamicCast<TracerouteDefinition>();

    if (definition->type != ping::Udp)
    {
        setErrorString("Ping type not supported");
        return false;
    }

    connect(&m_ping, SIGNAL(destinationUnreachable(const PingProbe &)),
            this, SLOT(destinationUnreachable(const PingProbe &)));

    connect(&m_ping, SIGNAL(ttlExceeded(const PingProbe &)),
            this, SLOT(ttlExceeded(const PingProbe &)));

    connect(&m_ping, SIGNAL(timeout(const PingProbe &)),
            this, SLOT(timeout(const PingProbe &)));

    connect(&m_ping, SIGNAL(udpResponse(const PingProbe &)), this,
            SLOT(udpResponse(const PingProbe &)));

    connect(&m_ping, SIGNAL(finished()), this, SLOT(pingFinished()));

    connect(&m_ping, SIGNAL(error(const QString &)), &m_ping,
            SLOT(setErrorString(const QString &)));

    return true;
}

bool Traceroute::start()
{
    ping();

    return true;
}

bool Traceroute::stop()
{
    return true;
}

Result Traceroute::result() const
{
    QVariantList res;
    QVariantList pings;
    QVariantMap hop;
    QVariantMap probe;

    for (int i = 0; i < hops.size(); i += definition->count)
    {
        pings.clear();

        for (quint32 k = 0; k < definition->count; k++)
        {
            if ((quint32) hops.size() <= i + k)
            {
                break;
            }

            probe.insert("response", hops[i + k].response);
            probe.insert("rtt", (int)(hops[i + k].probe.recvTime -
                                      hops[i + k].probe.sendTime));
            pings.append(probe);
        }

        hop.insert("hop", QString(inet_ntoa(hops[i].probe.source.sin.sin_addr)));
        hop.insert("pings", pings);
        hop.insert("ttl", i / 3 + 1);

        res << hop;
    }

    return Result(QVariantList() << QVariant(res));
}

void Traceroute::ping()
{
    if (++ttl == 30)
    {
        emit finished();
        return;
    }

    PingDefinition pingDef(definition->host,
                                 definition->count,
                                 definition->interval,
                                 definition->receiveTimeout,
                                 ttl,
                                 definition->destinationPort,
                                 definition->sourcePort,
                                 definition->payload,
                                 definition->type);

    if (m_ping.prepare(NULL, PingPlugin().createMeasurementDefinition(
                           "ping",
                           pingDef.toVariant())))
    {
        m_ping.start();
    }
}

void Traceroute::destinationUnreachable(const PingProbe &probe)
{
    Hop hop = {probe, traceroute::DESTINATION_UNREACHABLE};
    hops << hop;
    endOfRoute = true;
}

void Traceroute::ttlExceeded(const PingProbe &probe)
{
    Hop hop = {probe, traceroute::TTL_EXCEEDED};
    hops << hop;
}

void Traceroute::timeout(const PingProbe &probe)
{
    Hop hop = {probe, traceroute::TIMEOUT};
    hops << hop;
}

void Traceroute::udpResponse(const PingProbe &probe)
{
    Hop hop = {probe, traceroute::UDP_RESPONSE};
    hops << hop;
    endOfRoute = true;
}

void Traceroute::pingFinished()
{
    if (endOfRoute)
    {
        emit finished();
    }
    else
    {
        ping();
    }
}
<commit_msg>traceroute: add statistics<commit_after>#include "../../log/logger.h"
#include "traceroute.h"

#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
#include <arpa/inet.h>
#elif defined(Q_OS_WIN)
#include <winsock2.h>
#endif
#include <numeric>
#include <QtMath>

LOGGER("Traceroute");

Traceroute::Traceroute(QObject *parent)
: Measurement(parent)
, currentStatus(Unknown)
, m_ping()
, endOfRoute(false)
, ttl(0)
{
    setResultHeader(QStringList() << "results" << "hop_count");
}

Traceroute::~Traceroute()
{
}

Measurement::Status Traceroute::status() const
{
    return currentStatus;
}

void Traceroute::setStatus(Status status)
{
    if (currentStatus != status)
    {
        currentStatus = status;
        emit statusChanged(status);
    }
}

bool Traceroute::prepare(NetworkManager *networkManager,
                         const MeasurementDefinitionPtr &measurementDefinition)
{
    Q_UNUSED(networkManager);
    definition = measurementDefinition.dynamicCast<TracerouteDefinition>();

    if (definition->type != ping::Udp)
    {
        setErrorString("Ping type not supported");
        return false;
    }

    connect(&m_ping, SIGNAL(destinationUnreachable(const PingProbe &)),
            this, SLOT(destinationUnreachable(const PingProbe &)));

    connect(&m_ping, SIGNAL(ttlExceeded(const PingProbe &)),
            this, SLOT(ttlExceeded(const PingProbe &)));

    connect(&m_ping, SIGNAL(timeout(const PingProbe &)),
            this, SLOT(timeout(const PingProbe &)));

    connect(&m_ping, SIGNAL(udpResponse(const PingProbe &)), this,
            SLOT(udpResponse(const PingProbe &)));

    connect(&m_ping, SIGNAL(finished()), this, SLOT(pingFinished()));

    connect(&m_ping, SIGNAL(error(const QString &)), &m_ping,
            SLOT(setErrorString(const QString &)));

    return true;
}

bool Traceroute::start()
{
    ping();

    return true;
}

bool Traceroute::stop()
{
    return true;
}

Result Traceroute::result() const
{
    QVariantList res;
    QVariantList pings;
    QVariantMap hop;
    QVariantMap probe;
    QList<quint64> pingTime;

    for (int i = 0; i < hops.size(); i += definition->count)
    {
        pings.clear();
        pingTime.clear();

        for (quint32 k = 0; k < definition->count; k++)
        {
            if ((quint32) hops.size() <= i + k)
            {
                break;
            }

            pingTime.append(hops[i + k].probe.recvTime - hops[i + k].probe.sendTime);
            probe.insert("response", hops[i + k].response);
            probe.insert("rtt", (int)(hops[i + k].probe.recvTime -
                                      hops[i + k].probe.sendTime));
            pings.append(probe);
        }

        // get max and min
        QList<quint64>::const_iterator it = std::max_element(pingTime.begin(), pingTime.end());
        quint64 max = *it;
        it = std::min_element(pingTime.begin(), pingTime.end());
        quint64 min = *it;

        float avg = 0.0;

        // calculate average and fill ping times
        foreach (quint64 val, pingTime)
        {
            avg += val;
        }

        qreal sq_sum = std::inner_product(pingTime.begin(), pingTime.end(), pingTime.begin(), 0.0);
        qreal stdev = 0.0;

        if (pingTime.size() > 0)
        {
            avg /= pingTime.size();
            // calculate standard deviation
            stdev = qSqrt(sq_sum / pingTime.size() - avg * avg);
        }

        hop.insert("hop", QString(inet_ntoa(hops[i].probe.source.sin.sin_addr)));
        hop.insert("pings", pings);
        hop.insert("ttl", i / 3 + 1);
        hop.insert("rtt_min", min);
        hop.insert("rtt_max", max);
        hop.insert("rtt_avg", avg);
        hop.insert("rtt_stdev", stdev);
        hop.insert("rtt_count", definition->count);

        res << hop;
    }

    return Result(QVariantList() << QVariant(res) << static_cast<int>(hops.size() / definition->count));
}

void Traceroute::ping()
{
    if (++ttl == 30)
    {
        emit finished();
        return;
    }

    PingDefinition pingDef(definition->host,
                                 definition->count,
                                 definition->interval,
                                 definition->receiveTimeout,
                                 ttl,
                                 definition->destinationPort,
                                 definition->sourcePort,
                                 definition->payload,
                                 definition->type);

    if (m_ping.prepare(NULL, PingPlugin().createMeasurementDefinition(
                           "ping",
                           pingDef.toVariant())))
    {
        m_ping.start();
    }
}

void Traceroute::destinationUnreachable(const PingProbe &probe)
{
    Hop hop = {probe, traceroute::DESTINATION_UNREACHABLE};
    hops << hop;
    endOfRoute = true;
}

void Traceroute::ttlExceeded(const PingProbe &probe)
{
    Hop hop = {probe, traceroute::TTL_EXCEEDED};
    hops << hop;
}

void Traceroute::timeout(const PingProbe &probe)
{
    Hop hop = {probe, traceroute::TIMEOUT};
    hops << hop;
}

void Traceroute::udpResponse(const PingProbe &probe)
{
    Hop hop = {probe, traceroute::UDP_RESPONSE};
    hops << hop;
    endOfRoute = true;
}

void Traceroute::pingFinished()
{
    if (endOfRoute)
    {
        emit finished();
    }
    else
    {
        ping();
    }
}
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014-2015 Francois Beaune, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "genericsamplerenderer.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"
#include "renderer/global/globaltypes.h"
#include "renderer/kernel/aov/spectrumstack.h"
#include "renderer/kernel/intersection/intersector.h"
#include "renderer/kernel/intersection/tracecontext.h"
#include "renderer/kernel/lighting/ilightingengine.h"
#include "renderer/kernel/lighting/tracer.h"
#ifdef APPLESEED_WITH_OSL
#include "renderer/kernel/shading/oslshadergroupexec.h"
#endif
#include "renderer/kernel/shading/shadingcontext.h"
#include "renderer/kernel/shading/shadingengine.h"
#include "renderer/kernel/shading/shadingfragment.h"
#include "renderer/kernel/shading/shadingpoint.h"
#include "renderer/kernel/shading/shadingray.h"
#include "renderer/kernel/shading/shadingresult.h"
#include "renderer/kernel/texturing/texturecache.h"
#include "renderer/modeling/camera/camera.h"
#include "renderer/modeling/frame/frame.h"
#include "renderer/modeling/scene/scene.h"

// appleseed.foundation headers.
#include "foundation/image/color.h"
#include "foundation/image/colorspace.h"
#include "foundation/image/image.h"
#include "foundation/image/regularspectrum.h"
#include "foundation/math/vector.h"
#include "foundation/platform/types.h"
#include "foundation/utility/statistics.h"
#include "foundation/utility/string.h"

// Standard headers.
#include <cstddef>
#include <limits>
#include <string>

// Forward declarations.
namespace renderer  { class PixelContext; }

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    //
    // Generic sample renderer.
    //

    // If defined, the texture cache returns solid tiles whose color depends on whether
    // the requested tile could be found in the cache or not.
    #undef DEBUG_DISPLAY_TEXTURE_CACHE_PERFORMANCES

    class GenericSampleRenderer
      : public ISampleRenderer
    {
      public:
        GenericSampleRenderer(
            const Scene&            scene,
            const Frame&            frame,
            const TraceContext&     trace_context,
            TextureStore&           texture_store,
            ILightingEngineFactory* lighting_engine_factory,
            ShadingEngine&          shading_engine,
#ifdef APPLESEED_WITH_OIIO
            OIIO::TextureSystem&    oiio_texture_system,
#endif
#ifdef APPLESEED_WITH_OSL
            OSL::ShadingSystem&     shading_system,
#endif
            const size_t            thread_index,
            const ParamArray&       params)
          : m_params(params)
          , m_scene(scene)
          , m_lighting_conditions(frame.get_lighting_conditions())
          , m_opacity_threshold(1.0f - m_params.m_transparency_threshold)
          , m_texture_cache(texture_store)
          , m_intersector(trace_context, m_texture_cache, m_params.m_report_self_intersections)
#ifdef APPLESEED_WITH_OSL
          , m_shadergroup_exec(shading_system)
#endif
          , m_tracer(
                m_scene,
                m_intersector,
                m_texture_cache,
#ifdef APPLESEED_WITH_OSL
                m_shadergroup_exec,
#endif
                m_params.m_transparency_threshold,
                m_params.m_max_iterations,
                thread_index == 0)
          , m_lighting_engine(lighting_engine_factory->create())
          , m_shading_context(
                m_intersector,
                m_tracer,
                m_texture_cache,
#ifdef APPLESEED_WITH_OIIO
                oiio_texture_system,
#endif
#ifdef APPLESEED_WITH_OSL
                m_shadergroup_exec,
#endif
                thread_index,
                m_lighting_engine,
                m_params.m_transparency_threshold,
                m_params.m_max_iterations)
          , m_shading_engine(shading_engine)
        {
            // 1/4 of a pixel, like in Renderman RIS.
            const CanvasProperties& c = frame.image().properties();
            m_image_point_dx = Vector2d(1.0 / (4.0 * c.m_canvas_width), 0.0);
            m_image_point_dy = Vector2d(0.0, 1.0 / (4.0 * c.m_canvas_height));
        }

        ~GenericSampleRenderer()
        {
            m_lighting_engine->release();
        }

        virtual void release() APPLESEED_OVERRIDE
        {
            delete this;
        }

        virtual void render_sample(
            SamplingContext&        sampling_context,
            const PixelContext&     pixel_context,
            const Vector2d&         image_point,
            ShadingResult&          shading_result) APPLESEED_OVERRIDE
        {
#ifdef DEBUG_DISPLAY_TEXTURE_CACHE_PERFORMANCES

            const uint64 last_texture_cache_hit_count = m_texture_cache.get_hit_count();
            const uint64 last_texture_cache_miss_count = m_texture_cache.get_miss_count();

#endif

            // Construct a primary ray.
            ShadingRay primary_ray;
            m_scene.get_camera()->spawn_ray(
                sampling_context,
                Dual2d(image_point, m_image_point_dx, m_image_point_dy),
                primary_ray);

            ShadingPoint shading_points[2];
            size_t shading_point_index = 0;
            const ShadingPoint* shading_point_ptr = 0;
            size_t iterations = 0;

            while (true)
            {
                // Put a hard limit on the number of iterations.
                if (++iterations >= m_params.m_max_iterations)
                {
                    RENDERER_LOG_WARNING(
                        "reached hard iteration limit (%s), breaking primary ray trace loop.",
                        pretty_int(m_params.m_max_iterations).c_str());
                    break;
                }

                // Trace the ray.
                shading_points[shading_point_index].clear();
                m_intersector.trace(
                    primary_ray,
                    shading_points[shading_point_index],
                    shading_point_ptr);

                // Update the pointers to the shading points.
                shading_point_ptr = &shading_points[shading_point_index];
                shading_point_index = 1 - shading_point_index;

                if (iterations == 1)
                {
                    // Shade the intersection point.
                    m_shading_engine.shade(
                        sampling_context,
                        pixel_context,
                        m_shading_context,
                        *shading_point_ptr,
                        shading_result);

                    // Transform the result to the linear RGB color space.
                    shading_result.transform_to_linear_rgb(m_lighting_conditions);

                    // Apply alpha premultiplication.
                    if (shading_point_ptr->hit())
                        shading_result.apply_alpha_premult_linear_rgb();

                    // Store the depth value.
                    shading_result.m_depth =
                        shading_point_ptr->hit()
                            ? shading_point_ptr->get_distance()
                            : -1.0;
                }
                else
                {
                    // Shade the intersection point.
                    ShadingResult local_result(shading_result.m_aovs.size());
                    m_shading_engine.shade(
                        sampling_context,
                        pixel_context,
                        m_shading_context,
                        *shading_point_ptr,
                        local_result);

                    // Transform the result to the linear RGB color space.
                    local_result.transform_to_linear_rgb(m_lighting_conditions);

                    // Apply alpha premultiplication.
                    if (shading_point_ptr->hit())
                        local_result.apply_alpha_premult_linear_rgb();

                    // Compositing.
                    shading_result.composite_over_linear_rgb(local_result);
                }

                // Stop once we hit the environment.
                if (!shading_point_ptr->hit())
                    break;

                // Stop once we hit full opacity.
                if (max_value(shading_result.m_main.m_alpha) > m_opacity_threshold)
                    break;

                // Move the ray origin to the intersection point.
                primary_ray.m_org = shading_point_ptr->get_point();
                if (primary_ray.m_has_differentials)
                {
                    primary_ray.m_rx.m_org = primary_ray.m_rx.point_at(primary_ray.m_tmax);
                    primary_ray.m_ry.m_org = primary_ray.m_ry.point_at(primary_ray.m_tmax);
                }

                primary_ray.m_tmax = numeric_limits<double>::max();
            }

#ifdef DEBUG_DISPLAY_TEXTURE_CACHE_PERFORMANCES

            const uint64 delta_hit_count = m_texture_cache.get_hit_count() - last_texture_cache_hit_count;
            const uint64 delta_miss_count = m_texture_cache.get_miss_count() - last_texture_cache_miss_count;

            if (delta_hit_count + delta_miss_count == 0)
            {
                // In black: no access to the texture cache.
                shading_result.set_main_to_linear_rgba(Color4f(0.0f, 0.0f, 0.0f, 1.0f));
            }
            else if (delta_hit_count > delta_miss_count)
            {
                // In green: a majority of cache hits.
                shading_result.set_main_to_linear_rgba(Color4f(0.0f, 1.0f, 0.0f, 1.0f));
            }
            else
            {
                // In red: a majority of cache misses.
                shading_result.set_main_to_linear_rgba(Color4f(1.0f, 0.0f, 0.0f, 1.0f));
            }

#endif
        }

        virtual StatisticsVector get_statistics() const APPLESEED_OVERRIDE
        {
            StatisticsVector stats;
            stats.merge(m_texture_cache.get_statistics());
            stats.merge(m_intersector.get_statistics());
            stats.merge(m_lighting_engine->get_statistics());
            return stats;
        }

      private:
        struct Parameters
        {
            const float     m_transparency_threshold;
            const size_t    m_max_iterations;
            const bool      m_report_self_intersections;

            explicit Parameters(const ParamArray& params)
              : m_transparency_threshold(params.get_optional<float>("transparency_threshold", 0.001f))
              , m_max_iterations(params.get_optional<size_t>("max_iterations", 1000))
              , m_report_self_intersections(params.get_optional<bool>("report_self_intersections", false))
            {
            }
        };

        const Parameters            m_params;
        const Scene&                m_scene;
        const LightingConditions&   m_lighting_conditions;
        const float                 m_opacity_threshold;

        TextureCache                m_texture_cache;
        Intersector                 m_intersector;
#ifdef APPLESEED_WITH_OSL
        OSLShaderGroupExec          m_shadergroup_exec;
#endif
        Tracer                      m_tracer;
        ILightingEngine*            m_lighting_engine;
        const ShadingContext        m_shading_context;
        ShadingEngine&              m_shading_engine;
        Vector2d                    m_image_point_dx;
        Vector2d                    m_image_point_dy;
    };
}

//
// GenericSampleRendererFactory class implementation.
//

GenericSampleRendererFactory::GenericSampleRendererFactory(
    const Scene&            scene,
    const Frame&            frame,
    const TraceContext&     trace_context,
    TextureStore&           texture_store,
    ILightingEngineFactory* lighting_engine_factory,
    ShadingEngine&          shading_engine,
#ifdef APPLESEED_WITH_OIIO
    OIIO::TextureSystem&    oiio_texture_system,
#endif
#ifdef APPLESEED_WITH_OSL
    OSL::ShadingSystem&     shading_system,
#endif
    const ParamArray&       params)
  : m_scene(scene)
  , m_frame(frame)
  , m_trace_context(trace_context)
  , m_texture_store(texture_store)
  , m_lighting_engine_factory(lighting_engine_factory)
  , m_shading_engine(shading_engine)
#ifdef APPLESEED_WITH_OIIO
  , m_oiio_texture_system(oiio_texture_system)
#endif
#ifdef APPLESEED_WITH_OSL
  , m_shading_system(shading_system)
#endif
  , m_params(params)
{
}

void GenericSampleRendererFactory::release()
{
    delete this;
}

ISampleRenderer* GenericSampleRendererFactory::create(const size_t thread_index)
{
    return
        new GenericSampleRenderer(
            m_scene,
            m_frame,
            m_trace_context,
            m_texture_store,
            m_lighting_engine_factory,
            m_shading_engine,
#ifdef APPLESEED_WITH_OIIO
            m_oiio_texture_system,
#endif
#ifdef APPLESEED_WITH_OSL
            m_shading_system,
#endif
            thread_index,
            m_params);
}

}   // namespace renderer
<commit_msg>Fixed the orientation of dPdy.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
// Copyright (c) 2014-2015 Francois Beaune, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "genericsamplerenderer.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"
#include "renderer/global/globaltypes.h"
#include "renderer/kernel/aov/spectrumstack.h"
#include "renderer/kernel/intersection/intersector.h"
#include "renderer/kernel/intersection/tracecontext.h"
#include "renderer/kernel/lighting/ilightingengine.h"
#include "renderer/kernel/lighting/tracer.h"
#ifdef APPLESEED_WITH_OSL
#include "renderer/kernel/shading/oslshadergroupexec.h"
#endif
#include "renderer/kernel/shading/shadingcontext.h"
#include "renderer/kernel/shading/shadingengine.h"
#include "renderer/kernel/shading/shadingfragment.h"
#include "renderer/kernel/shading/shadingpoint.h"
#include "renderer/kernel/shading/shadingray.h"
#include "renderer/kernel/shading/shadingresult.h"
#include "renderer/kernel/texturing/texturecache.h"
#include "renderer/modeling/camera/camera.h"
#include "renderer/modeling/frame/frame.h"
#include "renderer/modeling/scene/scene.h"

// appleseed.foundation headers.
#include "foundation/image/color.h"
#include "foundation/image/colorspace.h"
#include "foundation/image/image.h"
#include "foundation/image/regularspectrum.h"
#include "foundation/math/vector.h"
#include "foundation/platform/types.h"
#include "foundation/utility/statistics.h"
#include "foundation/utility/string.h"

// Standard headers.
#include <cstddef>
#include <limits>
#include <string>

// Forward declarations.
namespace renderer  { class PixelContext; }

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    //
    // Generic sample renderer.
    //

    // If defined, the texture cache returns solid tiles whose color depends on whether
    // the requested tile could be found in the cache or not.
    #undef DEBUG_DISPLAY_TEXTURE_CACHE_PERFORMANCES

    class GenericSampleRenderer
      : public ISampleRenderer
    {
      public:
        GenericSampleRenderer(
            const Scene&            scene,
            const Frame&            frame,
            const TraceContext&     trace_context,
            TextureStore&           texture_store,
            ILightingEngineFactory* lighting_engine_factory,
            ShadingEngine&          shading_engine,
#ifdef APPLESEED_WITH_OIIO
            OIIO::TextureSystem&    oiio_texture_system,
#endif
#ifdef APPLESEED_WITH_OSL
            OSL::ShadingSystem&     shading_system,
#endif
            const size_t            thread_index,
            const ParamArray&       params)
          : m_params(params)
          , m_scene(scene)
          , m_lighting_conditions(frame.get_lighting_conditions())
          , m_opacity_threshold(1.0f - m_params.m_transparency_threshold)
          , m_texture_cache(texture_store)
          , m_intersector(trace_context, m_texture_cache, m_params.m_report_self_intersections)
#ifdef APPLESEED_WITH_OSL
          , m_shadergroup_exec(shading_system)
#endif
          , m_tracer(
                m_scene,
                m_intersector,
                m_texture_cache,
#ifdef APPLESEED_WITH_OSL
                m_shadergroup_exec,
#endif
                m_params.m_transparency_threshold,
                m_params.m_max_iterations,
                thread_index == 0)
          , m_lighting_engine(lighting_engine_factory->create())
          , m_shading_context(
                m_intersector,
                m_tracer,
                m_texture_cache,
#ifdef APPLESEED_WITH_OIIO
                oiio_texture_system,
#endif
#ifdef APPLESEED_WITH_OSL
                m_shadergroup_exec,
#endif
                thread_index,
                m_lighting_engine,
                m_params.m_transparency_threshold,
                m_params.m_max_iterations)
          , m_shading_engine(shading_engine)
        {
            // 1/4 of a pixel, like in Renderman RIS.
            const CanvasProperties& c = frame.image().properties();
            m_image_point_dx = Vector2d(1.0 / (4.0 * c.m_canvas_width), 0.0);
            m_image_point_dy = Vector2d(0.0, -1.0 / (4.0 * c.m_canvas_height));
        }

        ~GenericSampleRenderer()
        {
            m_lighting_engine->release();
        }

        virtual void release() APPLESEED_OVERRIDE
        {
            delete this;
        }

        virtual void render_sample(
            SamplingContext&        sampling_context,
            const PixelContext&     pixel_context,
            const Vector2d&         image_point,
            ShadingResult&          shading_result) APPLESEED_OVERRIDE
        {
#ifdef DEBUG_DISPLAY_TEXTURE_CACHE_PERFORMANCES

            const uint64 last_texture_cache_hit_count = m_texture_cache.get_hit_count();
            const uint64 last_texture_cache_miss_count = m_texture_cache.get_miss_count();

#endif

            // Construct a primary ray.
            ShadingRay primary_ray;
            m_scene.get_camera()->spawn_ray(
                sampling_context,
                Dual2d(image_point, m_image_point_dx, m_image_point_dy),
                primary_ray);

            ShadingPoint shading_points[2];
            size_t shading_point_index = 0;
            const ShadingPoint* shading_point_ptr = 0;
            size_t iterations = 0;

            while (true)
            {
                // Put a hard limit on the number of iterations.
                if (++iterations >= m_params.m_max_iterations)
                {
                    RENDERER_LOG_WARNING(
                        "reached hard iteration limit (%s), breaking primary ray trace loop.",
                        pretty_int(m_params.m_max_iterations).c_str());
                    break;
                }

                // Trace the ray.
                shading_points[shading_point_index].clear();
                m_intersector.trace(
                    primary_ray,
                    shading_points[shading_point_index],
                    shading_point_ptr);

                // Update the pointers to the shading points.
                shading_point_ptr = &shading_points[shading_point_index];
                shading_point_index = 1 - shading_point_index;

                if (iterations == 1)
                {
                    // Shade the intersection point.
                    m_shading_engine.shade(
                        sampling_context,
                        pixel_context,
                        m_shading_context,
                        *shading_point_ptr,
                        shading_result);

                    // Transform the result to the linear RGB color space.
                    shading_result.transform_to_linear_rgb(m_lighting_conditions);

                    // Apply alpha premultiplication.
                    if (shading_point_ptr->hit())
                        shading_result.apply_alpha_premult_linear_rgb();

                    // Store the depth value.
                    shading_result.m_depth =
                        shading_point_ptr->hit()
                            ? shading_point_ptr->get_distance()
                            : -1.0;
                }
                else
                {
                    // Shade the intersection point.
                    ShadingResult local_result(shading_result.m_aovs.size());
                    m_shading_engine.shade(
                        sampling_context,
                        pixel_context,
                        m_shading_context,
                        *shading_point_ptr,
                        local_result);

                    // Transform the result to the linear RGB color space.
                    local_result.transform_to_linear_rgb(m_lighting_conditions);

                    // Apply alpha premultiplication.
                    if (shading_point_ptr->hit())
                        local_result.apply_alpha_premult_linear_rgb();

                    // Compositing.
                    shading_result.composite_over_linear_rgb(local_result);
                }

                // Stop once we hit the environment.
                if (!shading_point_ptr->hit())
                    break;

                // Stop once we hit full opacity.
                if (max_value(shading_result.m_main.m_alpha) > m_opacity_threshold)
                    break;

                // Move the ray origin to the intersection point.
                primary_ray.m_org = shading_point_ptr->get_point();
                if (primary_ray.m_has_differentials)
                {
                    primary_ray.m_rx.m_org = primary_ray.m_rx.point_at(primary_ray.m_tmax);
                    primary_ray.m_ry.m_org = primary_ray.m_ry.point_at(primary_ray.m_tmax);
                }

                primary_ray.m_tmax = numeric_limits<double>::max();
            }

#ifdef DEBUG_DISPLAY_TEXTURE_CACHE_PERFORMANCES

            const uint64 delta_hit_count = m_texture_cache.get_hit_count() - last_texture_cache_hit_count;
            const uint64 delta_miss_count = m_texture_cache.get_miss_count() - last_texture_cache_miss_count;

            if (delta_hit_count + delta_miss_count == 0)
            {
                // In black: no access to the texture cache.
                shading_result.set_main_to_linear_rgba(Color4f(0.0f, 0.0f, 0.0f, 1.0f));
            }
            else if (delta_hit_count > delta_miss_count)
            {
                // In green: a majority of cache hits.
                shading_result.set_main_to_linear_rgba(Color4f(0.0f, 1.0f, 0.0f, 1.0f));
            }
            else
            {
                // In red: a majority of cache misses.
                shading_result.set_main_to_linear_rgba(Color4f(1.0f, 0.0f, 0.0f, 1.0f));
            }

#endif
        }

        virtual StatisticsVector get_statistics() const APPLESEED_OVERRIDE
        {
            StatisticsVector stats;
            stats.merge(m_texture_cache.get_statistics());
            stats.merge(m_intersector.get_statistics());
            stats.merge(m_lighting_engine->get_statistics());
            return stats;
        }

      private:
        struct Parameters
        {
            const float     m_transparency_threshold;
            const size_t    m_max_iterations;
            const bool      m_report_self_intersections;

            explicit Parameters(const ParamArray& params)
              : m_transparency_threshold(params.get_optional<float>("transparency_threshold", 0.001f))
              , m_max_iterations(params.get_optional<size_t>("max_iterations", 1000))
              , m_report_self_intersections(params.get_optional<bool>("report_self_intersections", false))
            {
            }
        };

        const Parameters            m_params;
        const Scene&                m_scene;
        const LightingConditions&   m_lighting_conditions;
        const float                 m_opacity_threshold;

        TextureCache                m_texture_cache;
        Intersector                 m_intersector;
#ifdef APPLESEED_WITH_OSL
        OSLShaderGroupExec          m_shadergroup_exec;
#endif
        Tracer                      m_tracer;
        ILightingEngine*            m_lighting_engine;
        const ShadingContext        m_shading_context;
        ShadingEngine&              m_shading_engine;
        Vector2d                    m_image_point_dx;
        Vector2d                    m_image_point_dy;
    };
}

//
// GenericSampleRendererFactory class implementation.
//

GenericSampleRendererFactory::GenericSampleRendererFactory(
    const Scene&            scene,
    const Frame&            frame,
    const TraceContext&     trace_context,
    TextureStore&           texture_store,
    ILightingEngineFactory* lighting_engine_factory,
    ShadingEngine&          shading_engine,
#ifdef APPLESEED_WITH_OIIO
    OIIO::TextureSystem&    oiio_texture_system,
#endif
#ifdef APPLESEED_WITH_OSL
    OSL::ShadingSystem&     shading_system,
#endif
    const ParamArray&       params)
  : m_scene(scene)
  , m_frame(frame)
  , m_trace_context(trace_context)
  , m_texture_store(texture_store)
  , m_lighting_engine_factory(lighting_engine_factory)
  , m_shading_engine(shading_engine)
#ifdef APPLESEED_WITH_OIIO
  , m_oiio_texture_system(oiio_texture_system)
#endif
#ifdef APPLESEED_WITH_OSL
  , m_shading_system(shading_system)
#endif
  , m_params(params)
{
}

void GenericSampleRendererFactory::release()
{
    delete this;
}

ISampleRenderer* GenericSampleRendererFactory::create(const size_t thread_index)
{
    return
        new GenericSampleRenderer(
            m_scene,
            m_frame,
            m_trace_context,
            m_texture_store,
            m_lighting_engine_factory,
            m_shading_engine,
#ifdef APPLESEED_WITH_OIIO
            m_oiio_texture_system,
#endif
#ifdef APPLESEED_WITH_OSL
            m_shading_system,
#endif
            thread_index,
            m_params);
}

}   // namespace renderer
<|endoftext|>