<commit_before>#if !defined(_IMAPSESSION_HPP_INCLUDED_)
#define _IMAPSESSION_HPP_INCLUDED_

#include <iostream>

#include <map>
#include <string>

#include <stdint.h>

#include <libcppserver/insensitive.hpp>
#include <libcppserver/internetsession.hpp>
#include <libcppserver/internetserver.hpp>
#include <libcppserver/sessiondriver.hpp>

#include "imapuser.hpp"
#include "namespace.hpp"
#include "sasl.hpp"
#include "mailsearch.hpp"
#include "mailmessage.hpp"

class ImapMaster;
class SessionDriver;
class MailSearch;
class MailMessage;

enum ImapState
  {
    ImapNotAuthenticated = 0,
    ImapAuthenticated,
    ImapSelected,
    ImapLogoff
  };

enum ImapStringState
  {
    ImapStringGood,
    ImapStringBad,
    ImapStringPending
  };

/*--------------------------------------------------------------------------------------*/
//* Imap											*/
/*--------------------------------------------------------------------------------------*/

class ImapSession;

typedef enum
  {
    IMAP_OK,
    IMAP_NO,
    IMAP_BAD,
    IMAP_NOTDONE,
    IMAP_NO_WITH_PAUSE,
    IMAP_MBOX_ERROR,
    IMAP_IN_LITERAL,
    IMAP_TRY_AGAIN
  } IMAP_RESULTS;

#define MAX_RESPONSE_STRING_LENGTH	80
#define IMAP_BUFFER_LEN			8192

typedef struct {
  bool levels[ImapLogoff+1];
  bool sendUpdatedStatus;
  // The flag is a bit of an odd duck.  It's here because I need to pass what essentially amounts to random bools to the
  // handler.  It means different things for different methods.
  // It distinguishes subscribe (flag = true) from unsubscribe (flag = false)
  // It distinguishes list (flag = true) from lsub (flag = false)
  // It distinguishes examine (flag = true) from select (flag = false)
  // It distinguishes uid (flag = true) from copy, close, search, fetch, and store (flag = false)
  bool flag;
  IMAP_RESULTS (ImapSession::*handler)(uint8_t *data, size_t dataLen, size_t &parsingAt, bool flag);
} symbol;

typedef std::map<insensitiveString, symbol> IMAPSYMBOLS;

class ImapSession : public InternetSession {
public:
  ImapSession(ImapMaster *master, SessionDriver *driver, InternetServer *server);
  virtual ~ImapSession();
  static void BuildSymbolTables(void);
  void ReceiveData(uint8_t* pData, size_t dwDataLen );

  void AsynchronousEvent(void);
  ImapMaster *GetMaster(void) const { return m_master; }
  InternetServer *GetServer(void) const { return m_server; }
  SessionDriver *GetDriver(void) const { return m_driver; };
  time_t GetLastCommandTime() const { return m_lastCommandTime; }
  ImapState GetState(void) const { return m_state; }
  const ImapUser *GetUser(void) const { return m_userData; }
  // ReceiveData processes data as it comes it.  It's primary job is to chop the incoming data into
  // lines and to pass each line to HandleOneLine, which is the core command processor for the system
  void HandleOneLine(uint8_t *pData, size_t dwDataLen);
  void DoRetry(void);
  void IdleTimeout(void);

private:
  // These are configuration items
  bool m_LoginDisabled;
  static bool m_anonymousEnabled;
  unsigned m_failedLoginPause;
  SessionDriver *m_driver;
  MailStore::MAIL_STORE_RESULT m_mboxErrorCode;

  // These constitute the session's state
  enum ImapState m_state;
  IMAP_RESULTS (ImapSession::*m_currentHandler)(uint8_t *data, const size_t dataLen, size_t &parsingAt, bool flag);
  bool m_flag;

  uint32_t m_mailFlags;
  uint8_t *m_lineBuffer;			// This buffers the incoming data into lines to be processed
  uint32_t m_lineBuffPtr, m_lineBuffLen;
  // As lines come in from the outside world, they are processed into m_bBuffer, which holds
  // them until the entire command has been received at which point it can be processed, often
  // by the *Execute() methods.
  uint8_t  *m_parseBuffer;
  uint32_t m_parseBuffLen;
  uint32_t m_parsePointer; 			// This points past the end of what's been put into the parse buffer

  // This is associated with handling appends
  size_t m_appendingUid;
  Namespace *m_store;
  char m_responseCode[MAX_RESPONSE_STRING_LENGTH+1];
  char m_responseText[MAX_RESPONSE_STRING_LENGTH+1];
  uint32_t m_commandString, m_arguments;
  uint32_t m_parseStage;
  uint32_t m_literalLength;
  bool m_usesUid;

  // These are used to send live updates in case the mailbox is accessed by multiple client simultaneously
  uint32_t m_currentNextUid, m_currentMessageCount;
  uint32_t m_currentRecentCount, m_currentUnseen, m_currentUidValidity;

  static IMAPSYMBOLS m_symbols;

  // This creates a properly formatted capability string based on the current state and configuration
  // of the IMAP server
  std::string BuildCapabilityString(void);
  // This sends the untagged responses associated with selecting a mailbox
  void SendSelectData(const std::string &mailbox, bool isReadWrite);
  // This appends data to the Parse Buffer, extending the parse buffer as necessary.
  void AddToParseBuffer(const uint8_t *data, size_t length, bool bNulTerminate = true);

  IMAP_RESULTS LoginHandlerExecute();
  IMAP_RESULTS SearchKeyParse(uint8_t *data, size_t dataLen, size_t &parsingAt);
  IMAP_RESULTS SearchHandlerInternal(uint8_t *data, size_t dataLen, size_t &parsingAt, bool usingUid);
  IMAP_RESULTS StoreHandlerInternal(uint8_t *data, size_t dataLen, size_t &parsingAt, bool usingUid);
  IMAP_RESULTS FetchHandlerInternal(uint8_t *data, size_t dataLen, size_t &parsingAt, bool usingUid);
  IMAP_RESULTS CopyHandlerInternal(uint8_t *data, size_t dataLen, size_t &parsingAt, bool usingUid);

  size_t ReadEmailFlags(uint8_t *data, const size_t dataLen, size_t &parsingAt, bool &okay);
  bool UpdateSearchTerms(MailSearch &searchTerm, size_t &tokenPointer, bool isSubExpression);
  bool MsnSequenceSet(SEARCH_RESULT &r_srVector, size_t &tokenPointer);
  bool UidSequenceSet(SEARCH_RESULT &r_srVector, size_t &tokenPointer);
  bool UpdateSearchTerm(MailSearch &searchTerm, size_t &tokenPointer);

  IMAP_RESULTS SelectHandlerExecute(bool isReadWrite = true);
  IMAP_RESULTS CreateHandlerExecute();
  IMAP_RESULTS DeleteHandlerExecute();
  IMAP_RESULTS RenameHandlerExecute();
  IMAP_RESULTS SubscribeHandlerExecute(bool isSubscribe);
  IMAP_RESULTS ListHandlerExecute(bool listAll);
  IMAP_RESULTS StatusHandlerExecute(uint8_t *data, size_t dataLen, size_t parsingAt);
  IMAP_RESULTS AppendHandlerExecute(uint8_t *data, size_t dataLen, size_t &parsingAt);
  IMAP_RESULTS SearchHandlerExecute(bool usingUid);
  IMAP_RESULTS FetchHandlerExecute(bool usingUid);
  IMAP_RESULTS CopyHandlerExecute(bool usingUid);

  void atom(uint8_t *data, const size_t dataLen, size_t &parsingAt);
  enum ImapStringState astring(uint8_t *pData, const size_t dataLen, size_t &parsingAt, bool makeUppercase,
			       const char *additionalChars);
  std::string FormatTaggedResponse(IMAP_RESULTS status, bool sendUpdatedStatus);

  // This is what is called if a command is unrecognized or if a command is not implemented
  IMAP_RESULTS UnimplementedHandler();

  // What follows are the handlers for the various IMAP command.  These are grouped similarly to the
  // way the commands are grouped in RFC-3501.  They all have identical function signatures so that
  // they can be called indirectly through a function pointer returned from the command map.
  IMAP_RESULTS CapabilityHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS NoopHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS LogoutHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);

  IMAP_RESULTS StarttlsHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS AuthenticateHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS LoginHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);

  IMAP_RESULTS NamespaceHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS SelectHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool isReadOnly);
  IMAP_RESULTS CreateHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS DeleteHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS RenameHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS SubscribeHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool isSubscribe);
  IMAP_RESULTS ListHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool listAll);
  IMAP_RESULTS StatusHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS AppendHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);

  IMAP_RESULTS CheckHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS CloseHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS ExpungeHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS SearchHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool useUid);
  IMAP_RESULTS FetchHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool useUid);
  IMAP_RESULTS StoreHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool useUid);
  IMAP_RESULTS CopyHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool useUid);
  IMAP_RESULTS UidHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);

  // These are for fetches, which are special because they can generate arbitrarily large responses
  void FetchResponseFlags(uint32_t flags);
  void FetchResponseInternalDate(const MailMessage *message);
  void FetchResponseRfc822(unsigned long uid, const MailMessage *message);
  void FetchResponseRfc822Header(unsigned long uid, const MailMessage *message);
  void FetchResponseRfc822Size(const MailMessage *message);
  void FetchResponseRfc822Text(unsigned long uid, const MailMessage *message);
  void FetchResponseEnvelope(const MailMessage *message);
  void FetchResponseBodyStructure(const MailMessage *message);
  void FetchResponseBody(const MailMessage *message);
  void FetchResponseUid(unsigned long uid);
  void SendMessageChunk(unsigned long uid, size_t offset, size_t length);
  ImapUser *m_userData;
  ImapMaster *m_master;
  InternetServer *m_server;
  Sasl *m_auth;
  time_t m_lastCommandTime;
  NUMBER_SET m_purgedMessages;
  bool m_sendUpdatedStatus;
  unsigned m_retries;
  unsigned m_maxRetries;
  unsigned m_retryDelay;
};

#endif //_IMAPSESSION_HPP_INCLUDED_
<commit_msg>ReceiveData is really a virtual function.<commit_after>#if !defined(_IMAPSESSION_HPP_INCLUDED_)
#define _IMAPSESSION_HPP_INCLUDED_

#include <iostream>

#include <map>
#include <string>

#include <stdint.h>

#include <libcppserver/insensitive.hpp>
#include <libcppserver/internetsession.hpp>
#include <libcppserver/internetserver.hpp>
#include <libcppserver/sessiondriver.hpp>

#include "imapuser.hpp"
#include "namespace.hpp"
#include "sasl.hpp"
#include "mailsearch.hpp"
#include "mailmessage.hpp"

class ImapMaster;
class SessionDriver;
class MailSearch;
class MailMessage;

enum ImapState
  {
    ImapNotAuthenticated = 0,
    ImapAuthenticated,
    ImapSelected,
    ImapLogoff
  };

enum ImapStringState
  {
    ImapStringGood,
    ImapStringBad,
    ImapStringPending
  };

/*--------------------------------------------------------------------------------------*/
//* Imap											*/
/*--------------------------------------------------------------------------------------*/

class ImapSession;

typedef enum
  {
    IMAP_OK,
    IMAP_NO,
    IMAP_BAD,
    IMAP_NOTDONE,
    IMAP_NO_WITH_PAUSE,
    IMAP_MBOX_ERROR,
    IMAP_IN_LITERAL,
    IMAP_TRY_AGAIN
  } IMAP_RESULTS;

#define MAX_RESPONSE_STRING_LENGTH	80
#define IMAP_BUFFER_LEN			8192

typedef struct {
  bool levels[ImapLogoff+1];
  bool sendUpdatedStatus;
  // The flag is a bit of an odd duck.  It's here because I need to pass what essentially amounts to random bools to the
  // handler.  It means different things for different methods.
  // It distinguishes subscribe (flag = true) from unsubscribe (flag = false)
  // It distinguishes list (flag = true) from lsub (flag = false)
  // It distinguishes examine (flag = true) from select (flag = false)
  // It distinguishes uid (flag = true) from copy, close, search, fetch, and store (flag = false)
  bool flag;
  IMAP_RESULTS (ImapSession::*handler)(uint8_t *data, size_t dataLen, size_t &parsingAt, bool flag);
} symbol;

typedef std::map<insensitiveString, symbol> IMAPSYMBOLS;

class ImapSession : public InternetSession {
public:
  ImapSession(ImapMaster *master, SessionDriver *driver, InternetServer *server);
  virtual ~ImapSession();
  static void BuildSymbolTables(void);
  virtual void ReceiveData(uint8_t* pData, size_t dwDataLen );

