Skip to content
Snippets Groups Projects
Commit 604abc7c authored by Scott Snyder's avatar Scott Snyder Committed by Graeme Stewart
Browse files

root6 fixes. (PyKernel-00-00-39)

parent ac6c62bc
No related branches found
No related tags found
No related merge requests found
/*
Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
*/
#ifndef PYANALYSISCORE_PYITPATCH_H
#define PYANALYSISCORE_PYITPATCH_H
// An utility class to remove '*' from a class type
template <class T> struct NonPointer
{
typedef T Type;
};
template <class T> struct NonPointer<T *>
{
typedef T Type;
};
// An utility class to remove 'const' from a class type
template <class T> struct NonConst
{
typedef T Type;
};
template <class T> struct NonConst<const T>
{
typedef T Type;
};
/**
This class provides some pathces for an iterator.
Some c++ classes have methods to return iterators instead of vectors.
In this case people need to use iterators directly. PyKernel addes next()
and patches __eq__()/__ne__() instead. Then one can use the iterator like
as a python iterator.
**/
template <class IT>
struct PyItPatch
{
PyItPatch() : m_cache(0) {}
PyItPatch(IT &it) : m_it(it)
{
m_cache = new typename NonConst<typename NonPointer<typename IT::pointer>::Type>::Type();
}
virtual ~PyItPatch() { if (m_cache!=0) delete m_cache; }
// next() for python iterator
typename IT::reference next()
{
// this implementation is needed for LCG dict
// 'return *m_it++' doesn't compile
*m_cache = *m_it;
++m_it;
return *m_cache;
}
// __eq__() for python iterator
bool eq(IT & rhs)
{
return rhs == m_it;
}
// __ne__() for python iterator
bool ne(IT & rhs)
{
return !eq(rhs);
}
private:
IT m_it;
typename NonConst<typename NonPointer<typename IT::pointer>::Type>::Type *m_cache;
};
#endif
/*
Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
*/
#ifndef PYKERNEL_PYKERNELDICT_H
#define PYKERNEL_PYKERNELDICT_H
#include "PyKernel/PyReverseProxy.h"
#endif
/*
Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
*/
#ifndef PYKERNEL_PYREVERSEPROXY_H
#define PYKERNEL_PYREVERSEPROXY_H
/**
A utility class to convert a C++ object to a PyObject
@author Tadashi Maeno
*/
#include "Python.h"
#include <map>
#include <string>
struct PyReverseProxy
{
/// destructor
~PyReverseProxy()
{
m_proxyMap.erase(m_key);
}
/// setter
void setFunc (PyObject * func)
{
Py_DECREF(m_func);
m_func = func;
Py_INCREF(m_func);
}
// getter
void getObj (void *& obj)
{
obj = m_obj;
}
PyObject * toPyObj (void * obj)
{
m_obj = obj;
return PyObject_CallObject(m_func,NULL);
}
/// factory method
static PyReverseProxy * getProxy(const std::string & key)
{
if (m_proxyMap.count(key) == 0)
m_proxyMap[key] = new PyReverseProxy(key);
return m_proxyMap[key];
}
private:
/// default constructor : never used
PyReverseProxy()
{}
/// constructor
PyReverseProxy(const std::string &key)
: m_key(key), m_obj(0), m_func(0)
{}
/// key
std::string m_key;
/// C++ obj
void * m_obj;
/// python code fragment to convert C++ obj to PyObj
PyObject * m_func;
/// proxy map
static std::map<std::string, PyReverseProxy *> m_proxyMap;
};
#endif
<lcgdict>
<class name="PyReverseProxy" />
</lcgdict>
\ No newline at end of file
package PyKernel
author Tadashi Maeno <Tadashi.Maeno@cern.ch>
use AtlasPolicy AtlasPolicy-*
use AtlasPython AtlasPython-* External
apply_pattern declare_python_modules files="*.py"
apply_pattern declare_joboptions files="*.py"
library PyKernel *.cxx
apply_pattern installed_library
private
use AtlasReflex AtlasReflex* External
apply_pattern lcgdict dict=PyKernel selectionfile=selection.xml \
headerfiles="../PyKernel/PyKernelDict.h"
/*
Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
*/
/**
@mainpage
@section PyKernelIntro Introduction
The PyKernel package contains some python modules
and python-bindings for interactive anaysis using Athena.
Note that this package is for python but doxygen doesn't
treat python very well. See <a href="http://tmaeno.home.cern.ch/tmaeno/PyKernel/index.html">PyKernel doc</a> instead.
@section PyKernelPythonMod Python modules
- PyKernel.py: core module to help StoreGate access, histogramming and visualization
- PyKHist.py: wrapper module for histograms
@section PyKernelPythonBind Python bindings
- PyItPatch: contains patches to treat C++ iterators as python's iterator
- PyReverseProxy: converts a C++ object to a PyObject
@section PyKernelExtras Extra Pages
- @ref PyKernelUsed
- @ref PyKernelReq
*/
/**
@page PyKernelUsed Used Packages
@htmlinclude used_packages.html
*/
/**
@page PyKernelReq Requirements
@include requirements
*/
# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
import re
import math
import ROOT
# a function object for wrapping ROOT methods
# update ROOT histogram and then call the ROOT method
# :param pykObj : PyKHist object
# :param rootClass : base class of the object
# :param methodName: method name (e.g., Draw)
# :param var : arguments of the method
class _PyKMethod:
def __init__(self,pykObj,rootClass,methodName):
self.pykObj = pykObj
# get pointer to the method
self.methodObj = getattr(rootClass,methodName)
# method emulation
def __call__(self,*var):
# update ROOT histogram
self.pykObj._updateROOT()
# call ROOT method
return apply(self.methodObj,(self.pykObj,)+var)
# special methods not to be patched
_specialMethod = ['Fill','Add']
# wrapper class for 1D histogram
class PyKHist1D (ROOT.TH1D):
# constructor
# :param aidaHist: AIDA hist obj
def __init__(self,aidaHist):
self.aidaHist = aidaHist
# go to the global directory. Otherwise this object is destroyed
# when a pool is closed
ROOT.gROOT.cd()
# init ROOT hist
ROOT.TH1D.__init__(self,aidaHist.title(),aidaHist.title(),\
aidaHist.axis().bins(),aidaHist.axis().lowerEdge(),\
aidaHist.axis().upperEdge())
# update ROOT histogram
self._updateROOT()
# patch ROOT methods
rootClass = ROOT.TH1D
attrs = dir(rootClass)
for attr in attrs:
# choose ROOT method only
if re.match('^[A-Z]',attr) == None:
continue
attrObj = getattr(rootClass,attr)
# method?
if not callable(attrObj):
continue
# special method?
if _specialMethod.count(attr) != 0:
continue
# instantiate function object
mObj = _PyKMethod(self,rootClass,attr)
# patch
setattr(self,attr,mObj)
# update ROOT part
def _updateROOT(self):
for i in range(0,self.aidaHist.axis().bins()):
ROOT.TH1D.SetBinContent(self,i+1,self.aidaHist.binHeight(i))
ROOT.TH1D.SetEntries(self,self.aidaHist.allEntries())
# overload of Fill
def Fill(self,*var):
apply(self.aidaHist.fill,var)
apply(ROOT.TH1D.Fill,(self,)+var)
# overload of Add
def Add(self,hist):
self.aidaHist.add(hist.aidaHist)
# ROOT.TH1D.Add(self,hist,1) causes a crash
ROOT.TH1D.Add(self,hist,hist,1,0)
# wrapper class for 2D histogram
class PyKHist2D (ROOT.TH2D):
# constructor
# :param aidaHist: AIDA hist obj
def __init__(self,aidaHist):
self.aidaHist = aidaHist
# go to the global directory. Otherwise this object is destroyed
# when a pool is closed
ROOT.gROOT.cd()
# init ROOT hist
ROOT.TH2D.__init__(self,aidaHist.title(),aidaHist.title(),\
aidaHist.xAxis().bins(),aidaHist.xAxis().lowerEdge(),\
aidaHist.xAxis().upperEdge(),aidaHist.yAxis().bins(),\
aidaHist.yAxis().lowerEdge(),aidaHist.yAxis().upperEdge())
# update ROOT histogram
self._updateROOT()
# patch ROOT methods
rootClass = ROOT.TH2D
attrs = dir(rootClass)
for attr in attrs:
# choose ROOT method only
if re.match('^[A-Z]',attr) == None:
continue
attrObj = getattr(rootClass,attr)
# method?
if not callable(attrObj):
continue
# special method?
if _specialMethod.count(attr) != 0:
continue
# instantiate function object
mObj = _PyKMethod(self,rootClass,attr)
# patch
setattr(self,attr,mObj)
# update ROOT part
def _updateROOT(self):
for i in range(0,self.aidaHist.xAxis().bins()):
for j in range(0,self.aidaHist.yAxis().bins()):
ROOT.TH2D.SetBinContent(self,i+1,j+1,self.aidaHist.binHeight(i,j))
ROOT.TH2D.SetEntries(self,self.aidaHist.allEntries())
# overload of Fill
def Fill(self,*var):
apply(self.aidaHist.fill,var)
apply(ROOT.TH2D.Fill,(self,)+var)
# overload of Add
def Add(self,hist):
self.aidaHist.add(hist.aidaHist)
# ROOT.TH2D.Add(self,hist,1) causes a crash
ROOT.TH2D.Add(self,hist,hist,1,0)
# wrapper class for profile histogram
class PyKHistProf (ROOT.TProfile):
# constructor
# :param aidaHist: AIDA hist obj
def __init__(self,aidaHist):
self.aidaHist = aidaHist
# go to the global directory. Otherwise this object is destroyed
# when a pool is closed
ROOT.gROOT.cd()
# init ROOT hist
ROOT.TProfile.__init__(self,aidaHist.title(),aidaHist.title(),\
aidaHist.axis().bins(),aidaHist.axis().lowerEdge(),\
aidaHist.axis().upperEdge())
# update ROOT histogram
self._updateROOT()
# patch ROOT methods
rootClass = ROOT.TProfile
attrs = dir(rootClass)
for attr in attrs:
# choose ROOT method only
if re.match('^[A-Z]',attr) == None:
continue
attrObj = getattr(rootClass,attr)
# method?
if not callable(attrObj):
continue
# public method?
if attr[0] == '_':
continue
# special method?
if _specialMethod.count(attr) != 0:
continue
# instantiate function object
mObj = _PyKMethod(self,rootClass,attr)
# patch
setattr(self,attr,mObj)
# update ROOT part
def _updateROOT(self):
for i in range(0,self.aidaHist.axis().bins()):
sumwyBin = self.aidaHist.binHeight(i)*self.aidaHist.binEntries(i)
sumwy2Bin = (self.aidaHist.binRms(i)*self.aidaHist.binRms(i)+\
self.aidaHist.binHeight(i)*self.aidaHist.binHeight(i))*self.aidaHist.binEntries(i)
ROOT.TProfile.SetBinContent(self,i+1,sumwyBin)
ROOT.TProfile.SetBinError(self,i+1,math.sqrt(sumwy2Bin))
ROOT.TProfile.SetBinEntries(self,i+1,self.aidaHist.binEntries(i))
ROOT.TProfile.SetEntries(self,self.aidaHist.allEntries())
# overload of Fill
def Fill(self,*var):
apply(self.aidaHist.fill,var)
apply(ROOT.TProfile.Fill,(self,)+var)
# overload of Add
def Add(self,hist):
self.aidaHist.add(hist.aidaHist)
# ROOT.TProfile.Add(self,hist,1) causes a crash
ROOT.TProfile.Add(self,hist,hist,1,0)
This diff is collapsed.
# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
from PyKernel import PyKernel
from PyKernel.PyKernel import plot,plot2,fill,fill2,dumpSG,book,bookProf
from PyKernel.PyKernel import plotProf,fillProf,unregister,dumpHist,retrieveHist
import PyCintex
PyCintex.loadDictionary("libPyKernelDict")
# Bind the C++ global namespace to the Python variable g
g = PyCintex.Namespace('')
## temporary hack to 'fix' #58078
if 0:
# set ROOT stream
import re
import ROOT
rootStream=None
from AthenaCommon.AppMgr import ServiceMgr as svcMgr
EventSelector = svcMgr.EventSelector
if hasattr(EventSelector,"CollectionType") and EventSelector.CollectionType == "ExplicitROOT":
filename = EventSelector.InputCollections[0]
if not re.search('\.root$',filename):
filename = filename+'.root'
file = ROOT.TFile(filename)
rootStream=ROOT.gROOT.FindObject('CollectionTree')
# this must be the last one
PyKernel.init(theApp,rootStream)
pass # temporary hack
/*
Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
*/
#include "PyKernel/PyReverseProxy.h"
std::map<std::string, PyReverseProxy *> PyReverseProxy::m_proxyMap
= std::map<std::string, PyReverseProxy *>();
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment