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

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

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

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

=========================================================================*/
#include "otbComputePolylineFeatureFromImage.h"

#include <iostream>
#include "otbCommandLineArgumentParser.h"

#include "otbVectorImage.h"
#include "otbImageFileReader.h"

#include "otbVectorData.h"
#include "otbVectorDataFileReader.h"
#include "otbVectorDataFileWriter.h"
#include "itkPreOrderTreeIterator.h"

#include "otbVectorDataIntoImageProjectionFilter.h"
#include "otbVectorDataProjectionFilter.h"
#include "otbVectorDataTransformFilter.h"
#include "itkAffineTransform.h"

#include "otbParserConditionDataNodeFeatureFunction.h"
#include "otbNDVIDataNodeFeatureFunction.h"

namespace otb
{

int ComputePolylineFeatureFromImage::Describe(ApplicationDescriptor* descriptor)
{
  descriptor->SetName("ComputePolylineFeatureFromImage");
  descriptor->SetDescription("Compute a polyline feature from an input image: part of the polyline pixels that verify the FeatureExpression");
  descriptor->AddOption("InputImage", "An image from which to compute description",
                        "img",   1, true, ApplicationDescriptor::InputImage);
  descriptor->AddOption("InputVectorData", "Vector Data containing the polylines onto which the feature will be computed",
                        "vdin",  1, true, ApplicationDescriptor::FileName);
  descriptor->AddOption("FeatureExpression", "The feature formula (b1 > 0.3)",
                        "expr",  1, true, ApplicationDescriptor::String);
  descriptor->AddOption("FieldName", "The feature name (NONDVI, ROADSA...)",
                        "field", 1, true, ApplicationDescriptor::String);
  descriptor->AddOption("OutputVectorData", "The output Vector Data containing the feature",
                        "out",   1, true, ApplicationDescriptor::FileName);

  descriptor->AddOption("DEMDirectory", "DEM directory",
                        "dem", 1, false, ApplicationDescriptor::DirectoryName);

  return EXIT_SUCCESS;
}

int ComputePolylineFeatureFromImage::Execute(otb::ApplicationOptionsResult* parseResult)
{
  // Images
  typedef float                                           PixelType;
  typedef VectorImage<PixelType, 2>                       ImageType;
  typedef otb::ImageFileReader<ImageType>                 ReaderType;

  // VectorData
  typedef VectorData<>                                    VectorDataType;
  typedef VectorDataType::DataNodeType                    DataNodeType;
  typedef DataNodeType::ValuePrecisionType                PrecisionType;
  typedef DataNodeType::PrecisionType                     CoordRepType;
  typedef itk::PreOrderTreeIterator<VectorDataType::DataTreeType>
                                                          TreeIteratorType;
  typedef VectorDataFileReader<VectorDataType>            VectorDataReaderType;
  typedef VectorDataFileWriter<VectorDataType>            VectorDataWriterType;

  typedef VectorDataIntoImageProjectionFilter
    <VectorDataType, ImageType>                           VectorDataIntoImageProjType;
  typedef VectorDataProjectionFilter
    <VectorDataType, VectorDataType>                      VectorDataProjectionFilterType;

  typedef ParserConditionDataNodeFeatureFunction<ImageType, CoordRepType, PrecisionType>
                                                          ParserConditionFeatureFunctionType;

  // Vector Data into Image projection
  //// Read the Image
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(parseResult->GetParameterString("InputImage"));
  reader->UpdateOutputInformation();
  reader->Update();
  ImageType::Pointer inputImage = reader->GetOutput();
  //// Read the Vectordata
  VectorDataReaderType::Pointer vdreader = VectorDataReaderType::New();
  vdreader->SetFileName(parseResult->GetParameterString("InputVectorData"));
  vdreader->Update();
  //// Projection
  VectorDataIntoImageProjType::Pointer vprojIm = VectorDataIntoImageProjType::New();
  vprojIm->SetInputVectorData(vdreader->GetOutput());
  vprojIm->SetInputImage(inputImage);
  if( parseResult->IsOptionPresent("DEMDirectory") )
    {
      vprojIm->SetDEMDirectory(parseResult->GetParameterString("DEMDirectory"));
    }
  vprojIm->SetUseOutputSpacingAndOriginFromImage(true); // we want index as input;
  vprojIm->Update();

  // Add description
  ParserConditionFeatureFunctionType::Pointer vdescriptor = ParserConditionFeatureFunctionType::New();
  vdescriptor->SetExpression(parseResult->GetParameterString("FeatureExpression"));
  vdescriptor->SetInputImage(inputImage);

  VectorDataType::Pointer outVD = VectorDataType::New();
  // Retrieving root node
  DataNodeType::Pointer root = outVD->GetDataTree()->GetRoot()->Get();
  // Create the document node
  DataNodeType::Pointer document = DataNodeType::New();
  document->SetNodeType(otb::DOCUMENT);
  // Adding the layer to the data tree
  outVD->GetDataTree()->Add(document, root);
  // Create the folder node
  DataNodeType::Pointer folder = DataNodeType::New();
  folder->SetNodeType(otb::FOLDER);
  // Adding the layer to the data tree
  outVD->GetDataTree()->Add(folder, document);

  TreeIteratorType itVector(vprojIm->GetOutput()->GetDataTree());
  itVector.GoToBegin();

  while (!itVector.IsAtEnd())
    {
    vdescriptor->SetInputImage(reader->GetOutput());
    if (!itVector.Get()->IsRoot() && !itVector.Get()->IsDocument() && !itVector.Get()->IsFolder())
      {
      DataNodeType::Pointer currentGeometry = itVector.Get();
      currentGeometry->SetFieldAsDouble(parseResult->GetParameterString("FieldName"),
                                        (double)(vdescriptor->Evaluate(*(currentGeometry.GetPointer()))[0]));

      outVD->GetDataTree()->Add(currentGeometry, folder);
      }
    ++itVector;
    }

  /*
   * Reprojection of the output VectorData
   *
   * The output of VectorDataToRoadDescription is in image index coordinates
   *
   * 3 cases :
   * - input image has no geo-information : pass through
   * - input image is in cartographic projection : apply image spacing and origin, and set the ProjectionRef
   * - input image is in sensor model geometry : reproject in WGS84
   *
   */

  std::string projRef = inputImage->GetProjectionRef();
  ImageKeywordlist kwl;
  itk::ExposeMetaData<ImageKeywordlist>(inputImage->GetMetaDataDictionary(),
                                        MetaDataKey::OSSIMKeywordlistKey,
                                        kwl);

  VectorDataType::Pointer projectedVD;

  if ( !projRef.empty() )
    {
    // image is in cartographic projection
    // apply spacing and origin + set projection WKT
    // The VectorData in output of the chain is in image index coordinate,
    // and the projection information is lost
    // Apply an affine transform to apply image origin and spacing,
    // and arbitrarily set the ProjectionRef to the input image ProjectionRef

    typedef itk::AffineTransform<VectorDataType::PrecisionType, 2> TransformType;
    typedef otb::VectorDataTransformFilter<VectorDataType, VectorDataType> VDTransformType;

    TransformType::ParametersType params;
    params.SetSize(6);
    params[0] = inputImage->GetSpacing()[0];
    params[1] = 0;
    params[2] = 0;
    params[3] = inputImage->GetSpacing()[1];
    params[4] = inputImage->GetOrigin()[0];
    params[5] = inputImage->GetOrigin()[1];

    TransformType::Pointer transform = TransformType::New();
    transform->SetParameters(params);

    VDTransformType::Pointer vdTransform = VDTransformType::New();
    vdTransform->SetTransform(transform);
    vdTransform->SetInput(outVD);
    vdTransform->Update();

    projectedVD = vdTransform->GetOutput();

    projectedVD->SetProjectionRef(inputImage->GetProjectionRef());
    }
    else if ( kwl.GetSize() > 0 )
    {
    // image is in sensor model geometry

    // Reproject VectorData in image projection
    VectorDataProjectionFilterType::Pointer vproj = VectorDataProjectionFilterType::New();
    vproj->SetInput(outVD);

    vproj->SetOutputKeywordList(inputImage->GetImageKeywordlist());
    vproj->SetOutputProjectionRef(inputImage->GetProjectionRef());
    vproj->SetOutputOrigin(inputImage->GetOrigin());
    vproj->SetOutputSpacing(inputImage->GetSpacing());

    if( parseResult->IsOptionPresent("DEMDirectory") )
      {
      vproj->SetDEMDirectory(parseResult->GetParameterString("DEMDirectory"));
      }

    vproj->Update();
    projectedVD = vproj->GetOutput();
    }
    else
    {
    // no georeferencing information

    projectedVD = outVD;

    }

   // Write vectordata with description
   VectorDataWriterType::Pointer vdwriter = VectorDataWriterType::New();
   vdwriter->SetFileName(parseResult->GetParameterString("OutputVectorData"));
   vdwriter->SetInput(projectedVD);
   vdwriter->Update();

  return EXIT_SUCCESS;
}

}

<commit_msg>DOC:improve documentation of cartographic db validation framework applications<commit_after>/*=========================================================================

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

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

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

=========================================================================*/
#include "otbComputePolylineFeatureFromImage.h"

#include <iostream>
#include "otbCommandLineArgumentParser.h"

#include "otbVectorImage.h"
#include "otbImageFileReader.h"

#include "otbVectorData.h"
#include "otbVectorDataFileReader.h"
#include "otbVectorDataFileWriter.h"
#include "itkPreOrderTreeIterator.h"

#include "otbVectorDataIntoImageProjectionFilter.h"
#include "otbVectorDataProjectionFilter.h"
#include "otbVectorDataTransformFilter.h"
#include "itkAffineTransform.h"

#include "otbParserConditionDataNodeFeatureFunction.h"
#include "otbNDVIDataNodeFeatureFunction.h"

namespace otb
{

int ComputePolylineFeatureFromImage::Describe(ApplicationDescriptor* descriptor)
{
  descriptor->SetName("ComputePolylineFeatureFromImage");
  descriptor->SetDescription("Compute a polyline feature descriptors from an input image which are part of the polyline pixels that verify the FeatureExpression");
  descriptor->AddOption("InputImage", "An image from which to compute description",
                        "img",   1, true, ApplicationDescriptor::InputImage);
  descriptor->AddOption("InputVectorData", "Vector data containing the polylines onto which the feature will be computed",
                        "vdin",  1, true, ApplicationDescriptor::FileName);
  descriptor->AddOption("FeatureExpression", "The feature formula (b1 > 0.3)",
                        "expr",  1, true, ApplicationDescriptor::String);
  descriptor->AddOption("FieldName", "The feature name (NONDVI, ROADSA...)",
                        "field", 1, true, ApplicationDescriptor::String);
  descriptor->AddOption("OutputVectorData", "The output vector data containing the feature",
                        "out",   1, true, ApplicationDescriptor::FileName);

  descriptor->AddOption("DEMDirectory", "DEM directory",
                        "dem", 1, false, ApplicationDescriptor::DirectoryName);

  return EXIT_SUCCESS;
}

int ComputePolylineFeatureFromImage::Execute(otb::ApplicationOptionsResult* parseResult)
{
  // Images
  typedef float                                           PixelType;
  typedef VectorImage<PixelType, 2>                       ImageType;
  typedef otb::ImageFileReader<ImageType>                 ReaderType;

  // VectorData
  typedef VectorData<>                                    VectorDataType;
  typedef VectorDataType::DataNodeType                    DataNodeType;
  typedef DataNodeType::ValuePrecisionType                PrecisionType;
  typedef DataNodeType::PrecisionType                     CoordRepType;
  typedef itk::PreOrderTreeIterator<VectorDataType::DataTreeType>
                                                          TreeIteratorType;
  typedef VectorDataFileReader<VectorDataType>            VectorDataReaderType;
  typedef VectorDataFileWriter<VectorDataType>            VectorDataWriterType;

  typedef VectorDataIntoImageProjectionFilter
    <VectorDataType, ImageType>                           VectorDataIntoImageProjType;
  typedef VectorDataProjectionFilter
    <VectorDataType, VectorDataType>                      VectorDataProjectionFilterType;

  typedef ParserConditionDataNodeFeatureFunction<ImageType, CoordRepType, PrecisionType>
                                                          ParserConditionFeatureFunctionType;

  // Vector Data into Image projection
  //// Read the Image
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(parseResult->GetParameterString("InputImage"));
  reader->UpdateOutputInformation();
  reader->Update();
  ImageType::Pointer inputImage = reader->GetOutput();
  //// Read the Vectordata
  VectorDataReaderType::Pointer vdreader = VectorDataReaderType::New();
  vdreader->SetFileName(parseResult->GetParameterString("InputVectorData"));
  vdreader->Update();
  //// Projection
  VectorDataIntoImageProjType::Pointer vprojIm = VectorDataIntoImageProjType::New();
  vprojIm->SetInputVectorData(vdreader->GetOutput());
  vprojIm->SetInputImage(inputImage);
  if( parseResult->IsOptionPresent("DEMDirectory") )
    {
      vprojIm->SetDEMDirectory(parseResult->GetParameterString("DEMDirectory"));
    }
  vprojIm->SetUseOutputSpacingAndOriginFromImage(true); // we want index as input;
  vprojIm->Update();

  // Add description
  ParserConditionFeatureFunctionType::Pointer vdescriptor = ParserConditionFeatureFunctionType::New();
  vdescriptor->SetExpression(parseResult->GetParameterString("FeatureExpression"));
  vdescriptor->SetInputImage(inputImage);

  VectorDataType::Pointer outVD = VectorDataType::New();
  // Retrieving root node
  DataNodeType::Pointer root = outVD->GetDataTree()->GetRoot()->Get();
  // Create the document node
  DataNodeType::Pointer document = DataNodeType::New();
  document->SetNodeType(otb::DOCUMENT);
  // Adding the layer to the data tree
  outVD->GetDataTree()->Add(document, root);
  // Create the folder node
  DataNodeType::Pointer folder = DataNodeType::New();
  folder->SetNodeType(otb::FOLDER);
  // Adding the layer to the data tree
  outVD->GetDataTree()->Add(folder, document);

  TreeIteratorType itVector(vprojIm->GetOutput()->GetDataTree());
  itVector.GoToBegin();

  while (!itVector.IsAtEnd())
    {
    vdescriptor->SetInputImage(reader->GetOutput());
    if (!itVector.Get()->IsRoot() && !itVector.Get()->IsDocument() && !itVector.Get()->IsFolder())
      {
      DataNodeType::Pointer currentGeometry = itVector.Get();
      currentGeometry->SetFieldAsDouble(parseResult->GetParameterString("FieldName"),
                                        (double)(vdescriptor->Evaluate(*(currentGeometry.GetPointer()))[0]));

      outVD->GetDataTree()->Add(currentGeometry, folder);
      }
    ++itVector;
    }

  /*
   * Reprojection of the output VectorData
   *
   * The output of VectorDataToRoadDescription is in image index coordinates
   *
   * 3 cases :
   * - input image has no geo-information : pass through
   * - input image is in cartographic projection : apply image spacing and origin, and set the ProjectionRef
   * - input image is in sensor model geometry : reproject in WGS84
   *
   */

  std::string projRef = inputImage->GetProjectionRef();
  ImageKeywordlist kwl;
  itk::ExposeMetaData<ImageKeywordlist>(inputImage->GetMetaDataDictionary(),
                                        MetaDataKey::OSSIMKeywordlistKey,
                                        kwl);

  VectorDataType::Pointer projectedVD;

  if ( !projRef.empty() )
    {
    // image is in cartographic projection
    // apply spacing and origin + set projection WKT
    // The VectorData in output of the chain is in image index coordinate,
    // and the projection information is lost
    // Apply an affine transform to apply image origin and spacing,
    // and arbitrarily set the ProjectionRef to the input image ProjectionRef

    typedef itk::AffineTransform<VectorDataType::PrecisionType, 2> TransformType;
    typedef otb::VectorDataTransformFilter<VectorDataType, VectorDataType> VDTransformType;

    TransformType::ParametersType params;
    params.SetSize(6);
    params[0] = inputImage->GetSpacing()[0];
    params[1] = 0;
    params[2] = 0;
    params[3] = inputImage->GetSpacing()[1];
    params[4] = inputImage->GetOrigin()[0];
    params[5] = inputImage->GetOrigin()[1];

    TransformType::Pointer transform = TransformType::New();
    transform->SetParameters(params);

    VDTransformType::Pointer vdTransform = VDTransformType::New();
    vdTransform->SetTransform(transform);
    vdTransform->SetInput(outVD);
    vdTransform->Update();

    projectedVD = vdTransform->GetOutput();

    projectedVD->SetProjectionRef(inputImage->GetProjectionRef());
    }
    else if ( kwl.GetSize() > 0 )
    {
    // image is in sensor model geometry

    // Reproject VectorData in image projection
    VectorDataProjectionFilterType::Pointer vproj = VectorDataProjectionFilterType::New();
    vproj->SetInput(outVD);

    vproj->SetOutputKeywordList(inputImage->GetImageKeywordlist());
    vproj->SetOutputProjectionRef(inputImage->GetProjectionRef());
    vproj->SetOutputOrigin(inputImage->GetOrigin());
    vproj->SetOutputSpacing(inputImage->GetSpacing());

    if( parseResult->IsOptionPresent("DEMDirectory") )
      {
      vproj->SetDEMDirectory(parseResult->GetParameterString("DEMDirectory"));
      }

    vproj->Update();
    projectedVD = vproj->GetOutput();
    }
    else
    {
    // no georeferencing information

    projectedVD = outVD;

    }

   // Write vectordata with description
   VectorDataWriterType::Pointer vdwriter = VectorDataWriterType::New();
   vdwriter->SetFileName(parseResult->GetParameterString("OutputVectorData"));
   vdwriter->SetInput(projectedVD);
   vdwriter->Update();

  return EXIT_SUCCESS;
}

}

<|endoftext|>


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

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

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

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

 =========================================================================*/
#include "otbWrapperApplicationFactory.h"

#include "otbMultiToMonoChannelExtractROI.h"
#include "otbGenericRSResampleImageFilter.h"
#include "otbGridResampleImageFilter.h"
#include "otbImportGeoInformationImageFilter.h"
#include "otbBCOInterpolateImageFunction.h"
#include "otbSimpleRcsPanSharpeningFusionImageFilter.h"
#include "itkFixedArray.h"

// Elevation handler
#include "otbWrapperElevationParametersHandler.h"

#include "otbPleiadesPToXSAffineTransformCalculator.h"

namespace otb
{
namespace Wrapper
{
class BundleToPerfectSensor : public Application
{
public:
  /** Standard class typedefs. */
  typedef BundleToPerfectSensor         Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(BundleToPerfectSensor, otb::Application);

private:

  void DoInit() ITK_OVERRIDE
  {
    SetName("BundleToPerfectSensor");
    SetDescription("Perform P+XS pansharpening");

    // Documentation
    SetDocName("Bundle to perfect sensor");
    SetDocLongDescription("This application performs P+XS pansharpening. The default mode use Pan and XS sensor models to estimate the transformation to superimpose XS over Pan before the fusion (\"default mode\"). The application provides also a PHR mode for Pleiades images which does not use sensor models as Pan and XS products are already coregistered but only estimate an affine transformation to superimpose XS over the Pan.Note that this option is automatically activated in case Pleiades images are detected as input.");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso(" ");

    AddDocTag(Tags::Geometry);
    AddDocTag(Tags::Pansharpening);

    AddParameter(ParameterType_InputImage,   "inp",   "Input PAN Image");
    SetParameterDescription("inp"," Input panchromatic image.");
    AddParameter(ParameterType_InputImage,   "inxs",  "Input XS Image");
    SetParameterDescription("inxs"," Input XS image.");

    // Elevation
    ElevationParametersHandler::AddElevationParameters(this, "elev");

    // Superposition mode
    AddParameter(ParameterType_Choice,"mode", "Mode");
    SetParameterDescription("mode", "Superimposition mode");

    AddChoice("mode.default", "Default mode");
    SetParameterDescription("mode.default", "Default superimposition mode : "
      "uses any projection reference or sensor model found in the images");

    AddChoice("mode.phr", "Pleiades mode");
    SetParameterDescription("mode.phr", "Pleiades superimposition mode, "
      "designed for the case of a P+XS bundle in SENSOR geometry. It uses"
      " a simple transform on the XS image : a scaling and a residual "
      "translation.");

    AddParameter(ParameterType_Float,        "lms",   "Spacing of the deformation field");
    SetParameterDescription("lms"," Spacing of the deformation field. Default is 10 times the PAN image spacing.");
    AddParameter(ParameterType_OutputImage,  "out",   "Output image");
    SetParameterDescription("out"," Output image.");
    AddRAMParameter();

    MandatoryOff("lms");

    // Doc example parameter settings
    SetDocExampleParameterValue("inp", "QB_Toulouse_Ortho_PAN.tif");
    SetDocExampleParameterValue("inxs", "QB_Toulouse_Ortho_XS.tif");
    SetDocExampleParameterValue("out", "BundleToPerfectSensor.png uchar");

  }

  void DoUpdateParameters() ITK_OVERRIDE
  {
    if(!HasUserValue("mode") && HasValue("inp") && HasValue("inxs") && otb::PleiadesPToXSAffineTransformCalculator::CanCompute(GetParameterImage("inp"),GetParameterImage("inxs")))
      {
      otbAppLogWARNING("Forcing PHR mode with PHR data. You need to add \"-mode default\" to force the default mode with PHR images.");
      SetParameterString("mode","phr");
      }
  }