  void AsynchronousEvent(void);
  ImapMaster *GetMaster(void) const { return m_master; }
  InternetServer *GetServer(void) const { return m_server; }
  SessionDriver *GetDriver(void) const { return m_driver; };
  time_t GetLastCommandTime() const { return m_lastCommandTime; }
  ImapState GetState(void) const { return m_state; }
  const ImapUser *GetUser(void) const { return m_userData; }
  // ReceiveData processes data as it comes it.  It's primary job is to chop the incoming data into
  // lines and to pass each line to HandleOneLine, which is the core command processor for the system
  void HandleOneLine(uint8_t *pData, size_t dwDataLen);
  void DoRetry(void);
  void IdleTimeout(void);

private:
  // These are configuration items
  bool m_LoginDisabled;
  static bool m_anonymousEnabled;
  unsigned m_failedLoginPause;
  SessionDriver *m_driver;
  MailStore::MAIL_STORE_RESULT m_mboxErrorCode;

  // These constitute the session's state
  enum ImapState m_state;
  IMAP_RESULTS (ImapSession::*m_currentHandler)(uint8_t *data, const size_t dataLen, size_t &parsingAt, bool flag);
  bool m_flag;

  uint32_t m_mailFlags;
  uint8_t *m_lineBuffer;			// This buffers the incoming data into lines to be processed
  uint32_t m_lineBuffPtr, m_lineBuffLen;
  // As lines come in from the outside world, they are processed into m_bBuffer, which holds
  // them until the entire command has been received at which point it can be processed, often
  // by the *Execute() methods.
  uint8_t  *m_parseBuffer;
  uint32_t m_parseBuffLen;
  uint32_t m_parsePointer; 			// This points past the end of what's been put into the parse buffer

  // This is associated with handling appends
  size_t m_appendingUid;
  Namespace *m_store;
  char m_responseCode[MAX_RESPONSE_STRING_LENGTH+1];
  char m_responseText[MAX_RESPONSE_STRING_LENGTH+1];
  uint32_t m_commandString, m_arguments;
  uint32_t m_parseStage;
  uint32_t m_literalLength;
  bool m_usesUid;

  // These are used to send live updates in case the mailbox is accessed by multiple client simultaneously
  uint32_t m_currentNextUid, m_currentMessageCount;
  uint32_t m_currentRecentCount, m_currentUnseen, m_currentUidValidity;

  static IMAPSYMBOLS m_symbols;

  // This creates a properly formatted capability string based on the current state and configuration
  // of the IMAP server
  std::string BuildCapabilityString(void);
  // This sends the untagged responses associated with selecting a mailbox
  void SendSelectData(const std::string &mailbox, bool isReadWrite);
  // This appends data to the Parse Buffer, extending the parse buffer as necessary.
  void AddToParseBuffer(const uint8_t *data, size_t length, bool bNulTerminate = true);

  IMAP_RESULTS LoginHandlerExecute();
  IMAP_RESULTS SearchKeyParse(uint8_t *data, size_t dataLen, size_t &parsingAt);
  IMAP_RESULTS SearchHandlerInternal(uint8_t *data, size_t dataLen, size_t &parsingAt, bool usingUid);
  IMAP_RESULTS StoreHandlerInternal(uint8_t *data, size_t dataLen, size_t &parsingAt, bool usingUid);
  IMAP_RESULTS FetchHandlerInternal(uint8_t *data, size_t dataLen, size_t &parsingAt, bool usingUid);
  IMAP_RESULTS CopyHandlerInternal(uint8_t *data, size_t dataLen, size_t &parsingAt, bool usingUid);

  size_t ReadEmailFlags(uint8_t *data, const size_t dataLen, size_t &parsingAt, bool &okay);
  bool UpdateSearchTerms(MailSearch &searchTerm, size_t &tokenPointer, bool isSubExpression);
  bool MsnSequenceSet(SEARCH_RESULT &r_srVector, size_t &tokenPointer);
  bool UidSequenceSet(SEARCH_RESULT &r_srVector, size_t &tokenPointer);
  bool UpdateSearchTerm(MailSearch &searchTerm, size_t &tokenPointer);

  IMAP_RESULTS SelectHandlerExecute(bool isReadWrite = true);
  IMAP_RESULTS CreateHandlerExecute();
  IMAP_RESULTS DeleteHandlerExecute();
  IMAP_RESULTS RenameHandlerExecute();
  IMAP_RESULTS SubscribeHandlerExecute(bool isSubscribe);
  IMAP_RESULTS ListHandlerExecute(bool listAll);
  IMAP_RESULTS StatusHandlerExecute(uint8_t *data, size_t dataLen, size_t parsingAt);
  IMAP_RESULTS AppendHandlerExecute(uint8_t *data, size_t dataLen, size_t &parsingAt);
  IMAP_RESULTS SearchHandlerExecute(bool usingUid);
  IMAP_RESULTS FetchHandlerExecute(bool usingUid);
  IMAP_RESULTS CopyHandlerExecute(bool usingUid);

  void atom(uint8_t *data, const size_t dataLen, size_t &parsingAt);
  enum ImapStringState astring(uint8_t *pData, const size_t dataLen, size_t &parsingAt, bool makeUppercase,
			       const char *additionalChars);
  std::string FormatTaggedResponse(IMAP_RESULTS status, bool sendUpdatedStatus);

  // This is what is called if a command is unrecognized or if a command is not implemented
  IMAP_RESULTS UnimplementedHandler();

  // What follows are the handlers for the various IMAP command.  These are grouped similarly to the
  // way the commands are grouped in RFC-3501.  They all have identical function signatures so that
  // they can be called indirectly through a function pointer returned from the command map.
  IMAP_RESULTS CapabilityHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS NoopHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS LogoutHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);

  IMAP_RESULTS StarttlsHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS AuthenticateHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS LoginHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);

  IMAP_RESULTS NamespaceHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS SelectHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool isReadOnly);
  IMAP_RESULTS CreateHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS DeleteHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS RenameHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS SubscribeHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool isSubscribe);
  IMAP_RESULTS ListHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool listAll);
  IMAP_RESULTS StatusHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS AppendHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);

  IMAP_RESULTS CheckHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS CloseHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS ExpungeHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);
  IMAP_RESULTS SearchHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool useUid);
  IMAP_RESULTS FetchHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool useUid);
  IMAP_RESULTS StoreHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool useUid);
  IMAP_RESULTS CopyHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool useUid);
  IMAP_RESULTS UidHandler(uint8_t *data, size_t dataLen, size_t &parsingAt, bool unused);

  // These are for fetches, which are special because they can generate arbitrarily large responses
  void FetchResponseFlags(uint32_t flags);
  void FetchResponseInternalDate(const MailMessage *message);
  void FetchResponseRfc822(unsigned long uid, const MailMessage *message);
  void FetchResponseRfc822Header(unsigned long uid, const MailMessage *message);
  void FetchResponseRfc822Size(const MailMessage *message);
  void FetchResponseRfc822Text(unsigned long uid, const MailMessage *message);
  void FetchResponseEnvelope(const MailMessage *message);
  void FetchResponseBodyStructure(const MailMessage *message);
  void FetchResponseBody(const MailMessage *message);
  void FetchResponseUid(unsigned long uid);
  void SendMessageChunk(unsigned long uid, size_t offset, size_t length);
  ImapUser *m_userData;
  ImapMaster *m_master;
  InternetServer *m_server;
  Sasl *m_auth;
  time_t m_lastCommandTime;
  NUMBER_SET m_purgedMessages;
  bool m_sendUpdatedStatus;
  unsigned m_retries;
  unsigned m_maxRetries;
  unsigned m_retryDelay;
};

#endif //_IMAPSESSION_HPP_INCLUDED_
<|endoftext|>


<commit_before>AliAnalysisTaskSEVertexingHF *AddTaskVertexingHFFilter(TString configPWG3d2h="$ALICE_ROOT/PWGHF/vertexingHF/ConfigVertexingHF_Pb_AllCent_NoLS_PIDLc.C", Bool_t registerFile=kFALSE)
{

  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskVertexingHFFilter", "No analysis manager to connect to.");
    return NULL;
  }

  gROOT->LoadMacro("$ALICE_ROOT/PWGHF/vertexingHF/macros/AddTaskVertexingHF.C");
  //  TFile::Cp(gSystem->ExpandPathName(configPWG3d2h.Data()), Form("%s/ConfigVertexingHF.C", train_name.Data()));
  TFile::Cp(gSystem->ExpandPathName(configPWG3d2h.Data()), Form("ConfigVertexingHF.C"));
  AliAnalysisTaskSEVertexingHF *taskvertexingHF = AddTaskVertexingHF();
  // Now we need to keep in sync with the ESD filter
  if (!taskvertexingHF) ::Warning("AddTaskVertexingHFFilter", "AliAnalysisTaskSEVertexingHF cannot run for this train conditions - EXCLUDED");

  if(registerFile) mgr->RegisterExtraFile("AliAOD.VertexingHF.root");
  taskvertexingHF->SelectCollisionCandidates(0);

  mgr->AddTask(taskvertexingHF);

  return taskvertexingHF;
}
<commit_msg>Change default value of one argument<commit_after>AliAnalysisTaskSEVertexingHF *AddTaskVertexingHFFilter(TString configPWG3d2h="$ALICE_ROOT/PWGHF/vertexingHF/ConfigVertexingHF_Pb_AllCent_NoLS_PIDLc.C", Bool_t registerFile=kTRUE)
{

  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskVertexingHFFilter", "No analysis manager to connect to.");
    return NULL;
  }

  gROOT->LoadMacro("$ALICE_ROOT/PWGHF/vertexingHF/macros/AddTaskVertexingHF.C");
  //  TFile::Cp(gSystem->ExpandPathName(configPWG3d2h.Data()), Form("%s/ConfigVertexingHF.C", train_name.Data()));
  TFile::Cp(gSystem->ExpandPathName(configPWG3d2h.Data()), Form("ConfigVertexingHF.C"));
  AliAnalysisTaskSEVertexingHF *taskvertexingHF = AddTaskVertexingHF();
  // Now we need to keep in sync with the ESD filter
  if (!taskvertexingHF) ::Warning("AddTaskVertexingHFFilter", "AliAnalysisTaskSEVertexingHF cannot run for this train conditions - EXCLUDED");

  if(registerFile) mgr->RegisterExtraFile("AliAOD.VertexingHF.root");
  taskvertexingHF->SelectCollisionCandidates(0);

  mgr->AddTask(taskvertexingHF);

  return taskvertexingHF;
}
<|endoftext|>


<commit_before>#include <opencv/highgui.h>
#include <opencv/cv.h>
#include <iostream>
#include <stdlib.h>

#define WINDOW_NAME "WebCam Feed"
int const FPS = 50;

int main(){
	cv::VideoCapture cap(0);
	if(!cap.isOpened()){
		std::cerr << "could not initialize video capture." << std::endl;
		return EXIT_FAILURE;
	}
	cv::namedWindow(WINDOW_NAME, CV_WINDOW_AUTOSIZE);

	while(true){ // capture loop
		cv::Mat frame;
		if(!cap.read(frame)){
			std::cerr << "error reading frame from cam feed" << std::endl;
			return EXIT_FAILURE;
		}
		cv::imshow(WINDOW_NAME, frame);

		switch(cv::waitKey(1000 / FPS)){ //read key event
			case 27: //ESC
				return EXIT_SUCCESS;
				break;
			default:
				//do nothing
				break;
		}
	}

	return EXIT_SUCCESS;
}
<commit_msg>write video to file<commit_after>#include <opencv/highgui.h>
#include <opencv/cv.h>
#include <iostream>
#include <stdlib.h>

#define WINDOW_NAME "WebCam Feed"
#define FILE_NAME "test.avi"
int const FOURCC = CV_FOURCC('D','I','V','3');
int const FPS = 25;

