Ejemplo n.º 1
0
    def __call__(self, config):
        plot = Plot(**config)

        callbacks.trigger('before_plot', plt=plt, mpl=matplotlib)

        # plot each object
        id_regex = config.get('plot_id', '')
        if isinstance(id_regex, basestring) or not isinstance(id_regex, collections.Iterable):
            id_regex = [id_regex]
        items = ([(x, config['objects'][x]) for x in config.get('plot_order', []) if x in config['objects'].keys()] + 
                [(x, config['objects'][x]) for x in config['objects'].keys() if x not in config.get('plot_order', [])])
        for id, item in items:
            item['id'] = id
            if item.get('no_plot', False):
                log.debug('Omitting id {0} since no_plot setting was set.'.format(id))
                continue
            if not any([re.match(regex, id) for regex in id_regex]):
                log.debug('Omitting id {0} since it does not match the regex.'.format(id))
                continue
            if not item.get('obj', None):
                log.warning('Not obj found for id {0}. Skipping this id.'.format(id))
                continue
            log.info('Drawing id {0}'.format(id))
            artist = plot.plot(**item)

        # Save plot
        plot.finish()
Ejemplo n.º 2
0
Archivo: core.py Proyecto: claria/plot
    def build_config(self, input_config=None, log_level='info'):
        """ Parse arguments. To set log level, load additional module parsers etc. the sys.args[1:] are parsed
            multiple times.
        :return: dict of parsed args
        """
        base_parser = SettingParser(add_help=False)
        base_parser_group = base_parser.add_argument_group(title='Base Parser', description='')
        base_parser_group.add_argument("--log-level", default=log_level, help="Set the log level.")
        base_parser_group.add_argument("--list-modules", action='store_true', help="List all available modules.")
        base_parser_group.add_argument("-l", "--load-config", default=[], nargs='+',
                                       help="Load json configs, with decreasing precedence,  or a python scripts from file.")

        # Parse only log level to set it as early as possible
        args = vars(base_parser.parse_known_args()[0])
        # Set log level
        log_level = getattr(logging, args['log_level'].upper(), None)
        if not isinstance(log_level, int):
            raise ValueError('Invalid log level: %s' % log_level)
        logging.basicConfig(format='%(message)s', level=log_level)

        # Discover all available modules
        self._all_modules = discover_modules()

        # If module list requested, print it and exit program
        if args['list_modules']:
            for label, module in self._all_modules.iteritems():
                print label
            sys.exit(0)

        # Load configs/python scripts from files if requested
        file_config = ConfigDict()
        for item in args.pop('load_config', []):
            if item.endswith('.json'):
                merge(file_config, read_config(item))
            elif item.endswith('.py'):
                log.info('Running python file {}'.format(item))
                runpy.run_path(item)
            else:
                raise ValueError('The file type of {0} is not supported.'.format(item))

        base_parser_group.add_argument("--input-modules", nargs='+', default=['RootModule'], help="Input modules .")
        base_parser_group.add_argument("--ana-modules", nargs='+', default=[], help="Analysis modules.")
        base_parser_group.add_argument("--output-modules", nargs='+', default=['PlotModule'], help="Output modules.")
        # Parse also the modules to add their parsers
        args = vars(base_parser.parse_known_args()[0])

        module_parsers = [self._all_modules[name]().parser for name in
                          args['input_modules'] + args['ana_modules'] + args['output_modules']]

        # Additional arguments for complete parser
        base_parser_group.add_argument("-p", "--print-config", default=False, action="store_true",
                                       help="Print out the JSON config before running Artus.")
        base_parser_group.add_argument("--store-json", type='bool', default=True,
                                       help="Save the config as json file.")
        base_parser_group.add_argument("--merge-args", nargs='+', default=[],
                                       help=("If json file configs and command line configs are provided the settings are "
                                       "merged for the provided args. Works only for list arguments."))
        base_parser_group.add_argument('--output-path', default='plot.png', help='Path to output file.')
        base_parser_group.add_argument('--output-prefix', default='plots/', help='Prefix to output paths.')


        # Final parser consists of baseparser + active module parsers
        parser = SettingParser(parents=[base_parser] + module_parsers,
                               description='''Plotting tool to read, manipulate and plot root objects.''')

        # Triggers before actual parameters are parsed.
        callbacks.trigger('before_parsing', config=file_config)

        # Final parsing of parameters
        args = vars(parser.parse_args())

        # If a config was loaded, merge it with the args
        if file_config:
            provided_args = args.pop('provided_args')
            merge_args = args.pop('merge_args')
            merge(file_config, args, precedence_keys=provided_args, merge_keys=merge_args)
            config = file_config

            if input_config:
                merge(input_config, config, precedence_keys=provided_args, merge_keys=merge_args)
                config = input_config
        else:
            config = args

        # ConfigDict is just a simple wrapper around a dict with some helper functions.
        return ConfigDict(config)
Ejemplo n.º 3
0
Archivo: core.py Proyecto: claria/plot
    def __call__(self, config=None, log_level=None):
        # Prepare configs from parsed args and provided input configs/python files
        config = self.build_config(config, log_level=log_level)

        # Triggered after config built
        callbacks.trigger('after_config', config=config)

        # At this point the config is 'complete'
        # While modules may add settings/etc to the config later on, the actual config is feature complete now
        # and can be saved to disk.
        if config.get('store_json', False):
            path = os.path.splitext(os.path.join('configs', config['output_path']))[0]
            write_config(config, path + '.json')

        # Replace values with lookup values
        perform_lookup_replacement(config)
        # Replace all environment variables
        walk_dic(config, os.path.expandvars)
        # Replace all symlinks with the real path
        walk_dic(config, relpath_replace)

        # Run all modules
        # Input modules
        for module in [self._all_modules[name]() for name in config['input_modules']]:
            log.info("Processing {0}...".format(module.label))
            callbacks.trigger('before_module_{0}'.format(module), config=config)
            module(config)
            callbacks.trigger('after_module_{0}'.format(module), config=config)
            update_with_default(config['objects'])
        # Triggered after all input modules processed.
        callbacks.trigger('after_input_modules', config=config)

        # Ana modules
        for module in [self._all_modules[name]() for name in config['ana_modules']]:
            log.info("Processing {0}...".format(module.label))
            callbacks.trigger('before_module_{0}'.format(module), config=config)
            module(config)
            callbacks.trigger('after_module_{0}'.format(module), config=config)
            update_with_default(config['objects'])
        # Triggered after all ana modules processed.
        callbacks.trigger('after_ana_modules', config=config)

        # Output modules
        for module in [self._all_modules[name]() for name in config['output_modules']]:
            log.info("Processing {0}...".format(module.label))
            callbacks.trigger('before_module_{0}'.format(module), config=config)
            module(config)
            callbacks.trigger('after_module_{0}'.format(module), config=config)
            update_with_default(config['objects'])
        # Triggered after all output modules processed.
        callbacks.trigger('after_ana_modules', config=config)

        path = os.path.splitext(os.path.join(config['output_prefix'], config['output_path']))[0]
        write_config(config, path + '.json')