  void DoExecute() ITK_OVERRIDE
  {
    FloatVectorImageType* panchroV = GetParameterImage("inp");
    FloatVectorImageType* xs = GetParameterImage("inxs");

    if ( panchroV->GetNumberOfComponentsPerPixel() != 1 )
      {
      itkExceptionMacro(<< "The panchromatic image must be a single channel image")
      }

    // Transform the PAN image to otb::Image
    typedef otb::Image<FloatVectorImageType::InternalPixelType> InternalImageType;
    typedef otb::MultiToMonoChannelExtractROI<float,float> ExtractFilterType;

    ExtractFilterType::Pointer channelSelect = ExtractFilterType::New();
    m_Ref.push_back(channelSelect.GetPointer());
    channelSelect->SetChannel(1);
    channelSelect->SetInput(panchroV);
    channelSelect->UpdateOutputInformation();
    InternalImageType::Pointer panchro = channelSelect->GetOutput();

    typedef otb::BCOInterpolateImageFunction<FloatVectorImageType> InterpolatorType;
    typedef otb::GenericRSResampleImageFilter<FloatVectorImageType, FloatVectorImageType>  ResamplerType;
    typedef otb::GridResampleImageFilter<FloatVectorImageType, FloatVectorImageType>  BasicResamplerType;
    typedef otb::ImportGeoInformationImageFilter<FloatVectorImageType,InternalImageType> ImportGeoInformationFilterType;
    typedef otb::SimpleRcsPanSharpeningFusionImageFilter<InternalImageType, FloatVectorImageType, FloatVectorImageType> FusionFilterType;

    // Resample filter
    ResamplerType::Pointer    resampler = ResamplerType::New();
    m_Ref.push_back(resampler.GetPointer());

    BasicResamplerType::Pointer basicResampler = BasicResamplerType::New();
    m_Ref.push_back(basicResampler.GetPointer());

    ImportGeoInformationFilterType::Pointer geoImport = ImportGeoInformationFilterType::New();
    m_Ref.push_back(geoImport.GetPointer());

    InterpolatorType::Pointer interpolator = InterpolatorType::New();
    resampler->SetInterpolator(interpolator);
    basicResampler->SetInterpolator(interpolator);

    // Fusion filter
    FusionFilterType::Pointer  fusionFilter = FusionFilterType::New();
    m_Ref.push_back(fusionFilter.GetPointer());
    fusionFilter->SetPanInput(panchro);

    // Setup the DEM Handler
    otb::Wrapper::ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(this,"elev");

    // Set up output image information
    FloatVectorImageType::SpacingType spacing = panchro->GetSpacing();
    FloatVectorImageType::IndexType   start = panchro->GetLargestPossibleRegion().GetIndex();
    FloatVectorImageType::SizeType    size = panchro->GetLargestPossibleRegion().GetSize();
    FloatVectorImageType::PointType   origin = panchro->GetOrigin();

    FloatVectorImageType::PixelType defaultValue;
    itk::NumericTraits<FloatVectorImageType::PixelType>::SetLength(defaultValue, xs->GetNumberOfComponentsPerPixel());

    if(GetParameterString("mode") == "default")
      {
      otbAppLogINFO("Using the default mode");
      if(IsParameterEnabled("lms") && HasValue("lms"))
        {
        double defScalarSpacing = GetParameterFloat("lms");
        otbAppLogINFO(<< "Generating coarse deformation field (spacing="<<defScalarSpacing<<")" << std::endl);
        FloatVectorImageType::SpacingType defSpacing;

        defSpacing[0] = defScalarSpacing;
        defSpacing[1] = defScalarSpacing;

        resampler->SetDisplacementFieldSpacing(defSpacing);
        }
      else
        {
        FloatVectorImageType::SpacingType defSpacing;
        defSpacing[0]=10*spacing[0];
        defSpacing[1]=10*spacing[1];
        resampler->SetDisplacementFieldSpacing(defSpacing);
        }

      resampler->SetInput(xs);
      resampler->SetOutputOrigin(origin);
      resampler->SetOutputSpacing(spacing);
      resampler->SetOutputSize(size);
      resampler->SetOutputStartIndex(start);
      resampler->SetOutputKeywordList(panchro->GetImageKeywordlist());
      resampler->SetOutputProjectionRef(panchro->GetProjectionRef());
      resampler->SetEdgePaddingValue(defaultValue);
      fusionFilter->SetXsInput(resampler->GetOutput());
      }
    else if(GetParameterString("mode")=="phr")
      {
      otbAppLogINFO("Using the PHR mode");

      otb::PleiadesPToXSAffineTransformCalculator::TransformType::OffsetType offset
        = otb::PleiadesPToXSAffineTransformCalculator::ComputeOffset(GetParameterImage("inp"),
                                                                     GetParameterImage("inxs"));

      origin+=offset;
      origin[0]=origin[0]/4;
      origin[1]=origin[1]/4;

      basicResampler->SetOutputOrigin(origin);
      basicResampler->SetInput(xs);
      basicResampler->SetOutputOrigin(origin);

      FloatVectorImageType::SpacingType xsSpacing = GetParameterImage("inxs")->GetSpacing();
      xsSpacing*=0.25;

      basicResampler->SetOutputSpacing(xsSpacing);
      basicResampler->SetOutputSize(size);
      basicResampler->SetOutputStartIndex(start);
      basicResampler->SetEdgePaddingValue(defaultValue);

      geoImport->SetInput(basicResampler->GetOutput());
      geoImport->SetSource(panchro);

      fusionFilter->SetXsInput(geoImport->GetOutput());

      // Set the profRef & Keywordlist from Pan into the resampled XS image
      basicResampler->UpdateOutputInformation();
      itk::MetaDataDictionary& dict = basicResampler->GetOutput()->GetMetaDataDictionary();
      itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::ProjectionRefKey,
                                            panchro->GetProjectionRef());
      itk::EncapsulateMetaData<ImageKeywordlist>(dict, MetaDataKey::OSSIMKeywordlistKey,
                                                 panchro->GetImageKeywordlist());
      }
    else
      {
      otbAppLogWARNING("Unknown mode");
      }

    SetParameterOutputImage("out", fusionFilter->GetOutput());
  }

  std::vector<itk::ProcessObject::Pointer> m_Ref;

};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::BundleToPerfectSensor)
<commit_msg>BUG: Mantis-1237: fix parameter order<commit_after>/*=========================================================================

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

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

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

 =========================================================================*/
#include "otbWrapperApplicationFactory.h"

#include "otbMultiToMonoChannelExtractROI.h"
#include "otbGenericRSResampleImageFilter.h"
#include "otbGridResampleImageFilter.h"
#include "otbImportGeoInformationImageFilter.h"
#include "otbBCOInterpolateImageFunction.h"
#include "otbSimpleRcsPanSharpeningFusionImageFilter.h"
#include "itkFixedArray.h"

// Elevation handler
#include "otbWrapperElevationParametersHandler.h"

#include "otbPleiadesPToXSAffineTransformCalculator.h"

namespace otb
{
namespace Wrapper
{
class BundleToPerfectSensor : public Application
{
public:
  /** Standard class typedefs. */
  typedef BundleToPerfectSensor         Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  /** Standard macro */
  itkNewMacro(Self);

  itkTypeMacro(BundleToPerfectSensor, otb::Application);

private:

  void DoInit() ITK_OVERRIDE
  {
    SetName("BundleToPerfectSensor");
    SetDescription("Perform P+XS pansharpening");

    // Documentation
    SetDocName("Bundle to perfect sensor");
    SetDocLongDescription("This application performs P+XS pansharpening. The default mode use Pan and XS sensor models to estimate the transformation to superimpose XS over Pan before the fusion (\"default mode\"). The application provides also a PHR mode for Pleiades images which does not use sensor models as Pan and XS products are already coregistered but only estimate an affine transformation to superimpose XS over the Pan.Note that this option is automatically activated in case Pleiades images are detected as input.");
    SetDocLimitations("None");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso(" ");

    AddDocTag(Tags::Geometry);
    AddDocTag(Tags::Pansharpening);

    AddParameter(ParameterType_InputImage,   "inp",   "Input PAN Image");
    SetParameterDescription("inp"," Input panchromatic image.");
    AddParameter(ParameterType_InputImage,   "inxs",  "Input XS Image");
    SetParameterDescription("inxs"," Input XS image.");

    AddParameter(ParameterType_OutputImage,  "out",   "Output image");
    SetParameterDescription("out"," Output image.");

    // Elevation
    ElevationParametersHandler::AddElevationParameters(this, "elev");

    // Superposition mode
    AddParameter(ParameterType_Choice,"mode", "Mode");
    SetParameterDescription("mode", "Superimposition mode");

    AddChoice("mode.default", "Default mode");
    SetParameterDescription("mode.default", "Default superimposition mode : "
      "uses any projection reference or sensor model found in the images");

    AddChoice("mode.phr", "Pleiades mode");
    SetParameterDescription("mode.phr", "Pleiades superimposition mode, "
      "designed for the case of a P+XS bundle in SENSOR geometry. It uses"
      " a simple transform on the XS image : a scaling and a residual "
      "translation.");

    AddParameter(ParameterType_Float,        "lms",   "Spacing of the deformation field");
    SetParameterDescription("lms"," Spacing of the deformation field. Default is 10 times the PAN image spacing.");

    AddRAMParameter();

    MandatoryOff("lms");

    // Doc example parameter settings
    SetDocExampleParameterValue("inp", "QB_Toulouse_Ortho_PAN.tif");
    SetDocExampleParameterValue("inxs", "QB_Toulouse_Ortho_XS.tif");
    SetDocExampleParameterValue("out", "BundleToPerfectSensor.png uchar");

  }

  void DoUpdateParameters() ITK_OVERRIDE
  {
    if(!HasUserValue("mode") && HasValue("inp") && HasValue("inxs") && otb::PleiadesPToXSAffineTransformCalculator::CanCompute(GetParameterImage("inp"),GetParameterImage("inxs")))
      {
      otbAppLogWARNING("Forcing PHR mode with PHR data. You need to add \"-mode default\" to force the default mode with PHR images.");
      SetParameterString("mode","phr");
      }
  }

