Example #1
0
    def test_replace_context_nested_list_dict(self):
        _cfg = deepcopy(self.BASE_CFG)
        _cfg['templates'][0].update({
            'replace_under_here': {
                'context_nested_list_dict': [{
                    'inner_key': [
                        ContextValue('namespace[key]'),
                        ContextValue('namespace[key]')
                    ]
                }, {
                    'inner_key': [
                        ContextValue('namespace[key]'),
                        ContextValue('namespace[key]')
                    ]
                }],
            }
        })

        _results = self._run_palisade(config=_cfg)
        self.assertEqual(len(_results), 1)
        for _i in range(2):
            for _j in range(2):
                self.assertEqual(
                    _results[0]['replace_under_here']
                    ['context_nested_list_dict'][_i]['inner_key'][_j],
                    self.BASE_CFG['expansions']['namespace'][0]['key'])
Example #2
0
    def test_replace_context_value_lazy_arithmetic_2(self):
        _cfg = deepcopy(self.BASE_CFG)
        _cfg['templates'][0].update({
            'replace_under_here': {
                'context_value':
                ContextValue('namespace[key]') *
                ContextValue('namespace[key]'),
            }
        })

        _results = self._run_palisade(config=_cfg)
        self.assertEqual(len(_results), 1)
        self.assertEqual(_results[0]['replace_under_here']['context_value'],
                         self.BASE_CFG['expansions']['namespace'][0]['key']**2)
Example #3
0
    def test_replace_context_value_lazy_meta_key(self):
        _cfg = deepcopy(self.BASE_CFG)
        _cfg['templates'][0].update({
            'replace_under_here': {
                'context_value':
                ContextValue(
                    String("namespace[{}]").format(
                        ContextValue('namespace[meta_key]'))),
            }
        })

        _results = self._run_palisade(config=_cfg)
        self.assertEqual(len(_results), 1)
        self.assertEqual(_results[0]['replace_under_here']['context_value'],
                         self.BASE_CFG['expansions']['namespace'][0]['key'])
Example #4
0
    def test_context_value_unsupported_syntax(self):
        _cfg = deepcopy(self.BASE_CFG)
        _cfg['templates'][0].update({
            'replace_under_here': {
                'context_value': ContextValue('namespace+key'),
            }
        })

        with self.assertRaises(ConfigurationError):
            _results = self._run_palisade(config=_cfg)
Example #5
0
    def test_replace_context_string_top_level_key(self):
        _cfg = deepcopy(self.BASE_CFG)
        _cfg['templates'][0].update({
            'replace_this_as_well':
            ContextValue('namespace[key]'),
        })

        _results = self._run_palisade(config=_cfg)
        self.assertEqual(len(_results), 1)
        self.assertEqual(_results[0]['replace_this_as_well'],
                         self.BASE_CFG['expansions']['namespace'][0]['key'])
Example #6
0
    def test_context_value_inexistent_key_raise(self):
        _cfg = deepcopy(self.BASE_CFG)
        _cfg['templates'][0].update({
            'replace_under_here': {
                'context_value': ContextValue('namespace[inexistent_key]'),
            }
        })

        with self.assertRaises(ConfigurationError) as _err:
            _results = self._run_palisade(config=_cfg)
        self.assertIn("'inexistent_key'", _err.exception.args[0])
Example #7
0
    def test_replace_context_value_namespace_with_space(self):
        _cfg = deepcopy(self.BASE_CFG)
        _cfg['expansions'] = {
            # ...times fifteen contexts
            'namespace with space': [dict(key=42)],
        }
        _cfg['templates'][0].update({
            'replace_under_here': {
                'context_value': ContextValue('"namespace with space"[key]'),
            }
        })

        _results = self._run_palisade(config=_cfg)
        self.assertEqual(len(_results), 1)
        self.assertEqual(_results[0]['replace_under_here']['context_value'],
                         42)
Example #8
0
    def test_replace_context_nested_list(self):
        _cfg = deepcopy(self.BASE_CFG)
        _cfg['templates'][0].update({
            'replace_under_here': {
                'context_nested_list': [[{
                    'inner_key':
                    ContextValue('namespace[key]')
                }]],
            }
        })

        _results = self._run_palisade(config=_cfg)
        self.assertEqual(len(_results), 1)
        self.assertEqual(
            _results[0]['replace_under_here']['context_nested_list'][0][0]
            ['inner_key'], self.BASE_CFG['expansions']['namespace'][0]['key'])