int main(){
	std::cout << "SPACEBAR: Toggle recording" << std::endl;
	std::cout << "ESC: Quit programm" << std::endl;

	cv::VideoCapture cap(0);
	if(!cap.isOpened()){
		std::cerr << "could not initialize video capture." << std::endl;
		return EXIT_FAILURE;
	}
	cv::Size const FRAME_SIZE(cap.get(CV_CAP_PROP_FRAME_WIDTH), cap.get(CV_CAP_PROP_FRAME_HEIGHT));

	cv::VideoWriter writer(FILE_NAME, FOURCC, FPS, FRAME_SIZE);
	if(!writer.isOpened()){
		std::cerr << "error opening videowriter" << std::endl;
		return EXIT_FAILURE;
	}

	cv::namedWindow(WINDOW_NAME, CV_WINDOW_AUTOSIZE);
	cv::Mat frame;
	bool recording = true;
	while(true){ // capture loop
		if(!cap.read(frame)){
			std::cerr << "error reading frame from cam feed" << std::endl;
			return EXIT_FAILURE;
		}
		if(recording){
			writer.write(frame);
			cv::putText(frame, "[REC]", cv::Point(0, 20), 1, 1, cv::Scalar(0,0,255));
		}
		cv::imshow(WINDOW_NAME, frame);

		switch(cv::waitKey(1000 / FPS)){ //read key event
			case 27: //ESC
				return EXIT_SUCCESS;
				break;
			case 32: // SPACEBAR
				recording = !recording;
				break;
			default:
				//do nothing
				break;
		}
	}

	return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "mergeduniverselogger.h"

#include <QDateTime>

MergedUniverseLogger::MergedUniverseLogger() :
    QObject(nullptr),
    m_file(nullptr)
{
    //reserve a bit more than max length for sACNView1 format - see levelsChanged()
    m_stringBuffer.reserve(3000);
}

MergedUniverseLogger::~MergedUniverseLogger()
{
    //listener memory is dealt with externally
    closeFile();
}

void MergedUniverseLogger::start(QString fileName, QSharedPointer<sACNListener>listener)
{
    m_elapsedTimer.start();
    setUpFile(fileName);
    m_listener = listener;
    connect(m_listener.data(), &sACNListener::levelsChanged,
            this, &MergedUniverseLogger::levelsChanged);
}

void MergedUniverseLogger::stop()
{
    disconnect(m_listener.data(), 0, this, 0);
    closeFile();
}

void MergedUniverseLogger::levelsChanged()
{
    //Must have valid stream and listener set up via start()
    //Also possible that this is getting called as we're wrapping up in stop()
    if(!m_stream || !m_listener) {
        return;
    }

    //Following sACNView1 format
    //MM/DD/YYYY HH:mm:SS AP,0.0000,[0,]x512

    //log levels to file
    auto levels = m_listener->mergedLevels();
    m_stringBuffer.clear();
    m_stringBuffer.append(QDateTime::currentDateTime().toString("M/d/yyyy h:mm:ss AP,"));
    m_stringBuffer.append(QString::number((double)m_elapsedTimer.elapsed()/1000, 'f', 4));
    for(auto level : levels) {
        m_stringBuffer.append(',');
        m_stringBuffer.append(QString::number(level.level));
    }
    m_stringBuffer.append('\n');
    *m_stream << m_stringBuffer;
}

void MergedUniverseLogger::setUpFile(QString fileName)
{
    Q_ASSERT(m_file == nullptr);

    m_file = new QFile(fileName);
    m_file->open(QIODevice::WriteOnly | QIODevice::Truncate);
    m_stream = new QTextStream(m_file);
}

void MergedUniverseLogger::closeFile()
{
    //finish out
    m_stream->flush();

    if(m_file->isOpen()) {
        m_file->close();
    }
    delete m_stream;
    m_file->deleteLater();

    m_stream = nullptr;
    m_file = nullptr;
}
<commit_msg>Fix crash when pressing Stop after starting log to file<commit_after>#include "mergeduniverselogger.h"

#include <QDateTime>

MergedUniverseLogger::MergedUniverseLogger() :
    QObject(nullptr),
    m_file(nullptr)
{
    //reserve a bit more than max length for sACNView1 format - see levelsChanged()
    m_stringBuffer.reserve(3000);
}

MergedUniverseLogger::~MergedUniverseLogger()
{
    //listener memory is dealt with externally
    closeFile();
}

void MergedUniverseLogger::start(QString fileName, QSharedPointer<sACNListener>listener)
{
    m_elapsedTimer.start();
    setUpFile(fileName);
    m_listener = listener;
    connect(m_listener.data(), &sACNListener::levelsChanged,
            this, &MergedUniverseLogger::levelsChanged);
}

void MergedUniverseLogger::stop()
{
    disconnect(m_listener.data(), 0, this, 0);
    closeFile();
}

void MergedUniverseLogger::levelsChanged()
{
    //Must have valid stream and listener set up via start()
    //Also possible that this is getting called as we're wrapping up in stop()
    if(!m_stream || !m_listener) {
        return;
    }

    //Following sACNView1 format
    //MM/DD/YYYY HH:mm:SS AP,0.0000,[0,]x512

    //log levels to file
    auto levels = m_listener->mergedLevels();
    m_stringBuffer.clear();
    m_stringBuffer.append(QDateTime::currentDateTime().toString("M/d/yyyy h:mm:ss AP,"));
    m_stringBuffer.append(QString::number((double)m_elapsedTimer.elapsed()/1000, 'f', 4));
    for(auto level : levels) {
        m_stringBuffer.append(',');
        m_stringBuffer.append(QString::number(level.level));
    }
    m_stringBuffer.append('\n');
    *m_stream << m_stringBuffer;
}

void MergedUniverseLogger::setUpFile(QString fileName)
{
    Q_ASSERT(m_file == nullptr);

    m_file = new QFile(fileName);
    m_file->open(QIODevice::WriteOnly | QIODevice::Truncate);
    m_stream = new QTextStream(m_file);
}

void MergedUniverseLogger::closeFile()
{
    if(!m_file) {
        //already finished - bail out
        Q_ASSERT(m_stream == nullptr);
        return;
    }
    //finish out
    m_stream->flush();

    if(m_file->isOpen()) {
        m_file->close();
    }
    delete m_stream;
    m_file->deleteLater();

    m_stream = nullptr;
    m_file = nullptr;
}
<|endoftext|>


<commit_before>// __BEGIN_LICENSE__
//  Copyright (c) 2009-2013, United States Government as represented by the
//  Administrator of the National Aeronautics and Space Administration. All
//  rights reserved.
//
//  The NGT platform is licensed under the Apache License, Version 2.0 (the
//  "License"); you may not use this file except in compliance with the
//  License. You may obtain a copy of the License at
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// __END_LICENSE__

#include <vw/Cartography/PointImageManipulation.h>
#include <vw/Cartography/GeoTransform.h>
#include <vw/Cartography/MapTransform.h>
#include <vw/Image/MaskViews.h>
#include <vw/Camera/CameraModel.h>

namespace vw { namespace cartography {

  MapTransform::MapTransform( vw::camera::CameraModel const* cam,
                              GeoReference const& image_georef,
                              GeoReference const& dem_georef,
                              boost::shared_ptr<DiskImageResource> dem_rsrc ) :
    m_cam(cam), m_image_georef(image_georef), m_dem_georef(dem_georef),
    m_dem(dem_rsrc) {

    if ( dem_rsrc->has_nodata_read() )
      m_point_cloud =
        geo_transform(
                      geodetic_to_cartesian(
                                            dem_to_geodetic( create_mask( m_dem, dem_rsrc->nodata_read()),
                                                             m_dem_georef ), m_dem_georef.datum() ),
                      m_dem_georef, m_image_georef,
                      ValueEdgeExtension<Vector3>( Vector3() ),
                      BicubicInterpolation());
    else
      m_point_cloud =
        geo_transform(
                      geodetic_to_cartesian(
                                            dem_to_geodetic( m_dem, m_dem_georef ),
                                            m_dem_georef.datum() ),
                      m_dem_georef, m_image_georef,
                      ValueEdgeExtension<Vector3>( Vector3() ),
                      BicubicInterpolation());
  }

  vw::Vector2
  MapTransform::reverse(const vw::Vector2 &p) const {

    double NaN = std::numeric_limits<double>::quiet_NaN();

    // If possible, we will interpolate into the cached point cloud
    ImageViewRef<Vector3> interp_point_cloud =
      interpolate(m_point_cloud_cache, BicubicInterpolation(),
                  ZeroEdgeExtension());

    // Avoid interpolating close to edges
    BBox2i shrank_bbox = m_cache_size;
    shrank_bbox.contract(BicubicInterpolation::pixel_buffer);

    Vector3 xyz =
      shrank_bbox.contains( p ) ?
      interp_point_cloud(p.x() - m_cache_size.min().x(),
                         p.y() - m_cache_size.min().y()):
      m_point_cloud(p.x(),p.y());

    // The case when xyz does not have data
    if (xyz == Vector3())
      return vw::Vector2(NaN, NaN);

    try{
      return m_cam->point_to_pixel(xyz);
    }catch(...){}
    return vw::Vector2(NaN, NaN);

  }

  // This function will be called whenever we start to apply the
  // transform in a tile. It computes and caches the point cloud at
  // each pixel in the tile, to be used later when we iterate over
  // pixels.
  vw::BBox2i
  MapTransform::reverse_bbox( vw::BBox2i const& bbox ) const {
    cache_dem( bbox );
    vw::BBox2i out_box = vw::TransformBase<MapTransform>::reverse_bbox( bbox );
    if (out_box.empty()) return vw::BBox2i(0, 0, 1, 1);
    return out_box;
  }

  void
  MapTransform::cache_dem( vw::BBox2i const& bbox ) const {
    m_cache_size = bbox;

    // For bicubic interpolation later
    m_cache_size.expand(BicubicInterpolation::pixel_buffer);

    m_point_cloud_cache = crop( m_point_cloud, m_cache_size );
  }

  // Duplicate code we use for map_project.
  MapTransform2::MapTransform2( vw::camera::CameraModel const* cam,
                              GeoReference const& image_georef,
                              GeoReference const& dem_georef,
                              boost::shared_ptr<DiskImageResource> dem_rsrc,
                              vw::Vector2i image_size) :
    m_cam(cam), m_image_georef(image_georef), m_dem_georef(dem_georef),
    m_dem_rsrc(dem_rsrc), m_dem(dem_rsrc), m_image_size(image_size),
    m_has_nodata(false),
    m_nodata(std::numeric_limits<double>::quiet_NaN() ){
    m_has_nodata = dem_rsrc->has_nodata_read();
    if (m_has_nodata) m_nodata = dem_rsrc->nodata_read();

    if (m_image_size != Vector2(-1, -1))
      m_invalid_pix = Vector2(-1e6, -1e6); // for mapproject
    else
      m_invalid_pix = Vector2(-1, -1);     // for stereo
  }

  vw::Vector2
  MapTransform2::reverse(const vw::Vector2 &p) const {

    if (m_img_cache_box.contains(p)){
      PixelMask<Vector2> v = m_cache_interp_mask(p.x() - m_img_cache_box.min().x(),
                                                 p.y() - m_img_cache_box.min().y());
      if (is_valid(v)) return v.child();
      else             return m_invalid_pix;
    }

    int b = BicubicInterpolation::pixel_buffer;
    Vector2 lonlat = m_image_georef.pixel_to_lonlat(p);
    Vector2 dem_pix = m_dem_georef.lonlat_to_pixel(lonlat);
    if (dem_pix[0] < b - 1 || dem_pix[0] >= m_dem.cols() - b ||
        dem_pix[1] < b - 1 || dem_pix[1] >= m_dem.rows() - b
        ){
      // No DEM data
      return m_invalid_pix;
    }

    Vector2 sdem_pix = dem_pix - m_dem_cache_box.min(); // since we cropped the DEM
    if (m_dem_cache_box.empty() ||
        sdem_pix[0] < b - 1 || sdem_pix[0] >= m_cropped_dem.cols() - b ||
        sdem_pix[1] < b - 1 || sdem_pix[1] >= m_cropped_dem.rows() - b
        ){
      // Cache miss. Will not happen often.
      BBox2i box;
      box.min() = floor(p) - Vector2(1, 1);
      box.max() = ceil(p)  + Vector2(1, 1);
      cache_dem(box);
      return reverse(p);
    }

    PixelMask<float> h = m_interp_dem(sdem_pix[0], sdem_pix[1]);
    if (!is_valid(h))
      return m_invalid_pix;

    Vector3 xyz = m_dem_georef.datum().geodetic_to_cartesian
      (Vector3(lonlat[0], lonlat[1], h.child()));
    Vector2 pt;
    try{
      pt = m_cam->point_to_pixel(xyz);
      if ( (m_image_size != Vector2i(-1, -1)) &&
           (pt[0] < b - 1 || pt[0] >= m_image_size[0] - b ||
            pt[1] < b - 1 || pt[1] >= m_image_size[1] - b)
           ){
        // Won't be able to interpolate into image in transform(...)
        return m_invalid_pix;
      }
    }catch(...){ // If a point failed to project
      return m_invalid_pix;
    }

    return pt;
  }

  void MapTransform2::cache_dem(vw::BBox2i const& bbox) const{

    BBox2 dbox;
    dbox.grow( m_dem_georef.lonlat_to_pixel(m_image_georef.pixel_to_lonlat( Vector2(bbox.min().x(),bbox.min().y()) ) )); // Top left
    dbox.grow( m_dem_georef.lonlat_to_pixel(m_image_georef.pixel_to_lonlat( Vector2(bbox.max().x()-1,bbox.min().y()) ) )); // Top right
    dbox.grow( m_dem_georef.lonlat_to_pixel(m_image_georef.pixel_to_lonlat( Vector2(bbox.min().x(),bbox.max().y()-1) ) )); // Bottom left
    dbox.grow( m_dem_georef.lonlat_to_pixel(m_image_georef.pixel_to_lonlat( Vector2(bbox.max().x()-1,bbox.max().y()-1) ) )); // Bottom right

    // A lot of care is needed here when going from real box to int
    // box, and if in doubt, better expand more rather than less.
    dbox.expand(1);
    m_dem_cache_box = grow_bbox_to_int(dbox);
    m_dem_cache_box.expand(BicubicInterpolation::pixel_buffer); // for interp
    m_dem_cache_box.crop(bounding_box(m_dem));
    // Read the dem in memory for speed.
    m_cropped_dem = crop(m_dem, m_dem_cache_box);

    if (m_has_nodata){
      m_masked_dem = create_mask(m_cropped_dem, m_nodata);
    }else{
      m_masked_dem = pixel_cast< PixelMask<float> >(m_cropped_dem);
    }
    m_interp_dem =
      interpolate(m_masked_dem, BicubicInterpolation(), ZeroEdgeExtension());

  }

  // This function will be called whenever we start to apply the
  // transform in a tile. It computes and caches the point cloud at
  // each pixel in the tile, to be used later when we iterate over
  // pixels.
  vw::BBox2i
  MapTransform2::reverse_bbox( vw::BBox2i const& bbox ) const {

    // Custom reverse_bbox() function which can handle invalid pixels.
    if (!m_cached_rv_box.empty()) return m_cached_rv_box;

    cache_dem(bbox);

    // Cache the reverse transform

    m_img_cache_box = BBox2i();
    BBox2i local_cache_box = bbox;
    local_cache_box.expand(BicubicInterpolation::pixel_buffer); // for interpolation
    m_cache.set_size(local_cache_box.width(), local_cache_box.height());
    vw::BBox2 out_box;
    for( int32 y=local_cache_box.min().y(); y<local_cache_box.max().y(); ++y ){
      for( int32 x=local_cache_box.min().x(); x<local_cache_box.max().x(); ++x ){
        Vector2 p = reverse( Vector2(x,y) );
        m_cache(x - local_cache_box.min().x(), y - local_cache_box.min().y()) = p;
        if (p == m_invalid_pix) continue;
        if (bbox.contains(Vector2i(x, y))) out_box.grow( p );
      }
    }
    out_box = grow_bbox_to_int( out_box );

    // Must happen after all calls to reverse finished.
    m_img_cache_box = local_cache_box;

    m_cache_interp_mask = interpolate(create_mask(m_cache, m_invalid_pix),
                                      BicubicInterpolation(), ZeroEdgeExtension());

    // Need the check below as to not try to create images with
    // negative dimensions.
    if (out_box.empty())
      out_box = vw::BBox2i(0, 0, 0, 0);

    m_cached_rv_box = out_box;
    return m_cached_rv_box;
  }

}} // namespace vw::cartography
<commit_msg>MapTransform: Indent<commit_after>// __BEGIN_LICENSE__
//  Copyright (c) 2009-2013, United States Government as represented by the
//  Administrator of the National Aeronautics and Space Administration. All
//  rights reserved.
//
//  The NGT platform is licensed under the Apache License, Version 2.0 (the
//  "License"); you may not use this file except in compliance with the
//  License. You may obtain a copy of the License at
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// __END_LICENSE__

#include <vw/Cartography/PointImageManipulation.h>
#include <vw/Cartography/GeoTransform.h>
#include <vw/Cartography/MapTransform.h>
#include <vw/Image/MaskViews.h>
#include <vw/Camera/CameraModel.h>

namespace vw { namespace cartography {

  MapTransform::MapTransform( vw::camera::CameraModel const* cam,
                              GeoReference const& image_georef,
                              GeoReference const& dem_georef,
                              boost::shared_ptr<DiskImageResource> dem_rsrc ) :
    m_cam(cam), m_image_georef(image_georef), m_dem_georef(dem_georef),
    m_dem(dem_rsrc) {

    if ( dem_rsrc->has_nodata_read() )
      m_point_cloud =
        geo_transform
        (geodetic_to_cartesian
         (dem_to_geodetic( create_mask( m_dem, dem_rsrc->nodata_read()),
                           m_dem_georef ), m_dem_georef.datum() ),
         m_dem_georef, m_image_georef,
         ValueEdgeExtension<Vector3>( Vector3() ),
         BicubicInterpolation());
    else
      m_point_cloud =
        geo_transform
        (geodetic_to_cartesian
         (dem_to_geodetic( m_dem, m_dem_georef ),
          m_dem_georef.datum() ),
         m_dem_georef, m_image_georef,
         ValueEdgeExtension<Vector3>( Vector3() ),
         BicubicInterpolation());
  }

  vw::Vector2
  MapTransform::reverse(const vw::Vector2 &p) const {

    double NaN = std::numeric_limits<double>::quiet_NaN();

    // If possible, we will interpolate into the cached point cloud
    ImageViewRef<Vector3> interp_point_cloud =
      interpolate(m_point_cloud_cache, BicubicInterpolation(),
                  ZeroEdgeExtension());

    // Avoid interpolating close to edges
    BBox2i shrank_bbox = m_cache_size;
    shrank_bbox.contract(BicubicInterpolation::pixel_buffer);

    Vector3 xyz =
      shrank_bbox.contains( p ) ?
      interp_point_cloud(p.x() - m_cache_size.min().x(),
                         p.y() - m_cache_size.min().y()):
      m_point_cloud(p.x(),p.y());

    // The case when xyz does not have data
    if (xyz == Vector3())
      return vw::Vector2(NaN, NaN);

    try{
      return m_cam->point_to_pixel(xyz);
    }catch(...){}
    return vw::Vector2(NaN, NaN);

  }

  // This function will be called whenever we start to apply the
  // transform in a tile. It computes and caches the point cloud at
  // each pixel in the tile, to be used later when we iterate over
  // pixels.
  vw::BBox2i
  MapTransform::reverse_bbox( vw::BBox2i const& bbox ) const {
    cache_dem( bbox );
    vw::BBox2i out_box = vw::TransformBase<MapTransform>::reverse_bbox( bbox );
    if (out_box.empty()) return vw::BBox2i(0, 0, 1, 1);
    return out_box;
  }

  void
  MapTransform::cache_dem( vw::BBox2i const& bbox ) const {
    m_cache_size = bbox;

    // For bicubic interpolation later
    m_cache_size.expand(BicubicInterpolation::pixel_buffer);

    m_point_cloud_cache = crop( m_point_cloud, m_cache_size );
  }

  // Duplicate code we use for map_project.
  MapTransform2::MapTransform2( vw::camera::CameraModel const* cam,
                              GeoReference const& image_georef,
                              GeoReference const& dem_georef,
                              boost::shared_ptr<DiskImageResource> dem_rsrc,
                              vw::Vector2i image_size) :
    m_cam(cam), m_image_georef(image_georef), m_dem_georef(dem_georef),
    m_dem_rsrc(dem_rsrc), m_dem(dem_rsrc), m_image_size(image_size),
    m_has_nodata(false),
    m_nodata(std::numeric_limits<double>::quiet_NaN() ){
    m_has_nodata = dem_rsrc->has_nodata_read();
    if (m_has_nodata) m_nodata = dem_rsrc->nodata_read();

    if (m_image_size != Vector2(-1, -1))
      m_invalid_pix = Vector2(-1e6, -1e6); // for mapproject
    else
      m_invalid_pix = Vector2(-1, -1);     // for stereo
  }

  vw::Vector2
  MapTransform2::reverse(const vw::Vector2 &p) const {

    if (m_img_cache_box.contains(p)){
      PixelMask<Vector2> v = m_cache_interp_mask(p.x() - m_img_cache_box.min().x(),
                                                 p.y() - m_img_cache_box.min().y());
      if (is_valid(v)) return v.child();
      else             return m_invalid_pix;
    }

    int b = BicubicInterpolation::pixel_buffer;
    Vector2 lonlat = m_image_georef.pixel_to_lonlat(p);
    Vector2 dem_pix = m_dem_georef.lonlat_to_pixel(lonlat);
    if (dem_pix[0] < b - 1 || dem_pix[0] >= m_dem.cols() - b ||
        dem_pix[1] < b - 1 || dem_pix[1] >= m_dem.rows() - b
        ){
      // No DEM data
      return m_invalid_pix;
    }

    Vector2 sdem_pix = dem_pix - m_dem_cache_box.min(); // since we cropped the DEM
    if (m_dem_cache_box.empty() ||
        sdem_pix[0] < b - 1 || sdem_pix[0] >= m_cropped_dem.cols() - b ||
        sdem_pix[1] < b - 1 || sdem_pix[1] >= m_cropped_dem.rows() - b
        ){
      // Cache miss. Will not happen often.
      BBox2i box;
      box.min() = floor(p) - Vector2(1, 1);
      box.max() = ceil(p)  + Vector2(1, 1);
      cache_dem(box);
      return reverse(p);
    }

    PixelMask<float> h = m_interp_dem(sdem_pix[0], sdem_pix[1]);
    if (!is_valid(h))
      return m_invalid_pix;

    Vector3 xyz = m_dem_georef.datum().geodetic_to_cartesian
      (Vector3(lonlat[0], lonlat[1], h.child()));
    Vector2 pt;
    try{
      pt = m_cam->point_to_pixel(xyz);
      if ( (m_image_size != Vector2i(-1, -1)) &&
           (pt[0] < b - 1 || pt[0] >= m_image_size[0] - b ||
            pt[1] < b - 1 || pt[1] >= m_image_size[1] - b)
           ){
        // Won't be able to interpolate into image in transform(...)
        return m_invalid_pix;
      }
    }catch(...){ // If a point failed to project
      return m_invalid_pix;
    }

    return pt;
  }

  void MapTransform2::cache_dem(vw::BBox2i const& bbox) const{

    BBox2 dbox;
    dbox.grow( m_dem_georef.lonlat_to_pixel(m_image_georef.pixel_to_lonlat( Vector2(bbox.min().x(),bbox.min().y()) ) )); // Top left
    dbox.grow( m_dem_georef.lonlat_to_pixel(m_image_georef.pixel_to_lonlat( Vector2(bbox.max().x()-1,bbox.min().y()) ) )); // Top right
    dbox.grow( m_dem_georef.lonlat_to_pixel(m_image_georef.pixel_to_lonlat( Vector2(bbox.min().x(),bbox.max().y()-1) ) )); // Bottom left
    dbox.grow( m_dem_georef.lonlat_to_pixel(m_image_georef.pixel_to_lonlat( Vector2(bbox.max().x()-1,bbox.max().y()-1) ) )); // Bottom right

    // A lot of care is needed here when going from real box to int
    // box, and if in doubt, better expand more rather than less.
    dbox.expand(1);
    m_dem_cache_box = grow_bbox_to_int(dbox);
    m_dem_cache_box.expand(BicubicInterpolation::pixel_buffer); // for interp
    m_dem_cache_box.crop(bounding_box(m_dem));
    // Read the dem in memory for speed.
    m_cropped_dem = crop(m_dem, m_dem_cache_box);

    if (m_has_nodata){
      m_masked_dem = create_mask(m_cropped_dem, m_nodata);
    }else{
      m_masked_dem = pixel_cast< PixelMask<float> >(m_cropped_dem);
    }
    m_interp_dem =
      interpolate(m_masked_dem, BicubicInterpolation(), ZeroEdgeExtension());

  }

  // This function will be called whenever we start to apply the
  // transform in a tile. It computes and caches the point cloud at
  // each pixel in the tile, to be used later when we iterate over
  // pixels.
  vw::BBox2i
  MapTransform2::reverse_bbox( vw::BBox2i const& bbox ) const {

    // Custom reverse_bbox() function which can handle invalid pixels.
    if (!m_cached_rv_box.empty()) return m_cached_rv_box;

    cache_dem(bbox);

    // Cache the reverse transform

    m_img_cache_box = BBox2i();
    BBox2i local_cache_box = bbox;
    local_cache_box.expand(BicubicInterpolation::pixel_buffer); // for interpolation
    m_cache.set_size(local_cache_box.width(), local_cache_box.height());
    vw::BBox2 out_box;
    for( int32 y=local_cache_box.min().y(); y<local_cache_box.max().y(); ++y ){
      for( int32 x=local_cache_box.min().x(); x<local_cache_box.max().x(); ++x ){
        Vector2 p = reverse( Vector2(x,y) );
        m_cache(x - local_cache_box.min().x(), y - local_cache_box.min().y()) = p;
        if (p == m_invalid_pix) continue;
        if (bbox.contains(Vector2i(x, y))) out_box.grow( p );
      }
    }
    out_box = grow_bbox_to_int( out_box );

    // Must happen after all calls to reverse finished.
    m_img_cache_box = local_cache_box;

    m_cache_interp_mask = interpolate(create_mask(m_cache, m_invalid_pix),
                                      BicubicInterpolation(), ZeroEdgeExtension());

    // Need the check below as to not try to create images with
    // negative dimensions.
    if (out_box.empty())
      out_box = vw::BBox2i(0, 0, 0, 0);

    m_cached_rv_box = out_box;
    return m_cached_rv_box;
  }

}} // namespace vw::cartography
<|endoftext|>


<commit_before>#include "compress_keyword_encoding.h"
#include "bytebuffer.h"

#include <stdexcept>
#include <sstream>
#include <map>
#include <unordered_map>

std::string  initializeSymbols()
{
	std::string s;
	for(int i = 0; i < 127; ++i)
		s += i;

	return s;
}

static std::string symbols = initializeSymbols();

bool CompressKeywordEncoding::CompressImpl(const ByteBuffer& input, ByteBuffer& output)
{
	const char * inChars = (const char *)input.Data();

	size_t symIndex;
	char c;
	for(size_t i=0; i < input.Size(); ++i)
	{
		c = inChars[i];

		if((symIndex = symbols.find(c)) != std::string::npos)
			symbols.erase(symbols.begin() + symIndex);
	}

	std::map<std::string, unsigned int>::iterator it;
	std::map<std::string, unsigned int> stringFrequencies;

	std::istringstream in((char *)input.Data());
	std::string temp;
	while(in.good())
	{
		in >> temp;
		it = stringFrequencies.find(temp);

		if(it != stringFrequencies.end())
			++it->second;
		else
			stringFrequencies.insert(it, std::make_pair(temp, 1));
	}

	std::map<unsigned int, std::vector<std::string>> reverseStringFrequencies;
	std::map<unsigned int, std::vector<std::string>>::iterator it1;

	for (const auto& elem: stringFrequencies)
	{
		it1 = reverseStringFrequencies.find(elem.second);
		if (it1 != reverseStringFrequencies.end())
		{
			it1->second.push_back(elem.first);
		}
		else
		{
			it1 = reverseStringFrequencies.insert(it1, std::make_pair(elem.second, std::vector<std::string>()));
			it1->second.push_back(elem.first);
		}
	}

	std::unordered_map<std::string, char> encodedStrings;
	std::unordered_map<std::string, char>::iterator encodedStringsIt;

	it1 = reverseStringFrequencies.begin();
	for(std::string::iterator it_s = symbols.begin(); it_s != symbols.end() && it1 != reverseStringFrequencies.end(); ++it_s, ++it1)
		for(size_t i=0; i < it1->second.size(); ++i, ++it_s)
		{
			encodedStrings.insert(std::make_pair(it1->second[i], *it_s));
			if(it_s == symbols.end())
				break;
		}

		output.WriteDynInt(encodedStrings.size());
		for(encodedStringsIt = encodedStrings.begin(); encodedStringsIt != encodedStrings.end(); ++encodedStringsIt)
		{
			output.WriteUInt8(encodedStringsIt->second);
			output.WriteString(encodedStringsIt->first);
		}

		in = std::istringstream((char *)input.Data());
		std::ostringstream out;
		while(in.good())
		{
			in >> temp;
			if((encodedStringsIt = encodedStrings.find(temp)) != encodedStrings.end())
				output.WriteString(std::string(1,encodedStringsIt->second));
			else
				output.WriteString(temp);
		}

		return true;
}

bool CompressKeywordEncoding::DecompressImpl(const ByteBuffer& input, ByteBuffer& output)
{
	ByteBuffer* hack = const_cast<ByteBuffer*>(&input);

	std::unordered_map<char, std::string> encodedSymbols;
	std::unordered_map<char, std::string>::iterator encodedSymbolsIt;

	int numTableEntries;
	numTableEntries = hack->ReadDynInt();

	char symbol;
	std::string expression;
	for(; numTableEntries > 0; --numTableEntries)
	{
		symbol = (char)hack->ReadUInt8();
		expression = hack->ReadString();
		encodedSymbols.insert(std::make_pair(symbol, expression));
	}

	std::string temp;
	do
	{
		temp = hack->ReadString();

		if(temp.size() > 0 && (encodedSymbolsIt = encodedSymbols.find(temp.at(0))) != encodedSymbols.end())
			output.WriteString(encodedSymbolsIt->second);
		else
			output.WriteString(temp);
	} while(hack->CanRead());
	return true;
}
<commit_msg>Fix keyword encoding<commit_after>#include "compress_keyword_encoding.h"
#include "bytebuffer.h"

#include <stdexcept>
#include <sstream>
#include <map>
#include <unordered_map>

#include <iostream>

std::string  initializeSymbols()
{
	std::string s;
	for(int i = 0; i < 127; ++i)
		s += i;

	return s;
}

bool CompressKeywordEncoding::CompressImpl(const ByteBuffer& input, ByteBuffer& output)
{
    std::string symbols = initializeSymbols();

	const char * inChars = (const char *)input.Data();

	size_t symIndex;
	char c;
	for(size_t i=0; i < input.Size(); ++i)
	{
		c = inChars[i];

		if((symIndex = symbols.find(c)) != std::string::npos)
			symbols.erase(symbols.begin() + symIndex);
	}

	std::map<std::string, unsigned int>::iterator it;
	std::map<std::string, unsigned int> stringFrequencies;

	std::istringstream in((char *)input.Data());
	std::string temp;
	while(in.good())
	{
		in >> temp;
		it = stringFrequencies.find(temp);

		if(it != stringFrequencies.end())
			++it->second;
		else
			stringFrequencies.insert(it, std::make_pair(temp, 1));
	}

	std::map<unsigned int, std::vector<std::string>> reverseStringFrequencies;
	std::map<unsigned int, std::vector<std::string>>::iterator it1;

	for (const auto& elem: stringFrequencies)
	{
		it1 = reverseStringFrequencies.find(elem.second);
		if (it1 != reverseStringFrequencies.end())
		{
			it1->second.push_back(elem.first);
		}
		else
		{
			it1 = reverseStringFrequencies.insert(it1, std::make_pair(elem.second, std::vector<std::string>()));
			it1->second.push_back(elem.first);
		}
	}

	std::unordered_map<std::string, char> encodedStrings;
	std::unordered_map<std::string, char>::iterator encodedStringsIt;

	std::map<unsigned int, std::vector<std::string>>::reverse_iterator it2 = reverseStringFrequencies.rbegin();
    for (size_t i = 0; i < symbols.size() && it2 != reverseStringFrequencies.rend(); ++i, ++it2)
    {
        for (size_t j = 0; j < it2->second.size(); ++j, ++i)
        {
            if (i < symbols.size())
                encodedStrings.insert(std::make_pair(it2->second[j], symbols[i]));
        }
    }

    output.WriteDynInt(encodedStrings.size());
    for(encodedStringsIt = encodedStrings.begin(); encodedStringsIt != encodedStrings.end(); ++encodedStringsIt)
    {
    	output.WriteUInt8(encodedStringsIt->second);
    	output.WriteString(encodedStringsIt->first);
    }

    in = std::istringstream((char *)input.Data());

    std::string str = in.str();

    std::ostringstream out;
    //int end = input.Data()[input.Size() - 1];

    while (in.good())
    {
        std::streamoff prev = in.tellg();
    	in >> temp;
        std::streamoff after = in.tellg();

    	if ((encodedStringsIt = encodedStrings.find(temp)) != encodedStrings.end())
    		output.WriteString(std::string(1,encodedStringsIt->second));
    	else
    		output.WriteString(temp);

        if (after != -1)
            output.WriteDynInt(after - prev - temp.size());
        else
            output.WriteDynInt(input.Size() - prev - temp.size() - 1);
    }

    return true;
}

bool CompressKeywordEncoding::DecompressImpl(const ByteBuffer& input, ByteBuffer& output)
{
	ByteBuffer* hack = const_cast<ByteBuffer*>(&input);

	std::unordered_map<char, std::string> encodedSymbols;
	std::unordered_map<char, std::string>::iterator encodedSymbolsIt;

	size_t numTableEntries = hack->ReadDynInt();
	for(; numTableEntries > 0; --numTableEntries)
		encodedSymbols.insert(std::make_pair((char)hack->ReadUInt8(), hack->ReadString()));

    std::stringstream str;

	std::string temp;
	while (hack->CanRead())
	{
        temp = hack->ReadString();
        size_t spaceCount = hack->ReadDynInt();

        for (size_t i = 0; i < spaceCount; ++i)
            str << ' ';

		if (temp.size() > 0 && (encodedSymbolsIt = encodedSymbols.find(temp.at(0))) != encodedSymbols.end())
			str << encodedSymbolsIt->second;
		else
			str << temp;
	};

    std::string r = str.str();
    output.WriteBuffer(r.c_str(), r.size());

	return true;
}
<|endoftext|>


<commit_before>// Copyright 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0

/* This larger example shows how to use the MPIDistributedDevice to write an
 * interactive rendering application, which shows a UI on rank 0 and uses
 * all ranks in the MPI world for data loading and rendering. Each rank
 * generates a local sub-piece of spheres data, e.g., as if rendering some
 * large distributed dataset.
 */

#include <imgui.h>
#include <mpi.h>
#include <array>
#include <iterator>
#include <memory>
#include <random>
#include "GLFWDistribOSPRayWindow.h"
#include "ospray/ospray_cpp.h"
#include "ospray/ospray_cpp/ext/rkcommon.h"

using namespace ospray;
using namespace rkcommon;
using namespace rkcommon::math;

// Generate the rank's local spheres within its assigned grid cell, and
// return the bounds of this grid cell
cpp::Instance makeLocalSpheres(
    const int mpiRank, const int mpiWorldSize, box3f &bounds);

int main(int argc, char **argv)
{
  int mpiThreadCapability = 0;
  MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &mpiThreadCapability);
  if (mpiThreadCapability != MPI_THREAD_MULTIPLE
      && mpiThreadCapability != MPI_THREAD_SERIALIZED) {
    fprintf(stderr,
        "OSPRay requires the MPI runtime to support thread "
        "multiple or thread serialized.\n");
    return 1;
  }

  int mpiRank = 0;
  int mpiWorldSize = 0;
  MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
  MPI_Comm_size(MPI_COMM_WORLD, &mpiWorldSize);

  std::cout << "OSPRay rank " << mpiRank << "/" << mpiWorldSize << "\n";

  // load the MPI module, and select the MPI distributed device. Here we
  // do not call ospInit, as we want to explicitly pick the distributed
  // device. This can also be done by passing --osp:mpi-distributed when
  // using ospInit, however if the user doesn't pass this argument your
  // application will likely not behave as expected
  ospLoadModule("mpi");

  {
    cpp::Device mpiDevice("mpiDistributed");
    mpiDevice.commit();
    mpiDevice.setCurrent();

    // set an error callback to catch any OSPRay errors and exit the application
    ospDeviceSetErrorCallback(
        mpiDevice.handle(),
        [](void *, OSPError error, const char *errorDetails) {
          std::cerr << "OSPRay error: " << errorDetails << std::endl;
          exit(error);
        },
        nullptr);

    // all ranks specify the same rendering parameters, with the exception of
    // the data to be rendered, which is distributed among the ranks
    box3f regionBounds;
    cpp::Instance spheres =
        makeLocalSpheres(mpiRank, mpiWorldSize, regionBounds);

    // create the "world" model which will contain all of our geometries
    cpp::World world;
    world.setParam("instance", cpp::CopiedData(spheres));

    /*
     * Note: We've taken care that all the generated spheres are completely
     * within the bounds, and we don't have ghost data or portions of speres
     * to clip off. Thus we actually don't need to set region at all in
     * this tutorial. Example:
     * world.setParam("region", cpp::CopiedData(regionBounds));
     */

    world.commit();

    // create OSPRay renderer
    cpp::Renderer renderer("mpiRaycast");

    // create and setup an ambient light
    std::array<cpp::Light, 2> lights = {
        cpp::Light("ambient"), cpp::Light("distant")};
    lights[0].commit();

    lights[1].setParam("direction", vec3f(-1.f, -1.f, 0.5f));
    lights[1].commit();

    renderer.setParam("lights", cpp::CopiedData(lights));
    renderer.setParam("aoSamples", 1);

    // create a GLFW OSPRay window: this object will create and manage the
    // OSPRay frame buffer and camera directly
    auto glfwOSPRayWindow =
        std::unique_ptr<GLFWDistribOSPRayWindow>(new GLFWDistribOSPRayWindow(
            vec2i{1024, 768}, box3f(vec3f(-1.f), vec3f(1.f)), world, renderer));

    int spp = 1;
    int currentSpp = 1;
    if (mpiRank == 0) {
      glfwOSPRayWindow->registerImGuiCallback(
          [&]() { ImGui::SliderInt("pixelSamples", &spp, 1, 64); });
    }

    glfwOSPRayWindow->registerDisplayCallback(
        [&](GLFWDistribOSPRayWindow *win) {
          // Send the UI changes out to the other ranks so we can synchronize
          // how many samples per-pixel we're taking
          MPI_Bcast(&spp, 1, MPI_INT, 0, MPI_COMM_WORLD);
          if (spp != currentSpp) {
            currentSpp = spp;
            renderer.setParam("pixelSamples", spp);
            win->addObjectToCommit(renderer.handle());
          }
        });

    // start the GLFW main loop, which will continuously render
    glfwOSPRayWindow->mainLoop();
  }

  // cleanly shut OSPRay down
  ospShutdown();

  MPI_Finalize();

  return 0;
}

