Exemplo n.º 1
0
def test_kisa2 () :
       
    logger = getLogger ( 'ostap.test_kisa2' )

    if 62400 <= ROOT.gROOT.GetVersionInt() < 62406 :
        logger.warning ('Test can fail for %s' % ROOT.gROOT.GetVersion() )

    from ostap.fitting.pyselectors import SelectorWithVars, Variable  
    variables = [
        Variable   ( 'mass'  , 'mass(mu+mu-)' ,  3.09 , 3.11 ) , 
        Variable   ( 'c2dtf' , 'chi2(dtf)'    , -1    , 10   ) , 
        Variable   ( 'mass2' , 'mass(mu+mu-)' , 1 , 5 , MASS()  ) , 
        Variable   ( 'mass3' , 'mass(mu+mu-)' , 1 , 5 , 'mass'  ) 
        ]
    
    from sys import version_info  as python_version
    if  python_version.major < 3 :
        variables.append ( Variable ( 'mass1' , 'mass(mu+mu-)' , 2 , 4 , lambda s : s.mass ) )
    
    ppservers = () ## 'lxplus051' , )
    ## ppservers = 'auto'
    
    nf   = len ( data.files )
    nf //= 40
    nf  += 1 
    nf   = min ( nf , 25 )
    
    with timing('%d files in sequence %s' % ( nf , len( data.chain )  ) ) :
        selector = SelectorWithVars  (
            variables = variables ,
            selection = '2<=mass && mass<4 && 0<=c2dtf && c2dtf<5' ,
            silence   = False
            )
        chain =  data.chain[:nf]
        st = chain.process ( selector , silent = False , shortcut = True )
        ds = selector.data
        del selector 
    logger.info ( 'Dataset (sequential):\n%s' % ds.table()  )
    
    with timing('%s files in parallel %s' % ( len ( data.files ) , len( data.chain ) ) ) :
        selector = SelectorWithVars  (
            variables = variables ,
            selection = '2<=mass && mass<4 && 0<=c2dtf && c2dtf<5' ,
            silence   = True 
            )
        st = data.chain.parallel_fill ( selector               ,
                                        silent     = False     ,
                                        chunk_size = -1        ,
                                        max_files  =  1        ,
                                        ppservers  = ppservers )
        ds = selector.data 
        del selector 
    logger.info ( 'Dataset (paralell):\n%s' % ds.table ( prefix = '# ' ) )
Exemplo n.º 2
0
def test_kisa3():

    logger = getLogger('ostap.test_kisa3')

    if 62400 <= ROOT.gROOT.GetVersionInt() < 62406:
        logger.warning('Test can fail for %s' % ROOT.gROOT.GetVersion())

    h1 = ROOT.TH1D('h1', '', 100, 0, 20)
    h1 += lambda x: x

    ## from  ostap.trees.funcs import H1DFunc
    ## xh1 = H1DFunc ( histo = h1 , xvar = 'pt' )
    ## from  ostap.trees.funcs import FuncTH1
    ## xh1 = FuncTH1 ( histo = h1 , xvar = 'pt' )

    from ostap.fitting.pyselectors import SelectorWithVars, Variable
    variables = [
        ## Variable ( 'mass1' , 'mass(mu+mu-)' , 2 , 4 , lambda s : s.mass ) ,
        Variable('mass', 'mass(mu+mu-)', 3.09, 3.11),
        Variable('c2dtf', 'chi2(dtf)', -1, 10),
        ## Variable ( 'xpt'   , 'xpt'          , -1    , 30   , xh1 ) ,
        Variable('mass2', 'mass(mu+mu-)', 1, 5, MASS()),
        Variable('mass3', 'mass(mu+mu-)', 1, 5, 'mass')
    ]

    with timing('fill it!'):
        selector = SelectorWithVars(
            variables=variables,
            selection='2<=mass && mass<4 && 0<=c2dtf && c2dtf<5',
            silence=True)
        chain = data.chain
        st = chain.pprocess(selector, silent=False, shortcut=True)
        ds = selector.data
        del selector
    logger.info('Dataset (paralell):\n%s' % ds.table(prefix='# '))
