<commit_before>
#if GOOGLE_CUDA
#define EIGEN_USE_GPU

#include "sparsemax_functor.h"

#include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor"
#include "tensorflow/core/framework/op.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/register_types.h"

#include <cmath>
#include <type_traits>
#include <math_constants.h>

namespace tensorflow {

typedef Eigen::ThreadPoolDevice CPUDevice;
typedef Eigen::GpuDevice GPUDevice;

namespace functor {

#define anyswap(T, A,B) {T temp=A;A=B;B=temp;}

template <typename T>
__global__ void odd_even_sort_kernel(T *sorted,
                                     const int num_rows,
                                     const int num_cols,
                                     const int iterations) {
  const int col_index = blockIdx.x * blockDim.x + threadIdx.x;
  const int row_index = blockIdx.y;

  T* sorted_row = &sorted[row_index * num_cols];

  for(int i = 0; i < iterations; i++) {
    //even phase
    if (!(col_index & 1) && col_index < (num_cols - 1)) {
        if (sorted_row[col_index] < sorted_row[col_index + 1]) {
          T temp = sorted_row[col_index];
          sorted_row[col_index] = sorted_row[col_index + 1];
          sorted_row[col_index + 1] = temp;
        }
    }
    __syncthreads();

    //odd phase
    if ((col_index & 1) && col_index < (num_cols - 1)) {
        if (sorted_row[col_index] < sorted_row[col_index + 1]) {
          T temp = sorted_row[col_index];
          sorted_row[col_index] = sorted_row[col_index + 1];
          sorted_row[col_index + 1] = temp;
        }
    }
    __syncthreads();
  }
}

template <typename T>
void odd_even_sort(typename TTypes<T>::Matrix sorted,
                   const int num_rows,
                   const int num_cols) {
  // calculate paramization constants
  const int col_threads_per_block = 256;
  const int col_blocks = static_cast<int>(std::ceil(
   static_cast<double>(num_cols) / static_cast<double>(col_threads_per_block)
  ));

  dim3 threads_per_block(col_threads_per_block, 1, 1);
  dim3 blocks(col_blocks, num_rows, 1);

  // calculate number of odd-even iterations
  const int iterations = (num_cols % 2 == 0) ? num_cols/2 : (num_cols/2)+1;

  // launch kernel
  odd_even_sort_kernel<T><<<blocks, threads_per_block>>>(
    sorted.data(), num_rows, num_cols, iterations
  );
}

template <typename T>
__global__ void support_threshold_kernel(const T* cumsum,
                                         const int num_rows,
                                         const int num_cols,
                                         T* sorted) {
  const int col_index = blockIdx.x * blockDim.x + threadIdx.x;
  const int row_index = blockIdx.y;

  const T* cumsum_row = &cumsum[row_index * num_cols];
  T* sorted_row = &sorted[row_index * num_cols];

  const T one = static_cast<T>(1);

  if (col_index < num_cols) {
    const T k = static_cast<T>(col_index + 1);
    sorted_row[col_index] = static_cast<T>(
      one + k * sorted_row[col_index] > cumsum_row[col_index]
    );
  }
}

template <typename T>
void support_threshold(typename TTypes<T>::Matrix cumsum,
                       const int num_rows,
                       const int num_cols,
                       typename TTypes<T>::Matrix sorted) {
   // calculate paramization constants
   const int col_threads_per_block = 256;
   const int col_blocks = static_cast<int>(std::ceil(
    static_cast<double>(num_cols) / static_cast<double>(col_threads_per_block)
   ));

   dim3 threads_per_block(col_threads_per_block, 1, 1);
   dim3 blocks(col_blocks, num_rows, 1);

   // launch kernel
   support_threshold_kernel<T><<<blocks, threads_per_block>>>(
     cumsum.data(), num_rows, num_cols, sorted.data()
   );
}

template <typename T>
__global__ void calculate_tau_kernel(const T* cumsum,
                                     const int num_rows,
                                     const int num_cols,
                                     T* support) {
  const int row_index = blockIdx.x * blockDim.x + threadIdx.x;

  const T one = static_cast<T>(1);

  if (row_index < num_rows) {
    const int support_index = static_cast<int>(support[row_index]) - 1;
    const T cumsum_value = cumsum[row_index * num_cols + support_index];
    support[row_index] = (cumsum_value - one) / support[row_index];
  }
}

template <typename T>
void calculate_tau(typename TTypes<T>::Matrix cumsum,
                   const int num_rows,
                   const int num_cols,
                   typename TTypes<T>::Matrix support) {
   // calculate paramization constants
   const int threads_per_block = 256;
   const int blocks = static_cast<int>(std::ceil(
    static_cast<double>(num_rows) / static_cast<double>(threads_per_block)
   ));

   // launch kernel
   calculate_tau_kernel<T><<<blocks, threads_per_block>>>(
     cumsum.data(), num_rows, num_cols, support.data()
   );
}

template <typename T>
__global__ void calculate_properbility_kernel(const T* input,
                                              const T* tau,
                                              const int num_rows,
                                              const int num_cols,
                                              T* output) {
  const int col_index = blockIdx.x * blockDim.x + threadIdx.x;
  const int row_index = blockIdx.y;

  T zero = static_cast<T>(0);

  if (col_index < num_cols) {
    const int flat_index = row_index * num_cols + col_index;
    output[flat_index] = max(input[flat_index] - tau[row_index], zero);
  }
}

template <typename T>
void calculate_properbility(typename TTypes<T>::ConstMatrix input,
                            typename TTypes<T>::Matrix tau,
                            const int num_rows,
                            const int num_cols,
                            typename TTypes<T>::Matrix output) {
  // calculate paramization constants
  const int col_threads_per_block = 256;
  const int col_blocks = static_cast<int>(std::ceil(
   static_cast<double>(num_cols) / static_cast<double>(col_threads_per_block)
  ));

  dim3 threads_per_block(col_threads_per_block, 1, 1);
  dim3 blocks(col_blocks, num_rows, 1);

  // launch kernel
  calculate_properbility_kernel<T><<<blocks, threads_per_block>>>(
    input.data(), tau.data(), num_rows, num_cols, output.data()
  );
}

template <typename T>
struct Sparsemax<GPUDevice, T> {
  void operator()(const GPUDevice& d,
                  typename TTypes<T>::ConstMatrix input,
                  typename TTypes<T>::Matrix temp,
                  typename TTypes<T>::Matrix output) {

    const int num_rows = input.dimension(0); // batch_size
    const int num_cols = input.dimension(1);

    // define class axis
    const int kClassDim = 1;
    #if !defined(EIGEN_HAS_INDEX_LIST)
        Eigen::DSizes<int, 1> along_class(kClassDim);
    #else
        Eigen::IndexList<Eigen::type2index<kClassDim> > along_class;
    #endif

    // move input to sorted (temp), and sort inplace
    cudaMemcpy(temp.data(), input.data(),
               num_rows * num_cols * sizeof(T),
               cudaMemcpyDeviceToDevice);
    odd_even_sort<T>(temp, num_rows, num_cols);

    // Cumsum the sorted matrix along axis 1.
    // Put results in output as the the sorted and cumsum needs to be used
    // together.
    Eigen::internal::SumReducer<T> reducer;
    output.device(d) = temp.scan(1, reducer, false).eval();

    // Calculate threshold used in support calculation.
    // Replace sorted matrix, with the threshold booleans.
    support_threshold<T>(output, num_rows, num_cols, temp);

    // Sum each row, to get the support index.
    // This will reuse the temporary matrix, which is larger than required,
    // but the results will just be stored as if it was a flat vector.
    temp.device(d) = temp.sum(along_class).eval();

    // Calculate tau
    // Overwrites temp results with tau(z), again this just uses temp
    // as a flat vector.
    calculate_tau<T>(output, num_rows, num_cols, temp);

    // Calculate properbility
    // Use temp and input, and put results in output
    calculate_properbility<T>(input, temp, num_rows, num_cols, output);
  }
};

template struct Sparsemax<GPUDevice, Eigen::half>;
template struct Sparsemax<GPUDevice, float>;
template struct Sparsemax<GPUDevice, double>;

}  // namespace functor
}  // namespace tensorflow

#endif
<commit_msg>fix odd-even sort for large vectors<commit_after>
#if GOOGLE_CUDA
#define EIGEN_USE_GPU

#include "sparsemax_functor.h"

#include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor"
#include "tensorflow/core/framework/op.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/register_types.h"

#include <cmath>
#include <type_traits>
#include <math_constants.h>