bool computeDivisor(int x, int &divisor)
{
  int upperBound = std::sqrt(x);
  for (int i = 2; i <= upperBound; ++i) {
    if (x % i == 0) {
      divisor = i;
      return true;
    }
  }
  return false;
}

// Compute an X x Y x Z grid to have 'num' grid cells,
// only gives a nice grid for numbers with even factors since
// we don't search for factors of the number, we just try dividing by two
vec3i computeGrid(int num)
{
  vec3i grid(1);
  int axis = 0;
  int divisor = 0;
  while (computeDivisor(num, divisor)) {
    grid[axis] *= divisor;
    num /= divisor;
    axis = (axis + 1) % 3;
  }
  if (num != 1) {
    grid[axis] *= num;
  }
  return grid;
}

cpp::Instance makeLocalSpheres(
    const int mpiRank, const int mpiWorldSize, box3f &bounds)
{
  const float sphereRadius = 0.1;
  std::vector<vec3f> spheres(50);

  // To simulate loading a shared dataset all ranks generate the same
  // sphere data.
  std::random_device rd;
  std::mt19937 rng(rd());

  const vec3i grid = computeGrid(mpiWorldSize);
  const vec3i brickId(mpiRank % grid.x,
      (mpiRank / grid.x) % grid.y,
      mpiRank / (grid.x * grid.y));

  // The grid is over the [-1, 1] box
  const vec3f brickSize = vec3f(2.0) / vec3f(grid);
  const vec3f brickLower = brickSize * brickId - vec3f(1.f);
  const vec3f brickUpper = brickSize * brickId - vec3f(1.f) + brickSize;

  bounds.lower = brickLower;
  bounds.upper = brickUpper;

  // Generate spheres within the box padded by the radius, so we don't need
  // to worry about ghost bounds
  std::uniform_real_distribution<float> distX(
      brickLower.x + sphereRadius, brickUpper.x - sphereRadius);
  std::uniform_real_distribution<float> distY(
      brickLower.y + sphereRadius, brickUpper.y - sphereRadius);
  std::uniform_real_distribution<float> distZ(
      brickLower.z + sphereRadius, brickUpper.z - sphereRadius);

  for (auto &s : spheres) {
    s.x = distX(rng);
    s.y = distY(rng);
    s.z = distZ(rng);
  }

  cpp::Geometry sphereGeom("sphere");
  sphereGeom.setParam("radius", sphereRadius);
  sphereGeom.setParam("sphere.position", cpp::CopiedData(spheres));
  sphereGeom.commit();

  vec3f color(0.f, 0.f, (mpiRank + 1.f) / mpiWorldSize);
  cpp::Material material(nullptr, "obj");
  material.setParam("kd", color);
  material.commit();

  cpp::GeometricModel model(sphereGeom);
  model.setParam("material", material);
  model.commit();

  cpp::Group group;
  group.setParam("geometry", cpp::CopiedData(model));
  group.commit();

  cpp::Instance instance(group);
  instance.commit();

  return instance;
}
<commit_msg>Fix parameter to C++ Material wrapper, must be empty str not null<commit_after>// Copyright 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0