Exemplo n.º 3
0
    def process ( self , jobid , item ) :

        import ROOT
        from ostap.logger.logger import logWarning
        with logWarning() :
            import ostap.core.pyrouts            
            import ostap.trees.trees
            import ostap.fitting.roofit 

        
        ## reconstruct chain from the item 
        chain    = item.chain
        ll       = len ( chain )  
        
        first    = item.first
        nevents  = item.nevents 

        all = 0 == first and ( nevents < 0 or ll <= nevents )
        
        if self.trivial and all : 
            import ostap.fitting.pyselectors
            self.__output = chain.make_dataset ( self.variables , self.selection , silent = True ) 
            return self.__output 

        from   ostap.fitting.pyselectors import SelectorWithVars
        
        ## use selector  
        selector = SelectorWithVars ( variables = self.variables ,
                                      selection = self.selection ,
                                      roo_cuts  = self.roo_cuts  , 
                                      silence   = True           )
        
        args = ()  
        if not all : args  = nevents , first 
        
        dataset , stat  = chain.fill_dataset2 ( selector  ,
                                                *args     ,
                                                silent    = True                 , 
                                                shortcut  = all and self.trivial ,
                                                use_frame = self.use_frame       )
        
        ## self.__output = selector.data, selector.stat  
        self.__output = dataset, stat 
        
        ## if  num < 0 :
        ##   logger.warning ("Processing status %s (jobid #%s)"  %  ( num % jobid ) ) 
        
        ## del selector.data
        ## del      selector        
        logger.debug ( 'Processed %s and filled %d entries (jobid #%s)' % ( stat , len ( dataset ) , jobid ) )

        return self.__output 
Exemplo n.º 4
0
def test_selector_with_vars3():
    """Use dedicated selector-with-vars (3) to loop
    over good entries in  the  chain and fill   dataset 
    """

    logger = getLogger("test_selector_with_vars3")

    from ostap.fitting.pyselectors import SelectorWithVars

    mySel = SelectorWithVars(variables=[mass, c2dtf, pt],
                             selection=cuts,
                             logger=logger)

    with timing("Selector with vars&logic&kisa", logger):
        data.chain.pprocess(mySel, shortcut=False)

    dataset = mySel.data

    logger.info("Data set (selector-with-vars):\n%s" %
                dataset.table(prefix="# "))
Exemplo n.º 5
0
def test_selector_with_vars1():
    """Use dedicated selector-with-vars (1) to loop
    over good entries in  the  chain and fill   dataset 
    """

    logger = getLogger("test_selector_with_vars1")

    from ostap.fitting.pyselectors import SelectorWithVars

    mySel = SelectorWithVars(variables=[mass, c2dtf, pt],
                             selection=cuts,
                             logger=logger)

    with timing("Selector with vars", logger):
        Ostap.Utils.process(data.chain, mySel)

    dataset = mySel.data

    logger.info("Data set (selector-with-vars):\n%s" %
                dataset.table(prefix="# "))
Exemplo n.º 6
0
## for m in methods :
##     method = reader[m]
##     logger.info ( 'Method  %12s , response %s' % ( m , method ( 1.1 , 0.8 , 0.3 ) ) )
##     del method
## # =============================================================================

## ## 2.2) declare/add TMVA  variables with TMVAreader
## for m in methods :
##     variables += [ Variable( 'tmva_%s' % m , 'TMVA(%s)' % m , accessor = reader[m] ) ]
## # =============================================================================
## ## The END of TMVA.Reader fragment
## # =============================================================================

## 3) Run Ostap to   fill   RooDataSet
dsS = SelectorWithVars(
    variables=variables,
    selection="var1 < 100",
)
dsB = SelectorWithVars(
    variables=variables,
    selection="var1 < 100",
)

## read input data file
with ROOT.TFile.Open(data_file, 'READ') as datafile:

    datafile.ls()
    tSignal = datafile['S']
    tBkg = datafile['B']

    from ostap.utils.timing import timing
    with timing("Process signal"):