def get_config(directory_name, channel, sample_names, quantities,
               split_quantity, basename_fullsim, basename_noNP,
               file_suffix_fullsim, file_suffix_noNP, output_format,
               info_labels, upper_label):
    """
    function to create configurations for the plots
    :param directory_name:      Name of the analysis which produced the histograms or identifying prefix in the ROOT file
    :param channel:             Lepton channel of the corresponding data
    :param sample_names:        Name of the samples
    :param quantities:          Quantities to plot 
    :param split_quantities:    Quantities for which the data was selected and ordered
    :param basename_fullsim:    prefix for (path to) ROOT files containing histograms from full simulation
    :param basename_noNP:       prefix for (path to) ROOT files containing histograms from simulation with turned-off non-perturbative part
    :param file_suffix_fullsim: suffix of ROOT files containing histograms from full simulation
    :param file_suffix_noNP:    suffix of ROOT files containing histograms with turned-off non-perturbative part
    :param output_format:       format string indicating full path to output plot
    :param info_labels:         labels indicating additional information, shown as annotations in plot
    :param upper_label:         label to use in upper-right corner of plot
    :return:                    Karma config dictionary for plotting in the format described in the [Palisade user doc](https://karma-hep.readthedocs.io/en/latest/parts/palisade/user_guide.html)
    """

    # raise exception if samples specified are unknown
    _unknown_quantities = set(sample_names).difference(
        LOOKUP_SAMPLE_EXPANSION.keys())
    if _unknown_quantities:
        raise ValueError("Unknown samples: {}".format(
            ', '.join(_unknown_quantities)))

    # raise exception if quantities specified are unknown
    _unknown_quantities = set(quantities).difference(
        _q['name'] for _q in QUANTITIES['global'].values())
    if _unknown_quantities:
        raise ValueError("Unknown quantities: {}".format(
            ', '.join(_unknown_quantities)))

    # -- construct list of input files and correction level expansion dicts
    _input_files = dict()
    for _sample in sample_names:
        # fullsim: with non-perturbative parts
        _input_file_withNP = os.path.join(
            "{BASENAME_FULLSIM}".format(BASENAME_FULLSIM=basename_fullsim),
            "{SAMPLE_NAME}{SUFFIX_FULLSIM}.root".format(
                SUFFIX_FULLSIM="_" +
                str(file_suffix_fullsim) if str(file_suffix_fullsim) else "",
                SAMPLE_NAME=_sample))
        # raise exception if inputfile doesn't exist
        if not os.path.exists(_input_file_withNP):
            raise ValueError("Couldn't find inputfile {} for sample {}".format(
                _input_file_withNP, _sample))
        _input_files['withNP_{}'.format(_sample)] = _input_file_withNP

        # NP off: non-perturbative parts of simulation turned-off
        _input_file_noNP = os.path.join(
            "{BASENAME_NONP}".format(BASENAME_NONP=basename_noNP),
            "{SAMPLE_NAME}{SUFFIX_NONP}.root".format(SUFFIX_NONP="_" +
                                                     str(file_suffix_noNP),
                                                     SAMPLE_NAME=_sample))
        # raise exception if inputfile doesn't exist
        if not os.path.exists(_input_file_noNP):
            raise ValueError("Couldn't find inputfile {} for sample {}".format(
                _input_file_noNP, _sample))
        _input_files['noNP_{}'.format(_sample)] = _input_file_noNP

    # -- expansions
    # quantities to plot
    _expansions = {
        'quantity': [
            _q_dict for _q_dict in EXPANSIONS['quantity']
            if _q_dict['name'] in quantities
        ]
    }

    # ystar-yboost-bins
    if split_quantity == 'ystar':
        _expansions.update({
            'split': [
                dict(name=_k,
                     label=r"${}\leq y^{{*}}<{}$".format(
                         _v['ystar'][0], _v['ystar'][1]))
                for _k, _v in SPLITTINGS['ystar'].iteritems()
            ]
        })
    elif split_quantity == 'yboost':
        _expansions.update({
            'split': [
                dict(name=_k,
                     label=r"${}\leq y_{{\mathrm{{b}}}}<{}$".format(
                         _v['yboost'][0], _v['yboost'][1]))
                for _k, _v in SPLITTINGS['zpt'].iteritems()
            ]
        })
    elif split_quantity is None:
        _expansions['split'] = [dict(name='', label=r"incl.")]
    elif split_quantity == 'ystar*yboost':
        _expansions.update({
            'split': [
                dict(name=_k1 + _k2,
                     label=(r"${}\leq y_{{\mathrm{{b}}}}<{}$".format(
                         _v2['yboost'][0], _v2['yboost'][1]) +
                            r", ${}\leq y^{{*}}<{}$".format(
                                _v1['ystar'][0], _v1['ystar'][1])))
                for _k1, _v1 in SPLITTINGS['ystar'].iteritems()
                for _k2, _v2 in SPLITTINGS['yboost'].iteritems()
                if _v1['ystar'][0] + _v2['yboost'][0] <= 2
            ]
        })
    else:
        raise ValueError(
            'Expansions not implemented for split quantity {}!'.format(
                split_quantity))

    # append '[name]' to format keys that correspond to above expansion keys
    output_format = output_format.format(
        channel=channel,
        # get other possible replacements from expansions definition
        **{
            _expansion_key: "{{{0}[name]}}".format(_expansion_key)
            for _expansion_key in _expansions.keys()
        })

    # check which samples are requested with their identifier or sample name
    _sample_dicts = [LOOKUP_SAMPLE_EXPANSION[_s] for _s in sample_names]

    return {
        'input_files':
        _input_files,
        'figures': [
            {
                'filename':
                output_format,
                'dump_yaml':
                True,
                'figsize': (6, 6),
                'subplots': [
                    # NP-Corr = Ratio withNP/noNP
                    dict(expression="({})/({})".format(
                        build_expression("withNP", _s.get('name'),
                                         directory_name, "{quantity[name]}"),
                        build_expression("noNP", _s.get('name'),
                                         directory_name, "{quantity[name]}")),
                         label=_s.get('label', _s.get('name')),
                         plot_method='errorbar',
                         color=_s.get('style', dict()).get('color', 'k'),
                         marker=_s.get('style', dict()).get('marker', 'd'),
                         marker_style="full",
                         pad=0) for _s in _sample_dicts
                ] + [
                    # Ratio to first sample
                    dict(expression="({})/({})".format(
                        "({})/({})".format(
                            build_expression("withNP", _s.get('name'),
                                             directory_name,
                                             "{quantity[name]}"),
                            build_expression(
                                "noNP", _s.get('name'), directory_name,
                                "{quantity[name]}")), "({})/({})".format(
                                    build_expression(
                                        "withNP", _sample_dicts[0].get('name'),
                                        directory_name, "{quantity[name]}"),
                                    build_expression(
                                        "noNP", _sample_dicts[0].get('name'),
                                        directory_name, "{quantity[name]}"))),
                         label=None,
                         plot_method='errorbar',
                         color=_s.get('style', dict()).get('color', 'k'),
                         marker=_s.get('style', dict()).get('marker', 'd'),
                         marker_style="full",
                         pad=1) for _s in _sample_dicts
                ],
                'pad_spec': {
                    'right': 0.95,
                    'bottom': 0.15,
                    'top': 0.925,
                    'hspace': 0.075,
                },
                'pads': [
                    # top pad
                    {
                        'height_share':
                        3,
                        'x_range':
                        None,
                        'x_scale':
                        '{quantity[scale]}',
                        'y_label':
                        'non-pert. corr.',
                        # 'y_range' : (1e-3, 1e9),
                        'axvlines': [
                            dict(values=ContextValue(
                                'quantity[expected_values]'))
                        ],
                        'x_ticklabels': [],
                        'y_scale':
                        'linear',
                        'legend_kwargs':
                        dict(loc='upper right'),
                    },
                    # ratio pad
                    {
                        'height_share':
                        1,
                        'x_label':
                        '{quantity[label]}',
                        'x_range':
                        None,
                        'x_scale':
                        '{quantity[scale]}',
                        'y_label':
                        'Ratio',
                        'y_range': (0.8, 1.2),
                        'axhlines': [dict(values=[1.0])],
                        'axvlines': [
                            dict(values=ContextValue(
                                'quantity[expected_values]'))
                        ],
                        'y_scale':
                        'linear',
                        'legend_kwargs':
                        dict(loc='upper right'),
                    },
                ],
                'texts': [
                    dict(TEXTS['bold_label'],
                         xy=(0, 0),
                         xycoords='axes fraction',
                         xytext=(15, 15),
                         textcoords='offset points',
                         text="{split[label]}"),
                    TEXTS["CMS-in-plot-v2"],
                    TEXTS["Preliminary-in-plot-v2"],
                    TEXTS["Z{}".format(channel)],
                    dict(TEXTS['upper_label'],
                         text=upper_label if upper_label is not None else ""),
                ] + [
                    # labels with other information
                    dict(text=_label,
                         xy=(0, 0),
                         xycoords='axes fraction',
                         xytext=(15, 35 + 15 * _i_label),
                         textcoords='offset points')
                    for _i_label, _label in enumerate(reversed(info_labels))
                ],
            },
        ],
        'expansions':
        _expansions
    }
Example #10
0
 def test_context_value_nested(self):
     _cval = ContextValue(
         String("namespace[{}]").format(
             ContextValue('namespace[meta_key]')))
     self.assertEquals(_cval.eval(self._context),
                       self._context['namespace']['key_1'])
Example #11
0
 def test_context_value_expression(self):
     _cval = ContextValue('namespace[key_1]') + ContextValue(
         'namespace[key_2]')
     self.assertEquals(
         _cval.eval(self._context), self._context['namespace']['key_1'] +
         self._context['namespace']['key_2'])
Example #12
0
 def test_context_value_simple(self):
     _cval = ContextValue('namespace[key_1]')
     self.assertEquals(_cval.eval(self._context),
                       self._context['namespace']['key_1'])