/* This larger example shows how to use the MPIDistributedDevice to write an
 * interactive rendering application, which shows a UI on rank 0 and uses
 * all ranks in the MPI world for data loading and rendering. Each rank
 * generates a local sub-piece of spheres data, e.g., as if rendering some
 * large distributed dataset.
 */

#include <imgui.h>
#include <mpi.h>
#include <array>
#include <iterator>
#include <memory>
#include <random>
#include "GLFWDistribOSPRayWindow.h"
#include "ospray/ospray_cpp.h"
#include "ospray/ospray_cpp/ext/rkcommon.h"

using namespace ospray;
using namespace rkcommon;
using namespace rkcommon::math;

// Generate the rank's local spheres within its assigned grid cell, and
// return the bounds of this grid cell
cpp::Instance makeLocalSpheres(
    const int mpiRank, const int mpiWorldSize, box3f &bounds);

int main(int argc, char **argv)
{
  int mpiThreadCapability = 0;
  MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &mpiThreadCapability);
  if (mpiThreadCapability != MPI_THREAD_MULTIPLE
      && mpiThreadCapability != MPI_THREAD_SERIALIZED) {
    fprintf(stderr,
        "OSPRay requires the MPI runtime to support thread "
        "multiple or thread serialized.\n");
    return 1;
  }

  int mpiRank = 0;
  int mpiWorldSize = 0;
  MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank);
  MPI_Comm_size(MPI_COMM_WORLD, &mpiWorldSize);

  std::cout << "OSPRay rank " << mpiRank << "/" << mpiWorldSize << "\n";

  // load the MPI module, and select the MPI distributed device. Here we
  // do not call ospInit, as we want to explicitly pick the distributed
  // device. This can also be done by passing --osp:mpi-distributed when
  // using ospInit, however if the user doesn't pass this argument your
  // application will likely not behave as expected
  ospLoadModule("mpi");

  {
    cpp::Device mpiDevice("mpiDistributed");
    mpiDevice.commit();
    mpiDevice.setCurrent();

    // set an error callback to catch any OSPRay errors and exit the application
    ospDeviceSetErrorCallback(
        mpiDevice.handle(),
        [](void *, OSPError error, const char *errorDetails) {
          std::cerr << "OSPRay error: " << errorDetails << std::endl;
          exit(error);
        },
        nullptr);

    // all ranks specify the same rendering parameters, with the exception of
    // the data to be rendered, which is distributed among the ranks
    box3f regionBounds;
    cpp::Instance spheres =
        makeLocalSpheres(mpiRank, mpiWorldSize, regionBounds);

    // create the "world" model which will contain all of our geometries
    cpp::World world;
    world.setParam("instance", cpp::CopiedData(spheres));

    /*
     * Note: We've taken care that all the generated spheres are completely
     * within the bounds, and we don't have ghost data or portions of speres
     * to clip off. Thus we actually don't need to set region at all in
     * this tutorial. Example:
     * world.setParam("region", cpp::CopiedData(regionBounds));
     */

    world.commit();

    // create OSPRay renderer
    cpp::Renderer renderer("mpiRaycast");

    // create and setup an ambient light
    std::array<cpp::Light, 2> lights = {
        cpp::Light("ambient"), cpp::Light("distant")};
    lights[0].commit();

    lights[1].setParam("direction", vec3f(-1.f, -1.f, 0.5f));
    lights[1].commit();

    renderer.setParam("lights", cpp::CopiedData(lights));
    renderer.setParam("aoSamples", 1);

    // create a GLFW OSPRay window: this object will create and manage the
    // OSPRay frame buffer and camera directly
    auto glfwOSPRayWindow =
        std::unique_ptr<GLFWDistribOSPRayWindow>(new GLFWDistribOSPRayWindow(
            vec2i{1024, 768}, box3f(vec3f(-1.f), vec3f(1.f)), world, renderer));

    int spp = 1;
    int currentSpp = 1;
    if (mpiRank == 0) {
      glfwOSPRayWindow->registerImGuiCallback(
          [&]() { ImGui::SliderInt("pixelSamples", &spp, 1, 64); });
    }

    glfwOSPRayWindow->registerDisplayCallback(
        [&](GLFWDistribOSPRayWindow *win) {
          // Send the UI changes out to the other ranks so we can synchronize
          // how many samples per-pixel we're taking
          MPI_Bcast(&spp, 1, MPI_INT, 0, MPI_COMM_WORLD);
          if (spp != currentSpp) {
            currentSpp = spp;
            renderer.setParam("pixelSamples", spp);
            win->addObjectToCommit(renderer.handle());
          }
        });

    // start the GLFW main loop, which will continuously render
    glfwOSPRayWindow->mainLoop();
  }

  // cleanly shut OSPRay down
  ospShutdown();

  MPI_Finalize();

  return 0;
}

