Source code for plums.plot.engine.orchestrator

from plums.commons import PropertyContainer, DataPoint, Annotation, Tile, RecordCollection
from plums.plot.engine.color_engine import ColorEngine
from plums.plot.engine.compositor import Compositor


[docs]class OrchestratorBase(PropertyContainer): """Medium-level orchestrator which configure a |Compositor| and a |ColorEngine| from |Descriptor| and a layout. It serves as an intermediary between high-level *porcelain classes* and low-level *plumbing classes*: * Its constructor gives access to all *plumbing classes* parameters to allow extensive configuration of the internal potting machinery (Moreover, every *plumbing classes* used parameters are accessible and parameterizable as attributes of the orchestrator instance.) * Its :meth:`draw(layout) <draw>` method takes a generic ``layout`` iterable as input with no assumption on the semantic role of a particular figure cell. However, the *plumbing call sequence* does assume a standard workflow which reflect the *porcelain classes* API. Args: main_descriptor (|Descriptor|): A |Descriptor| to be used as primary descriptor in the |ColorEngine|. secondary_descriptor (|Descriptor|): Optional. Default to ``None``. A |Descriptor| to be used as secondary descriptor in the |ColorEngine|. zoom (float): Optional. Default to ``1``. The zooming factor for each |Tile| in the ``layout``. title (str): Optional. Default to ``None``. The composite figure global title, if provided. plot_centers (bool): Optional. Default to ``False``. If ``True``, only a dot at the center of each |Record| is painted instead of the polygon geometry. plot_tag (|Descriptor|): Optional. Defaults to ``None``. Besides the geometry, display a |Record| description in a tag attached to the |Record|. fill (bool): Optional. Default to ``False``. A flag which represents whether to draw filled polygons. **kwargs (Any): Additional parameters to set. Attributes: main_descriptor (|Descriptor|): |ColorEngine| **parameter**: A |Descriptor| to be used as primary descriptor. secondary_descriptor (|Descriptor|): |ColorEngine| **parameter**: A |Descriptor| to be used as secondary descriptor. n_cols (int): |Compositor| **parameter**: Number of data points per line to not exceed (if 1D array-like of |DataPoint|). margins (tuple): |Compositor| **parameter**: Margin to use between each image of the mosaic. title (str): |Compositor| **parameter**: The composite figure global title, if provided. title_size (int): |Compositor| **parameter**: Font size of the title (in pixels). center (bool): |Compositor| **parameter**: Center the last line of data points (if 1D array-like of |DataPoint|). background_color (tuple): (|Compositor|, |LegendPainter|) Background color to use for the mosaic and the legend. scale (float): |LegendPainter| **parameter**: Scale to use, regarding the default dimensions used. axis (int): |LegendPainter| **parameter**: Main direction of the legend (**0** = vertically, **1** = horizontally) item_margins (tuple): |LegendPainter| **parameter**: Margins around the item (left/right and top/bottom). main_axis_align (str): |LegendPainter| **parameter**: Alignment of the item in its cell along the main axis. minor_axis_align (str): |LegendPainter| **parameter**: Alignment of the item in its cell along the minor axis. zoom (float): |Painter| **parameter**: The zooming factor for each |Tile| in the ``layout``. plot_centers (bool): |Painter| **parameter**: If ``True``, only a dot at the center of each |Record| is painted instead of the polygon geometry. plot_confidences (bool): |Painter| **parameter**: If ``True``, a label with the confidence is painted next to each |Record|. fill (bool): |Painter| **parameter**: A flag which represents whether to draw filled polygons. alpha (int): |Painter| **parameter**: A positive integer (between 0 and 255) that represents the fill transparency. """ __options__ = ('zoom', 'plot_centers', 'plot_confidences', 'plot_tag', 'title', 'background_color', 'fill', 'n_cols', 'margins', 'background_color', 'title', 'title_size', 'center', 'plot_centers', 'plot_confidences', 'zoom', 'fill', 'alpha', 'scale', 'axis', 'item_margins', 'main_axis_align', 'minor_axis_align', 'main_descriptor', 'secondary_descriptor') def __init__(self): super(OrchestratorBase, self).__init__(**{option: None for option in self.__options__})
[docs]class Orchestrator(OrchestratorBase): """Medium-level orchestrator which configure a |Compositor| and a |ColorEngine| from |Descriptor| and a layout. It serves as an intermediary between high-level *porcelain classes* and low-level *plumbing classes*: * Its constructor gives access to all *plumbing classes* parameters to allow extensive configuration of the internal potting machinery (Moreover, every *plumbing classes* used parameters are accessible and parameterizable as attributes of the orchestrator instance.) * Its :meth:`draw(layout) <draw>` method takes a generic ``layout`` iterable as input with no assumption on the semantic role of a particular figure cell. However, the *plumbing call sequence* does assume a standard workflow which reflect the *porcelain classes* API. Args: main_descriptor (|Descriptor|): A |Descriptor| to be used as primary descriptor in the |ColorEngine|. secondary_descriptor (|Descriptor|): Optional. Default to ``None``. A |Descriptor| to be used as secondary descriptor in the |ColorEngine|. zoom (float): Optional. Default to ``1``. The zooming factor for each |Tile| in the ``layout``. title (str): Optional. Default to ``None``. The composite figure global title, if provided. plot_centers (bool): Optional. Default to ``False``. If ``True``, only a dot at the center of each |Record| is painted instead of the polygon geometry. plot_confidences (bool): Optional. Deprecated (Superseded by ``plot_tag``). Defaults to ``False``. If ``True``, a label with the confidence is painted next to each |Record|. plot_tag (|Descriptor|): Optional. Defaults to ``None``. Besides the geometry, display a |Record| description in a tag attached to the |Record|. Note that while ``plot_confidences`` is being deprecated, specifying it will override ``plot_tag``. fill (bool): Optional. Default to ``False``. A flag which represents whether to draw filled polygons. **kwargs (Any): Additional parameters to set. Attributes: main_descriptor (|Descriptor|): |ColorEngine| **parameter**: A |Descriptor| to be used as primary descriptor. secondary_descriptor (|Descriptor|): |ColorEngine| **parameter**: A |Descriptor| to be used as secondary descriptor. n_cols (int): |Compositor| **parameter**: Number of data points per line to not exceed (if 1D array-like of |DataPoint|). margins (tuple): |Compositor| **parameter**: Margin to use between each image of the mosaic. title (str): |Compositor| **parameter**: The composite figure global title, if provided. title_size (int): |Compositor| **parameter**: Font size of the title (in pixels). center (bool): |Compositor| **parameter**: Center the last line of data points (if 1D array-like of |DataPoint|). background_color (tuple): (|Compositor|, |LegendPainter|) Background color to use for the mosaic and the legend. scale (float): |LegendPainter| **parameter**: Scale to use, regarding the default dimensions used. axis (int): |LegendPainter| **parameter**: Main direction of the legend (**0** = vertically, **1** = horizontally) item_margins (tuple): |LegendPainter| **parameter**: Margins around the item (left/right and top/bottom). main_axis_align (str): |LegendPainter| **parameter**: Alignment of the item in its cell along the main axis. minor_axis_align (str): |LegendPainter| **parameter**: Alignment of the item in its cell along the minor axis. zoom (float): |Painter| **parameter**: The zooming factor for each |Tile| in the ``layout``. plot_centers (bool): |Painter| **parameter**: If ``True``, only a dot at the center of each |Record| is painted instead of the polygon geometry. plot_tag (|Descriptor|):|Painter| **parameter**: Besides the geometry, display a |Record| description in a tag attached to the |Record|. Note that while :attr:`plot_confidences` is being deprecated, specifying it will override :attr:`plot_tag`. fill (bool): |Painter| **parameter**: A flag which represents whether to draw filled polygons. alpha (int): |Painter| **parameter**: A positive integer (between 0 and 255) that represents the fill transparency. """ def __init__(self, main_descriptor, secondary_descriptor=None, zoom=1, title=None, plot_centers=False, plot_tag=None, fill=False, **kwargs): # Initialize properties dictionary super(Orchestrator, self).__init__() # Set defaults option values as properties self.n_cols = 20 self.margins = (5, 5) self.title_size = 25 self.background_color = (255, 255, 255) self.center = True self.alpha = 64 self.scale = 1.0 self.axis = 0 self.item_margins = (10, 10) self.main_axis_align = 'start' self.minor_axis_align = 'start' # Update properties with optional user-provided values self.properties.update(kwargs) # Set explicit kwargs values self.fill = fill self.plot_tag = plot_tag self.plot_centers = plot_centers self.title = title self.zoom = zoom self.secondary_descriptor = secondary_descriptor self.main_descriptor = main_descriptor
[docs] def draw(self, layout): # noqa: R701 """Draw a composite figure according to the stored *plumbing class* parameters and a layout array. Args: layout (array-like): Two formats are allowed: a 2D array-like of |DataPoint|-like collection of |Tile| and |RecordCollection| to be drawn. Each line of the 2D array-like is expected to correspond to a line layout in the final mosaic cell. Or a 1D array-like of |DataPoint|. In that case, the data points will be placed side by side, forming a mosaic of tiles, with rows of same length. Returns: :class:`~PIL.Image.Image`: A composite figure. """ # Sanity check if not isinstance(layout, (list, tuple)): raise ValueError('`layout` should either be a list/tuple, but given {}'.format(type(layout))) if not all(isinstance(value, (list, tuple)) for value in layout): raise ValueError('`layout` should either be a list/tuple of DataPoint-like array ' 'or a list/tuple of lists/tuples of DataPoint-like array.') if all(isinstance(sub_value, (list, tuple)) for value in layout for sub_value in value): layout_2d = True elif all(isinstance(sub_value, (Tile, RecordCollection)) for value in layout for sub_value in value): layout_2d = False else: raise ValueError('`layout` should either be a list/tuple of DataPoint-like array ' 'or a list/tuple of lists/tuples of DataPoint-like array.') tag_descriptor = self.plot_tag color_engine = ColorEngine(self.main_descriptor, self.secondary_descriptor) # Update descriptors with total data range if layout_2d: for line in layout: for data_point_like in line: # If plot tag next to record: Handle tag descriptor first if tag_descriptor is not None: tag_descriptor.update(*data_point_like[1:]) # Handle colors color_engine.update(*data_point_like[1:]) else: for data_point_like in layout: # If plot tag next to record: Handle tag descriptor first if tag_descriptor is not None: tag_descriptor.update(*data_point_like[1:]) # Handle colors color_engine.update(*data_point_like[1:]) # Compute Colors and retrieve RecordCollections to paint data_point_layout = [] if layout_2d: for line in layout: data_point_line = [] for data_point_like in line: # If plot tag next to record: Handle tag descriptor first if tag_descriptor is not None: record_collection_tuple = tag_descriptor.compute(*data_point_like[1:]) data_point_like = (data_point_like[0], ) + record_collection_tuple # Handle colors record_collection = color_engine.compute(*data_point_like[1:])[0] data_point_line.append(DataPoint(data_point_like[0], Annotation(record_collection))) data_point_layout.append(data_point_line) else: for data_point_like in layout: # If plot tag next to record: Handle tag descriptor first if tag_descriptor is not None: record_collection_tuple = tag_descriptor.compute(*data_point_like[1:]) data_point_like = (data_point_like[0], ) + record_collection_tuple # Handle colors record_collection = color_engine.compute(*data_point_like[1:])[0] data_point_layout.append(DataPoint(data_point_like[0], Annotation(record_collection))) # Compose the total figure from computed, described DataPoint layout compositor = Compositor(data_point_layout, color_engine.__descriptor__) pillow_figure = compositor.plot(**self.properties) return pillow_figure