  void DoExecute() ITK_OVERRIDE
  {
    FloatVectorImageType* panchroV = GetParameterImage("inp");
    FloatVectorImageType* xs = GetParameterImage("inxs");

    if ( panchroV->GetNumberOfComponentsPerPixel() != 1 )
      {
      itkExceptionMacro(<< "The panchromatic image must be a single channel image")
      }

    // Transform the PAN image to otb::Image
    typedef otb::Image<FloatVectorImageType::InternalPixelType> InternalImageType;
    typedef otb::MultiToMonoChannelExtractROI<float,float> ExtractFilterType;

    ExtractFilterType::Pointer channelSelect = ExtractFilterType::New();
    m_Ref.push_back(channelSelect.GetPointer());
    channelSelect->SetChannel(1);
    channelSelect->SetInput(panchroV);
    channelSelect->UpdateOutputInformation();
    InternalImageType::Pointer panchro = channelSelect->GetOutput();

    typedef otb::BCOInterpolateImageFunction<FloatVectorImageType> InterpolatorType;
    typedef otb::GenericRSResampleImageFilter<FloatVectorImageType, FloatVectorImageType>  ResamplerType;
    typedef otb::GridResampleImageFilter<FloatVectorImageType, FloatVectorImageType>  BasicResamplerType;
    typedef otb::ImportGeoInformationImageFilter<FloatVectorImageType,InternalImageType> ImportGeoInformationFilterType;
    typedef otb::SimpleRcsPanSharpeningFusionImageFilter<InternalImageType, FloatVectorImageType, FloatVectorImageType> FusionFilterType;

    // Resample filter
    ResamplerType::Pointer    resampler = ResamplerType::New();
    m_Ref.push_back(resampler.GetPointer());

    BasicResamplerType::Pointer basicResampler = BasicResamplerType::New();
    m_Ref.push_back(basicResampler.GetPointer());

    ImportGeoInformationFilterType::Pointer geoImport = ImportGeoInformationFilterType::New();
    m_Ref.push_back(geoImport.GetPointer());

    InterpolatorType::Pointer interpolator = InterpolatorType::New();
    resampler->SetInterpolator(interpolator);
    basicResampler->SetInterpolator(interpolator);

    // Fusion filter
    FusionFilterType::Pointer  fusionFilter = FusionFilterType::New();
    m_Ref.push_back(fusionFilter.GetPointer());
    fusionFilter->SetPanInput(panchro);

    // Setup the DEM Handler
    otb::Wrapper::ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(this,"elev");

    // Set up output image information
    FloatVectorImageType::SpacingType spacing = panchro->GetSpacing();
    FloatVectorImageType::IndexType   start = panchro->GetLargestPossibleRegion().GetIndex();
    FloatVectorImageType::SizeType    size = panchro->GetLargestPossibleRegion().GetSize();
    FloatVectorImageType::PointType   origin = panchro->GetOrigin();

    FloatVectorImageType::PixelType defaultValue;
    itk::NumericTraits<FloatVectorImageType::PixelType>::SetLength(defaultValue, xs->GetNumberOfComponentsPerPixel());

    if(GetParameterString("mode") == "default")
      {
      otbAppLogINFO("Using the default mode");
      if(IsParameterEnabled("lms") && HasValue("lms"))
        {
        double defScalarSpacing = GetParameterFloat("lms");
        otbAppLogINFO(<< "Generating coarse deformation field (spacing="<<defScalarSpacing<<")" << std::endl);
        FloatVectorImageType::SpacingType defSpacing;

        defSpacing[0] = defScalarSpacing;
        defSpacing[1] = defScalarSpacing;

        resampler->SetDisplacementFieldSpacing(defSpacing);
        }
      else
        {
        FloatVectorImageType::SpacingType defSpacing;
        defSpacing[0]=10*spacing[0];
        defSpacing[1]=10*spacing[1];
        resampler->SetDisplacementFieldSpacing(defSpacing);
        }

      resampler->SetInput(xs);
      resampler->SetOutputOrigin(origin);
      resampler->SetOutputSpacing(spacing);
      resampler->SetOutputSize(size);
      resampler->SetOutputStartIndex(start);
      resampler->SetOutputKeywordList(panchro->GetImageKeywordlist());
      resampler->SetOutputProjectionRef(panchro->GetProjectionRef());
      resampler->SetEdgePaddingValue(defaultValue);
      fusionFilter->SetXsInput(resampler->GetOutput());
      }
    else if(GetParameterString("mode")=="phr")
      {
      otbAppLogINFO("Using the PHR mode");

      otb::PleiadesPToXSAffineTransformCalculator::TransformType::OffsetType offset
        = otb::PleiadesPToXSAffineTransformCalculator::ComputeOffset(GetParameterImage("inp"),
                                                                     GetParameterImage("inxs"));

      origin+=offset;
      origin[0]=origin[0]/4;
      origin[1]=origin[1]/4;

      basicResampler->SetOutputOrigin(origin);
      basicResampler->SetInput(xs);
      basicResampler->SetOutputOrigin(origin);

      FloatVectorImageType::SpacingType xsSpacing = GetParameterImage("inxs")->GetSpacing();
      xsSpacing*=0.25;

      basicResampler->SetOutputSpacing(xsSpacing);
      basicResampler->SetOutputSize(size);
      basicResampler->SetOutputStartIndex(start);
      basicResampler->SetEdgePaddingValue(defaultValue);

      geoImport->SetInput(basicResampler->GetOutput());
      geoImport->SetSource(panchro);

      fusionFilter->SetXsInput(geoImport->GetOutput());

      // Set the profRef & Keywordlist from Pan into the resampled XS image
      basicResampler->UpdateOutputInformation();
      itk::MetaDataDictionary& dict = basicResampler->GetOutput()->GetMetaDataDictionary();
      itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::ProjectionRefKey,
                                            panchro->GetProjectionRef());
      itk::EncapsulateMetaData<ImageKeywordlist>(dict, MetaDataKey::OSSIMKeywordlistKey,
                                                 panchro->GetImageKeywordlist());
      }
    else
      {
      otbAppLogWARNING("Unknown mode");
      }

    SetParameterOutputImage("out", fusionFilter->GetOutput());
  }

  std::vector<itk::ProcessObject::Pointer> m_Ref;

};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::BundleToPerfectSensor)
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef __PERF_HPP__
#define __PERF_HPP__

#include <unistd.h>

#include <set>
#include <string>

#include <process/future.hpp>

#include <stout/duration.hpp>
#include <stout/hashmap.hpp>

// For PerfStatistics protobuf.
#include "mesos/mesos.hpp"

namespace perf {

// Sample the perf events for process(es) in the perf_event cgroups
// for duration. The returned hashmap is keyed by cgroup.
// NOTE: cgroups should be relative to the perf_event subsystem mount,
// e.g., mesos/test for /sys/fs/cgroup/perf_event/mesos/test.
process::Future<hashmap<std::string, mesos::PerfStatistics>> sample(
    const std::set<std::string>& events,
    const std::set<std::string>& cgroups,
    const Duration& duration);

// Validate a set of events are accepted by `perf stat`.
bool valid(const std::set<std::string>& events);

// Returns whether perf is supported on this host. Returns false if
// the kernel is too old (requires >= 2.6.39).
bool supported();

// Note: The parse function is exposed to allow testing of the
// multiple supported perf stat output formats.
Try<hashmap<std::string, mesos::PerfStatistics>> parse(
    const std::string& output,
    const Version& version);

} // namespace perf {

#endif // __PERF_HPP__
<commit_msg>Added missing header `version.hpp` in `src/linux/perf.hpp`.<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef __PERF_HPP__
#define __PERF_HPP__

#include <unistd.h>

#include <set>
#include <string>

#include <process/future.hpp>

#include <stout/duration.hpp>
#include <stout/hashmap.hpp>
#include <stout/version.hpp>

// For PerfStatistics protobuf.
#include "mesos/mesos.hpp"

namespace perf {

// Sample the perf events for process(es) in the perf_event cgroups
// for duration. The returned hashmap is keyed by cgroup.
// NOTE: cgroups should be relative to the perf_event subsystem mount,
// e.g., mesos/test for /sys/fs/cgroup/perf_event/mesos/test.
process::Future<hashmap<std::string, mesos::PerfStatistics>> sample(
    const std::set<std::string>& events,
    const std::set<std::string>& cgroups,
    const Duration& duration);

// Validate a set of events are accepted by `perf stat`.
bool valid(const std::set<std::string>& events);

// Returns whether perf is supported on this host. Returns false if
// the kernel is too old (requires >= 2.6.39).
bool supported();

// Note: The parse function is exposed to allow testing of the
// multiple supported perf stat output formats.
Try<hashmap<std::string, mesos::PerfStatistics>> parse(
    const std::string& output,
    const Version& version);

} // namespace perf {

#endif // __PERF_HPP__
<|endoftext|>


<commit_before>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2015-2018 Baldur Karlsson
 *
 * 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.
 ******************************************************************************/

#include "vk_core.h"
#include "vk_replay.h"

static int dllLocator = 0;

void VulkanReplay::OutputWindow::SetWindowHandle(WindowingData window)
{
  RDCASSERT(window.system == WindowingSystem::Win32, window.system);
  wnd = window.win32.window;
}

void VulkanReplay::OutputWindow::CreateSurface(VkInstance inst)
{
  VkWin32SurfaceCreateInfoKHR createInfo;

  createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
  createInfo.pNext = NULL;
  createInfo.flags = 0;
  createInfo.hwnd = wnd;

  GetModuleHandleExA(
      GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
      (const char *)&dllLocator, (HMODULE *)&createInfo.hinstance);

  VkResult vkr = ObjDisp(inst)->CreateWin32SurfaceKHR(Unwrap(inst), &createInfo, NULL, &surface);
  RDCASSERTEQUAL(vkr, VK_SUCCESS);
}

void VulkanReplay::GetOutputWindowDimensions(uint64_t id, int32_t &w, int32_t &h)
{
  if(id == 0 || m_OutputWindows.find(id) == m_OutputWindows.end())
    return;

  OutputWindow &outw = m_OutputWindows[id];

  RECT rect = {0};
  GetClientRect(outw.wnd, &rect);
  w = rect.right - rect.left;
  h = rect.bottom - rect.top;
}

bool VulkanReplay::IsOutputWindowVisible(uint64_t id)
{
  if(id == 0 || m_OutputWindows.find(id) == m_OutputWindows.end())
    return false;

  return (IsWindowVisible(m_OutputWindows[id].wnd) == TRUE);
}

void WrappedVulkan::AddRequiredExtensions(bool instance, vector<string> &extensionList,
                                          const std::set<string> &supportedExtensions)
{
  bool device = !instance;

  if(instance)
  {
    // for windows we require both extensions as there's no alternative
    if(supportedExtensions.find(VK_KHR_SURFACE_EXTENSION_NAME) == supportedExtensions.end())
    {
      RDCERR("Unsupported required instance extension '%s'", VK_KHR_SURFACE_EXTENSION_NAME);
    }
    else
    {
      // don't add duplicates
      if(std::find(extensionList.begin(), extensionList.end(), VK_KHR_SURFACE_EXTENSION_NAME) ==
         extensionList.end())
        extensionList.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
    }

    if(supportedExtensions.find(VK_KHR_WIN32_SURFACE_EXTENSION_NAME) == supportedExtensions.end())
    {
      RDCERR("Unsupported required instance extension '%s'", VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
    }
    else
    {
      if(std::find(extensionList.begin(), extensionList.end(),
                   VK_KHR_WIN32_SURFACE_EXTENSION_NAME) == extensionList.end())
        extensionList.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
    }
  }
  else if(device)
  {
    if(supportedExtensions.find(VK_KHR_SWAPCHAIN_EXTENSION_NAME) == supportedExtensions.end())
    {
      RDCERR("Unsupported required device extension '%s'", VK_KHR_SWAPCHAIN_EXTENSION_NAME);
    }
    else
    {
      // don't add duplicates
      if(std::find(extensionList.begin(), extensionList.end(), VK_KHR_SWAPCHAIN_EXTENSION_NAME) ==
         extensionList.end())
        extensionList.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
    }
  }
}

#if !defined(VK_USE_PLATFORM_WIN32_KHR)
#error "Win32 KHR platform not defined"
#endif

VkResult WrappedVulkan::vkCreateWin32SurfaceKHR(VkInstance instance,
                                                const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
                                                const VkAllocationCallbacks *pAllocator,
                                                VkSurfaceKHR *pSurface)
{
  // should not come in here at all on replay
  RDCASSERT(IsCaptureMode(m_State));

  VkResult ret =
      ObjDisp(instance)->CreateWin32SurfaceKHR(Unwrap(instance), pCreateInfo, pAllocator, pSurface);

  if(ret == VK_SUCCESS)
  {
    GetResourceManager()->WrapResource(Unwrap(instance), *pSurface);

    WrappedVkSurfaceKHR *wrapped = GetWrapped(*pSurface);

    // since there's no point in allocating a full resource record and storing the window
    // handle under there somewhere, we just cast. We won't use the resource record for anything
    wrapped->record = (VkResourceRecord *)pCreateInfo->hwnd;

    Keyboard::AddInputWindow((void *)pCreateInfo->hwnd);
  }

  return ret;
}

VkBool32 WrappedVulkan::vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice,
                                                                       uint32_t queueFamilyIndex)
{
  return ObjDisp(physicalDevice)
      ->GetPhysicalDeviceWin32PresentationSupportKHR(Unwrap(physicalDevice), queueFamilyIndex);
}

const char *VulkanLibraryName = "vulkan-1.dll";

std::wstring GetJSONPath(bool wow6432)
{
  wchar_t curFile[1024];
  GetModuleFileNameW(NULL, curFile, 1024);

  wchar_t *lastSlash = wcsrchr(curFile, '\\');
  if(lastSlash)
    *(lastSlash + 1) = 0;

  if(wow6432)
    wcscat_s(curFile, L"x86\\");

  wcscat_s(curFile, L"renderdoc.json");

  return curFile;
}

static HKEY GetImplicitLayersKey(bool writeable, bool wow6432)
{
  std::string basepath = "SOFTWARE\\";

  if(wow6432)
    basepath += "Wow6432Node\\";

  basepath += "Khronos\\Vulkan\\ImplicitLayers";

  HKEY key = NULL;
  LSTATUS ret = ERROR_SUCCESS;

  if(writeable)
    ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, basepath.c_str(), 0, NULL, 0, KEY_READ | KEY_WRITE,
                          NULL, &key, NULL);
  else
    ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, basepath.c_str(), 0, KEY_READ, &key);

  if(ret != ERROR_SUCCESS)
  {
    if(key)
      RegCloseKey(key);

    // find to fail to open for read, the key may not exist
    if(writeable)
      RDCERR("Couldn't open %s for write", basepath.c_str());

    return NULL;
  }

  return key;
}