namespace tensorflow {

typedef Eigen::ThreadPoolDevice CPUDevice;
typedef Eigen::GpuDevice GPUDevice;

namespace functor {

template <typename T>
__global__ void even_sort_kernel(T *sorted,
                                 const int num_rows,
                                 const int num_cols) {
  const int col_index = blockIdx.x * blockDim.x + threadIdx.x;
  const int row_index = blockIdx.y;

  T* sorted_row = &sorted[row_index * num_cols];

  if (!(col_index & 1) && col_index < (num_cols - 1)) {
      if (sorted_row[col_index] < sorted_row[col_index + 1]) {
        T temp = sorted_row[col_index];
        sorted_row[col_index] = sorted_row[col_index + 1];
        sorted_row[col_index + 1] = temp;
      }
  }
}

template <typename T>
__global__ void odd_sort_kernel(T *sorted,
                                const int num_rows,
                                const int num_cols) {
  const int col_index = blockIdx.x * blockDim.x + threadIdx.x;
  const int row_index = blockIdx.y;

  T* sorted_row = &sorted[row_index * num_cols];

  if ((col_index & 1) && col_index < (num_cols - 1)) {
      if (sorted_row[col_index] < sorted_row[col_index + 1]) {
        T temp = sorted_row[col_index];
        sorted_row[col_index] = sorted_row[col_index + 1];
        sorted_row[col_index + 1] = temp;
      }
  }
}

template <typename T>
void odd_even_sort(typename TTypes<T>::Matrix sorted,
                   const int num_rows,
                   const int num_cols) {
  // calculate paramization constants
  const int col_threads_per_block = 256;
  const int col_blocks = static_cast<int>(std::ceil(
   static_cast<double>(num_cols) / static_cast<double>(col_threads_per_block)
  ));

  dim3 threads_per_block(col_threads_per_block, 1, 1);
  dim3 blocks(col_blocks, num_rows, 1);

  // calculate number of odd-even iterations
  const int iterations = static_cast<int>(std::ceil(
   static_cast<double>(num_cols) / 2.0
  ));

  // Launch the even and odd kernels separately to get a global syncronization.
  // This is a very naive approach, as global syncronization is expensive.
  for(int i = 0; i < iterations; i++) {
    // launch even kernel
    even_sort_kernel<T><<<blocks, threads_per_block>>>(
      sorted.data(), num_rows, num_cols
    );

    // launch odd kernel
    odd_sort_kernel<T><<<blocks, threads_per_block>>>(
      sorted.data(), num_rows, num_cols
    );
  }
}

template <typename T>
__global__ void support_threshold_kernel(const T* cumsum,
                                         const int num_rows,
                                         const int num_cols,
                                         T* sorted) {
  const int col_index = blockIdx.x * blockDim.x + threadIdx.x;
  const int row_index = blockIdx.y;

  const T* cumsum_row = &cumsum[row_index * num_cols];
  T* sorted_row = &sorted[row_index * num_cols];

  const T one = static_cast<T>(1);

  if (col_index < num_cols) {
    const T k = static_cast<T>(col_index + 1);
    sorted_row[col_index] = static_cast<T>(
      one + k * sorted_row[col_index] > cumsum_row[col_index]
    );
  }
}

template <typename T>
void support_threshold(typename TTypes<T>::Matrix cumsum,
                       const int num_rows,
                       const int num_cols,
                       typename TTypes<T>::Matrix sorted) {
   // calculate paramization constants
   const int col_threads_per_block = 256;
   const int col_blocks = static_cast<int>(std::ceil(
    static_cast<double>(num_cols) / static_cast<double>(col_threads_per_block)
   ));

   dim3 threads_per_block(col_threads_per_block, 1, 1);
   dim3 blocks(col_blocks, num_rows, 1);

   // launch kernel
   support_threshold_kernel<T><<<blocks, threads_per_block>>>(
     cumsum.data(), num_rows, num_cols, sorted.data()
   );
}

template <typename T>
__global__ void calculate_tau_kernel(const T* cumsum,
                                     const int num_rows,
                                     const int num_cols,
                                     T* support) {
  const int row_index = blockIdx.x * blockDim.x + threadIdx.x;

  const T one = static_cast<T>(1);

  if (row_index < num_rows) {
    const int support_index = static_cast<int>(support[row_index]) - 1;
    const T cumsum_value = cumsum[row_index * num_cols + support_index];
    support[row_index] = (cumsum_value - one) / support[row_index];
  }
}

template <typename T>
void calculate_tau(typename TTypes<T>::Matrix cumsum,
                   const int num_rows,
                   const int num_cols,
                   typename TTypes<T>::Matrix support) {
   // calculate paramization constants
   const int threads_per_block = 256;
   const int blocks = static_cast<int>(std::ceil(
    static_cast<double>(num_rows) / static_cast<double>(threads_per_block)
   ));

   // launch kernel
   calculate_tau_kernel<T><<<blocks, threads_per_block>>>(
     cumsum.data(), num_rows, num_cols, support.data()
   );
}

template <typename T>
__global__ void calculate_properbility_kernel(const T* input,
                                              const T* tau,
                                              const int num_rows,
                                              const int num_cols,
                                              T* output) {
  const int col_index = blockIdx.x * blockDim.x + threadIdx.x;
  const int row_index = blockIdx.y;

  T zero = static_cast<T>(0);

  if (col_index < num_cols) {
    const int flat_index = row_index * num_cols + col_index;
    output[flat_index] = max(input[flat_index] - tau[row_index], zero);
  }
}

template <typename T>
void calculate_properbility(typename TTypes<T>::ConstMatrix input,
                            typename TTypes<T>::Matrix tau,
                            const int num_rows,
                            const int num_cols,
                            typename TTypes<T>::Matrix output) {
  // calculate paramization constants
  const int col_threads_per_block = 256;
  const int col_blocks = static_cast<int>(std::ceil(
   static_cast<double>(num_cols) / static_cast<double>(col_threads_per_block)
  ));

  dim3 threads_per_block(col_threads_per_block, 1, 1);
  dim3 blocks(col_blocks, num_rows, 1);

  // launch kernel
  calculate_properbility_kernel<T><<<blocks, threads_per_block>>>(
    input.data(), tau.data(), num_rows, num_cols, output.data()
  );
}

template <typename T>
struct Sparsemax<GPUDevice, T> {
  void operator()(const GPUDevice& d,
                  typename TTypes<T>::ConstMatrix input,
                  typename TTypes<T>::Matrix temp,
                  typename TTypes<T>::Matrix output) {

    const int num_rows = input.dimension(0); // batch_size
    const int num_cols = input.dimension(1);

    // define class axis
    const int kClassDim = 1;
    #if !defined(EIGEN_HAS_INDEX_LIST)
        Eigen::DSizes<int, 1> along_class(kClassDim);
    #else
        Eigen::IndexList<Eigen::type2index<kClassDim> > along_class;
    #endif

    // move input to sorted (temp), and sort inplace
    cudaMemcpy(temp.data(), input.data(),
               num_rows * num_cols * sizeof(T),
               cudaMemcpyDeviceToDevice);
    odd_even_sort<T>(temp, num_rows, num_cols);

    // Cumsum the sorted matrix along axis 1.
    // Put results in output as the the sorted and cumsum needs to be used
    // together.
    Eigen::internal::SumReducer<T> reducer;
    output.device(d) = temp.scan(1, reducer, false).eval();

    // Calculate threshold used in support calculation.
    // Replace sorted matrix, with the threshold booleans.
    support_threshold<T>(output, num_rows, num_cols, temp);

    // Sum each row, to get the support index.
    // This will reuse the temporary matrix, which is larger than required,
    // but the results will just be stored as if it was a flat vector.
    temp.device(d) = temp.sum(along_class).eval();

    // Calculate tau
    // Overwrites temp results with tau(z), again this just uses temp
    // as a flat vector.
    calculate_tau<T>(output, num_rows, num_cols, temp);

    // Calculate properbility
    // Use temp and input, and put results in output
    calculate_properbility<T>(input, temp, num_rows, num_cols, output);
  }
};

template struct Sparsemax<GPUDevice, Eigen::half>;
template struct Sparsemax<GPUDevice, float>;
template struct Sparsemax<GPUDevice, double>;

}  // namespace functor
}  // namespace tensorflow

#endif
<|endoftext|>


<commit_before>#if !defined(__CINT__) || defined(__MAKECINT__)
#include <TChain.h>
#include <TSystem.h>
#include "AliAnalysisManager.h"
#include "AliESDInputHandler.h"
#include "AliAODHandler.h"
#include "AliAnalysisTaskESDfilter.h"
#include "AliAnalysisDataContainer.h"
#endif

void CreateAODfromESD(const char *inFileName = "AliESDs.root",
		      const char *outFileName = "AliAODs.root") {

    gSystem->Load("libTree");
    gSystem->Load("libGeom");
    gSystem->Load("libPhysics");
    gSystem->Load("libVMC");
    gSystem->Load("libSTEERBase");
    gSystem->Load("libESD");
    gSystem->Load("libAOD");

    gSystem->Load("libANALYSIS");
    gSystem->Load("libANALYSISalice");
    gSystem->Load("libPWG3muon");

    TChain *chain = new TChain("esdTree");
    // Steering input chain
    chain->Add(inFileName);
    AliAnalysisManager *mgr  = new AliAnalysisManager("ESD to AOD", "Analysis Manager");

    // Input
    AliESDInputHandler* inpHandler = new AliESDInputHandler();
    inpHandler->SetReadTags();
    mgr->SetInputEventHandler  (inpHandler);

    // Output
    AliAODHandler* aodHandler   = new AliAODHandler();
    aodHandler->SetOutputFileName(outFileName);
    mgr->SetOutputEventHandler(aodHandler);

    // Task
    // Barrel Tracks
    AliAnalysisTaskESDfilter *filter = new AliAnalysisTaskESDfilter("Filter");
    mgr->AddTask(filter);
    // Muons
    AliAnalysisTaskESDMuonFilter *esdmuonfilter = new AliAnalysisTaskESDMuonFilter("ESD Muon Filter");
    mgr->AddTask(esdmuonfilter);

    // Cuts on primary tracks
    AliESDtrackCuts* esdTrackCutsL = new AliESDtrackCuts("AliESDtrackCuts", "Standard");
    esdTrackCutsL->SetMinNClustersTPC(50);
    esdTrackCutsL->SetMaxChi2PerClusterTPC(3.5);
    esdTrackCutsL->SetMaxCovDiagonalElements(2, 2, 0.5, 0.5, 2);
    esdTrackCutsL->SetRequireTPCRefit(kTRUE);
    esdTrackCutsL->SetMaxDCAToVertexXY(3.0);
    esdTrackCutsL->SetMaxDCAToVertexZ(3.0);
    esdTrackCutsL->SetDCAToVertex2D(kTRUE);
    esdTrackCutsL->SetRequireSigmaToVertex(kFALSE);
    esdTrackCutsL->SetAcceptKingDaughters(kFALSE);
    // ITS stand-alone tracks
    AliESDtrackCuts* esdTrackCutsITSsa = new AliESDtrackCuts("AliESDtrackCuts", "ITS stand-alone");
    esdTrackCutsITSsa->SetRequireITSStandAlone(kTRUE);

    AliAnalysisFilter* trackFilter = new AliAnalysisFilter("trackFilter");
    trackFilter->AddCuts(esdTrackCutsL);
    trackFilter->AddCuts(esdTrackCutsITSsa);

    // Cuts on V0s
    AliESDv0Cuts*   esdV0Cuts = new AliESDv0Cuts("AliESDv0Cuts", "Standard pp");
    esdV0Cuts->SetMinRadius(0.2);
    esdV0Cuts->SetMaxRadius(100);
    esdV0Cuts->SetMinDcaPosToVertex(0.05);
    esdV0Cuts->SetMinDcaNegToVertex(0.05);
    esdV0Cuts->SetMaxDcaV0Daughters(0.5);
    esdV0Cuts->SetMinCosinePointingAngle(0.99);
    AliAnalysisFilter* v0Filter = new AliAnalysisFilter("v0Filter");
    v0Filter->AddCuts(esdV0Cuts);

//
    filter->SetTrackFilter(trackFilter);
    filter->SetV0Filter(v0Filter);

//  Create AOD Tags
    AliAnalysisTaskTagCreator* tagTask = new AliAnalysisTaskTagCreator("AOD Tag Creator");
    mgr->AddTask(tagTask);

    // Pipelining
    AliAnalysisDataContainer *cinput1 = mgr->GetCommonInputContainer();
    AliAnalysisDataContainer *coutput1 = mgr->GetCommonOutputContainer();
    AliAnalysisDataContainer *coutputT
	= mgr->CreateContainer("cTag",  TTree::Class(), AliAnalysisManager::kOutputContainer, "AOD.tag.root");

    mgr->ConnectInput (filter, 0, cinput1 );
    mgr->ConnectOutput(filter, 0, coutput1);

    mgr->ConnectInput (esdmuonfilter, 0, cinput1 );
//    mgr->ConnectOutput(esdmuonfilter, 0, coutput1);

    mgr->ConnectInput (tagTask, 0, cinput1);
    mgr->ConnectOutput(tagTask, 1, coutputT);

    //
    // Run the analysis
    //
    mgr->InitAnalysis();
    mgr->PrintStatus();
    mgr->StartAnalysis("local", chain);
}

<commit_msg>Write Monte Carlo Particles.<commit_after>#if !defined(__CINT__) || defined(__MAKECINT__)
#include <TChain.h>
#include <TSystem.h>
#include "AliAnalysisManager.h"
#include "AliESDInputHandler.h"
#include "AliAODHandler.h"
#include "AliAnalysisTaskESDfilter.h"
#include "AliAnalysisDataContainer.h"
#endif