Ejemplo n.º 4
0
    def finish(self):

        # Add colorbar if there is a mappable
        if self.colorbar_mappable:
            cb = self.fig.colorbar(self.colorbar_mappable, ax=self.ax)
            cb.ax.minorticks_on()
            cb.solids.set_rasterized(True)
            if self.z_label:
                cb.set_label(self.z_label)

        # Add axis texts
        for text in self.texts:
            text = get_lookup_val('ax_texts', text)
            default_text_kwargs = {'x': 0.05, 'y': 0.95, 'va': 'top', 'ha': 'left'}
            text_kwargs = parse_query(text)
            default_text_kwargs.update(text_kwargs)
            ax_name = default_text_kwargs.pop('axis', 'ax')

            s = default_text_kwargs.pop('s')
            r = re.compile(r'\$([^$]*)\$')
            s = r.sub(lambda m: m.group().replace('.', '.\!'), s)
            try:
                cax = getattr(self, ax_name)
            except AttributeError as e:
                log.critical('The axis name {0} does not exist.'.format(ax_name))
                log.critical(e)
                raise
            cax.text(s=s, transform=cax.transAxes, **default_text_kwargs)

        # Add horizontal lines to ax
        for hline_kwargs in self.hlines:
            ax_name = hline_kwargs.pop('axis', 'ax')
            try:
                cax = getattr(self, ax_name)
            except AttributeError as e:
                log.critical('The axis name {0} does not exist.'.format(ax_name))
                log.critical(e)
                raise
            cax.axhline(**hline_kwargs)

        # Add vertical lines to ax
        for vline_kwargs in self.vlines:
            ax_name = vline_kwargs.pop('axis', 'ax')
            try:
                cax = getattr(self, ax_name)
            except AttributeError as e:
                log.critical('The axis name {0} does not exist.'.format(ax_name))
                log.critical(e)
                raise
            cax.axvline(**vline_kwargs)

        # a specified position of the label can be set via label?json_dict
        x_label_kwargs = {'position': (1.0, 0.0), 'ha': 'right', 'va': 'top'}
        x_label, user_x_label_kwargs = parse_optionstring(self.x_label)
        x_label_kwargs.update(user_x_label_kwargs)
        if self.ax1:
            self.ax1.set_xlabel(x_label, **x_label_kwargs)
        else:
            self.ax.set_xlabel(x_label, **x_label_kwargs)

        y_label_kwargs = {'position': (0.0, 1.0), 'ha': 'right', 'va': 'bottom'}
        y_label, user_y_label_kwargs = parse_optionstring(self.y_label)
        y_label_kwargs.update(user_y_label_kwargs)
        self.ax.set_ylabel(y_label, **y_label_kwargs)

        if self.ax1:
            y_subplot_label, y_subplot_label_kwargs = parse_optionstring(self.y_subplot_label)
            self.ax1.set_ylabel(y_subplot_label, **y_subplot_label_kwargs)

        if self.x_log:
            self.ax.set_xscale('log')

            if self.x_axis_formatter == 'scalar':
                xfmt = ScalarFormatter()
                self.ax.xaxis.set_major_formatter(xfmt)
            elif self.x_axis_formatter == 'scalar2':
                xfmt = ScalarFormatter()
                self.ax.xaxis.set_minor_formatter(plt.FuncFormatter(log_locator_filter))
                self.ax.xaxis.set_major_formatter(xfmt)
            if self.ax1:
                self.ax1.set_xscale('log')
                if self.x_axis_formatter == 'scalar':
                    xfmt = ScalarFormatter()
                    self.ax1.xaxis.set_major_formatter(xfmt)
                elif self.x_axis_formatter == 'scalar2':
                    xfmt = ScalarFormatter()
                    self.ax1.xaxis.set_minor_formatter(plt.FuncFormatter(log_locator_filter))
                    self.ax1.xaxis.set_major_formatter(xfmt)

        else:
            self.ax.set_xscale('linear')


        if self.y_log:
            self.ax.set_yscale('log', nonposy='clip')
            if self.y_axis_formatter == 'scalar':
                xfmt = ScalarFormatter()
                self.ax.yaxis.set_major_formatter(xfmt)
            elif self.y_axis_formatter == 'scalar2':
                xfmt = ScalarFormatter()
                self.ax.yaxis.set_major_formatter(xfmt)
                self.ax.yaxis.set_minor_formatter(plt.FuncFormatter(log_locator_filter))
        else:
            self.ax.set_yscale('linear')
       
        # By default set a 10% margin
        plot_tools.set_margin(margin=self.margin)

        self.ax.set_ylim(ymin=self.y_lims[0], ymax=self.y_lims[1])
        self.ax.set_xlim(xmin=self.x_lims[0], xmax=self.x_lims[1])

        if self.show_legend:
            # handles, labels = self.ax.get_legend_handles_labels()
            no_legend_ids = ['nolegend', '_nolegend_', '__nolegend__','none', '']

            # handles = self._legend_handles
            # labels = self._legend_labels
            # TODO combine legend entries
            for id, id2 in self.combine_legend_entries:
                log.debug('Combining legend entries {0} and {1}'.format(id, id2))
                if id in self._ids and id2 in self._ids:
                    self._legend_handles[self._ids.index(id)] = (self._legend_handles[self._ids.index(id2)],self._legend_handles[self._ids.index(id)]) 
            leg_entry_dict = OrderedDict(zip(self._legend_labels, self._legend_handles))
            for key in leg_entry_dict.keys():
                if key.lower() in no_legend_ids:
                    del leg_entry_dict[key]

            if leg_entry_dict:
                labels, handles = zip(*leg_entry_dict.items())
                if 'outside' in self.legend_loc:
                    if self.legend_bbox_anchor:
                        bbox_to_anchor = self.legend_bbox_anchor
                    else:
                        bbox_to_anchor = (1, 1)

                    self.legend_loc = self.legend_loc.replace('outside', '').strip()
                else:
                    bbox_to_anchor = None
                legend = self.ax.legend(handles, labels, loc=self.legend_loc, ncol=self.legend_ncol, bbox_to_anchor=bbox_to_anchor)
                legend.get_frame().set_alpha(0.0)

                # [obj.set_rasterized(True) for obj in legend.get_patches()]
                # for obj in legend.get_patches():
                    # obj.set_rasterized(True)

                # legend.draw()
                # self.ax.legend_ = None
                # self.ax.add_artist(legend)
            else:
                log.debug('Omit legend since all labels are empty.')

        if self.ax1:
            self.ax1.set_ylim(ymin=self.y_subplot_lims[0], ymax=self.y_subplot_lims[1])
            plt.setp(self.ax.get_xticklabels(), visible=False)
            plt.setp(self.ax.get_xticklabels(minor=True), visible=False)
            # self.ax1.set_xscale(self.ax.get_xscale())
            self.ax1.set_xlim(self.ax.get_xlim())
            plt.subplots_adjust(hspace=0.15)

        callbacks.trigger('after_plot', plt=self)

        self.save_fig()
        plt.close(self.fig)