bool ProcessImplicitLayersKey(HKEY key, const std::wstring &path,
                              std::vector<std::string> *otherJSONs, bool deleteOthers)
{
  bool thisRegistered = false;

  wchar_t name[1025] = {};
  DWORD nameSize = 1024;
  DWORD idx = 0;

  LONG ret = RegEnumValueW(key, idx++, name, &nameSize, NULL, NULL, NULL, NULL);

  std::wstring myJSON = path;
  for(size_t i = 0; i < myJSON.size(); i++)
    myJSON[i] = towlower(myJSON[i]);

  while(ret == ERROR_SUCCESS)
  {
    // convert the name here so we preserve casing
    std::string utf8name = StringFormat::Wide2UTF8(name);

    for(DWORD i = 0; i <= nameSize && name[i]; i++)
      name[i] = towlower(name[i]);

    if(wcscmp(name, myJSON.c_str()) == 0)
    {
      thisRegistered = true;
    }
    else if(wcsstr(name, L"renderdoc.json") != NULL)
    {
      if(otherJSONs)
        otherJSONs->push_back(utf8name);

      if(deleteOthers)
        RegDeleteValueW(key, name);
    }

    nameSize = 1024;
    ret = RegEnumValueW(key, idx++, name, &nameSize, NULL, NULL, NULL, NULL);
  }

  return thisRegistered;
}

bool VulkanReplay::CheckVulkanLayer(VulkanLayerFlags &flags, std::vector<std::string> &myJSONs,
                                    std::vector<std::string> &otherJSONs)
{
  std::wstring normalPath = GetJSONPath(false);
  myJSONs.push_back(StringFormat::Wide2UTF8(normalPath));

#if ENABLED(RDOC_X64)
  std::wstring wow6432Path = GetJSONPath(true);
  myJSONs.push_back(StringFormat::Wide2UTF8(wow6432Path));
#endif

  HKEY key = GetImplicitLayersKey(false, false);

  // if we couldn't even get the ImplicitLayers reg key the system doesn't have the
  // vulkan runtime, so we return as if we are not registered (as that's the case).
  // People not using vulkan can either ignore the message, or click to set it up
  // and it will go away as we'll have rights to create it.
  if(!key)
  {
    flags = VulkanLayerFlags::NeedElevation | VulkanLayerFlags::RegisterAll;
    return true;
  }

  bool thisRegistered = ProcessImplicitLayersKey(key, normalPath, &otherJSONs, false);

  RegCloseKey(key);

#if ENABLED(RDOC_X64)
  {
    key = GetImplicitLayersKey(false, true);

    // if we're on 64-bit, the layer isn't registered unless both keys are registered.
    thisRegistered = false;

    if(key)
    {
      thisRegistered = ProcessImplicitLayersKey(key, wow6432Path, &otherJSONs, false);

      RegCloseKey(key);
    }
  }
#endif

  flags = VulkanLayerFlags::NeedElevation | VulkanLayerFlags::RegisterAll;

  if(thisRegistered)
    flags |= VulkanLayerFlags::ThisInstallRegistered;

  if(!otherJSONs.empty())
    flags |= VulkanLayerFlags::OtherInstallsRegistered;

  // return true if any changes are needed
  return !otherJSONs.empty() || !thisRegistered;
}

void VulkanReplay::InstallVulkanLayer(bool systemLevel)
{
  HKEY key = GetImplicitLayersKey(true, false);

  const DWORD zero = 0;

  if(key)
  {
    std::wstring path = GetJSONPath(false);

    // this function will delete all non-matching renderdoc.json values, and return true if our own
    // is registered
    bool thisRegistered = ProcessImplicitLayersKey(key, path, NULL, true);

    if(!thisRegistered)
      RegSetValueExW(key, path.c_str(), 0, REG_DWORD, (const BYTE *)&zero, sizeof(zero));

    RegCloseKey(key);
  }

// if we're a 64-bit process, update the 32-bit key
#if ENABLED(RDOC_X64)
  {
    key = GetImplicitLayersKey(true, true);

    if(key)
    {
      std::wstring path = GetJSONPath(true);

      // this function will delete all non-matching renderdoc.json values, and return true if our
      // own is registered
      bool thisRegistered = ProcessImplicitLayersKey(key, path, NULL, true);

      if(!thisRegistered)
        RegSetValueExW(key, path.c_str(), 0, REG_DWORD, (const BYTE *)&zero, sizeof(zero));

      RegCloseKey(key);
    }
  }
#endif
}
<commit_msg>Don't allow registered x86 layer to hide a non-registered x64 layer<commit_after>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2015-2018 Baldur Karlsson
 *
 * 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.
 ******************************************************************************/

#include "vk_core.h"
#include "vk_replay.h"

static int dllLocator = 0;

void VulkanReplay::OutputWindow::SetWindowHandle(WindowingData window)
{
  RDCASSERT(window.system == WindowingSystem::Win32, window.system);
  wnd = window.win32.window;
}

void VulkanReplay::OutputWindow::CreateSurface(VkInstance inst)
{
  VkWin32SurfaceCreateInfoKHR createInfo;

  createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
  createInfo.pNext = NULL;
  createInfo.flags = 0;
  createInfo.hwnd = wnd;

  GetModuleHandleExA(
      GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
      (const char *)&dllLocator, (HMODULE *)&createInfo.hinstance);

  VkResult vkr = ObjDisp(inst)->CreateWin32SurfaceKHR(Unwrap(inst), &createInfo, NULL, &surface);
  RDCASSERTEQUAL(vkr, VK_SUCCESS);
}

void VulkanReplay::GetOutputWindowDimensions(uint64_t id, int32_t &w, int32_t &h)
{
  if(id == 0 || m_OutputWindows.find(id) == m_OutputWindows.end())
    return;

  OutputWindow &outw = m_OutputWindows[id];

  RECT rect = {0};
  GetClientRect(outw.wnd, &rect);
  w = rect.right - rect.left;
  h = rect.bottom - rect.top;
}

bool VulkanReplay::IsOutputWindowVisible(uint64_t id)
{
  if(id == 0 || m_OutputWindows.find(id) == m_OutputWindows.end())
    return false;

  return (IsWindowVisible(m_OutputWindows[id].wnd) == TRUE);
}

void WrappedVulkan::AddRequiredExtensions(bool instance, vector<string> &extensionList,
                                          const std::set<string> &supportedExtensions)
{
  bool device = !instance;

  if(instance)
  {
    // for windows we require both extensions as there's no alternative
    if(supportedExtensions.find(VK_KHR_SURFACE_EXTENSION_NAME) == supportedExtensions.end())
    {
      RDCERR("Unsupported required instance extension '%s'", VK_KHR_SURFACE_EXTENSION_NAME);
    }
    else
    {
      // don't add duplicates
      if(std::find(extensionList.begin(), extensionList.end(), VK_KHR_SURFACE_EXTENSION_NAME) ==
         extensionList.end())
        extensionList.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
    }

    if(supportedExtensions.find(VK_KHR_WIN32_SURFACE_EXTENSION_NAME) == supportedExtensions.end())
    {
      RDCERR("Unsupported required instance extension '%s'", VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
    }
    else
    {
      if(std::find(extensionList.begin(), extensionList.end(),
                   VK_KHR_WIN32_SURFACE_EXTENSION_NAME) == extensionList.end())
        extensionList.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
    }
  }
  else if(device)
  {
    if(supportedExtensions.find(VK_KHR_SWAPCHAIN_EXTENSION_NAME) == supportedExtensions.end())
    {
      RDCERR("Unsupported required device extension '%s'", VK_KHR_SWAPCHAIN_EXTENSION_NAME);
    }
    else
    {
      // don't add duplicates
      if(std::find(extensionList.begin(), extensionList.end(), VK_KHR_SWAPCHAIN_EXTENSION_NAME) ==
         extensionList.end())
        extensionList.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
    }
  }
}

#if !defined(VK_USE_PLATFORM_WIN32_KHR)
#error "Win32 KHR platform not defined"
#endif

VkResult WrappedVulkan::vkCreateWin32SurfaceKHR(VkInstance instance,
                                                const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
                                                const VkAllocationCallbacks *pAllocator,
                                                VkSurfaceKHR *pSurface)
{
  // should not come in here at all on replay
  RDCASSERT(IsCaptureMode(m_State));

  VkResult ret =
      ObjDisp(instance)->CreateWin32SurfaceKHR(Unwrap(instance), pCreateInfo, pAllocator, pSurface);

  if(ret == VK_SUCCESS)
  {
    GetResourceManager()->WrapResource(Unwrap(instance), *pSurface);

    WrappedVkSurfaceKHR *wrapped = GetWrapped(*pSurface);

    // since there's no point in allocating a full resource record and storing the window
    // handle under there somewhere, we just cast. We won't use the resource record for anything
    wrapped->record = (VkResourceRecord *)pCreateInfo->hwnd;

    Keyboard::AddInputWindow((void *)pCreateInfo->hwnd);
  }

  return ret;
}

VkBool32 WrappedVulkan::vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice,
                                                                       uint32_t queueFamilyIndex)
{
  return ObjDisp(physicalDevice)
      ->GetPhysicalDeviceWin32PresentationSupportKHR(Unwrap(physicalDevice), queueFamilyIndex);
}

const char *VulkanLibraryName = "vulkan-1.dll";

std::wstring GetJSONPath(bool wow6432)
{
  wchar_t curFile[1024];
  GetModuleFileNameW(NULL, curFile, 1024);

  wchar_t *lastSlash = wcsrchr(curFile, '\\');
  if(lastSlash)
    *(lastSlash + 1) = 0;

  if(wow6432)
    wcscat_s(curFile, L"x86\\");

  wcscat_s(curFile, L"renderdoc.json");

  return curFile;
}

static HKEY GetImplicitLayersKey(bool writeable, bool wow6432)
{
  std::string basepath = "SOFTWARE\\";

  if(wow6432)
    basepath += "Wow6432Node\\";

  basepath += "Khronos\\Vulkan\\ImplicitLayers";

  HKEY key = NULL;
  LSTATUS ret = ERROR_SUCCESS;

  if(writeable)
    ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, basepath.c_str(), 0, NULL, 0, KEY_READ | KEY_WRITE,
                          NULL, &key, NULL);
  else
    ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, basepath.c_str(), 0, KEY_READ, &key);

  if(ret != ERROR_SUCCESS)
  {
    if(key)
      RegCloseKey(key);

    // find to fail to open for read, the key may not exist
    if(writeable)
      RDCERR("Couldn't open %s for write", basepath.c_str());

    return NULL;
  }

  return key;
}

bool ProcessImplicitLayersKey(HKEY key, const std::wstring &path,
                              std::vector<std::string> *otherJSONs, bool deleteOthers)
{
  bool thisRegistered = false;

  wchar_t name[1025] = {};
  DWORD nameSize = 1024;
  DWORD idx = 0;

  LONG ret = RegEnumValueW(key, idx++, name, &nameSize, NULL, NULL, NULL, NULL);

  std::wstring myJSON = path;
  for(size_t i = 0; i < myJSON.size(); i++)
    myJSON[i] = towlower(myJSON[i]);

  while(ret == ERROR_SUCCESS)
  {
    // convert the name here so we preserve casing
    std::string utf8name = StringFormat::Wide2UTF8(name);

    for(DWORD i = 0; i <= nameSize && name[i]; i++)
      name[i] = towlower(name[i]);

    if(wcscmp(name, myJSON.c_str()) == 0)
    {
      thisRegistered = true;
    }
    else if(wcsstr(name, L"renderdoc.json") != NULL)
    {
      if(otherJSONs)
        otherJSONs->push_back(utf8name);

      if(deleteOthers)
        RegDeleteValueW(key, name);
    }

    nameSize = 1024;
    ret = RegEnumValueW(key, idx++, name, &nameSize, NULL, NULL, NULL, NULL);
  }

  return thisRegistered;
}