void CreateAODfromESD(const char *inFileName = "AliESDs.root",
		      const char *outFileName = "AliAODs.root",
		      Bool_t bKineFilter = kTRUE)
{

    gSystem->Load("libTree");
    gSystem->Load("libGeom");
    gSystem->Load("libPhysics");
    gSystem->Load("libVMC");
    gSystem->Load("libSTEERBase");
    gSystem->Load("libESD");
    gSystem->Load("libAOD");

    gSystem->Load("libANALYSIS");
    gSystem->Load("libANALYSISalice");
    gSystem->Load("libPWG3muon");

    TChain *chain = new TChain("esdTree");
    // Steering input chain
    chain->Add(inFileName);
    AliAnalysisManager *mgr  = new AliAnalysisManager("ESD to AOD", "Analysis Manager");

    // Input
    AliESDInputHandler* inpHandler = new AliESDInputHandler();
    inpHandler->SetReadTags();
    mgr->SetInputEventHandler  (inpHandler);
    // Output
    AliAODHandler* aodHandler   = new AliAODHandler();
    aodHandler->SetOutputFileName(outFileName);
    mgr->SetOutputEventHandler(aodHandler);

    // MC Truth
    if(bKineFilter){
	AliMCEventHandler* mcHandler = new AliMCEventHandler();
	mgr->SetMCtruthEventHandler(mcHandler);
    }

    // Tasks
    // Filtering of MC particles (decays conversions etc)
    // this task is also needed to set the MCEventHandler
    // to the AODHandler, this will not be needed when
    // AODHandler goes to ANALYSISalice
    AliAnalysisTaskMCParticleFilter *kinefilter = new AliAnalysisTaskMCParticleFilter("Particle Filter");
    if (bKineFilter) mgr->AddTask(kinefilter);

    // Barrel Tracks
    AliAnalysisTaskESDfilter *filter = new AliAnalysisTaskESDfilter("Filter");
    mgr->AddTask(filter);
    // Muons
    AliAnalysisTaskESDMuonFilter *esdmuonfilter = new AliAnalysisTaskESDMuonFilter("ESD Muon Filter");
    mgr->AddTask(esdmuonfilter);

    // Cuts on primary tracks
    AliESDtrackCuts* esdTrackCutsL = new AliESDtrackCuts("AliESDtrackCuts", "Standard");
    esdTrackCutsL->SetMinNClustersTPC(50);
    esdTrackCutsL->SetMaxChi2PerClusterTPC(3.5);
    esdTrackCutsL->SetMaxCovDiagonalElements(2, 2, 0.5, 0.5, 2);
    esdTrackCutsL->SetRequireTPCRefit(kTRUE);
    esdTrackCutsL->SetMaxDCAToVertexXY(3.0);
    esdTrackCutsL->SetMaxDCAToVertexZ(3.0);
    esdTrackCutsL->SetDCAToVertex2D(kTRUE);
    esdTrackCutsL->SetRequireSigmaToVertex(kFALSE);
    esdTrackCutsL->SetAcceptKinkDaughters(kFALSE);
    // ITS stand-alone tracks
    AliESDtrackCuts* esdTrackCutsITSsa = new AliESDtrackCuts("AliESDtrackCuts", "ITS stand-alone");
    esdTrackCutsITSsa->SetRequireITSStandAlone(kTRUE);

    AliAnalysisFilter* trackFilter = new AliAnalysisFilter("trackFilter");
    trackFilter->AddCuts(esdTrackCutsL);
    trackFilter->AddCuts(esdTrackCutsITSsa);

    // Cuts on V0s
    AliESDv0Cuts*   esdV0Cuts = new AliESDv0Cuts("AliESDv0Cuts", "Standard pp");
    esdV0Cuts->SetMinRadius(0.2);
    esdV0Cuts->SetMaxRadius(100);
    esdV0Cuts->SetMinDcaPosToVertex(0.05);
    esdV0Cuts->SetMinDcaNegToVertex(0.05);
    esdV0Cuts->SetMaxDcaV0Daughters(0.5);
    esdV0Cuts->SetMinCosinePointingAngle(0.99);
    AliAnalysisFilter* v0Filter = new AliAnalysisFilter("v0Filter");
    v0Filter->AddCuts(esdV0Cuts);

//
    filter->SetTrackFilter(trackFilter);
    filter->SetV0Filter(v0Filter);

//  Create AOD Tags
    AliAnalysisTaskTagCreator* tagTask = new AliAnalysisTaskTagCreator("AOD Tag Creator");
    mgr->AddTask(tagTask);

    // Pipelining
    AliAnalysisDataContainer *cinput1  = mgr->GetCommonInputContainer();
    AliAnalysisDataContainer *coutput1 = mgr->GetCommonOutputContainer();

    AliAnalysisDataContainer *coutputT
	= mgr->CreateContainer("cTag",  TTree::Class(), AliAnalysisManager::kOutputContainer, "AOD.tag.root");

    if(bKineFilter) {
	mgr->ConnectInput  (kinefilter,     0, cinput1  );
	mgr->ConnectOutput (kinefilter,     0, coutput1 );
    }

    mgr->ConnectInput (filter, 0, cinput1 );
    mgr->ConnectOutput(filter, 0, coutput1);

    mgr->ConnectInput (esdmuonfilter, 0, cinput1 );
//    mgr->ConnectOutput(esdmuonfilter, 0, coutput1);

    mgr->ConnectInput (tagTask, 0, cinput1);
    mgr->ConnectOutput(tagTask, 1, coutputT);

    //
    // Run the analysis
    //
    mgr->InitAnalysis();
    mgr->PrintStatus();
    mgr->StartAnalysis("local", chain);
}

<|endoftext|>


<commit_before>#ifndef BUILDERS_GENERATORS_CYLINDERGENERATOR_HPP_DEFINED
#define BUILDERS_GENERATORS_CYLINDERGENERATOR_HPP_DEFINED

#include "builders/generators/AbstractGenerator.hpp"
#include "math/Quaternion.hpp"
#include "utils/MathUtils.hpp"

namespace utymap { namespace builders {

/// Generates cylinder.
class CylinderGenerator : public AbstractGenerator
{
public:
    CylinderGenerator(const utymap::builders::BuilderContext& builderContext,
        utymap::builders::MeshContext& meshContext) :
        AbstractGenerator(builderContext, meshContext)
    {
    }

    /// Sets center of cylinder.
    CylinderGenerator& setCenter(const utymap::math::Vector3& center)
    {
        center_ = center;
        return *this;
    }

    /// Sets size of cylinder.
    CylinderGenerator& setSize(const utymap::math::Vector3& size)
    {
        size1_ = size;
        size2_ = size;
        return *this;
    }

    /// Sets size of cylinder for first and last segments.
    CylinderGenerator& setSize(const utymap::math::Vector3& size1,
                               const utymap::math::Vector3& size2)
    {
        size1_ = size1;
        size2_ = size2;
        return *this;
    }

    /// Sets orientation of cylinder in 3D space.
    CylinderGenerator& setDirection(const utymap::math::Vector3& direction,
                                    const utymap::math::Vector3& right)
    {
        direction_ = direction;
        right_ = right;
        return *this;
    }

    /// Sets radial segment count.
    CylinderGenerator& setRadialSegments(int radialSegments)
    {
        radialSegments_ = radialSegments;
        return *this;
    }

    /// Sets max segment height.
    CylinderGenerator& setMaxSegmentHeight(double maxSegmentHeight)
    {
        maxSegmentHeight_ = maxSegmentHeight;
        return *this;
    }

    void generate() override
    {
        int heightSegments = maxSegmentHeight_ != 0 ? static_cast<int>(std::ceil(size1_.y / maxSegmentHeight_)) : 1;
        double heightStep = size1_.y / heightSegments;
        double angleStep = 2 * pi / radialSegments_;

        for (int j = 0; j < radialSegments_; ++j) {
            auto direction1 = utymap::math::Quaternion::fromAngleAxis(j * angleStep, direction_);
            auto direction2 = utymap::math::Quaternion::fromAngleAxis((j == radialSegments_ - 1 ? 0 : j + 1) * angleStep, direction_);

            for (int i = 0; i < heightSegments; i++) {
                auto radius1 = getRadius(static_cast<double>(heightSegments - i) / heightSegments);
                auto radius2 = getRadius(static_cast<double>(heightSegments - i - 1) / heightSegments);

                auto center1 = center_ + direction_ * (heightStep * i);
                auto center2 = center_ + direction_ * (heightStep * (i + 1));

                auto v0 = translate(center1 + scale(direction1 * right_, radius1));
                auto v1 = translate(center1 + scale(direction2 * right_, radius1));
                auto v2 = translate(center2 + scale(direction2 * right_, radius2));
                auto v3 = translate(center2 + scale(direction1 * right_, radius2));

                // add side.
                addTriangle(v1, v2, v0);
                addTriangle(v0, v2, v3);

                // add bottom cap part.
                if (i == 0)
                    addTriangle(translate(center1), v1, v0);
                // add top cap part.
                if (i == heightSegments - 1 && !isCone())
                    addTriangle(translate(center2), v3, v2);
            }
        }
    }

private:

    bool isCone() const
    {
        return size2_ == utymap::math::Vector3::zero();
    }

    utymap::math::Vector3 getRadius(double value) const
    {
        return utymap::math::Vector3(utymap::utils::lerp(size2_.x, size1_.x, value),
                                     utymap::utils::lerp(size2_.y, size1_.y, value),
                                     utymap::utils::lerp(size2_.z, size1_.z, value));
    }

    utymap::math::Vector3 scale(const utymap::math::Vector3& value, const utymap::math::Vector3& size) const
    {
        return utymap::math::Vector3(value.x * size.x, value.y * size.y, value.z * size.z);
    }

    utymap::math::Vector3 center_ = utymap::math::Vector3::zero();
    utymap::math::Vector3 direction_ = utymap::math::Vector3::up();
    utymap::math::Vector3 right_ = utymap::math::Vector3::right();
    utymap::math::Vector3 size1_ = utymap::math::Vector3::zero();
    utymap::math::Vector3 size2_ = utymap::math::Vector3::zero();
    double maxSegmentHeight_ = 0;
    int radialSegments_ = 5;

};

}}
#endif // BUILDERS_GENERATORS_CYLINDERGENERATOR_HPP_DEFINED
<commit_msg>core: fix rotation issue in CylinderGenerator<commit_after>#ifndef BUILDERS_GENERATORS_CYLINDERGENERATOR_HPP_DEFINED
#define BUILDERS_GENERATORS_CYLINDERGENERATOR_HPP_DEFINED

#include "builders/generators/AbstractGenerator.hpp"
#include "math/Quaternion.hpp"
#include "utils/MathUtils.hpp"

namespace utymap { namespace builders {

/// Generates cylinder.
class CylinderGenerator : public AbstractGenerator
{
public:
    CylinderGenerator(const utymap::builders::BuilderContext& builderContext,
        utymap::builders::MeshContext& meshContext) :
        AbstractGenerator(builderContext, meshContext)
    {
    }

    /// Sets center of cylinder.
    CylinderGenerator& setCenter(const utymap::math::Vector3& center)
    {
        center_ = center;
        return *this;
    }

    /// Sets size of cylinder.
    CylinderGenerator& setSize(const utymap::math::Vector3& size)
    {
        size1_ = size;
        size2_ = size;
        return *this;
    }

    /// Sets size of cylinder for first and last segments.
    CylinderGenerator& setSize(const utymap::math::Vector3& size1,
                               const utymap::math::Vector3& size2)
    {
        size1_ = size1;
        size2_ = size2;
        return *this;
    }

    /// Sets orientation of cylinder in 3D space.
    CylinderGenerator& setDirection(const utymap::math::Vector3& direction,
                                    const utymap::math::Vector3& right)
    {
        direction_ = direction;
        right_ = right;
        return *this;
    }