bool computeDivisor(int x, int &divisor)
{
  int upperBound = std::sqrt(x);
  for (int i = 2; i <= upperBound; ++i) {
    if (x % i == 0) {
      divisor = i;
      return true;
    }
  }
  return false;
}

// Compute an X x Y x Z grid to have 'num' grid cells,
// only gives a nice grid for numbers with even factors since
// we don't search for factors of the number, we just try dividing by two
vec3i computeGrid(int num)
{
  vec3i grid(1);
  int axis = 0;
  int divisor = 0;
  while (computeDivisor(num, divisor)) {
    grid[axis] *= divisor;
    num /= divisor;
    axis = (axis + 1) % 3;
  }
  if (num != 1) {
    grid[axis] *= num;
  }
  return grid;
}

cpp::Instance makeLocalSpheres(
    const int mpiRank, const int mpiWorldSize, box3f &bounds)
{
  const float sphereRadius = 0.1;
  std::vector<vec3f> spheres(50);

  // To simulate loading a shared dataset all ranks generate the same
  // sphere data.
  std::random_device rd;
  std::mt19937 rng(rd());

  const vec3i grid = computeGrid(mpiWorldSize);
  const vec3i brickId(mpiRank % grid.x,
      (mpiRank / grid.x) % grid.y,
      mpiRank / (grid.x * grid.y));

  // The grid is over the [-1, 1] box
  const vec3f brickSize = vec3f(2.0) / vec3f(grid);
  const vec3f brickLower = brickSize * brickId - vec3f(1.f);
  const vec3f brickUpper = brickSize * brickId - vec3f(1.f) + brickSize;

  bounds.lower = brickLower;
  bounds.upper = brickUpper;

  // Generate spheres within the box padded by the radius, so we don't need
  // to worry about ghost bounds
  std::uniform_real_distribution<float> distX(
      brickLower.x + sphereRadius, brickUpper.x - sphereRadius);
  std::uniform_real_distribution<float> distY(
      brickLower.y + sphereRadius, brickUpper.y - sphereRadius);
  std::uniform_real_distribution<float> distZ(
      brickLower.z + sphereRadius, brickUpper.z - sphereRadius);

  for (auto &s : spheres) {
    s.x = distX(rng);
    s.y = distY(rng);
    s.z = distZ(rng);
  }

  cpp::Geometry sphereGeom("sphere");
  sphereGeom.setParam("radius", sphereRadius);
  sphereGeom.setParam("sphere.position", cpp::CopiedData(spheres));
  sphereGeom.commit();

  vec3f color(0.f, 0.f, (mpiRank + 1.f) / mpiWorldSize);
  cpp::Material material("", "obj");
  material.setParam("kd", color);
  material.commit();

  cpp::GeometricModel model(sphereGeom);
  model.setParam("material", material);
  model.commit();

  cpp::Group group;
  group.setParam("geometry", cpp::CopiedData(model));
  group.commit();

  cpp::Instance instance(group);
  instance.commit();

  return instance;
}
<|endoftext|>