bool VulkanReplay::CheckVulkanLayer(VulkanLayerFlags &flags, std::vector<std::string> &myJSONs,
                                    std::vector<std::string> &otherJSONs)
{
  std::wstring normalPath = GetJSONPath(false);
  myJSONs.push_back(StringFormat::Wide2UTF8(normalPath));

#if ENABLED(RDOC_X64)
  std::wstring wow6432Path = GetJSONPath(true);
  myJSONs.push_back(StringFormat::Wide2UTF8(wow6432Path));
#endif

  HKEY key = GetImplicitLayersKey(false, false);

  // if we couldn't even get the ImplicitLayers reg key the system doesn't have the
  // vulkan runtime, so we return as if we are not registered (as that's the case).
  // People not using vulkan can either ignore the message, or click to set it up
  // and it will go away as we'll have rights to create it.
  if(!key)
  {
    flags = VulkanLayerFlags::NeedElevation | VulkanLayerFlags::RegisterAll;
    return true;
  }

  bool thisRegistered = ProcessImplicitLayersKey(key, normalPath, &otherJSONs, false);

  RegCloseKey(key);

#if ENABLED(RDOC_X64)
  {
    key = GetImplicitLayersKey(false, true);

    if(key)
    {
      // if we're on 64-bit, the layer isn't registered unless both keys are registered.
      thisRegistered &= ProcessImplicitLayersKey(key, wow6432Path, &otherJSONs, false);

      RegCloseKey(key);
    }
    else
    {
      flags = VulkanLayerFlags::NeedElevation | VulkanLayerFlags::RegisterAll;
      return true;
    }
  }
#endif

  flags = VulkanLayerFlags::NeedElevation | VulkanLayerFlags::RegisterAll;

  if(thisRegistered)
    flags |= VulkanLayerFlags::ThisInstallRegistered;

  if(!otherJSONs.empty())
    flags |= VulkanLayerFlags::OtherInstallsRegistered;

  // return true if any changes are needed
  return !otherJSONs.empty() || !thisRegistered;
}