    /// Sets radial segment count.
    CylinderGenerator& setRadialSegments(int radialSegments)
    {
        radialSegments_ = radialSegments;
        return *this;
    }

    /// Sets max segment height.
    CylinderGenerator& setMaxSegmentHeight(double maxSegmentHeight)
    {
        maxSegmentHeight_ = maxSegmentHeight;
        return *this;
    }

    void generate() override
    {
        int heightSegments = maxSegmentHeight_ != 0 ? static_cast<int>(std::ceil(size1_.y / maxSegmentHeight_)) : 1;
        double heightStep = size1_.y / heightSegments;
        double angleStep = 2 * pi / radialSegments_;

        for (int j = 0; j < radialSegments_; ++j) {
            auto direction1 = utymap::math::Quaternion::fromAngleAxis(j * angleStep, direction_);
            auto direction2 = utymap::math::Quaternion::fromAngleAxis((j == radialSegments_ - 1 ? 0 : j + 1) * angleStep, direction_);

            for (int i = 0; i < heightSegments; i++) {
                auto radius1 = getRadius(static_cast<double>(heightSegments - i) / heightSegments);
                auto radius2 = getRadius(static_cast<double>(heightSegments - i - 1) / heightSegments);

                auto center1 = center_ + direction_ * (heightStep * i);
                auto center2 = center_ + direction_ * (heightStep * (i + 1));

                auto v0 = translate(center1 + scale(direction1 * right_, radius1));
                auto v1 = translate(center1 + scale(direction2 * right_, radius1));
                auto v2 = translate(center2 + scale(direction2 * right_, radius2));
                auto v3 = translate(center2 + scale(direction1 * right_, radius2));

                // add side.
                addTriangle(v1, v2, v0);
                addTriangle(v0, v2, v3);

                // add bottom cap part.
                if (i == 0)
                    addTriangle(translate(center1), v1, v0);
                // add top cap part.
                if (i == heightSegments - 1 && !isCone())
                    addTriangle(translate(center2), v3, v2);
            }
        }
    }

private:

    bool isCone() const
    {
        return size2_ == utymap::math::Vector3::zero();
    }

    utymap::math::Vector3 getRadius(double value) const
    {
        return utymap::math::Vector3(utymap::utils::lerp(size2_.x, size1_.x, value),
                                     utymap::utils::lerp(size2_.y, size1_.y, value),
                                     utymap::utils::lerp(size2_.z, size1_.z, value));
    }

    utymap::math::Vector3 scale(const utymap::math::Vector3& value, const utymap::math::Vector3& size) const
    {
        /// NOTE use size.x for value.y to handle rotations
        return utymap::math::Vector3(value.x * size.x, value.y * size.x, value.z * size.z);
    }

    utymap::math::Vector3 center_ = utymap::math::Vector3::zero();
    utymap::math::Vector3 direction_ = utymap::math::Vector3::up();
    utymap::math::Vector3 right_ = utymap::math::Vector3::right();
    utymap::math::Vector3 size1_ = utymap::math::Vector3::zero();
    utymap::math::Vector3 size2_ = utymap::math::Vector3::zero();
    double maxSegmentHeight_ = 0;
    int radialSegments_ = 5;

};

}}
#endif // BUILDERS_GENERATORS_CYLINDERGENERATOR_HPP_DEFINED
<|endoftext|>


<commit_before>/*
Copyright (c) 2012, Ronie Martinez
ronmarti18@gmail.com
All rights reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the GNU Lesser General Public License for more
details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301  USA
*/

#include "qpsdplugin.h"
#include <QRgb>
#include <QColor>

qpsdPlugn::qpsdPlugn(QObject *parent) :
    QImageIOPlugin(parent)
{
}

qpsdPlugn::~qpsdPlugn()
{

}

QStringList qpsdPlugn::keys() const
{
    return QStringList() << "psd";//TODO: add PSB (Photoshop Big) support
}

QImageIOPlugin::Capabilities qpsdPlugn::capabilities(
    QIODevice *device, const QByteArray &format) const
{
    if (format == "psd")
        return Capabilities(CanRead);//TODO: add CanWrite support
    if (!(format.isEmpty() && device->isOpen()))
        return 0;

    Capabilities cap;
    if (device->isReadable() && qpsdHandler::canRead(device))
        cap |= CanRead;
    // if (device->isWritable())
    //     cap |= CanWrite;
    return cap;
}

QImageIOHandler *qpsdPlugn::create(
    QIODevice *device, const QByteArray &format) const
{
    QImageIOHandler *handler = new qpsdHandler;
    handler->setDevice(device);
    handler->setFormat(format);
    return handler;
}

//Q_EXPORT_STATIC_PLUGIN(qpsdPlugn)
Q_EXPORT_PLUGIN2(qpsd, qpsdPlugn)

qpsdHandler::qpsdHandler()
{

}

qpsdHandler::~qpsdHandler()
{

}

bool qpsdHandler::canRead() const
{
    if (canRead(device())) {
        setFormat("psd");
        return true;
    }
    return false;
}

bool qpsdHandler::canRead(QIODevice *device)
{
    return device->peek(4) == QByteArray("\x38\x42\x50\x53"); //8BPS
}

bool qpsdHandler::read(QImage *image)
{
    QDataStream input(device());
    quint32 signature, height, width, colorModeDataLength, imageResourcesLength, layerAndMaskInformationLength;
    quint16 version, channels, depth, colorMode, compression;
    QByteArray colorData;
    input.setByteOrder(QDataStream::BigEndian);
    input >> signature >> version ;
    input.skipRawData(6);//reserved bytes should be 6-byte in size
    input >> channels >> height >> width >> depth >> colorMode;
    input >> colorModeDataLength;
    if (colorModeDataLength != 0) {
        quint8 byte;
        for(quint32 i=0; i<colorModeDataLength; ++i) {
            input >> byte;
            colorData.append(byte);
        }
    }

    input >> imageResourcesLength;
    input.skipRawData(imageResourcesLength);
    input >> layerAndMaskInformationLength;
    input.skipRawData(layerAndMaskInformationLength);
    input >> compression;

    if (input.status() != QDataStream::Ok || signature != 0x38425053 || version != 0x0001)
        return false;

    QByteArray decompressed;
    switch (compression) {
    case 0: /*RAW IMAGE DATA - UNIMPLEMENTED*/
        break;
    case 1: /*RLE COMPRESSED DATA*/
        // The RLE-compressed data is proceeded by a 2-byte data count for each row in the data,
        // which we're going to just skip.
        input.skipRawData(height*channels*2);

        quint8 byte,count;
        decompressed.clear();

        /*Code based on PackBits implementation which is primarily used by Photoshop for RLE encoding/decoding*/
        while (!input.atEnd()) {
            input >> byte;
            if (byte > 128) {
                count=256-byte;
                input >>  byte;
                for (quint8 i=0; i<=count; ++i) {
                    decompressed.append(byte);
                }
            } else if (byte < 128) {
                count = byte + 1;
                for(quint8 i=0; i<count; ++i) {
                    input >> byte;
                    decompressed.append(byte);
                }
            }
        }
        break;
    case 2:/*ZIP WITHOUT PREDICTION - UNIMPLEMENTED*/
        break;
    case 3:/*ZIP WITH PREDICTION - UNIMPLEMENTED*/
        break;
    }

    int totalBytes = width * height;

    //FIXME: find better alternative
    switch (colorMode) {
    case 0: //for bitmap
        if (decompressed.size() != (channels * totalBytes)/8)
            return false;
        break;
    default: //for non-bitmap
        if (decompressed.size() != channels * totalBytes)
            return false;

        break;
    }

    switch (colorMode) {
    case 0: /*BITMAP*/
        {
            QString head = QString("P4\n%1 %2\n").arg(width).arg(height);
            QByteArray buffer(head.toAscii());
            buffer.append(decompressed);
            QImage result = QImage::fromData(buffer);
            if (result.isNull())
                return false;
            else
                *image = result;
        }

        break;
    case 1: /*GRAYSCALE*/
        switch (depth) {
        case 8:
            switch (channels) {
            case 1:
                QImage result(width, height, QImage::Format_Indexed8);
                const int IndexCount = 256;
                for (int i = 0; i < IndexCount; ++i){
                    result.setColor(i, qRgb(i, i, i));
                }

                quint8 *data = (quint8*)decompressed.constData();
                for (quint32 i=0; i < height; ++i) {
                    for (quint32 j=0; j < width; ++j) {
                        result.setPixel(j,i, *data);
                        ++data;
                    }
                }

                *image = result;
                break;
            }
        }

        break;
    case 2: /*INDEXED*/
        switch (depth) {
        case 8:
            switch (channels) {
            case 1:
                QImage result(width, height, QImage::Format_Indexed8);
                int indexCount = colorData.size() / 3;
                Q_ASSERT(indexCount == 256);
                quint8 *red = (quint8*)colorData.constData();
                quint8 *green = red + indexCount;
                quint8 *blue = green + indexCount;
                for (int i=0; i < indexCount; ++i) {
                    /*
                     * reference https://github.com/OpenImageIO/oiio/blob/master/src/psd.imageio/psdinput.cpp
                     * function bool PSDInput::indexed_to_rgb (char *dst)
                     */
                    result.setColor(i, qRgb(*red, *green, *blue));
                    ++red; ++green; ++blue;
                }

                quint8 *data = (quint8*)decompressed.constData();
                for (quint32 i=0; i < height; ++i) {
                    for (quint32 j=0; j < width; ++j) {
                        result.setPixel(j,i,*data);
                        ++data;
                    }
                }
                *image=result;
                break;
            }
        }
        break;
    case 3: /*RGB*/
        switch (depth) {
        case 1:
            break;
        case 8:
            switch(channels) {
            case 1:
                break;
            case 3:
            {
                QImage result(width, height, QImage::Format_RGB32);
                quint8 *red = (quint8*)decompressed.constData();
                quint8 *green = red + totalBytes;
                quint8 *blue = green + totalBytes;
                QRgb  *p, *end;
                for (quint32 y = 0; y < height; ++y) {
                    p = (QRgb *)result.scanLine(y);
                    end = p + width;
                    while (p < end) {
                        *p = qRgb(*red, *green, *blue);
                        ++p; ++red; ++green; ++blue;
                    }
                }

                *image = result;
            }
                break;
            case 4:
            {
                QImage result(width, height, QImage::Format_ARGB32);
                quint8 *red = (quint8*)decompressed.constData();
                quint8 *green = red + totalBytes;
                quint8 *blue = green + totalBytes;
                quint8 *alpha = blue + totalBytes;
                QRgb  *p, *end;
                for (quint32 y = 0; y < height; ++y) {
                    p = (QRgb *)result.scanLine(y);
                    end = p + width;
                    while (p < end) {
                        *p = qRgba(*red, *green, *blue, *alpha);
                        ++p; ++red; ++green; ++blue; ++alpha;
                    }
                }

                *image = result;
            }
                break;
            case 5:
                qDebug("5 channels of rgb mode");
                return false;
            }

            break;
        case 16:
            break;
        }
        break;
    case 4: /*CMYK*/
        switch (depth) {
        case 8:
            switch (channels) {
            case 4:
            {
                QImage result(width, height, QImage::Format_RGB32);
                quint8 *cyan = (quint8*)decompressed.constData();
                quint8 *magenta = cyan + totalBytes;
                quint8 *yellow = magenta + totalBytes;
                quint8 *key = yellow + totalBytes;
                QRgb  *p, *end;
                for (quint32 y = 0; y < height; ++y) {
                    p = (QRgb *)result.scanLine(y);
                    end = p + width;
                    while (p < end) {
                        *p = QColor::fromCmyk(255-*cyan, 255-*magenta,
                                              255-*yellow, 255-*key).rgb();
                        ++p; ++cyan; ++magenta; ++yellow; ++key;
                    }
                }
                *image = result;
            }
                break;
            case 5:
            {
                QImage result(width, height, QImage::Format_ARGB32);
                quint8 *alpha = (quint8*)decompressed.constData();
                quint8 *cyan = alpha + totalBytes;
                quint8 *magenta = cyan + totalBytes;
                quint8 *yellow = magenta + totalBytes;
                quint8 *key = yellow + totalBytes;
                QRgb  *p, *end;
                for (quint32 y = 0; y < height; ++y) {
                    p = (QRgb *)result.scanLine(y);
                    end = p + width;
                    while (p < end) {
                        *p = QColor::fromCmyk(255-*cyan, 255-*magenta,
                                              255-*yellow, 255-*key,
                                              *alpha).rgba();
                        ++p; ++alpha; ++cyan; ++magenta; ++yellow; ++key;
                    }
                }
                *image = result;
            }
                break;
            }
        }
        break;
    case 7: /*MULTICHANNEL - UNIMPLEMENTED*/
        break;
    case 8: /*DUOTONE*/
        switch (depth) {
        case 8:
            switch (channels) {
            case 1:
                /*
                 *Duotone images: color data contains the duotone specification
                 *(the format of which is not documented). Other applications that
                 *read Photoshop files can treat a duotone image as a gray image,
                 *and just preserve the contents of the duotone information when
                 *reading and writing the file.
                 *
                 *TODO: find a way to actually get the duotone, tritone, and quadtone colors
                 *Noticed the added "Curve" layer when using photoshop
                 */
                QImage result(width, height, QImage::Format_Indexed8);
                const int IndexCount = 256;
                for(int i = 0; i < IndexCount; ++i){
                    result.setColor(i, qRgb(i, i, i));
                }
                quint8 *data = (quint8*)decompressed.constData();
                for(quint32 i=0; i < height; ++i)
                {
                    for(quint32 j=0; j < width; ++j)
                    {
                        result.setPixel(j,i, *data);
                        ++data;
                    }
                }
                *image = result;
                break;
            }

            break;
        }
        break;
    case 9: /*LAB - UNIMPLEMENTED*/
        break;
    }

    return input.status() == QDataStream::Ok;
}