<commit_before>AliAnalysisTaskElectronEfficiencyV2* AddTask_dsekihat_ElectronEfficiencyV2_PbPb(
    Bool_t getFromAlien = kFALSE,
    TString configFile="Config_dsekihat_ElectronEfficiencyV2_PbPb.C",
    TString libFile="LMEECutLib_dsekihat.C",
    UInt_t trigger = AliVEvent::kINT7,
    const Int_t CenMin =  0,
    const Int_t CenMax = 10,
    const TString pileupcut = "_woPU",//can be "_woPU", "_onlyPU",""
    const TString generators = "pizero_0;eta_1;etaprime_2;rho_3;omega_4;phi_5;jpsi_6;EvtGenDecay;Pythia CC_0;Pythia BB_0;Pythia B_0;",
    const TString calibFileName = "",
    const std::string resolutionFilename ="",
    const std::string cocktailFilename   ="",
    const std::string centralityFilename ="",
		const TString outname = "LMEE.root"
    ){

  // Configuring Analysis Manager
  AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
	if (!mgr) {
		Error("AddTask_dsekihat_ElectronEfficiencyV2_PbPb", "No analysis manager found.");
		return 0;
	}

  //TString configBasePath("$ALICE_PHYSICS/PWGDQ/dielectron/macrosLMEE/");
	TString configBasePath("./");
  if (!gSystem->AccessPathName(configFile) && !gSystem->AccessPathName(libFile) ) {
    printf("Configfile already present\n");
    configBasePath=Form("%s/",gSystem->pwd());
  }
	else if(getFromAlien
			&& (!gSystem->Exec(Form("alien_cp alien:///alice/cern.ch/user/d/dsekihat/PWGDQ/dielectron/macrosLMEE/%s .",configFile.Data())))
			&& (!gSystem->Exec(Form("alien_cp alien:///alice/cern.ch/user/d/dsekihat/PWGDQ/dielectron/macrosLMEE/%s .",libFile.Data())))
		){
		configBasePath=Form("%s/",gSystem->pwd());
	}

	TString configFilePath(configBasePath + configFile);
  TString libFilePath(configBasePath + libFile);
  std::cout << "Configpath:  " << configFilePath << std::endl;
  std::cout << "Libpath:  " << libFilePath << std::endl;

  gROOT->LoadMacro(libFilePath.Data());//library first
  gROOT->LoadMacro(configFilePath.Data());

  //if (!gROOT->GetListOfClasses()->FindObject("LMEECutLib")) {
  //  printf("Load library now\n");
  //  gROOT->LoadMacro(libFilePath.Data());
  //  //gROOT->AddClass(LMEECutLib::Class());
  //}

  //if (!gROOT->GetListOfGlobalFunctions()->FindObject("Config_dsekihat_ElectronEfficiencyV2_PbPb")) {
  //  printf("Load macro now\n");
  //  gROOT->LoadMacro(configFilePath.Data());
  //}

	TString suffix = "";
	if(generators.Contains("Pythia CC") && (generators.Contains("Pythia BB") || generators.Contains("Pythia B"))) suffix = "_CC_BB";
	else if(generators.Contains("Pythia CC")) suffix = "_CC";
	else if(generators.Contains("Pythia BB") || generators.Contains("Pythia B")) suffix = "_BB";
	else if(generators.Contains("pizero")) suffix = "_LF";
	else suffix = "";

  // Creating an instance of the task
  AliAnalysisTaskElectronEfficiencyV2* task = new AliAnalysisTaskElectronEfficiencyV2(Form("TaskElectronEfficiencyV2%s_Cen%d_%d_kINT7%s",suffix.Data(),CenMin,CenMax,pileupcut.Data()));
  gROOT->GetListOfSpecials()->Add(task);//this is only for ProcessLine(AddMCSignal);

	const Int_t nEC = Int_t(gROOT->ProcessLine("GetNEC()") );//event cuts
	const Int_t nTC = Int_t(gROOT->ProcessLine("GetNTC()") );//track cuts
	const Int_t nPC = Int_t(gROOT->ProcessLine("GetNPID()"));//pid cuts

  for (Int_t iec=0; iec<nEC; ++iec){
    for (Int_t itc=0; itc<nTC; ++itc){
      for (Int_t ipc=0; ipc<nPC; ++ipc){
				AliAnalysisFilter *filter = reinterpret_cast<AliAnalysisFilter*>(gROOT->ProcessLine(Form("Config_dsekihat_ElectronEfficiencyV2_PbPb(%d,%d,%d)",iec,itc,ipc)));
				task->AddTrackCuts(filter);
			}
		}
	}

  //It is important to apply pileup cuts at "task" level in M.C. for efficiency. (i.e. Both denominator and nominator has to be taken into account in exactly the same events.)

  // Event selection. Is the same for all the different cutsettings
  task->SetEnablePhysicsSelection(kTRUE);//always ON in Run2 analyses for both data and MC.
  task->SetTriggerMask(trigger);
  task->SetEventFilter(reinterpret_cast<AliDielectronEventCuts*>(gROOT->ProcessLine(Form("LMEECutLib::SetupEventCuts(%f,%f,%d,\"%s\")",(Float_t)CenMin,(Float_t)CenMax,kTRUE,"V0M"))));//kTRUE is for Run2

  //if(pileupcut == ""){
  //  printf("analyze all events in M.C.\n");
  //}
  //else if(pileupcut.Contains("woPU")){
  //  printf("analyze only in clean events in M.C.\n");
  //  TF1 *f1pu = reinterpret_cast<TF1*>(gROOT->ProcessLine("LMEECutLib::SetupPileupCuts()"));
  //  dynamic_cast<AliDielectronEventCuts*>(task->GetEventFilter())->SetMinCorrCutFunction(f1pu, AliDielectronVarManager::kNTPCclsEvent, AliDielectronVarManager::kNSDDSSDclsEvent);
  //}
  //else if(pileupcut.Contains("onlyPU")){
  //  printf("analyze only in pileup events in M.C.\n");
  //  TF1 *f1pu = reinterpret_cast<TF1*>(gROOT->ProcessLine("LMEECutLib::SetupPileupCuts()"));
  //  dynamic_cast<AliDielectronEventCuts*>(task->GetEventFilter())->SetMaxCorrCutFunction(f1pu, AliDielectronVarManager::kNTPCclsEvent, AliDielectronVarManager::kNSDDSSDclsEvent);
  //}
  //else{
  //  printf("Nothing with pileup cut in M.C.\n");
  //  printf("analyze all events in M.C.\n");
  //}

  printf("analyze all events in M.C.\n");
  dynamic_cast<AliDielectronEventCuts*>(task->GetEventFilter())->Print();

  // Set minimum and maximum values of generated tracks. Only used to save computing power.
  // Do not set here your analysis pt-cuts
  task->SetMinPtGen(0.1);
  task->SetMaxPtGen(1e+10);
  task->SetMinEtaGen(-1.5);
  task->SetMaxEtaGen(+1.5);

  // Set minimum and maximum values for pairing
  task->SetKinematicCuts(0.2, 10, -0.8, +0.8);

  // Set Binning
  task->SetPtBinsLinear   (0, 10, 100);
  task->SetEtaBinsLinear  (-1, +1, 20);
  task->SetPhiBinsLinear  (0, TMath::TwoPi(), 36);
  task->SetThetaBinsLinear(0, TMath::TwoPi(), 60);

  const Int_t Nmee = 195;
  Double_t mee[Nmee] = {};
  for(Int_t i=0  ;i<110; i++) mee[i] = 0.01 * (i-  0) + 0.0;//from 0 to 1.1 GeV/c2, every 0.01 GeV/c2
  for(Int_t i=110;i<126; i++) mee[i] = 0.1  * (i-110) + 1.1;//from 1.1 to 2.7 GeV/c2, every 0.1 GeV/c2
  for(Int_t i=126;i<176; i++) mee[i] = 0.01 * (i-126) + 2.7;//from 2.7 to 3.2 GeV/c2, every 0.01 GeV/c2 for J/psi
  for(Int_t i=176;i<Nmee;i++) mee[i] = 0.1  * (i-176) + 3.2;//from 3.2 to 5 GeV/c2, every 0.1 GeV/c2
  std::vector<double> v_mee(mee,std::end(mee));

  const Int_t NpTee = 146;
  Double_t pTee[NpTee] = {};
  for(Int_t i=0  ;i<50    ;i++) pTee[i] = 0.01 * (i-  0) +  0.0;//from 0 to 0.49 GeV/c, every 0.01 GeV/c
  for(Int_t i=50 ;i<NpTee ;i++) pTee[i] = 0.1  * (i- 50) +  0.5;//from 0.5 to 10 GeV/c, evety 0.1 GeV/c
  std::vector<double> v_pTee(pTee,std::end(pTee));

  task->SetMassBins(v_mee);
  task->SetPairPtBins(v_pTee);
  task->SetPhiVBinsLinear(0, TMath::Pi(), 100);
  task->SetFillPhiV(kFALSE);

  task->SetSmearGenerated(kFALSE);
  task->SetResolutionDeltaPtBinsLinear( -10,  +10, 2000);
  task->SetResolutionRelPtBinsLinear  (   0,    2,  400);
  task->SetResolutionEtaBinsLinear    (-0.4, +0.4,  200);
  task->SetResolutionPhiBinsLinear    (-0.4, +0.4,  200);
  task->SetResolutionThetaBinsLinear  (-0.4, +0.4,  200);

  // Set MCSignal and Cutsetting to fill the support histograms
  task->SetSupportHistoMCSignalAndCutsetting(0,0);//fill support histograms for first MCsignal and first cutsetting

  // Pairing related config
  task->SetDoPairing(kTRUE);
  task->SetULSandLS(kTRUE);
  task->SetDeactivateLS(kFALSE);

  cout<<"Efficiency based on MC generators: " << generators <<endl;
  TString generatorsPair=generators;
  task->SetGeneratorMCSignalName(generatorsPair);
  task->SetGeneratorULSSignalName(generators);

  task->SetResolutionFile(resolutionFilename , "/alice/cern.ch/user/d/dsekihat/PWGDQ/dielectron/resolution/" + resolutionFilename);
  task->SetCentralityFile(centralityFilename , "/alice/cern.ch/user/d/dsekihat/PWGDQ/dielectron/centrality/" + centralityFilename);

  if(cocktailFilename != "") task->SetDoCocktailWeighting(kTRUE);
  task->SetCocktailWeighting(cocktailFilename, "/alice/cern.ch/user/d/dsekihat/PWGDQ/dielectron/cocktail/"   + cocktailFilename);

  // Add MCSignals. Can be set to see differences of:
  // e.g. secondaries and primaries. or primaries from charm and resonances
  gROOT->ProcessLine(Form("AddSingleLegMCSignal(%s)",task->GetName()));//not task itself, task name
  gROOT->ProcessLine(Form("AddPairMCSignal(%s)"     ,task->GetName()));//not task itself, task name

  //set PID map for ITS TOF in MC.
  TFile *rootfile = 0x0;
  if(calibFileName != "") rootfile = TFile::Open(calibFileName,"READ");
  if(rootfile && rootfile->IsOpen()){
    TH3D *h3mean_ITS  = (TH3D*)rootfile->Get("h3mean_ITS");
    TH3D *h3width_ITS = (TH3D*)rootfile->Get("h3width_ITS");
    h3mean_ITS ->SetDirectory(0);
    h3width_ITS->SetDirectory(0);
    task->SetCentroidCorrFunction(AliAnalysisTaskElectronEfficiencyV2::kITS, h3mean_ITS, AliDielectronVarManager::kNSDDSSDclsEvent, AliDielectronVarManager::kPIn,  AliDielectronVarManager::kEta);
    task->SetWidthCorrFunction(AliAnalysisTaskElectronEfficiencyV2::kITS, h3width_ITS, AliDielectronVarManager::kNSDDSSDclsEvent, AliDielectronVarManager::kPIn,  AliDielectronVarManager::kEta );

    TH3D *h3mean_TOF = (TH3D*)rootfile->Get("h3mean_TOF");
    TH3D *h3width_TOF = (TH3D*)rootfile->Get("h3width_TOF");
    h3mean_TOF ->SetDirectory(0);
    h3width_TOF->SetDirectory(0);
    task->SetCentroidCorrFunction(AliAnalysisTaskElectronEfficiencyV2::kTOF, h3mean_TOF, AliDielectronVarManager::kNSDDSSDclsEvent, AliDielectronVarManager::kPIn,  AliDielectronVarManager::kEta);
    task->SetWidthCorrFunction(AliAnalysisTaskElectronEfficiencyV2::kTOF, h3width_TOF, AliDielectronVarManager::kNSDDSSDclsEvent, AliDielectronVarManager::kPIn,  AliDielectronVarManager::kEta);

    rootfile->Close();
  }
	TString outlistname = Form("Efficiency_dsekihat%s_Cen%d_%d_kINT7%s",suffix.Data(),CenMin,CenMax,pileupcut.Data());

  //const TString fileName = AliAnalysisManager::GetCommonFileName();
  const TString fileName = outname;
	//const TString dirname = Form("PWGDQ_LMEE_ElectronEfficiencyV2_Cen%d_%d_kINT7",CenMin,CenMax);
  mgr->AddTask(task);
  mgr->ConnectInput(task,  0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(task, 1, mgr->CreateContainer(outlistname, TList::Class(), AliAnalysisManager::kOutputContainer, Form("%s",fileName.Data())));
  return task;
}

<commit_msg>PWGDQ/LMEE: update AddTask.C<commit_after>AliAnalysisTaskElectronEfficiencyV2* AddTask_dsekihat_ElectronEfficiencyV2_PbPb(
    Bool_t getFromAlien = kFALSE,
    TString configFile="Config_dsekihat_ElectronEfficiencyV2_PbPb.C",
    TString libFile="LMEECutLib_dsekihat.C",
    UInt_t trigger = AliVEvent::kINT7,
    const Int_t CenMin =  0,
    const Int_t CenMax = 10,
    const TString pileupcut = "_woPU",//can be "_woPU", "_onlyPU",""
    const TString generators = "pizero_0;eta_1;etaprime_2;rho_3;omega_4;phi_5;jpsi_6;EvtGenDecay;Pythia CC_0;Pythia BB_0;Pythia B_0;",
    const TString calibFileName = "",
    const std::string resolutionFilename ="",
    const std::string cocktailFilename   ="",
    const std::string centralityFilename ="",
		const TString outname = "LMEE.root"
    ){

  // Configuring Analysis Manager
  AliAnalysisManager* mgr = AliAnalysisManager::GetAnalysisManager();
	if (!mgr) {
		Error("AddTask_dsekihat_ElectronEfficiencyV2_PbPb", "No analysis manager found.");
		return 0;
	}

  //TString configBasePath("$ALICE_PHYSICS/PWGDQ/dielectron/macrosLMEE/");
	TString configBasePath("./");
  if (!gSystem->AccessPathName(configFile) && !gSystem->AccessPathName(libFile) ) {
    printf("Configfile already present\n");
    configBasePath=Form("%s/",gSystem->pwd());
  }
	else if(getFromAlien
			&& (!gSystem->Exec(Form("alien_cp alien:///alice/cern.ch/user/d/dsekihat/PWGDQ/dielectron/macrosLMEE/%s .",configFile.Data())))
			&& (!gSystem->Exec(Form("alien_cp alien:///alice/cern.ch/user/d/dsekihat/PWGDQ/dielectron/macrosLMEE/%s .",libFile.Data())))
		){
		configBasePath=Form("%s/",gSystem->pwd());
	}

	TString configFilePath(configBasePath + configFile);
  TString libFilePath(configBasePath + libFile);
  std::cout << "Configpath:  " << configFilePath << std::endl;
  std::cout << "Libpath:  " << libFilePath << std::endl;

  gROOT->LoadMacro(libFilePath.Data());//library first
  gROOT->LoadMacro(configFilePath.Data());

  //if (!gROOT->GetListOfClasses()->FindObject("LMEECutLib")) {
  //  printf("Load library now\n");
  //  gROOT->LoadMacro(libFilePath.Data());
  //  //gROOT->AddClass(LMEECutLib::Class());
  //}

  //if (!gROOT->GetListOfGlobalFunctions()->FindObject("Config_dsekihat_ElectronEfficiencyV2_PbPb")) {
  //  printf("Load macro now\n");
  //  gROOT->LoadMacro(configFilePath.Data());
  //}

	TString suffix = "";
	if(generators.Contains("Pythia CC") && (generators.Contains("Pythia BB") || generators.Contains("Pythia B"))) suffix = "_CC_BB";
	else if(generators.Contains("Pythia CC")) suffix = "_CC";
	else if(generators.Contains("Pythia BB") || generators.Contains("Pythia B")) suffix = "_BB";
	else if(generators.Contains("pizero")) suffix = "_LF";
	else suffix = "";

  // Creating an instance of the task
  AliAnalysisTaskElectronEfficiencyV2* task = new AliAnalysisTaskElectronEfficiencyV2(Form("TaskElectronEfficiencyV2%s_Cen%d_%d_kINT7%s",suffix.Data(),CenMin,CenMax,pileupcut.Data()));
  gROOT->GetListOfSpecials()->Add(task);//this is only for ProcessLine(AddMCSignal);

	const Int_t nEC = Int_t(gROOT->ProcessLine("GetNEC()") );//event cuts
	const Int_t nTC = Int_t(gROOT->ProcessLine("GetNTC()") );//track cuts
	const Int_t nPC = Int_t(gROOT->ProcessLine("GetNPID()"));//pid cuts

  for (Int_t iec=0; iec<nEC; ++iec){
    for (Int_t itc=0; itc<nTC; ++itc){
      for (Int_t ipc=0; ipc<nPC; ++ipc){
				AliAnalysisFilter *filter = reinterpret_cast<AliAnalysisFilter*>(gROOT->ProcessLine(Form("Config_dsekihat_ElectronEfficiencyV2_PbPb(%d,%d,%d)",iec,itc,ipc)));
				task->AddTrackCuts(filter);
			}
		}
	}

  //It is important to apply pileup cuts at "task" level in M.C. for efficiency. (i.e. Both denominator and nominator has to be taken into account in exactly the same events.)

  // Event selection. Is the same for all the different cutsettings
  task->SetEnablePhysicsSelection(kTRUE);//always ON in Run2 analyses for both data and MC.
  task->SetTriggerMask(trigger);
  task->SetEventFilter(reinterpret_cast<AliDielectronEventCuts*>(gROOT->ProcessLine(Form("LMEECutLib::SetupEventCuts(%f,%f,%d,\"%s\")",(Float_t)CenMin,(Float_t)CenMax,kTRUE,"V0M"))));//kTRUE is for Run2
  task->SetRejectParticleFromOOB(kTRUE);

  //if(pileupcut == ""){
  //  printf("analyze all events in M.C.\n");
  //}
  //else if(pileupcut.Contains("woPU")){
  //  printf("analyze only in clean events in M.C.\n");
  //  TF1 *f1pu = reinterpret_cast<TF1*>(gROOT->ProcessLine("LMEECutLib::SetupPileupCuts()"));
  //  dynamic_cast<AliDielectronEventCuts*>(task->GetEventFilter())->SetMinCorrCutFunction(f1pu, AliDielectronVarManager::kNTPCclsEvent, AliDielectronVarManager::kNSDDSSDclsEvent);
  //}
  //else if(pileupcut.Contains("onlyPU")){
  //  printf("analyze only in pileup events in M.C.\n");
  //  TF1 *f1pu = reinterpret_cast<TF1*>(gROOT->ProcessLine("LMEECutLib::SetupPileupCuts()"));
  //  dynamic_cast<AliDielectronEventCuts*>(task->GetEventFilter())->SetMaxCorrCutFunction(f1pu, AliDielectronVarManager::kNTPCclsEvent, AliDielectronVarManager::kNSDDSSDclsEvent);
  //}
  //else{
  //  printf("Nothing with pileup cut in M.C.\n");
  //  printf("analyze all events in M.C.\n");
  //}

  printf("analyze all events in M.C.\n");
  dynamic_cast<AliDielectronEventCuts*>(task->GetEventFilter())->Print();

  // Set minimum and maximum values of generated tracks. Only used to save computing power.
  // Do not set here your analysis pt-cuts
  task->SetMinPtGen(0.1);
  task->SetMaxPtGen(1e+10);
  task->SetMinEtaGen(-1.5);
  task->SetMaxEtaGen(+1.5);

  // Set minimum and maximum values for pairing
  task->SetKinematicCuts(0.2, 10, -0.8, +0.8);

  // Set Binning
  task->SetPtBinsLinear   (0, 10, 100);
  task->SetEtaBinsLinear  (-1, +1, 20);
  task->SetPhiBinsLinear  (0, TMath::TwoPi(), 36);
  task->SetThetaBinsLinear(0, TMath::TwoPi(), 60);

  const Int_t Nmee = 195;
  Double_t mee[Nmee] = {};
  for(Int_t i=0  ;i<110; i++) mee[i] = 0.01 * (i-  0) + 0.0;//from 0 to 1.1 GeV/c2, every 0.01 GeV/c2
  for(Int_t i=110;i<126; i++) mee[i] = 0.1  * (i-110) + 1.1;//from 1.1 to 2.7 GeV/c2, every 0.1 GeV/c2
  for(Int_t i=126;i<176; i++) mee[i] = 0.01 * (i-126) + 2.7;//from 2.7 to 3.2 GeV/c2, every 0.01 GeV/c2 for J/psi
  for(Int_t i=176;i<Nmee;i++) mee[i] = 0.1  * (i-176) + 3.2;//from 3.2 to 5 GeV/c2, every 0.1 GeV/c2
  std::vector<double> v_mee(mee,std::end(mee));

  const Int_t NpTee = 146;
  Double_t pTee[NpTee] = {};
  for(Int_t i=0  ;i<50    ;i++) pTee[i] = 0.01 * (i-  0) +  0.0;//from 0 to 0.49 GeV/c, every 0.01 GeV/c
  for(Int_t i=50 ;i<NpTee ;i++) pTee[i] = 0.1  * (i- 50) +  0.5;//from 0.5 to 10 GeV/c, evety 0.1 GeV/c
  std::vector<double> v_pTee(pTee,std::end(pTee));

  task->SetMassBins(v_mee);
  task->SetPairPtBins(v_pTee);
  task->SetPhiVBinsLinear(0, TMath::Pi(), 100);
  task->SetFillPhiV(kFALSE);

  task->SetSmearGenerated(kFALSE);
  task->SetResolutionDeltaPtBinsLinear( -10,  +10, 2000);
  task->SetResolutionRelPtBinsLinear  (   0,    2,  400);
  task->SetResolutionEtaBinsLinear    (-0.4, +0.4,  200);
  task->SetResolutionPhiBinsLinear    (-0.4, +0.4,  200);
  task->SetResolutionThetaBinsLinear  (-0.4, +0.4,  200);

  // Set MCSignal and Cutsetting to fill the support histograms
  task->SetSupportHistoMCSignalAndCutsetting(0,0);//fill support histograms for first MCsignal and first cutsetting

  // Pairing related config
  task->SetDoPairing(kTRUE);
  task->SetULSandLS(kTRUE);
  task->SetDeactivateLS(kFALSE);

  cout<<"Efficiency based on MC generators: " << generators <<endl;
  TString generatorsPair=generators;
  task->SetGeneratorMCSignalName(generatorsPair);
  task->SetGeneratorULSSignalName(generators);

  task->SetResolutionFile(resolutionFilename , "/alice/cern.ch/user/d/dsekihat/PWGDQ/dielectron/resolution/" + resolutionFilename);
  task->SetCentralityFile(centralityFilename , "/alice/cern.ch/user/d/dsekihat/PWGDQ/dielectron/centrality/" + centralityFilename);

  if(cocktailFilename != "") task->SetDoCocktailWeighting(kTRUE);
  task->SetCocktailWeighting(cocktailFilename, "/alice/cern.ch/user/d/dsekihat/PWGDQ/dielectron/cocktail/"   + cocktailFilename);

  // Add MCSignals. Can be set to see differences of:
  // e.g. secondaries and primaries. or primaries from charm and resonances
  gROOT->ProcessLine(Form("AddSingleLegMCSignal(%s)",task->GetName()));//not task itself, task name
  gROOT->ProcessLine(Form("AddPairMCSignal(%s)"     ,task->GetName()));//not task itself, task name

  //set PID map for ITS TOF in MC.
  TFile *rootfile = 0x0;
  if(calibFileName != "") rootfile = TFile::Open(calibFileName,"READ");
  if(rootfile && rootfile->IsOpen()){
    TH3D *h3mean_ITS  = (TH3D*)rootfile->Get("h3mean_ITS");
    TH3D *h3width_ITS = (TH3D*)rootfile->Get("h3width_ITS");
    h3mean_ITS ->SetDirectory(0);
    h3width_ITS->SetDirectory(0);
    task->SetCentroidCorrFunction(AliAnalysisTaskElectronEfficiencyV2::kITS, h3mean_ITS, AliDielectronVarManager::kNSDDSSDclsEvent, AliDielectronVarManager::kPIn,  AliDielectronVarManager::kEta);
    task->SetWidthCorrFunction(AliAnalysisTaskElectronEfficiencyV2::kITS, h3width_ITS, AliDielectronVarManager::kNSDDSSDclsEvent, AliDielectronVarManager::kPIn,  AliDielectronVarManager::kEta );

    TH3D *h3mean_TOF = (TH3D*)rootfile->Get("h3mean_TOF");
    TH3D *h3width_TOF = (TH3D*)rootfile->Get("h3width_TOF");
    h3mean_TOF ->SetDirectory(0);
    h3width_TOF->SetDirectory(0);
    task->SetCentroidCorrFunction(AliAnalysisTaskElectronEfficiencyV2::kTOF, h3mean_TOF, AliDielectronVarManager::kNSDDSSDclsEvent, AliDielectronVarManager::kPIn,  AliDielectronVarManager::kEta);
    task->SetWidthCorrFunction(AliAnalysisTaskElectronEfficiencyV2::kTOF, h3width_TOF, AliDielectronVarManager::kNSDDSSDclsEvent, AliDielectronVarManager::kPIn,  AliDielectronVarManager::kEta);

    rootfile->Close();
  }
	TString outlistname = Form("Efficiency_dsekihat%s_Cen%d_%d_kINT7%s",suffix.Data(),CenMin,CenMax,pileupcut.Data());

  //const TString fileName = AliAnalysisManager::GetCommonFileName();
  const TString fileName = outname;
	//const TString dirname = Form("PWGDQ_LMEE_ElectronEfficiencyV2_Cen%d_%d_kINT7",CenMin,CenMax);
  mgr->AddTask(task);
  mgr->ConnectInput(task,  0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(task, 1, mgr->CreateContainer(outlistname, TList::Class(), AliAnalysisManager::kOutputContainer, Form("%s",fileName.Data())));
  return task;
}

<|endoftext|>