void VulkanReplay::InstallVulkanLayer(bool systemLevel)
{
  HKEY key = GetImplicitLayersKey(true, false);

  const DWORD zero = 0;

  if(key)
  {
    std::wstring path = GetJSONPath(false);

    // this function will delete all non-matching renderdoc.json values, and return true if our own
    // is registered
    bool thisRegistered = ProcessImplicitLayersKey(key, path, NULL, true);

    if(!thisRegistered)
      RegSetValueExW(key, path.c_str(), 0, REG_DWORD, (const BYTE *)&zero, sizeof(zero));

    RegCloseKey(key);
  }

// if we're a 64-bit process, update the 32-bit key
#if ENABLED(RDOC_X64)
  {
    key = GetImplicitLayersKey(true, true);

    if(key)
    {
      std::wstring path = GetJSONPath(true);

      // this function will delete all non-matching renderdoc.json values, and return true if our
      // own is registered
      bool thisRegistered = ProcessImplicitLayersKey(key, path, NULL, true);

      if(!thisRegistered)
        RegSetValueExW(key, path.c_str(), 0, REG_DWORD, (const BYTE *)&zero, sizeof(zero));

      RegCloseKey(key);
    }
  }
#endif
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// AliFemtoCorrFctnPairFractions - A correlation function that analyzes            //
// two particle correlations with respect to the azimuthal angle (phi)        //
// and pseudorapidity (eta) difference                                        //
//                                                                            //
// Authors: Malgorzata Janik, majanik@cern.ch                                   //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

#include "AliFemtoCorrFctnPairFractions.h"
#include "AliFemtoModelHiddenInfo.h"
//#include "AliFemtoHisto.hh"
#include <cstdio>
#include <TMath.h>

#ifdef __ROOT__
ClassImp(AliFemtoCorrFctnPairFractions)
#endif

#define PIH 1.57079632679489656
#define PIT 6.28318530717958623

//____________________________
AliFemtoCorrFctnPairFractions::AliFemtoCorrFctnPairFractions(char* title):
AliFemtoCorrFctn(),
  fPairFractions(0),
  fphiL(0),
  fphiT(0)
{

  //fphiL = (-(int)(aPhiBins/4)+0.5)*2.*TMath::Pi()/aPhiBins;
  //fphiT = 2*TMath::Pi()+(-(int)(aPhiBins/4)+0.5)*2.*TMath::Pi()/aPhiBins;

  TString  hname  = "hPairFraction"; hname+= title;
  TString  htitle = "Pair Fraction "; htitle+= title;
  fPairFractions = new TH1F(hname.Data(),htitle.Data(), 7, 0, 7);
  fPairFractions->GetXaxis()->SetBinLabel(1,"#pi#pi, MC");
  fPairFractions->GetXaxis()->SetBinLabel(2,"KK, MC");
  fPairFractions->GetXaxis()->SetBinLabel(3,"pp, MC");
  fPairFractions->GetXaxis()->SetBinLabel(4,"#pi K, MC");
  fPairFractions->GetXaxis()->SetBinLabel(5,"#pi p, MC");
  fPairFractions->GetXaxis()->SetBinLabel(6,"Kp, MC");
  fPairFractions->GetXaxis()->SetBinLabel(7,"Other, MC");

  // to enable error bar calculation...

  fPairFractions->Sumw2();
  fPairFractions->Sumw2();
}

//____________________________
AliFemtoCorrFctnPairFractions::AliFemtoCorrFctnPairFractions(const AliFemtoCorrFctnPairFractions& aCorrFctn) :
  AliFemtoCorrFctn(),
  fPairFractions(0),
  fphiL(0),
  fphiT(0)
{
  // copy constructor
  if (aCorrFctn.fPairFractions)
    fPairFractions = new TH1F(*aCorrFctn.fPairFractions);
  else
    fPairFractions = 0;

 if (aCorrFctn.fPairFractions)
    fPairFractions = new TH1F(*aCorrFctn.fPairFractions);
  else
    fPairFractions = 0;

  fphiL = aCorrFctn.fphiL;
  fphiT = aCorrFctn.fphiT;

}
//____________________________
AliFemtoCorrFctnPairFractions::~AliFemtoCorrFctnPairFractions(){
  // destructor
  delete fPairFractions;
  delete fPairFractions;
}
//_________________________
AliFemtoCorrFctnPairFractions& AliFemtoCorrFctnPairFractions::operator=(const AliFemtoCorrFctnPairFractions& aCorrFctn)
{
  // assignment operator
  if (this == &aCorrFctn)
    return *this;

  if (aCorrFctn.fPairFractions)
    fPairFractions = new TH1F(*aCorrFctn.fPairFractions);
  else
    fPairFractions = 0;

  fphiL = aCorrFctn.fphiL;
  fphiT = aCorrFctn.fphiT;

  return *this;
}
//_________________________
void AliFemtoCorrFctnPairFractions::Finish(){
  // here is where we should normalize, fit, etc...
  // we should NOT Draw() the histos (as I had done it below),
  // since we want to insulate ourselves from root at this level
  // of the code.  Do it instead at root command line with browser.
  //  mShareNumerator->Draw();
  // mShareDenominator->Draw();
  // mRatio->Draw();

}

//____________________________
AliFemtoString AliFemtoCorrFctnPairFractions::Report(){
  // create report
  string stemp = "Pair Fractions Correlation Function Report:\n";
  char ctemp[100];
  snprintf(ctemp , 100, "Number of entries in numerator:\t%E\n",fPairFractions->GetEntries());
  stemp += ctemp;
  snprintf(ctemp , 100, "Number of entries in denominator:\t%E\n",fPairFractions->GetEntries());
  stemp += ctemp;
  //  stemp += mCoulombWeight->Report();
  AliFemtoString returnThis = stemp;
  return returnThis;
}
//____________________________
void AliFemtoCorrFctnPairFractions::AddRealPair( AliFemtoPair* pair){
  // add real (effect) pair

  //Applying pair cuts
  if (fPairCut)
    if (!fPairCut->Pass(pair)) return;

  Int_t pdg1=0;
  AliFemtoModelHiddenInfo *info1 = ( AliFemtoModelHiddenInfo *) pair->Track1()->GetHiddenInfo();
  if(info1)pdg1 = info1->GetPDGPid();

  Int_t pdg2=0;
  AliFemtoModelHiddenInfo *info2 = ( AliFemtoModelHiddenInfo *) pair->Track2()->GetHiddenInfo();
  if(info2)pdg2 = info2->GetPDGPid();

  if(abs(pdg1)==211 && abs(pdg2)==211) //pi pi
      fPairFractions->Fill(0.5);
  else if(abs(pdg1)==321 && abs(pdg2)==321)// K K
      fPairFractions->Fill(1.5);
  else if(abs(pdg1)==2212 && abs(pdg2)==2212)// p p
      fPairFractions->Fill(2.5);
  else if(abs(pdg1)==211 && abs(pdg2)==321)// pi K
      fPairFractions->Fill(3.5);
  else if(abs(pdg1)==211 && abs(pdg2)==2212)// pi p
      fPairFractions->Fill(4.5);
  else if(abs(pdg1)==321 && abs(pdg2)==2212)//K p
      fPairFractions->Fill(5.5);
  else //other
      fPairFractions->Fill(6.5);

  /*double phi1 = pair->Track1()->Track()->P().Phi();
  double phi2 = pair->Track2()->Track()->P().Phi();
  double eta1 = pair->Track1()->Track()->P().PseudoRapidity();
  double eta2 = pair->Track2()->Track()->P().PseudoRapidity();

  double phi1 = pair->Track1()->FourMomentum().Phi();
  double phi2 = pair->Track2()->FourMomentum().Phi();
  double eta1 = pair->Track1()->FourMomentum().PseudoRapidity();
  double eta2 = pair->Track2()->FourMomentum().PseudoRapidity();

  double dphi = phi1 - phi2;
  while (dphi<fphiL) dphi+=PIT;
  while (dphi>fphiT) dphi-=PIT;

  double deta = eta1 - eta2;

   double px1 = pair->Track1()->Track()->P().x();
   double py1 = pair->Track1()->Track()->P().y();
   double px2 = pair->Track2()->Track()->P().x();
   double py2 = pair->Track2()->Track()->P().y();
   double pt1 = TMath::Hypot(px1, py1);
   double pt2 = TMath::Hypot(px2, py2);

   double PionMass = 0.13956995;*/

}
//____________________________
void AliFemtoCorrFctnPairFractions::AddMixedPair( AliFemtoPair* pair){
  // add mixed (background) pair
  if (fPairCut)
    if (!fPairCut->Pass(pair)) return;

}

void AliFemtoCorrFctnPairFractions::WriteHistos()
{
  // Write out result histograms
  fPairFractions->Write();
}

TList* AliFemtoCorrFctnPairFractions::GetOutputList()
{
  // Prepare the list of objects to be written to the output
  TList *tOutputList = new TList();

  tOutputList->Add(fPairFractions);

  return tOutputList;

}
<commit_msg>correction to new pair fraction correlation function<commit_after>////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// AliFemtoCorrFctnPairFractions - A correlation function that analyzes            //
// two particle correlations with respect to the azimuthal angle (phi)        //
// and pseudorapidity (eta) difference                                        //
//                                                                            //
// Authors: Malgorzata Janik, majanik@cern.ch                                   //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

#include "AliFemtoCorrFctnPairFractions.h"
#include "AliFemtoModelHiddenInfo.h"
//#include "AliFemtoHisto.hh"
#include <cstdio>
#include <TMath.h>

#ifdef __ROOT__
ClassImp(AliFemtoCorrFctnPairFractions)
#endif

#define PIH 1.57079632679489656
#define PIT 6.28318530717958623

//____________________________
AliFemtoCorrFctnPairFractions::AliFemtoCorrFctnPairFractions(char* title):
AliFemtoCorrFctn(),
  fPairFractions(0),
  fphiL(0),
  fphiT(0)
{

  //fphiL = (-(int)(aPhiBins/4)+0.5)*2.*TMath::Pi()/aPhiBins;
  //fphiT = 2*TMath::Pi()+(-(int)(aPhiBins/4)+0.5)*2.*TMath::Pi()/aPhiBins;

  TString  hname  = "hPairFraction"; hname+= title;
  TString  htitle = "Pair Fraction "; htitle+= title;
  fPairFractions = new TH1F(hname.Data(),htitle.Data(), 7, 0, 7);
  fPairFractions->GetXaxis()->SetBinLabel(1,"#pi#pi, MC");
  fPairFractions->GetXaxis()->SetBinLabel(2,"KK, MC");
  fPairFractions->GetXaxis()->SetBinLabel(3,"pp, MC");
  fPairFractions->GetXaxis()->SetBinLabel(4,"#pi K, MC");
  fPairFractions->GetXaxis()->SetBinLabel(5,"#pi p, MC");
  fPairFractions->GetXaxis()->SetBinLabel(6,"Kp, MC");
  fPairFractions->GetXaxis()->SetBinLabel(7,"Other, MC");

  // to enable error bar calculation...

  fPairFractions->Sumw2();
  fPairFractions->Sumw2();
}

//____________________________
AliFemtoCorrFctnPairFractions::AliFemtoCorrFctnPairFractions(const AliFemtoCorrFctnPairFractions& aCorrFctn) :
  AliFemtoCorrFctn(),
  fPairFractions(0),
  fphiL(0),
  fphiT(0)
{
  // copy constructor
  if (aCorrFctn.fPairFractions)
    fPairFractions = new TH1F(*aCorrFctn.fPairFractions);
  else
    fPairFractions = 0;

 if (aCorrFctn.fPairFractions)
    fPairFractions = new TH1F(*aCorrFctn.fPairFractions);
  else
    fPairFractions = 0;

  fphiL = aCorrFctn.fphiL;
  fphiT = aCorrFctn.fphiT;

}
//____________________________
AliFemtoCorrFctnPairFractions::~AliFemtoCorrFctnPairFractions(){
  // destructor
  if(fPairFractions)
    delete fPairFractions;

}
//_________________________
AliFemtoCorrFctnPairFractions& AliFemtoCorrFctnPairFractions::operator=(const AliFemtoCorrFctnPairFractions& aCorrFctn)
{
  // assignment operator
  if (this == &aCorrFctn)
    return *this;

  if (aCorrFctn.fPairFractions)
    fPairFractions = new TH1F(*aCorrFctn.fPairFractions);
  else
    fPairFractions = 0;

  fphiL = aCorrFctn.fphiL;
  fphiT = aCorrFctn.fphiT;

  return *this;
}
//_________________________
void AliFemtoCorrFctnPairFractions::Finish(){
  // here is where we should normalize, fit, etc...
  // we should NOT Draw() the histos (as I had done it below),
  // since we want to insulate ourselves from root at this level
  // of the code.  Do it instead at root command line with browser.
  //  mShareNumerator->Draw();
  // mShareDenominator->Draw();
  // mRatio->Draw();

}

//____________________________
AliFemtoString AliFemtoCorrFctnPairFractions::Report(){
  // create report
  string stemp = "Pair Fractions Correlation Function Report:\n";
  char ctemp[100];
  snprintf(ctemp , 100, "Number of entries in numerator:\t%E\n",fPairFractions->GetEntries());
  stemp += ctemp;
  snprintf(ctemp , 100, "Number of entries in denominator:\t%E\n",fPairFractions->GetEntries());
  stemp += ctemp;
  //  stemp += mCoulombWeight->Report();
  AliFemtoString returnThis = stemp;
  return returnThis;
}
//____________________________
void AliFemtoCorrFctnPairFractions::AddRealPair( AliFemtoPair* pair){
  // add real (effect) pair

  //Applying pair cuts
  if (fPairCut)
    if (!fPairCut->Pass(pair)) return;

  Int_t pdg1=0;
  AliFemtoModelHiddenInfo *info1 = ( AliFemtoModelHiddenInfo *) pair->Track1()->GetHiddenInfo();
  if(info1)pdg1 = info1->GetPDGPid();

  Int_t pdg2=0;
  AliFemtoModelHiddenInfo *info2 = ( AliFemtoModelHiddenInfo *) pair->Track2()->GetHiddenInfo();
  if(info2)pdg2 = info2->GetPDGPid();

  if(abs(pdg1)==211 && abs(pdg2)==211) //pi pi
      fPairFractions->Fill(0.5);
  else if(abs(pdg1)==321 && abs(pdg2)==321)// K K
      fPairFractions->Fill(1.5);
  else if(abs(pdg1)==2212 && abs(pdg2)==2212)// p p
      fPairFractions->Fill(2.5);
  else if(abs(pdg1)==211 && abs(pdg2)==321)// pi K
      fPairFractions->Fill(3.5);
  else if(abs(pdg1)==211 && abs(pdg2)==2212)// pi p
      fPairFractions->Fill(4.5);
  else if(abs(pdg1)==321 && abs(pdg2)==2212)//K p
      fPairFractions->Fill(5.5);
  else //other
      fPairFractions->Fill(6.5);

  /*double phi1 = pair->Track1()->Track()->P().Phi();
  double phi2 = pair->Track2()->Track()->P().Phi();
  double eta1 = pair->Track1()->Track()->P().PseudoRapidity();
  double eta2 = pair->Track2()->Track()->P().PseudoRapidity();

  double phi1 = pair->Track1()->FourMomentum().Phi();
  double phi2 = pair->Track2()->FourMomentum().Phi();
  double eta1 = pair->Track1()->FourMomentum().PseudoRapidity();
  double eta2 = pair->Track2()->FourMomentum().PseudoRapidity();

  double dphi = phi1 - phi2;
  while (dphi<fphiL) dphi+=PIT;
  while (dphi>fphiT) dphi-=PIT;

  double deta = eta1 - eta2;

   double px1 = pair->Track1()->Track()->P().x();
   double py1 = pair->Track1()->Track()->P().y();
   double px2 = pair->Track2()->Track()->P().x();
   double py2 = pair->Track2()->Track()->P().y();
   double pt1 = TMath::Hypot(px1, py1);
   double pt2 = TMath::Hypot(px2, py2);

   double PionMass = 0.13956995;*/

}
//____________________________
void AliFemtoCorrFctnPairFractions::AddMixedPair( AliFemtoPair* pair){
  // add mixed (background) pair
  if (fPairCut)
    if (!fPairCut->Pass(pair)) return;

}

void AliFemtoCorrFctnPairFractions::WriteHistos()
{
  // Write out result histograms
  fPairFractions->Write();
}

TList* AliFemtoCorrFctnPairFractions::GetOutputList()
{
  // Prepare the list of objects to be written to the output
  TList *tOutputList = new TList();

  tOutputList->Add(fPairFractions);

  return tOutputList;

}
<|endoftext|>


<commit_before>// runV0ChCorrelations.C
//
// AddTask for AliAnalysisTaskV0ChCorrelations task
//
AliAnalysisTaskV0ChCorrelations *AddTaskV0ChCorrelations(const Bool_t bMCtruth=kFALSE)
{
  // Creates a V0Ch correlations analysis task and adds it to the analysis manager.

  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================

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

    // mc event handlerrunEx01.C
    if(bMCtruth) {
        AliMCEventHandler* mchandler = new AliMCEventHandler();
        // Not reading track references
        mchandler->SetReadTR(kFALSE);
        mgr->SetMCtruthEventHandler(mchandler);
    }

	// create task
    AliAnalysisTaskV0ChCorrelations* task = new AliAnalysisTaskV0ChCorrelations("V0ChCorrelations_task");
    mgr->AddTask(task);

    // Create ONLY the output containers for the data produced by the task.
    // Get and connect other common input/output containers via the manager as below
    //==============================================================================
    TString outputFileName = AliAnalysisManager::GetCommonFileName();
    outputFileName = "list.grid.v0ch.root";

    // create containers for input/output
    AliAnalysisDataContainer *cinput = mgr->GetCommonInputContainer();
    AliAnalysisDataContainer *coutput1 = mgr->CreateContainer("coutput1", TList::Class(), AliAnalysisManager::kOutputContainer, outputFileName);

    // connect input/output
    mgr->ConnectInput(task, 0, cinput);
    mgr->ConnectOutput(task, 1, coutput1);

    // Return task pointer at the end
    return task;
}

<commit_msg><commit_after>// runV0ChCorrelations.C
//
// AddTask for AliAnalysisTaskV0ChCorrelations task
//
AliAnalysisTaskV0ChCorrelations *AddTaskV0ChCorrelations(const Bool_t bMCtruth=kFALSE,
														 Float_t DcaDToPV = 0.5,
														 Float_t DcaV0D = 0.1
														)
{
  // Creates a V0Ch correlations analysis task and adds it to the analysis manager.

  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================

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

    // mc event handlerrunEx01.C
    if(bMCtruth) {
        AliMCEventHandler* mchandler = new AliMCEventHandler();
        // Not reading track references
        mchandler->SetReadTR(kFALSE);
        mgr->SetMCtruthEventHandler(mchandler);
    }

	// create task
    AliAnalysisTaskV0ChCorrelations* task = new AliAnalysisTaskV0ChCorrelations("V0ChCorrelations_task");
	task->SetDcaDToPV(DcaDToPV);
	task->SetDcaV0D(DcaV0D);
    mgr->AddTask(task);

    // Create ONLY the output containers for the data produced by the task.
    // Get and connect other common input/output containers via the manager as below
    //==============================================================================
    TString outputFileName = AliAnalysisManager::GetCommonFileName();
    outputFileName = "list.grid.v0ch.root";

    // create containers for input/output
    AliAnalysisDataContainer *cinput = mgr->GetCommonInputContainer();
    AliAnalysisDataContainer *coutput1 = mgr->CreateContainer("coutput1", TList::Class(), AliAnalysisManager::kOutputContainer, outputFileName);

    // connect input/output
    mgr->ConnectInput(task, 0, cinput);
    mgr->ConnectOutput(task, 1, coutput1);

    // Return task pointer at the end
    return task;
}

<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/magnet_uri.hpp"
#include "libtorrent/session.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/escape_string.hpp"
#include "libtorrent/error_code.hpp"

#include <string>

namespace libtorrent
{
	std::string make_magnet_uri(torrent_handle const& handle)
	{
		if (!handle.is_valid()) return "";

		char ret[1024];
		sha1_hash const& ih = handle.info_hash();
		int num_chars = snprintf(ret, sizeof(ret), "magnet:?xt=urn:btih:%s"
			, base32encode(std::string((char const*)&ih[0], 20)).c_str());

		std::string name = handle.name();

		if (!name.empty())
			num_chars += snprintf(ret + num_chars, sizeof(ret) - num_chars, "&dn=%s"
				, escape_string(name.c_str(), name.length()).c_str());

		std::string tracker;
		torrent_status st = handle.status();
		if (!st.current_tracker.empty())
		{
			tracker = st.current_tracker;
		}
		else
		{
			std::vector<announce_entry> const& tr = handle.trackers();
			if (!tr.empty()) tracker = tr[0].url;
		}
		if (!tracker.empty())
			num_chars += snprintf(ret + num_chars, sizeof(ret) - num_chars, "&tr=%s"
				, escape_string(tracker.c_str(), tracker.size()).c_str());

		return ret;
	}

	std::string make_magnet_uri(torrent_info const& info)
	{
		char ret[1024];
		sha1_hash const& ih = info.info_hash();
		int num_chars = snprintf(ret, sizeof(ret), "magnet:?xt=urn:btih:%s"
			, base32encode(std::string((char*)&ih[0], 20)).c_str());

		std::string const& name = info.name();

		if (!name.empty())
			num_chars += snprintf(ret + num_chars, sizeof(ret) - num_chars, "&dn=%s"
				, escape_string(name.c_str(), name.length()).c_str());

		std::vector<announce_entry> const& tr = info.trackers();
		if (!tr.empty())
		{
			num_chars += snprintf(ret + num_chars, sizeof(ret) - num_chars, "&tr=%s"
				, escape_string(tr[0].url.c_str(), tr[0].url.length()).c_str());
		}

		return ret;
	}

#ifndef BOOST_NO_EXCEPTIONS
#ifndef TORRENT_NO_DEPRECATE
	torrent_handle add_magnet_uri(session& ses, std::string const& uri
		, std::string const& save_path
		, storage_mode_t storage_mode
		, bool paused
		, storage_constructor_type sc
		, void* userdata)
	{
		std::string name;
		std::string tracker;

		error_code ec;
		std::string display_name = url_has_argument(uri, "dn");
		if (!display_name.empty()) name = unescape_string(display_name.c_str(), ec);
		std::string tracker_string = url_has_argument(uri, "tr");
		if (!tracker_string.empty()) tracker = unescape_string(tracker_string.c_str(), ec);

		std::string btih = url_has_argument(uri, "xt");
		if (btih.empty()) return torrent_handle();

		if (btih.compare(0, 9, "urn:btih:") != 0) return torrent_handle();

		sha1_hash info_hash;
		if (btih.size() == 40 + 9) from_hex(&btih[9], 40, (char*)&info_hash[0]);
		else info_hash.assign(base32decode(btih.substr(9)));

		return ses.add_torrent(tracker.empty() ? 0 : tracker.c_str(), info_hash
			, name.empty() ? 0 : name.c_str(), save_path, entry()
			, storage_mode, paused, sc, userdata);
	}
#endif

	torrent_handle add_magnet_uri(session& ses, std::string const& uri
		, add_torrent_params p)
	{
		error_code ec;
		torrent_handle ret = add_magnet_uri(ses, uri, p, ec);
		if (ec) throw libtorrent_exception(ec);
		return ret;
	}
#endif

	torrent_handle add_magnet_uri(session& ses, std::string const& uri
		, add_torrent_params p, error_code& ec)
	{
		parse_magnet_uri(uri, p, ec);
		if (ec) return torrent_handle();
		return ses.add_torrent(p, ec);
	}

	void parse_magnet_uri(std::string const& uri, add_torrent_params& p, error_code& ec)
	{
		std::string name;
		std::string tracker;

		error_code e;
		std::string display_name = url_has_argument(uri, "dn");
		if (!display_name.empty()) name = unescape_string(display_name.c_str(), e);

		// parse trackers out of the magnet link
		std::string::size_type pos = std::string::npos;
		std::string url = url_has_argument(uri, "tr", &pos);
		while (pos != std::string::npos)
		{
			error_code e;
			url = unescape_string(url, e);
			if (e) continue;
			p.trackers.push_back(url);
			pos = uri.find("&tr=", pos);
			if (pos == std::string::npos) break;
			pos += 4;
			url = uri.substr(pos, uri.find('&', pos) - pos);
		}

		std::string btih = url_has_argument(uri, "xt");
		if (btih.empty())
		{
			ec = errors::missing_info_hash_in_uri;
			return;
		}

		if (btih.compare(0, 9, "urn:btih:") != 0)
		{
			ec = errors::missing_info_hash_in_uri;
			return;
		}

#ifndef TORRENT_DISABLE_DHT
		std::string::size_type node_pos = std::string::npos;
		std::string node = url_has_argument(uri, "dht", &node_pos);
		while (!node.empty())
		{
			std::string::size_type divider = node.find_last_of(':');
			if (divider != std::string::npos)
			{
				int port = atoi(node.c_str()+divider+1);
				if (port != 0)
					p.dht_nodes.push_back(std::make_pair(node.substr(0, divider), port));
			}

			node_pos = uri.find("&dht=", node_pos);
			if (node_pos == std::string::npos) break;
			node_pos += 5;
			node = uri.substr(node_pos, uri.find('&', node_pos) - node_pos);
		}
#endif

		sha1_hash info_hash;
		if (btih.size() == 40 + 9) from_hex(&btih[9], 40, (char*)&info_hash[0]);
		else info_hash.assign(base32decode(btih.substr(9)));

		p.info_hash = info_hash;
		if (!name.empty()) p.name = name;
	}
}

<commit_msg>fix build without deprecated functions<commit_after>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/magnet_uri.hpp"
#include "libtorrent/session.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/escape_string.hpp"
#include "libtorrent/error_code.hpp"

#include <string>

namespace libtorrent
{
	std::string make_magnet_uri(torrent_handle const& handle)
	{
		if (!handle.is_valid()) return "";

		char ret[1024];
		sha1_hash const& ih = handle.info_hash();
		int num_chars = snprintf(ret, sizeof(ret), "magnet:?xt=urn:btih:%s"
			, base32encode(std::string((char const*)&ih[0], 20)).c_str());

		std::string name = handle.name();

		if (!name.empty())
			num_chars += snprintf(ret + num_chars, sizeof(ret) - num_chars, "&dn=%s"
				, escape_string(name.c_str(), name.length()).c_str());

		std::string tracker;
		torrent_status st = handle.status();
		if (!st.current_tracker.empty())
		{
			tracker = st.current_tracker;
		}
		else
		{
			std::vector<announce_entry> const& tr = handle.trackers();
			if (!tr.empty()) tracker = tr[0].url;
		}
		if (!tracker.empty())
			num_chars += snprintf(ret + num_chars, sizeof(ret) - num_chars, "&tr=%s"
				, escape_string(tracker.c_str(), tracker.size()).c_str());

		return ret;
	}

	std::string make_magnet_uri(torrent_info const& info)
	{
		char ret[1024];
		sha1_hash const& ih = info.info_hash();
		int num_chars = snprintf(ret, sizeof(ret), "magnet:?xt=urn:btih:%s"
			, base32encode(std::string((char*)&ih[0], 20)).c_str());

		std::string const& name = info.name();

		if (!name.empty())
			num_chars += snprintf(ret + num_chars, sizeof(ret) - num_chars, "&dn=%s"
				, escape_string(name.c_str(), name.length()).c_str());

		std::vector<announce_entry> const& tr = info.trackers();
		if (!tr.empty())
		{
			num_chars += snprintf(ret + num_chars, sizeof(ret) - num_chars, "&tr=%s"
				, escape_string(tr[0].url.c_str(), tr[0].url.length()).c_str());
		}

		return ret;
	}

#ifndef TORRENT_NO_DEPRECATE
#ifndef BOOST_NO_EXCEPTIONS
	torrent_handle add_magnet_uri(session& ses, std::string const& uri
		, std::string const& save_path
		, storage_mode_t storage_mode
		, bool paused
		, storage_constructor_type sc
		, void* userdata)
	{
		std::string name;
		std::string tracker;

		error_code ec;
		std::string display_name = url_has_argument(uri, "dn");
		if (!display_name.empty()) name = unescape_string(display_name.c_str(), ec);
		std::string tracker_string = url_has_argument(uri, "tr");
		if (!tracker_string.empty()) tracker = unescape_string(tracker_string.c_str(), ec);

		std::string btih = url_has_argument(uri, "xt");
		if (btih.empty()) return torrent_handle();

		if (btih.compare(0, 9, "urn:btih:") != 0) return torrent_handle();

		sha1_hash info_hash;
		if (btih.size() == 40 + 9) from_hex(&btih[9], 40, (char*)&info_hash[0]);
		else info_hash.assign(base32decode(btih.substr(9)));

		return ses.add_torrent(tracker.empty() ? 0 : tracker.c_str(), info_hash
			, name.empty() ? 0 : name.c_str(), save_path, entry()
			, storage_mode, paused, sc, userdata);
	}

	torrent_handle add_magnet_uri(session& ses, std::string const& uri
		, add_torrent_params p)
	{
		error_code ec;
		torrent_handle ret = add_magnet_uri(ses, uri, p, ec);
		if (ec) throw libtorrent_exception(ec);
		return ret;
	}
#endif // BOOST_NO_EXCEPTIONS

	torrent_handle add_magnet_uri(session& ses, std::string const& uri
		, add_torrent_params p, error_code& ec)
	{
		parse_magnet_uri(uri, p, ec);
		if (ec) return torrent_handle();
		return ses.add_torrent(p, ec);
	}

#endif // TORRENT_NO_DEPRECATE

	void parse_magnet_uri(std::string const& uri, add_torrent_params& p, error_code& ec)
	{
		std::string name;
		std::string tracker;

		error_code e;
		std::string display_name = url_has_argument(uri, "dn");
		if (!display_name.empty()) name = unescape_string(display_name.c_str(), e);

		// parse trackers out of the magnet link
		std::string::size_type pos = std::string::npos;
		std::string url = url_has_argument(uri, "tr", &pos);
		while (pos != std::string::npos)
		{
			error_code e;
			url = unescape_string(url, e);
			if (e) continue;
			p.trackers.push_back(url);
			pos = uri.find("&tr=", pos);
			if (pos == std::string::npos) break;
			pos += 4;
			url = uri.substr(pos, uri.find('&', pos) - pos);
		}

		std::string btih = url_has_argument(uri, "xt");
		if (btih.empty())
		{
			ec = errors::missing_info_hash_in_uri;
			return;
		}

		if (btih.compare(0, 9, "urn:btih:") != 0)
		{
			ec = errors::missing_info_hash_in_uri;
			return;
		}

#ifndef TORRENT_DISABLE_DHT
		std::string::size_type node_pos = std::string::npos;
		std::string node = url_has_argument(uri, "dht", &node_pos);
		while (!node.empty())
		{
			std::string::size_type divider = node.find_last_of(':');
			if (divider != std::string::npos)
			{
				int port = atoi(node.c_str()+divider+1);
				if (port != 0)
					p.dht_nodes.push_back(std::make_pair(node.substr(0, divider), port));
			}

			node_pos = uri.find("&dht=", node_pos);
			if (node_pos == std::string::npos) break;
			node_pos += 5;
			node = uri.substr(node_pos, uri.find('&', node_pos) - node_pos);
		}
#endif

		sha1_hash info_hash;
		if (btih.size() == 40 + 9) from_hex(&btih[9], 40, (char*)&info_hash[0]);
		else info_hash.assign(base32decode(btih.substr(9)));

		p.info_hash = info_hash;
		if (!name.empty()) p.name = name;
	}
}

<|endoftext|>