bool qpsdHandler::supportsOption(ImageOption option) const
{
    return option == Size;
}

QVariant qpsdHandler::option(ImageOption option) const
{
    if (option == Size) {
        QByteArray bytes = device()->peek(26);
        QDataStream input(bytes);
        quint32 signature, height, width;
        quint16 version, channels, depth, colorMode;
        input.setByteOrder(QDataStream::BigEndian);
        input >> signature >> version ;
        input.skipRawData(6);//reserved bytes should be 6-byte in size
        input >> channels >> height >> width >> depth >> colorMode;
        if (input.status() == QDataStream::Ok && signature == 0x38425053 && version == 0x0001)
            return QSize(width, height);
    }
    return QVariant();
}
<commit_msg>Tried to add support for Lab color mode.<commit_after>/*
Copyright (c) 2012, Ronie Martinez
ronmarti18@gmail.com
All rights reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the GNU Lesser General Public License for more
details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301  USA
*/

#include "qpsdplugin.h"
#include <QRgb>
#include <QColor>
#include <qmath.h>

qpsdPlugn::qpsdPlugn(QObject *parent) :
    QImageIOPlugin(parent)
{
}

qpsdPlugn::~qpsdPlugn()
{

}

QStringList qpsdPlugn::keys() const
{
    return QStringList() << "psd";//TODO: add PSB (Photoshop Big) support
}

QImageIOPlugin::Capabilities qpsdPlugn::capabilities(
    QIODevice *device, const QByteArray &format) const
{
    if (format == "psd")
        return Capabilities(CanRead);//TODO: add CanWrite support
    if (!(format.isEmpty() && device->isOpen()))
        return 0;

    Capabilities cap;
    if (device->isReadable() && qpsdHandler::canRead(device))
        cap |= CanRead;
    // if (device->isWritable())
    //     cap |= CanWrite;
    return cap;
}

QImageIOHandler *qpsdPlugn::create(
    QIODevice *device, const QByteArray &format) const
{
    QImageIOHandler *handler = new qpsdHandler;
    handler->setDevice(device);
    handler->setFormat(format);
    return handler;
}

//Q_EXPORT_STATIC_PLUGIN(qpsdPlugn)
Q_EXPORT_PLUGIN2(qpsd, qpsdPlugn)

qpsdHandler::qpsdHandler()
{

}

qpsdHandler::~qpsdHandler()
{

}

bool qpsdHandler::canRead() const
{
    if (canRead(device())) {
        setFormat("psd");
        return true;
    }
    return false;
}

bool qpsdHandler::canRead(QIODevice *device)
{
    return device->peek(4) == QByteArray("\x38\x42\x50\x53"); //8BPS
}

bool qpsdHandler::read(QImage *image)
{
    QDataStream input(device());
    quint32 signature, height, width, colorModeDataLength, imageResourcesLength, layerAndMaskInformationLength;
    quint16 version, channels, depth, colorMode, compression;
    QByteArray colorData;
    input.setByteOrder(QDataStream::BigEndian);
    input >> signature >> version ;
    input.skipRawData(6);//reserved bytes should be 6-byte in size
    input >> channels >> height >> width >> depth >> colorMode;
    input >> colorModeDataLength;
    if (colorModeDataLength != 0) {
        quint8 byte;
        for(quint32 i=0; i<colorModeDataLength; ++i) {
            input >> byte;
            colorData.append(byte);
        }
    }

    input >> imageResourcesLength;
    input.skipRawData(imageResourcesLength);
    input >> layerAndMaskInformationLength;
    input.skipRawData(layerAndMaskInformationLength);
    input >> compression;

    if (input.status() != QDataStream::Ok || signature != 0x38425053 || version != 0x0001)
        return false;

    QByteArray decompressed;
    switch (compression) {
    case 0: /*RAW IMAGE DATA - UNIMPLEMENTED*/
        break;
    case 1: /*RLE COMPRESSED DATA*/
        // The RLE-compressed data is proceeded by a 2-byte data count for each row in the data,
        // which we're going to just skip.
        input.skipRawData(height*channels*2);

        quint8 byte,count;
        decompressed.clear();

        /*Code based on PackBits implementation which is primarily used by Photoshop for RLE encoding/decoding*/
        while (!input.atEnd()) {
            input >> byte;
            if (byte > 128) {
                count=256-byte;
                input >>  byte;
                for (quint8 i=0; i<=count; ++i) {
                    decompressed.append(byte);
                }
            } else if (byte < 128) {
                count = byte + 1;
                for(quint8 i=0; i<count; ++i) {
                    input >> byte;
                    decompressed.append(byte);
                }
            }
        }
        break;
    case 2:/*ZIP WITHOUT PREDICTION - UNIMPLEMENTED*/
        break;
    case 3:/*ZIP WITH PREDICTION - UNIMPLEMENTED*/
        break;
    }

    int totalBytes = width * height;

    //FIXME: find better alternative
    switch (colorMode) {
    case 0: //for bitmap
        if (decompressed.size() != (channels * totalBytes)/8)
            return false;
        break;
    default: //for non-bitmap
        if (decompressed.size() != channels * totalBytes)
            return false;

        break;
    }

    switch (colorMode) {
    case 0: /*BITMAP*/
        {
            QString head = QString("P4\n%1 %2\n").arg(width).arg(height);
            QByteArray buffer(head.toAscii());
            buffer.append(decompressed);
            QImage result = QImage::fromData(buffer);
            if (result.isNull())
                return false;
            else
                *image = result;
        }

        break;
    case 1: /*GRAYSCALE*/
        switch (depth) {
        case 8:
            switch (channels) {
            case 1:
                QImage result(width, height, QImage::Format_Indexed8);
                const int IndexCount = 256;
                for (int i = 0; i < IndexCount; ++i){
                    result.setColor(i, qRgb(i, i, i));
                }

                quint8 *data = (quint8*)decompressed.constData();
                for (quint32 i=0; i < height; ++i) {
                    for (quint32 j=0; j < width; ++j) {
                        result.setPixel(j,i, *data);
                        ++data;
                    }
                }

                *image = result;
                break;
            }
        }

        break;
    case 2: /*INDEXED*/
        switch (depth) {
        case 8:
            switch (channels) {
            case 1:
                QImage result(width, height, QImage::Format_Indexed8);
                int indexCount = colorData.size() / 3;
                Q_ASSERT(indexCount == 256);
                quint8 *red = (quint8*)colorData.constData();
                quint8 *green = red + indexCount;
                quint8 *blue = green + indexCount;
                for (int i=0; i < indexCount; ++i) {
                    /*
                     * reference https://github.com/OpenImageIO/oiio/blob/master/src/psd.imageio/psdinput.cpp
                     * function bool PSDInput::indexed_to_rgb (char *dst)
                     */
                    result.setColor(i, qRgb(*red, *green, *blue));
                    ++red; ++green; ++blue;
                }

                quint8 *data = (quint8*)decompressed.constData();
                for (quint32 i=0; i < height; ++i) {
                    for (quint32 j=0; j < width; ++j) {
                        result.setPixel(j,i,*data);
                        ++data;
                    }
                }
                *image=result;
                break;
            }
        }
        break;
    case 3: /*RGB*/
        switch (depth) {
        case 1:
            break;
        case 8:
            switch(channels) {
            case 1:
                break;
            case 3:
            {
                QImage result(width, height, QImage::Format_RGB32);
                quint8 *red = (quint8*)decompressed.constData();
                quint8 *green = red + totalBytes;
                quint8 *blue = green + totalBytes;
                QRgb  *p, *end;
                for (quint32 y = 0; y < height; ++y) {
                    p = (QRgb *)result.scanLine(y);
                    end = p + width;
                    while (p < end) {
                        *p = qRgb(*red, *green, *blue);
                        ++p; ++red; ++green; ++blue;
                    }
                }

                *image = result;
            }
                break;
            case 4:
            {
                QImage result(width, height, QImage::Format_ARGB32);
                quint8 *red = (quint8*)decompressed.constData();
                quint8 *green = red + totalBytes;
                quint8 *blue = green + totalBytes;
                quint8 *alpha = blue + totalBytes;
                QRgb  *p, *end;
                for (quint32 y = 0; y < height; ++y) {
                    p = (QRgb *)result.scanLine(y);
                    end = p + width;
                    while (p < end) {
                        *p = qRgba(*red, *green, *blue, *alpha);
                        ++p; ++red; ++green; ++blue; ++alpha;
                    }
                }

                *image = result;
            }
                break;
            case 5:
                qDebug("5 channels of rgb mode");
                return false;
            }

            break;
        case 16:
            break;
        }
        break;
    case 4: /*CMYK*/
        switch (depth) {
        case 8:
            switch (channels) {
            case 4:
            {
                QImage result(width, height, QImage::Format_RGB32);
                quint8 *cyan = (quint8*)decompressed.constData();
                quint8 *magenta = cyan + totalBytes;
                quint8 *yellow = magenta + totalBytes;
                quint8 *key = yellow + totalBytes;
                QRgb  *p, *end;
                for (quint32 y = 0; y < height; ++y) {
                    p = (QRgb *)result.scanLine(y);
                    end = p + width;
                    while (p < end) {
                        *p = QColor::fromCmyk(255-*cyan, 255-*magenta,
                                              255-*yellow, 255-*key).rgb();
                        ++p; ++cyan; ++magenta; ++yellow; ++key;
                    }
                }
                *image = result;
            }
                break;
            case 5:
            {
                QImage result(width, height, QImage::Format_ARGB32);
                quint8 *alpha = (quint8*)decompressed.constData();
                quint8 *cyan = alpha + totalBytes;
                quint8 *magenta = cyan + totalBytes;
                quint8 *yellow = magenta + totalBytes;
                quint8 *key = yellow + totalBytes;
                QRgb  *p, *end;
                for (quint32 y = 0; y < height; ++y) {
                    p = (QRgb *)result.scanLine(y);
                    end = p + width;
                    while (p < end) {
                        *p = QColor::fromCmyk(255-*cyan, 255-*magenta,
                                              255-*yellow, 255-*key,
                                              *alpha).rgba();
                        ++p; ++alpha; ++cyan; ++magenta; ++yellow; ++key;
                    }
                }
                *image = result;
            }
                break;
            }
        }
        break;
    case 7: /*MULTICHANNEL - UNIMPLEMENTED*/
        return 0;
        break;
    case 8: /*DUOTONE*/
        switch (depth) {
        case 8:
            switch (channels) {
            case 1:
                /*
                 *Duotone images: color data contains the duotone specification
                 *(the format of which is not documented). Other applications that
                 *read Photoshop files can treat a duotone image as a gray image,
                 *and just preserve the contents of the duotone information when
                 *reading and writing the file.
                 *
                 *TODO: find a way to actually get the duotone, tritone, and quadtone colors
                 *Noticed the added "Curve" layer when using photoshop
                 */
                QImage result(width, height, QImage::Format_Indexed8);
                const int IndexCount = 256;
                for(int i = 0; i < IndexCount; ++i){
                    result.setColor(i, qRgb(i, i, i));
                }
                quint8 *data = (quint8*)decompressed.constData();
                for(quint32 i=0; i < height; ++i)
                {
                    for(quint32 j=0; j < width; ++j)
                    {
                        result.setPixel(j,i, *data);
                        ++data;
                    }
                }
                *image = result;
                break;
            }

            break;
        }
        break;
    case 9: /*LAB - UNDER TESTING*/
        switch (depth) {
        case 8:
            switch (channels) {
            case 3:
                //FIXME: something is wrong with the computation
                //overflow?
                QImage result(width, height, QImage::Format_RGB32);
                quint8 *L = (quint8*)decompressed.constData();
                quint8 *a = L + totalBytes;
                quint8 *b = a + totalBytes;

                qreal var_X, var_Y, var_Z, var_R, var_G, var_B, X, Y, Z;
                qreal red, green, blue;
                QRgb  *p, *end;
                for (quint32 y = 0; y < height; ++y) {
                    p = (QRgb *)result.scanLine(y);
                    end = p + width;
                    while (p < end) {
                        //coversion from Lab to xyz
                        //http://www.easyrgb.com/index.php?X=MATH&H=08#text8
                        var_Y = (*L + 16) / 116;
                        var_X = *a / 500 + var_Y;
                        var_Z = var_Y - *b / 200;
                        if ( qPow(var_Y,3) > 0.008856 ) {
                            var_Y =  qPow(var_Y, 3);
                        } else {
                            var_Y = ( var_Y - 16 / 116 ) / 7.787;
                        }
                        if (  qPow(var_X, 3) > 0.008856 ) {
                            var_X =  qPow(var_X, 3);
                        } else {
                            var_X = ( var_X - 16 / 116 ) / 7.787;
                        }
                        if (  qPow(var_Z, 3) > 0.008856 ) {
                            var_Z =  qPow(var_Z, 3);
                        } else {
                            var_Z = ( var_Z - 16 / 116 ) / 7.787;
                        }
                        X = 95.047 * var_X;
                        Y = 100.000 * var_Y;
                        Z = 108.883 * var_Z;

                        //conversion from xyz to rgb
                        //http://www.easyrgb.com/index.php?X=MATH&H=01#text1
                        var_X = X / 100;        //X from 0 to  95.047      (Observer = 2°, Illuminant = D65)
                        var_Y = Y / 100;        //Y from 0 to 100.000
                        var_Z = Z / 100;        //Z from 0 to 108.883
                        var_R = var_X *  3.2406 + var_Y * -1.5372 + var_Z * -0.4986;
                        var_G = var_X * -0.9689 + var_Y *  1.8758 + var_Z *  0.0415;
                        var_B = var_X *  0.0557 + var_Y * -0.2040 + var_Z *  1.0570;
                        if (  var_R > 0.0031308) {
                            var_R = 1.055 * ( qPow( var_R, 1 / 2.4) ) - 0.055;
                        } else {
                            var_R = 12.92 * (var_R);
                        }
                        if ( var_G > 0.0031308 ) {
                            var_G = 1.055 * ( qPow(var_G, 1 / 2.4 ) ) - 0.055;
                        } else {
                            var_G = 12.92 * (var_G);
                        }
                        if ( var_B > 0.0031308 ) {
                            var_B = 1.055 * ( qPow(var_B , 1 / 2.4 ) ) - 0.055;
                        } else {
                            var_B = 12.92 * (var_B);
                        }

                        red = var_R * 255;
                        green = var_G * 255;
                        blue = var_B * 255;

                        *p = qRgb(red, green, blue);
                        ++p; ++L; ++a; ++b;
                    }

                }
                *image = result;
                break;
            }
            break;
        }
        break;
    }

    return input.status() == QDataStream::Ok;
}