Exemplo n.º 7
0
## configuration of reweighting
weightings = (
    ## variable          address in DB
    Weight.Var('x', 'x-reweight'),
    Weight.Var('y', 'y-reweight'),
    Weight.Var(('x', 'y'), '2D-reweight'),
)

# =============================================================================
## variables to be used in MC-dataset
variables = [
    Variable('x', 'x-var', 0, 20),
    Variable('y', 'y-var', 0, 15),
]
selector = SelectorWithVars(variables,
                            '0<x && x<20 && 0<y && y<20',
                            silence=True)
mctree.process(selector, silent=True)
mcds_ = selector.data  ## dataset
# =============================================================================
## start reweighting iterations:
for iter in range(1, maxIter + 1):

    tag = 'Reweighting iteration #%d' % iter
    logger.info(allright(tag))

    with timing(tag + ': prepare MC-dataset:', logger=logger):
        # =========================================================================
        ## 0) The weighter object
        weighter = Weight(dbname, weightings)
Exemplo n.º 8
0
# =============================================================================
## start iterations:
for iter in range(1, maxIter + 1):

    tag = 'Reweighting iteration #%d' % iter
    logger.info(allright(tag))

    with timing(tag + ': prepare MC-dataset:', logger=logger):

        # =============================================================================
        ## 0) The weighter object
        weighter = Weight(dbname, weighting)

        # ===============================================================================
        ## 1a) create mcdataset
        selector = SelectorWithVars(variables, '0<x && x<100 ', silence=True)
        mctree.process(selector, silent=True)
        mcds = selector.data  ## dataset

    with timing(tag + ': add weight to MC-dataset', logger=logger):

        ## 1b) add "weight" variable to the dataset
        mcds.add_reweighting(weighter, name='weight')
        if 1 == iter % 10: logger.info((tag + ' MCDATA:\n%s') % mcds)

    with timing(tag + ': make actual reweighting:', logger=logger):
        # ==============================================================================
        ## 2) update weights
        plots = [WeightingPlot('x', 'weight', 'x-reweight', hdata, hmc)]
        more = makeWeights(
            mcds,
Exemplo n.º 9
0
def test_fitting_fill_1():
    ## if 1 < 2 :
    logger = getLogger('test_fitting_fill_1')

    ## prepare data
    with timing("Prepare test data", logger=logger):
        files = prepare_data(4, 5000)
        data = Data('S', files)

    chain = data.chain

    mJPsi = ROOT.RooRealVar('mJPsi', 'mass(J/Psi) [GeV]', 3.0 * GeV, 3.2 * GeV)

    # =========================================================================
    logger.info(attention('All trivial variables'))
    # =========================================================================

    variables = [
        Variable(mJPsi, accessor='mass'),
        Variable('massMeV', 'mass in MeV', 3000, 3200, 'mass*1000.0'),
        Variable('vv102', 'vv10[2]', -1, 100, '1.0*vv10[2]'),
        Variable('fevt', accessor='1.0*evt'), ('pt', ), ('eta', ),
        ('x', 'some variable', 0, 5000, '(mass+pt+eta)/eta')
    ]

    config = {'variables': variables, 'selection': "pt>7 && eta<3"}

    with timing("No SHORTCUT, no FRAME", logger=None) as t1:
        logger.info(attention(t1.name))
        selector = SelectorWithVars(**config)
        chain.fill_dataset(selector, shortcut=False, use_frame=False)
        ds1_1 = selector.data
    with timing("   SHORTCUT, no FRAME", logger=None) as t2:
        logger.info(attention(t2.name))
        selector = SelectorWithVars(**config)
        chain.fill_dataset(selector, shortcut=True, use_frame=False)
        ds1_2 = selector.data
    with timing("No SHORTCUT,    FRAME", logger=None) as t3:
        logger.info(attention(t3.name))
        selector = SelectorWithVars(**config)
        chain.fill_dataset(selector, shortcut=False, use_frame=True)
        ds1_3 = selector.data
    with timing("   SHORTCUT,    FRAME", logger=None) as t4:
        logger.info(attention(t4.name))
        selector = SelectorWithVars(**config)
        chain.fill_dataset(selector, shortcut=True, use_frame=True)
        ds1_4 = selector.data

    if DataSet_NEW_FILL:
        with timing(" pure-FRAME (new) ", logger=None) as t5:
            logger.info(attention(t5.name))
            ds1_5, _ = chain.make_dataset(silent=False, **config)

    table = [('Configuration', 'CPU')]

    table.append((t1.name, '%.3fs' % t1.delta))
    table.append((t2.name, '%.3fs' % t2.delta))
    table.append((t3.name, '%.3fs' % t3.delta))
    table.append((t4.name, '%.3fs' % t4.delta))

    if DataSet_NEW_FILL:
        table.append((t5.name, '%.3fs' % t5.delta))

    title1 = "All trivial variables"
    table1 = T.table(table, title=title1, prefix='# ', alignment='rr')
    logger.info('%s\n%s' % (title1, table1))

    if ds1_1 != ds1_2:
        logger.error('Datasets ds1_1  and ds1_2   are different!')
    if ds1_1 != ds1_3:
        logger.error('Datasets ds1_1  and ds1_3   are different!')
    if ds1_1 != ds1_4:
        logger.error('Datasets ds1_1  and ds1_4   are different!')

    if DataSet_NEW_FILL:
        if ds1_1 != ds1_5:
            logger.error('Datasets ds1_1  and ds1_5   are different!')

    with timing("No SHORTCUT, no FRAME", logger=None) as t1:
        logger.info(attention(t1.name))
        selector = SelectorWithVars(**config)
        chain.parallel_fill(selector,
                            shortcut=False,
                            use_frame=False,
                            max_files=1)
        ds1p_1 = selector.data
    with timing("   SHORTCUT, no FRAME", logger=None) as t2:
        logger.info(attention(t2.name))
        selector = SelectorWithVars(**config)
        chain.parallel_fill(selector,
                            shortcut=True,
                            use_frame=False,
                            max_files=1)
        ds1p_2 = selector.data
    with timing("No SHORTCUT,    FRAME", logger=None) as t3:
        logger.info(attention(t3.name))
        selector = SelectorWithVars(**config)
        chain.parallel_fill(selector,
                            shortcut=False,
                            use_frame=True,
                            max_files=1)
        ds1p_3 = selector.data
    with timing("   SHORTCUT,    FRAME", logger=None) as t4:
        logger.info(attention(t4.name))
        selector = SelectorWithVars(**config)
        chain.parallel_fill(selector,
                            shortcut=True,
                            use_frame=True,
                            max_files=1)
        ds1p_4 = selector.data

    table = [('Configuration', 'CPU')]

    table.append((t1.name, '%.3fs' % t1.delta))
    table.append((t2.name, '%.3fs' % t2.delta))
    table.append((t3.name, '%.3fs' % t3.delta))
    table.append((t4.name, '%.3fs' % t4.delta))

    title1p = "All trivial variables (parallel)"
    table1p = T.table(table, title=title1p, prefix='# ', alignment='rr')
    logger.info('%s\n%s' % (title1p, table1p))

    if ds1_1 != ds1p_1:
        logger.error('Datasets ds1_1  and ds1p_1  are different!')
    if ds1_2 != ds1p_2:
        logger.error('Datasets ds1_2  and ds1p_2  are different!')
    if ds1_3 != ds1p_3:
        logger.error('Datasets ds1_3  and ds1p_3  are different!')
    if ds1_4 != ds1p_4:
        logger.error('Datasets ds1_4  and ds1p_4  are different!')

    # =========================================================================
    logger.info(attention('Trivial variables + CUT'))
    # =========================================================================

    variables = [
        Variable(mJPsi, accessor='mass'),
        Variable('massMeV', 'mass in MeV', 3000, 3200, 'mass*1000'),
        Variable('vv102', 'vv10[2]', -1, 100, '1.0*vv10[2]'),
        Variable('fevt', accessor='1.0*evt'), ('pt', ), ('eta', ),
        ('x', 'some variable', 0, 5000, '(mass+pt+eta)/eta')
    ]

    if not DILL_PY3_issue:

        config = {
            'variables': variables,
            'selection': "pt>7 && eta<3",
            'cuts': lambda s: s.pt > 3
        }  ## ATTENTION: no trivial cuts!

    else:

        logger.warning('There is an issue with dill+python3: avoid lambda!')
        config = {
            'variables': variables,
            'selection': "pt>7 && eta<3",
            'cuts': ptcut
        }  ## ATTENTION: no trivial cuts!

    with timing("No SHORTCUT, no FRAME", logger=None) as t1:
        logger.info(attention(t1.name))
        selector = SelectorWithVars(**config)
        chain.fill_dataset(selector, shortcut=False, use_frame=False)
        ds2_1 = selector.data
    with timing("   SHORTCUT, no FRAME", logger=None) as t2:
        logger.info(attention(t2.name))
        selector = SelectorWithVars(**config)
        chain.fill_dataset(selector, shortcut=True, use_frame=False)
        ds2_2 = selector.data
    with timing("No SHORTCUT,    FRAME", logger=None) as t3:
        logger.info(attention(t3.name))
        selector = SelectorWithVars(**config)
        chain.fill_dataset(selector, shortcut=False, use_frame=True)
        ds2_3 = selector.data
    with timing("   SHORTCUT,    FRAME", logger=None) as t4:
        logger.info(attention(t4.name))
        selector = SelectorWithVars(**config)
        chain.fill_dataset(selector, shortcut=True, use_frame=True)
        ds2_4 = selector.data

    table = [('Configuration', 'CPU')]

    table.append((t1.name, '%.3fs' % t1.delta))
    table.append((t2.name, '%.3fs' % t2.delta))
    table.append((t3.name, '%.3fs' % t3.delta))
    table.append((t4.name, '%.3fs' % t4.delta))

    title2 = "Trivial variables + CUT"
    table2 = T.table(table, title=title2, prefix='# ', alignment='rr')
    logger.info('%s\n%s' % (title2, table2))

    if ds2_1 != ds2_2:
        logger.error('Datasets ds2_1  and ds2_2   are different!')
    if ds2_1 != ds2_3:
        logger.error('Datasets ds2_1  and ds2_3   are different!')
    if ds2_1 != ds2_4:
        logger.error('Datasets ds2_1  and ds2_4   are different!')

    with timing("No SHORTCUT, no FRAME", logger=None) as t1:
        logger.info(attention(t1.name))
        selector = SelectorWithVars(**config)
        chain.parallel_fill(selector,
                            shortcut=False,
                            use_frame=False,
                            maX_files=1)
        ds2p_1 = selector.data
    with timing("   SHORTCUT, no FRAME", logger=None) as t2:
        logger.info(attention(t2.name))
        selector = SelectorWithVars(**config)
        chain.parallel_fill(selector,
                            shortcut=True,
                            use_frame=False,
                            maX_files=1)
        ds2p_2 = selector.data
    with timing("No SHORTCUT,    FRAME", logger=None) as t3:
        logger.info(attention(t3.name))
        selector = SelectorWithVars(**config)
        chain.parallel_fill(selector,
                            shortcut=False,
                            use_frame=True,
                            max_files=1)
        ds2p_3 = selector.data
    with timing("   SHORTCUT,    FRAME", logger=None) as t4:
        logger.info(attention(t4.name))
        selector = SelectorWithVars(**config)
        chain.parallel_fill(selector,
                            shortcut=True,
                            use_frame=True,
                            max_files=1)
        ds2p_4 = selector.data

    table = [('Configuration', 'CPU')]

    table.append((t1.name, '%.3fs' % t1.delta))
    table.append((t2.name, '%.3fs' % t2.delta))
    table.append((t3.name, '%.3fs' % t3.delta))
    table.append((t4.name, '%.3fs' % t4.delta))

    title2p = "Trivial variables + CUT (parallel)"
    table2p = T.table(table, title=title2p, prefix='# ', alignment='rr')
    logger.info('%s\n%s' % (title2p, table2p))

    if ds1_1 != ds2_1:
        logger.error('Datasets ds1_1  and ds2_1   are different!')

    if ds2_1 != ds2p_1:
        logger.error('Datasets ds2_1  and ds2p_1  are different!')
    if ds2_2 != ds2p_2:
        logger.error('Datasets ds2_2  and ds2p_2  are different!')
    if ds2_3 != ds2p_3:
        logger.error('Datasets ds2_3  and ds2p_3  are different!')
    if ds2_4 != ds2p_4:
        logger.error('Datasets ds2_4  and ds2p_4  are different!')

    # =========================================================================
    logger.info(attention('Non-trivial variables'))
    # =========================================================================

    if not DILL_PY3_issue:

        variables = [
            Variable(mJPsi, accessor='mass'),
            Variable('massMeV', 'mass in MeV', 3000, 3200, 'mass*1000'),
            Variable('vv102', 'vv10[2]', -1, 100, '1.0*vv10[2]'),
            Variable('fevt', accessor='1.0*evt'), ('pt', ), ('eta', ),
            ('x', 'some variable', 0, 5000, lambda s:
             (s.mass + s.pt + s.eta) / s.eta)
        ]

    else:

        logger.warning('There is an issue with dill+python3: avoid lambda!')
        variables = [
            Variable(mJPsi, accessor='mass'),
            Variable('massMeV', 'mass in MeV', 3000, 3200, 'mass*1000'),
            Variable('vv102', 'vv10[2]', -1, 100, '1.0*vv10[2]'),
            Variable('fevt', accessor='1.0*evt'), ('pt', ), ('eta', ),
            ('x', 'some variable', 0, 5000, xvar)
        ]

    config = {'variables': variables, 'selection': "pt>7 && eta<3"}

    with timing("No SHORTCUT, no FRAME", logger=None) as t1:
        logger.info(attention(t1.name))
        selector = SelectorWithVars(**config)
        chain.fill_dataset(selector, shortcut=False, use_frame=False)
        ds3_1 = selector.data
    with timing("   SHORTCUT, no FRAME", logger=None) as t2:
        logger.info(attention(t2.name))
        selector = SelectorWithVars(**config)
        chain.fill_dataset(selector, shortcut=True, use_frame=False)
        ds3_2 = selector.data
    with timing("No SHORTCUT,    FRAME", logger=None) as t3:
        logger.info(attention(t3.name))
        selector = SelectorWithVars(**config)
        chain.fill_dataset(selector, shortcut=False, use_frame=True)
        ds3_3 = selector.data
    with timing("   SHORTCUT,    FRAME", logger=None) as t4:
        logger.info(attention(t4.name))
        selector = SelectorWithVars(**config)
        chain.fill_dataset(selector, shortcut=True, use_frame=True)
        ds3_4 = selector.data

    table = [('Configuration', 'CPU')]

    table.append((t1.name, '%.3fs' % t1.delta))
    table.append((t2.name, '%.3fs' % t2.delta))
    table.append((t3.name, '%.3fs' % t3.delta))
    table.append((t4.name, '%.3fs' % t4.delta))

    title3 = "Non-trivial variables"
    table3 = T.table(table, title=title3, prefix='# ', alignment='rr')
    logger.info('%s\n%s' % (title3, table3))

    if ds1_1 != ds3_1:
        logger.error('Datasets ds1_1  and ds3_1   are different!')

    if ds3_1 != ds3_2:
        logger.error('Datasets ds3_1  and ds2_2   are different!')
    if ds3_1 != ds3_3:
        logger.error('Datasets ds3_1  and ds2_3   are different!')
    if ds3_1 != ds3_4:
        logger.error('Datasets ds3_1  and ds2_4   are different!')

    with timing("No SHORTCUT, no FRAME", logger=None) as t1:
        logger.info(attention(t1.name))
        selector = SelectorWithVars(**config)
        chain.parallel_fill(selector,
                            shortcut=False,
                            use_frame=False,
                            max_files=1)
        ds3p_1 = selector.data
    with timing("   SHORTCUT, no FRAME", logger=None) as t2:
        logger.info(attention(t2.name))
        selector = SelectorWithVars(**config)
        chain.parallel_fill(selector,
                            shortcut=True,
                            use_frame=False,
                            max_files=1)
        ds3p_2 = selector.data
    with timing("No SHORTCUT,    FRAME", logger=None) as t3:
        logger.info(attention(t3.name))
        selector = SelectorWithVars(**config)
        chain.parallel_fill(selector,
                            shortcut=False,
                            use_frame=True,
                            max_files=1)
        ds3p_3 = selector.data
    with timing("   SHORTCUT,    FRAME", logger=None) as t4:
        logger.info(attention(t4.name))
        selector = SelectorWithVars(**config)
        chain.parallel_fill(selector,
                            shortcut=True,
                            use_frame=True,
                            max_files=1)
        ds3p_4 = selector.data

    table = [('Configuration', 'CPU')]

    table.append((t1.name, '%.3fs' % t1.delta))
    table.append((t2.name, '%.3fs' % t2.delta))
    table.append((t3.name, '%.3fs' % t3.delta))
    table.append((t4.name, '%.3fs' % t4.delta))

    title3p = "Non-trivial variables (parallel)"
    table3p = T.table(table, title=title3p, prefix='# ', alignment='rr')
    logger.info('%s\n%s' % (title3p, table3p))

    if ds3_1 != ds3p_1:
        logger.error('Datasets ds3_1  and ds3p_1  are different!')
    if ds3_2 != ds3p_2:
        logger.error('Datasets ds3_2  and ds3p_2  are different!')
    if ds3_3 != ds3p_3:
        logger.error('Datasets ds3_3  and ds3p_3  are different!')
    if ds3_4 != ds3p_4:
        logger.error('Datasets ds3_4  and ds3p_4  are different!')

    # =========================================================================
    logger.info(attention('Non-trivial variables + CUT'))
    # =========================================================================

    if not DILL_PY3_issue:

        variables = [
            Variable(mJPsi, accessor='mass'),
            Variable('massMeV', 'mass in MeV', 3000, 3200, 'mass*1000'),
            Variable('vv102', 'vv10[2]', -1, 100, '1.0*vv10[2]'),
            Variable('fevt', accessor='1.0*evt'), ('pt', ), ('eta', ),
            ('x', 'some variable', 0, 5000, lambda s:
             (s.mass + s.pt + s.eta) / s.eta)
        ]

    else:

        logger.warning('There is an issue with dill+python3: avoid lambda!')
        variables = [
            Variable(mJPsi, accessor='mass'),
            Variable('massMeV', 'mass in MeV', 3000, 3200, 'mass*1000'),
            Variable('vv102', 'vv10[2]', -1, 100, '1.0*vv10[2]'),
            Variable('fevt', accessor='1.0*evt'), ('pt', ), ('eta', ),
            ('x', 'some variable', 0, 5000, xvar)
        ]

    if not DILL_PY3_issue:

        config = {
            'variables': variables,
            'selection': "pt>7 && eta<3",
            'cuts': lambda s: s.pt > 3
        }  ## ATTENTION: no trivial cuts!
    else:

        logger.warning('There is an issue with dill+python3: avoid lambda!')
        config = {
            'variables': variables,
            'selection': "pt>7 && eta<3",
            'cuts': ptcut
        }  ## ATTENTION: no trivial cuts!

    with timing("No SHORTCUT, no FRAME", logger=None) as t1:
        logger.info(attention(t1.name))
        selector = SelectorWithVars(**config)
        chain.fill_dataset(selector, shortcut=False, use_frame=False)
        ds4_1 = selector.data
    with timing("   SHORTCUT, no FRAME", logger=None) as t2:
        logger.info(attention(t2.name))
        selector = SelectorWithVars(**config)
        chain.fill_dataset(selector, shortcut=True, use_frame=False)
        ds4_2 = selector.data
    with timing("No SHORTCUT,    FRAME", logger=None) as t3:
        logger.info(attention(t3.name))
        selector = SelectorWithVars(**config)
        chain.fill_dataset(selector, shortcut=False, use_frame=True)
        ds4_3 = selector.data
    with timing("   SHORTCUT,    FRAME", logger=None) as t4:
        logger.info(attention(t4.name))
        selector = SelectorWithVars(**config)
        chain.fill_dataset(selector, shortcut=True, use_frame=True)
        ds4_4 = selector.data

    table = [('Configuration', 'CPU')]

    table.append((t1.name, '%.3fs' % t1.delta))
    table.append((t2.name, '%.3fs' % t2.delta))
    table.append((t3.name, '%.3fs' % t3.delta))
    table.append((t4.name, '%.3fs' % t4.delta))

    title4 = "Non-trivial variables + CUT"
    table4 = T.table(table, title=title4, prefix='# ', alignment='rr')
    logger.info('%s\n%s' % (title4, table4))

    if ds1_1 != ds4_1:
        logger.error('Datasets ds1_1  and ds4_1   are different!')

    if ds4_1 != ds4_2:
        logger.error('Datasets ds4_1  and ds4_2   are different!')
    if ds4_1 != ds4_3:
        logger.error('Datasets ds4_1  and ds4_3   are different!')
    if ds4_1 != ds4_4:
        logger.error('Datasets ds4_1  and ds4_4   are different!')

    with timing("No SHORTCUT, no FRAME", logger=None) as t1:
        logger.info(attention(t1.name))
        selector = SelectorWithVars(**config)
        chain.parallel_fill(selector,
                            shortcut=False,
                            use_frame=False,
                            max_files=1)
        ds4p_1 = selector.data
    with timing("   SHORTCUT, no FRAME", logger=None) as t2:
        logger.info(attention(t2.name))
        selector = SelectorWithVars(**config)
        chain.parallel_fill(selector,
                            shortcut=True,
                            use_frame=False,
                            max_files=1)
        ds4p_2 = selector.data
    with timing("No SHORTCUT,    FRAME", logger=None) as t3:
        logger.info(attention(t3.name))
        selector = SelectorWithVars(**config)
        chain.parallel_fill(selector,
                            shortcut=False,
                            use_frame=True,
                            max_files=1)
        ds4p_3 = selector.data
    with timing("   SHORTCUT,    FRAME", logger=None) as t4:
        logger.info(attention(t4.name))
        selector = SelectorWithVars(**config)
        chain.parallel_fill(selector,
                            shortcut=True,
                            use_frame=True,
                            max_files=1)
        ds4p_4 = selector.data

    table = [('Configuration', 'CPU')]

    table.append((t1.name, '%.3fs' % t1.delta))
    table.append((t2.name, '%.3fs' % t2.delta))
    table.append((t3.name, '%.3fs' % t3.delta))
    table.append((t4.name, '%.3fs' % t4.delta))

    title4p = "Non-trivial variables + CUT (parallel)"
    table4p = T.table(table, title=title4p, prefix='# ', alignment='rr')
    logger.info('%s\n%s' % (title4p, table4p))

    if ds4_1 != ds4p_1:
        logger.error('Datasets ds4_1  and ds4p_1  are different!')
    if ds4_2 != ds4p_2:
        logger.error('Datasets ds4_2  and ds4p_2  are different!')
    if ds4_3 != ds4p_3:
        logger.error('Datasets ds4_3  and ds4p_3  are different!')
    if ds4_4 != ds4p_4:
        logger.error('Datasets ds4_4  and ds4p_4  are different!')

    logger.info('%s\n%s' % (title1, table1))
    logger.info('%s\n%s' % (title1p, table1p))

    logger.info('%s\n%s' % (title2, table2))
    logger.info('%s\n%s' % (title2p, table2p))

    logger.info('%s\n%s' % (title3, table3))
    logger.info('%s\n%s' % (title3p, table3p))

    logger.info('%s\n%s' % (title4, table4))
    logger.info('%s\n%s' % (title4p, table4p))