bool qpsdHandler::supportsOption(ImageOption option) const
{
    return option == Size;
}

QVariant qpsdHandler::option(ImageOption option) const
{
    if (option == Size) {
        QByteArray bytes = device()->peek(26);
        QDataStream input(bytes);
        quint32 signature, height, width;
        quint16 version, channels, depth, colorMode;
        input.setByteOrder(QDataStream::BigEndian);
        input >> signature >> version ;
        input.skipRawData(6);//reserved bytes should be 6-byte in size
        input >> channels >> height >> width >> depth >> colorMode;
        if (input.status() == QDataStream::Ok && signature == 0x38425053 && version == 0x0001)
            return QSize(width, height);
    }
    return QVariant();
}
<|endoftext|>


<commit_before>/*
 * SessionCompilePdf.cpp
 *
 * Copyright (C) 2009-11 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionCompilePdf.hpp"

#include <core/FilePath.hpp>
#include <core/Exec.hpp>
#include <core/FileSerializer.hpp>

#include <core/tex/TexMagicComment.hpp>

#include <r/RSexp.hpp>
#include <r/RExec.hpp>
#include <r/RRoutines.hpp>

#include <session/SessionModuleContext.hpp>

#include "SessionPdfLatex.hpp"
#include "SessionTexi2Dvi.hpp"
#include "SessionRnwWeave.hpp"

// TODO: emulate texi2dvi on linux to workaround debian tilde
//       escaping bug (http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=534458)

// TODO: consider option for texi2dvi

// TODO: investigate whether texlive on windows uses -file-line-error

// TODO: check spaces in path constraint on various platforms

// TODO: investigate other texi2dvi and pdflatex options
//         -- shell-escape
//         -- clean
//         -- alternative output file location

using namespace core;

namespace session {
namespace modules {
namespace tex {
namespace compile_pdf {

namespace {

void viewPdf(const FilePath& texPath)
{
   FilePath pdfPath = texPath.parent().complete(texPath.stem() + ".pdf");
   module_context::showFile(pdfPath, "_rstudio_compile_pdf");
}

void publishPdf(const FilePath& texPath)
{
   std::string aliasedPath = module_context::createAliasedPath(texPath);
   ClientEvent event(client_events::kPublishPdf, aliasedPath);
   module_context::enqueClientEvent(event);
}

void showCompilationErrors(const FilePath& texPath)
{
   std::string errors;
   Error error = r::exec::RFunction(".rs.getCompilationErrors",
                                    texPath.absolutePath()).call(&errors);
   if (error)
      LOG_ERROR(error);

   if (!errors.empty())
   {
      module_context::consoleWriteOutput(errors);
   }
   else
   {
      FilePath logPath = texPath.parent().complete(texPath.stem() + ".log");
      std::string logContents;
      Error error = core::readStringFromFile(logPath,
                                             &logContents,
                                             string_utils::LineEndingPosix);
      if (error)
         LOG_ERROR(error);

        module_context::consoleWriteOutput(logContents);
   }
}

bool compilePdf(const FilePath& targetFilePath,
                const std::string& completedAction,
                std::string* pUserErrMsg)
{
   // set the working directory for the duration of the compile
   RestoreCurrentPathScope pathScope(module_context::safeCurrentPath());
   Error error = targetFilePath.parent().makeCurrentPath();
   if (error)
   {
      *pUserErrMsg = "Error setting current path: " + error.summary();
      return false;
   }

   // ensure no spaces in path
   std::string filename = targetFilePath.filename();
   if (filename.find(' ') != std::string::npos)
   {
      *pUserErrMsg = "Invalid filename: '" + filename +
                     "' (TeX does not understand paths with spaces)";
      return false;
   }

   // parse out magic comments
   core::tex::TexMagicComments magicComments;
   error = core::tex::parseMagicComments(targetFilePath, &magicComments);
   if (error)
      LOG_ERROR(error);

   // discover and validate tex program path
   FilePath texProgramPath;
   if (!pdflatex::latexProgramForFile(magicComments,
                                      &texProgramPath,
                                      pUserErrMsg))
   {
      return false;
   }

   // see if we need to sweave
   std::string ext = targetFilePath.extensionLowerCase();
   if (ext == ".rnw" || ext == ".snw" || ext == ".nw")
   {
      // attempt to weave the rnw
      bool success = rnw_weave::runWeave(targetFilePath,
                                         magicComments,
                                         pUserErrMsg);
      if (!success)
         return false;
   }

   // configure pdflatex options
   pdflatex::PdfLatexOptions options;
   options.fileLineError = false;
   options.syncTex = true;

   // run tex compile
   FilePath texFilePath = targetFilePath.parent().complete(
                                             targetFilePath.stem() +
                                             ".tex");
   core::system::ProcessResult result;
#if defined(_WIN32) || defined(__APPLE__)
   error = tex::texi2dvi::texToPdf(texProgramPath,
                                   texFilePath,
                                   options,
                                   &result);
#else
   // workaround for tex2dvi special character bug on linux:
   //   http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=577741
  error = tex::pdflatex::texToPdf(texProgramPath,
                                  texFilePath,
                                  options,
                                  &result);
#endif

   if (error)
   {
      *pUserErrMsg = "Unable to compile pdf: " + error.summary();
      return false;
   }
   else if (result.exitStatus != EXIT_SUCCESS)
   {
      showCompilationErrors(texFilePath);
      return false;
   }
   else
   {
      if (completedAction == "view")
         viewPdf(targetFilePath);
      else if (completedAction == "publish")
         publishPdf(targetFilePath);

      return true;
   }
}

SEXP rs_compilePdf(SEXP filePathSEXP, SEXP completedActionSEXP)
{
   try
   {
      // extract parameters
      FilePath targetFilePath = module_context::resolveAliasedPath(
                                          r::sexp::asString(filePathSEXP));
      std::string completedAction = r::sexp::asString(completedActionSEXP);

      // compile pdf
      std::string userErrMsg;
      if (!compilePdf(targetFilePath, completedAction, &userErrMsg))
      {
         if (!userErrMsg.empty())
            throw r::exec::RErrorException(userErrMsg);
      }
   }
   catch(const r::exec::RErrorException& e)
   {
      r::exec::error(e.message());
   }
   CATCH_UNEXPECTED_EXCEPTION

   return R_NilValue;
}

} // anonymous namespace

Error initialize()
{
   R_CallMethodDef compilePdfMethodDef;
   compilePdfMethodDef.name = "rs_compilePdf" ;
   compilePdfMethodDef.fun = (DL_FUNC) rs_compilePdf ;
   compilePdfMethodDef.numArgs = 2;
   r::routines::addCallMethod(compilePdfMethodDef);

   using boost::bind;
   using namespace module_context;
   ExecBlock initBlock ;
   initBlock.addFunctions()
      (bind(sourceModuleRFile, "SessionCompilePdf.R"));
   return initBlock.execute();

}

} // namespace compile_pdf
} // namespace tex
} // namespace modules
} // namesapce session

<commit_msg>update todo comments<commit_after>/*
 * SessionCompilePdf.cpp
 *
 * Copyright (C) 2009-11 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionCompilePdf.hpp"

#include <core/FilePath.hpp>
#include <core/Exec.hpp>
#include <core/FileSerializer.hpp>

#include <core/tex/TexMagicComment.hpp>

#include <r/RSexp.hpp>
#include <r/RExec.hpp>
#include <r/RRoutines.hpp>

#include <session/SessionModuleContext.hpp>

#include "SessionPdfLatex.hpp"
#include "SessionTexi2Dvi.hpp"
#include "SessionRnwWeave.hpp"

// TODO: write latex_program docs and deploy to site

// TODO: emulate texi2dvi on linux to workaround debian tilde
//       escaping bug (http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=534458)

// TODO: consider ability to opt out of texi2dvi (rather than the above)

// TODO: investigate whether texlive on windows uses -file-line-error

// TODO: check spaces in path constraint on various platforms

// TODO: investigate other texi2dvi and pdflatex options
//         -- shell-escape
//         -- clean
//         -- alternative output file location

using namespace core;

namespace session {
namespace modules {
namespace tex {
namespace compile_pdf {

namespace {

void viewPdf(const FilePath& texPath)
{
   FilePath pdfPath = texPath.parent().complete(texPath.stem() + ".pdf");
   module_context::showFile(pdfPath, "_rstudio_compile_pdf");
}

void publishPdf(const FilePath& texPath)
{
   std::string aliasedPath = module_context::createAliasedPath(texPath);
   ClientEvent event(client_events::kPublishPdf, aliasedPath);
   module_context::enqueClientEvent(event);
}

void showCompilationErrors(const FilePath& texPath)
{
   std::string errors;
   Error error = r::exec::RFunction(".rs.getCompilationErrors",
                                    texPath.absolutePath()).call(&errors);
   if (error)
      LOG_ERROR(error);

   if (!errors.empty())
   {
      module_context::consoleWriteOutput(errors);
   }
   else
   {
      FilePath logPath = texPath.parent().complete(texPath.stem() + ".log");
      std::string logContents;
      Error error = core::readStringFromFile(logPath,
                                             &logContents,
                                             string_utils::LineEndingPosix);
      if (error)
         LOG_ERROR(error);

        module_context::consoleWriteOutput(logContents);
   }
}

bool compilePdf(const FilePath& targetFilePath,
                const std::string& completedAction,
                std::string* pUserErrMsg)
{
   // set the working directory for the duration of the compile
   RestoreCurrentPathScope pathScope(module_context::safeCurrentPath());
   Error error = targetFilePath.parent().makeCurrentPath();
   if (error)
   {
      *pUserErrMsg = "Error setting current path: " + error.summary();
      return false;
   }

   // ensure no spaces in path
   std::string filename = targetFilePath.filename();
   if (filename.find(' ') != std::string::npos)
   {
      *pUserErrMsg = "Invalid filename: '" + filename +
                     "' (TeX does not understand paths with spaces)";
      return false;
   }

   // parse out magic comments
   core::tex::TexMagicComments magicComments;
   error = core::tex::parseMagicComments(targetFilePath, &magicComments);
   if (error)
      LOG_ERROR(error);

   // discover and validate tex program path
   FilePath texProgramPath;
   if (!pdflatex::latexProgramForFile(magicComments,
                                      &texProgramPath,
                                      pUserErrMsg))
   {
      return false;
   }

   // see if we need to sweave
   std::string ext = targetFilePath.extensionLowerCase();
   if (ext == ".rnw" || ext == ".snw" || ext == ".nw")
   {
      // attempt to weave the rnw
      bool success = rnw_weave::runWeave(targetFilePath,
                                         magicComments,
                                         pUserErrMsg);
      if (!success)
         return false;
   }

   // configure pdflatex options
   pdflatex::PdfLatexOptions options;
   options.fileLineError = false;
   options.syncTex = true;

   // run tex compile
   FilePath texFilePath = targetFilePath.parent().complete(
                                             targetFilePath.stem() +
                                             ".tex");
   core::system::ProcessResult result;
#if defined(_WIN32) || defined(__APPLE__)
   error = tex::texi2dvi::texToPdf(texProgramPath,
                                   texFilePath,
                                   options,
                                   &result);
#else
   // workaround for tex2dvi special character bug on linux:
   //   http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=577741
  error = tex::pdflatex::texToPdf(texProgramPath,
                                  texFilePath,
                                  options,
                                  &result);
#endif

   if (error)
   {
      *pUserErrMsg = "Unable to compile pdf: " + error.summary();
      return false;
   }
   else if (result.exitStatus != EXIT_SUCCESS)
   {
      showCompilationErrors(texFilePath);
      return false;
   }
   else
   {
      if (completedAction == "view")
         viewPdf(targetFilePath);
      else if (completedAction == "publish")
         publishPdf(targetFilePath);

      return true;
   }
}

SEXP rs_compilePdf(SEXP filePathSEXP, SEXP completedActionSEXP)
{
   try
   {
      // extract parameters
      FilePath targetFilePath = module_context::resolveAliasedPath(
                                          r::sexp::asString(filePathSEXP));
      std::string completedAction = r::sexp::asString(completedActionSEXP);

      // compile pdf
      std::string userErrMsg;
      if (!compilePdf(targetFilePath, completedAction, &userErrMsg))
      {
         if (!userErrMsg.empty())
            throw r::exec::RErrorException(userErrMsg);
      }
   }
   catch(const r::exec::RErrorException& e)
   {
      r::exec::error(e.message());
   }
   CATCH_UNEXPECTED_EXCEPTION

   return R_NilValue;
}

} // anonymous namespace

Error initialize()
{
   R_CallMethodDef compilePdfMethodDef;
   compilePdfMethodDef.name = "rs_compilePdf" ;
   compilePdfMethodDef.fun = (DL_FUNC) rs_compilePdf ;
   compilePdfMethodDef.numArgs = 2;
   r::routines::addCallMethod(compilePdfMethodDef);

   using boost::bind;
   using namespace module_context;
   ExecBlock initBlock ;
   initBlock.addFunctions()
      (bind(sourceModuleRFile, "SessionCompilePdf.R"));
   return initBlock.execute();

}

} // namespace compile_pdf
} // namespace tex
} // namespace modules
} // namesapce session

<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Syscoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

// NOTE: This file is intended to be customised by the end user, and includes only local node policy logic

#include "policy/policy.h"

#include "validation.h"
#include "tinyformat.h"
#include "util.h"
#include "utilstrencodings.h"

#include <boost/foreach.hpp>
// SYSCOIN need constant SYSCOIN_TX_VERSION
#include "alias.h"
    /**
     * Check transaction inputs to mitigate two
     * potential denial-of-service attacks:
     *
     * 1. scriptSigs with extra data stuffed into them,
     *    not consumed by scriptPubKey (or P2SH script)
     * 2. P2SH scripts with a crazy number of expensive
     *    CHECKSIG/CHECKMULTISIG operations
     *
     * Why bother? To avoid denial-of-service attacks; an attacker
     * can submit a standard HASH... OP_EQUAL transaction,
     * which will get accepted into blocks. The redemption
     * script can be anything; an attacker could use a very
     * expensive-to-check-upon-redemption script like:
     *   DUP CHECKSIG DROP ... repeated 100 times... OP_1
     */

bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
{
    std::vector<std::vector<unsigned char> > vSolutions;
    if (!Solver(scriptPubKey, whichType, vSolutions))
        return false;

    if (whichType == TX_MULTISIG)
    {
        unsigned char m = vSolutions.front()[0];
        unsigned char n = vSolutions.back()[0];
        // Support up to x-of-3 multisig txns as standard
        if (n < 1 || n > 3)
            return false;
        if (m < 1 || m > n)
            return false;
	}
	// SYSCOIN check for size of sys tx, normal tx size is checked in isstandardtx now
	else if (whichType == TX_NULL_DATA &&
		(!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes * 20))
          return false;

    return whichType != TX_NONSTANDARD;
}

bool IsStandardTx(const CTransaction& tx, std::string& reason)
{
	// SYSCOIN check for syscoin or bitcoin tx
	if ((tx.nVersion > CTransaction::MAX_STANDARD_VERSION || tx.nVersion < 1) && tx.nVersion != SYSCOIN_TX_VERSION) {
		reason = "version";
		return false;
	}

    // Extremely large transactions with lots of inputs can cost the network
    // almost as much to process as they cost the sender in fees, because
    // computing signature hashes is O(ninputs*txsize). Limiting transactions
    // to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks.
    unsigned int sz = GetSerializeSize(tx, SER_NETWORK, CTransaction::CURRENT_VERSION);
    if (sz >= MAX_STANDARD_TX_SIZE) {
        reason = "tx-size";
        return false;
    }

    BOOST_FOREACH(const CTxIn& txin, tx.vin)
    {
        // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
        // keys (remember the 520 byte limit on redeemScript size). That works
        // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627
        // bytes of scriptSig, which we round off to 1650 bytes for some minor
        // future-proofing. That's also enough to spend a 20-of-20
        // CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not
        // considered standard.
        if (txin.scriptSig.size() > 1650) {
            reason = "scriptsig-size";
            return false;
        }
        if (!txin.scriptSig.IsPushOnly()) {
            reason = "scriptsig-not-pushonly";
            return false;
        }
    }

    unsigned int nDataOut = 0;
    txnouttype whichType;
    BOOST_FOREACH(const CTxOut& txout, tx.vout) {
        if (!::IsStandard(txout.scriptPubKey, whichType)) {
            reason = "scriptpubkey";
            return false;
        }

		if (whichType == TX_NULL_DATA)
		{
			// SYSCOIN if not syscoin tx and opreturn size is bigger than maxcarrier bytes, return false
			// we need this because if it is a sys tx then we allow 20x maxcarrier bytes.
			if (tx.nVersion != SYSCOIN_TX_VERSION && txout.scriptPubKey.size() > nMaxDatacarrierBytes)
			{
				reason = "scriptpubkey";
				return false;
			}

			nDataOut++;
		}
        else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
            reason = "bare-multisig";
            return false;
        } else if (txout.IsDust(dustRelayFee)) {
            reason = "dust";
            return false;
        }
    }

    // only one OP_RETURN txout is permitted
    if (nDataOut > 1) {
        reason = "multi-op-return";
        return false;
    }

    return true;
}

bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
{
    if (tx.IsCoinBase())
        return true; // Coinbases don't use vin normally

    for (unsigned int i = 0; i < tx.vin.size(); i++)
    {
        const CTxOut& prev = mapInputs.AccessCoin(tx.vin[i].prevout).out;

        std::vector<std::vector<unsigned char> > vSolutions;
        txnouttype whichType;
        // get the scriptPubKey corresponding to this input:
        const CScript& prevScript = prev.scriptPubKey;
        if (!Solver(prevScript, whichType, vSolutions))
            return false;

        if (whichType == TX_SCRIPTHASH)
        {
            std::vector<std::vector<unsigned char> > stack;
            // convert the scriptSig into a stack, so we can inspect the redeemScript
            if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), 0))
                return false;
            if (stack.empty())
                return false;
            CScript subscript(stack.back().begin(), stack.back().end());
            if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) {
                return false;
            }
        }
    }

    return true;
}

CFeeRate incrementalRelayFee = CFeeRate(DEFAULT_INCREMENTAL_RELAY_FEE);
CFeeRate dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
<commit_msg>increase carrier bytes for asset send bulk<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Syscoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

// NOTE: This file is intended to be customised by the end user, and includes only local node policy logic

#include "policy/policy.h"

#include "validation.h"
#include "tinyformat.h"
#include "util.h"
#include "utilstrencodings.h"

#include <boost/foreach.hpp>
// SYSCOIN need constant SYSCOIN_TX_VERSION
#include "alias.h"
    /**
     * Check transaction inputs to mitigate two
     * potential denial-of-service attacks:
     *
     * 1. scriptSigs with extra data stuffed into them,
     *    not consumed by scriptPubKey (or P2SH script)
     * 2. P2SH scripts with a crazy number of expensive
     *    CHECKSIG/CHECKMULTISIG operations
     *
     * Why bother? To avoid denial-of-service attacks; an attacker
     * can submit a standard HASH... OP_EQUAL transaction,
     * which will get accepted into blocks. The redemption
     * script can be anything; an attacker could use a very
     * expensive-to-check-upon-redemption script like:
     *   DUP CHECKSIG DROP ... repeated 100 times... OP_1
     */

bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
{
    std::vector<std::vector<unsigned char> > vSolutions;
    if (!Solver(scriptPubKey, whichType, vSolutions))
        return false;

    if (whichType == TX_MULTISIG)
    {
        unsigned char m = vSolutions.front()[0];
        unsigned char n = vSolutions.back()[0];
        // Support up to x-of-3 multisig txns as standard
        if (n < 1 || n > 3)
            return false;
        if (m < 1 || m > n)
            return false;
	}
	// SYSCOIN check for size of sys tx, normal tx size is checked in isstandardtx now
	else if (whichType == TX_NULL_DATA &&
		(!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes * 200))
          return false;

    return whichType != TX_NONSTANDARD;
}

bool IsStandardTx(const CTransaction& tx, std::string& reason)
{
	// SYSCOIN check for syscoin or bitcoin tx
	if ((tx.nVersion > CTransaction::MAX_STANDARD_VERSION || tx.nVersion < 1) && tx.nVersion != SYSCOIN_TX_VERSION) {
		reason = "version";
		return false;
	}

    // Extremely large transactions with lots of inputs can cost the network
    // almost as much to process as they cost the sender in fees, because
    // computing signature hashes is O(ninputs*txsize). Limiting transactions
    // to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks.
    unsigned int sz = GetSerializeSize(tx, SER_NETWORK, CTransaction::CURRENT_VERSION);
    if (sz >= MAX_STANDARD_TX_SIZE) {
        reason = "tx-size";
        return false;
    }

    BOOST_FOREACH(const CTxIn& txin, tx.vin)
    {
        // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
        // keys (remember the 520 byte limit on redeemScript size). That works
        // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627
        // bytes of scriptSig, which we round off to 1650 bytes for some minor
        // future-proofing. That's also enough to spend a 20-of-20
        // CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not
        // considered standard.
        if (txin.scriptSig.size() > 1650) {
            reason = "scriptsig-size";
            return false;
        }
        if (!txin.scriptSig.IsPushOnly()) {
            reason = "scriptsig-not-pushonly";
            return false;
        }
    }

    unsigned int nDataOut = 0;
    txnouttype whichType;
    BOOST_FOREACH(const CTxOut& txout, tx.vout) {
        if (!::IsStandard(txout.scriptPubKey, whichType)) {
            reason = "scriptpubkey";
            return false;
        }

		if (whichType == TX_NULL_DATA)
		{
			// SYSCOIN if not syscoin tx and opreturn size is bigger than maxcarrier bytes, return false
			// we need this because if it is a sys tx then we allow 200x maxcarrier bytes.
			if (tx.nVersion != SYSCOIN_TX_VERSION && txout.scriptPubKey.size() > nMaxDatacarrierBytes)
			{
				reason = "scriptpubkey";
				return false;
			}

			nDataOut++;
		}
        else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
            reason = "bare-multisig";
            return false;
        } else if (txout.IsDust(dustRelayFee)) {
            reason = "dust";
            return false;
        }
    }

    // only one OP_RETURN txout is permitted
    if (nDataOut > 1) {
        reason = "multi-op-return";
        return false;
    }

    return true;
}

bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
{
    if (tx.IsCoinBase())
        return true; // Coinbases don't use vin normally

    for (unsigned int i = 0; i < tx.vin.size(); i++)
    {
        const CTxOut& prev = mapInputs.AccessCoin(tx.vin[i].prevout).out;

        std::vector<std::vector<unsigned char> > vSolutions;
        txnouttype whichType;
        // get the scriptPubKey corresponding to this input:
        const CScript& prevScript = prev.scriptPubKey;
        if (!Solver(prevScript, whichType, vSolutions))
            return false;

        if (whichType == TX_SCRIPTHASH)
        {
            std::vector<std::vector<unsigned char> > stack;
            // convert the scriptSig into a stack, so we can inspect the redeemScript
            if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), 0))
                return false;
            if (stack.empty())
                return false;
            CScript subscript(stack.back().begin(), stack.back().end());
            if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) {
                return false;
            }
        }
    }

    return true;
}

CFeeRate incrementalRelayFee = CFeeRate(DEFAULT_INCREMENTAL_RELAY_FEE);
CFeeRate dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (C) 2006-2008 Marc Boris Duerner                            *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 2 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   As a special exception, you may use this file as part of a free       *
 *   software library without restriction. Specifically, if other files    *
 *   instantiate templates or use macros or inline functions from this     *
 *   file, or you compile this file and link it with other files to        *
 *   produce an executable, this file does not by itself cause the         *
 *   resulting executable to be covered by the GNU General Public          *
 *   License. This exception does not however invalidate any other         *
 *   reasons why the executable file might be covered by the GNU Library   *
 *   General Public License.                                               *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "threadimpl.h"
#include "cxxtools/syserror.h"
#include <errno.h>

extern "C"
{
    static void* thread_entry(void* arg)
    {
        cxxtools::ThreadImpl* impl = (cxxtools::ThreadImpl*)arg;
        if( impl->cb() )
            impl->cb()->call();

        return 0;
    }
}

namespace
{
    void throwIf(int ret, pthread_t& id, const char* msg)
    {
        if(ret != 0)
        {
            id = 0;
            throw cxxtools::SysError(ret, msg);
        }
    }
}

namespace cxxtools {

void ThreadImpl::detach()
{
    if( _id )
    {
        int ret = pthread_detach(_id);
        throwIf(ret, _id, "Could not detach thread");
    }
}

void ThreadImpl::init(const Callable<void>& cb)
{
    if(_cb)
    {
        delete _cb;
        _cb = cb.clone();
    }
}

void ThreadImpl::start()
{
    size_t stacksize = 0;

    pthread_attr_t attrs;
    pthread_attr_init(&attrs);
    pthread_attr_setinheritsched(&attrs, PTHREAD_INHERIT_SCHED);

    if(stacksize > 0)
        pthread_attr_setstacksize(&attrs ,stacksize);

    int ret = pthread_create(&_id, &attrs, thread_entry, this);
    pthread_attr_destroy(&attrs);

    throwIf(ret, _id, "Could not create thread");
}

void ThreadImpl::join()
{
    void* threadRet = 0;
    int ret = pthread_join(_id, &threadRet);

    throwIf(ret, _id, "Could not join thread");
}

void ThreadImpl::terminate()
{
    int ret = pthread_kill(_id, SIGKILL);

    throwIf(ret, _id, "Could not terminate thread");
}

}
<commit_msg>init corrected, removed inheritsched<commit_after>/***************************************************************************
 *   Copyright (C) 2006-2008 Marc Boris Duerner                            *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 2 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   As a special exception, you may use this file as part of a free       *
 *   software library without restriction. Specifically, if other files    *
 *   instantiate templates or use macros or inline functions from this     *
 *   file, or you compile this file and link it with other files to        *
 *   produce an executable, this file does not by itself cause the         *
 *   resulting executable to be covered by the GNU General Public          *
 *   License. This exception does not however invalidate any other         *
 *   reasons why the executable file might be covered by the GNU Library   *
 *   General Public License.                                               *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "threadimpl.h"
#include "cxxtools/syserror.h"
#include <errno.h>

extern "C"
{
    static void* thread_entry(void* arg)
    {
        cxxtools::ThreadImpl* impl = (cxxtools::ThreadImpl*)arg;
        if( impl->cb() )
            impl->cb()->call();

        return 0;
    }
}

namespace
{
    void throwIf(int ret, pthread_t& id, const char* msg)
    {
        if(ret != 0)
        {
            id = 0;
            throw cxxtools::SysError(ret, msg);
        }
    }
}

namespace cxxtools {

void ThreadImpl::detach()
{
    if( _id )
    {
        int ret = pthread_detach(_id);
        throwIf(ret, _id, "Could not detach thread");
    }
}

void ThreadImpl::init(const Callable<void>& cb)
{
    delete _cb;
    _cb = cb.clone();
}

void ThreadImpl::start()
{
    size_t stacksize = 0;

    pthread_attr_t attrs;
    pthread_attr_init(&attrs);
    //pthread_attr_setinheritsched(&attrs, PTHREAD_INHERIT_SCHED);

    if(stacksize > 0)
        pthread_attr_setstacksize(&attrs ,stacksize);

    int ret = pthread_create(&_id, &attrs, thread_entry, this);
    pthread_attr_destroy(&attrs);

    throwIf(ret, _id, "Could not create thread");
}

void ThreadImpl::join()
{
    void* threadRet = 0;
    int ret = pthread_join(_id, &threadRet);

    throwIf(ret, _id, "Could not join thread");
}

void ThreadImpl::terminate()
{
    int ret = pthread_kill(_id, SIGKILL);

    throwIf(ret, _id, "Could not terminate thread");
}

}
<|endoftext|>