1e81fdcb135d0325e3bc22fae0583555d20aae280Brendan Jackman#    Copyright 2015-2017 ARM Limited
2c47d2dfb1de15e2a86e2d47ef822ae993375efdeJavi Merino#
3aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino# Licensed under the Apache License, Version 2.0 (the "License");
4aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino# you may not use this file except in compliance with the License.
5aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino# You may obtain a copy of the License at
6aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino#
7aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino#     http://www.apache.org/licenses/LICENSE-2.0
8aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino#
9aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino# Unless required by applicable law or agreed to in writing, software
10aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino# distributed under the License is distributed on an "AS IS" BASIS,
11aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino# See the License for the specific language governing permissions and
13aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino# limitations under the License.
14aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino#
15aace7c0732cac769f1ffe95a89591b6217fa9447Javi Merino
167319a880ca4883b064876f82654ce01aef9e60f8KP Singh"""This is the template class that all Plotters inherit"""
17341d912a093aaf9aaf831ed30a001ce9fea148e8Kapileshwar Singhfrom abc import abstractmethod, ABCMeta
187c1d99ea5405b5be263847a59c05495791894ce6Kapileshwar Singhfrom pandas import DataFrame
19e5c3597852f0bd31494b60b463d3b88e922d59cfJavi Merinoimport re
20b95a4c5504771224bfe6a4abec759c00d2612a73Javi Merinofrom trappy.utils import listify
217c1d99ea5405b5be263847a59c05495791894ce6Kapileshwar Singhfrom functools import reduce
227319a880ca4883b064876f82654ce01aef9e60f8KP Singh# pylint: disable=R0921
237319a880ca4883b064876f82654ce01aef9e60f8KP Singh# pylint: disable=R0903
247319a880ca4883b064876f82654ce01aef9e60f8KP Singh
257319a880ca4883b064876f82654ce01aef9e60f8KP Singh
267319a880ca4883b064876f82654ce01aef9e60f8KP Singhclass AbstractDataPlotter(object):
2721f9570fe513c87cf8de94449ca0e52d83ab3351Kapileshwar Singh    """This is an abstract data plotting Class defining an interface
2821f9570fe513c87cf8de94449ca0e52d83ab3351Kapileshwar Singh       for the various Plotting Classes"""
297319a880ca4883b064876f82654ce01aef9e60f8KP Singh
30341d912a093aaf9aaf831ed30a001ce9fea148e8Kapileshwar Singh    __metaclass__ = ABCMeta
31341d912a093aaf9aaf831ed30a001ce9fea148e8Kapileshwar Singh
32c26a323210533d4ed3a8b4e62c33744236e3bedaJavi Merino    def __init__(self, traces=None, attr=None, templates=None):
33bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh        self._event_map = {}
34bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh        self._attr = attr if attr else {}
35c26a323210533d4ed3a8b4e62c33744236e3bedaJavi Merino        self.traces = traces
3696602fc3cafea4e89a7b938e6d1363add1b9613fJohn Pocock        self.templates = templates
37bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh
387319a880ca4883b064876f82654ce01aef9e60f8KP Singh    @abstractmethod
397319a880ca4883b064876f82654ce01aef9e60f8KP Singh    def view(self):
407319a880ca4883b064876f82654ce01aef9e60f8KP Singh        """View the graph"""
417319a880ca4883b064876f82654ce01aef9e60f8KP Singh        raise NotImplementedError("Method Not Implemented")
425ebf1a3337a9e004d771a3fab8d72f4e3bfa2e9fKapileshwar Singh
435ebf1a3337a9e004d771a3fab8d72f4e3bfa2e9fKapileshwar Singh    @abstractmethod
445ebf1a3337a9e004d771a3fab8d72f4e3bfa2e9fKapileshwar Singh    def savefig(self, path):
4521f9570fe513c87cf8de94449ca0e52d83ab3351Kapileshwar Singh        """Save the image as a file
4621f9570fe513c87cf8de94449ca0e52d83ab3351Kapileshwar Singh
4721f9570fe513c87cf8de94449ca0e52d83ab3351Kapileshwar Singh        :param path: Location of the Saved File
4821f9570fe513c87cf8de94449ca0e52d83ab3351Kapileshwar Singh        :type path: str
4921f9570fe513c87cf8de94449ca0e52d83ab3351Kapileshwar Singh        """
505ebf1a3337a9e004d771a3fab8d72f4e3bfa2e9fKapileshwar Singh        raise NotImplementedError("Method Not Implemented")
51341d912a093aaf9aaf831ed30a001ce9fea148e8Kapileshwar Singh
527c1d99ea5405b5be263847a59c05495791894ce6Kapileshwar Singh    def _check_data(self):
537c1d99ea5405b5be263847a59c05495791894ce6Kapileshwar Singh        """Internal function to check the received data"""
547c1d99ea5405b5be263847a59c05495791894ce6Kapileshwar Singh
55c26a323210533d4ed3a8b4e62c33744236e3bedaJavi Merino        data = listify(self.traces)
567c1d99ea5405b5be263847a59c05495791894ce6Kapileshwar Singh
577c1d99ea5405b5be263847a59c05495791894ce6Kapileshwar Singh        if len(data):
587c1d99ea5405b5be263847a59c05495791894ce6Kapileshwar Singh            mask = map(lambda x: isinstance(x, DataFrame), data)
597c1d99ea5405b5be263847a59c05495791894ce6Kapileshwar Singh            data_frame = reduce(lambda x, y: x and y, mask)
60bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh            sig_or_template = self.templates or "signals" in self._attr
61bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh
62bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh            if not data_frame and not sig_or_template:
637c1d99ea5405b5be263847a59c05495791894ce6Kapileshwar Singh                raise ValueError(
644f4b18adce159f73b112ab789d695918ba45ef2fJavi Merino                    "Cannot understand data. Accepted DataFormats are pandas.DataFrame or trappy.FTrace/BareTrace/SysTrace (with templates)")
6544745135f3c7410d144115d3b50c9591d17baab1Javi Merino            elif data_frame and "column" not in self._attr:
66bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh                raise ValueError("Column not specified for DataFrame input")
677c1d99ea5405b5be263847a59c05495791894ce6Kapileshwar Singh        else:
687c1d99ea5405b5be263847a59c05495791894ce6Kapileshwar Singh            raise ValueError("Empty Data received")
69bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh
7025ffb28cd8c46e2f3c44e89b719cc79dcc33cb06Javi Merino    def _parse_value(self, signal_def):
7125ffb28cd8c46e2f3c44e89b719cc79dcc33cb06Javi Merino        """Parse a signal definition into a (template, column) tuple
7225ffb28cd8c46e2f3c44e89b719cc79dcc33cb06Javi Merino
7325ffb28cd8c46e2f3c44e89b719cc79dcc33cb06Javi Merino        :param signal_def: A signal definition. E.g. "trace_class:column"
7425ffb28cd8c46e2f3c44e89b719cc79dcc33cb06Javi Merino        :type signal_def: str
7525ffb28cd8c46e2f3c44e89b719cc79dcc33cb06Javi Merino        """
76bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh
77e5c3597852f0bd31494b60b463d3b88e922d59cfJavi Merino        match = re.match(r"(?P<event>[^:]+):(?P<column>[^:]+)(?P<color>:.+)?",
78e5c3597852f0bd31494b60b463d3b88e922d59cfJavi Merino                         signal_def)
7915c5a1f0d3927984b6c5d150127f83747fb135c8Brendan Jackman        if not match:
8015c5a1f0d3927984b6c5d150127f83747fb135c8Brendan Jackman            raise ValueError(
8115c5a1f0d3927984b6c5d150127f83747fb135c8Brendan Jackman                'Invalid signal definition "{}". '
8215c5a1f0d3927984b6c5d150127f83747fb135c8Brendan Jackman                'Should have the form "trace_class:column" '
8315c5a1f0d3927984b6c5d150127f83747fb135c8Brendan Jackman                'e.g. "cpu_frequency:frequency"'.format(signal_def))
84e5c3597852f0bd31494b60b463d3b88e922d59cfJavi Merino        event = match.group("event")
85e5c3597852f0bd31494b60b463d3b88e922d59cfJavi Merino        column = match.group("column")
86e5c3597852f0bd31494b60b463d3b88e922d59cfJavi Merino        color_match = match.group("color")
87e5c3597852f0bd31494b60b463d3b88e922d59cfJavi Merino        if color_match:
88e5c3597852f0bd31494b60b463d3b88e922d59cfJavi Merino            color_list = color_match[1:].split(",", 2)
89e5c3597852f0bd31494b60b463d3b88e922d59cfJavi Merino            color = [int(n, 16) if n.startswith("0x") else int(n) for n in color_list]
90e5c3597852f0bd31494b60b463d3b88e922d59cfJavi Merino        else:
91e5c3597852f0bd31494b60b463d3b88e922d59cfJavi Merino            color = None
92bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh
93bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh        try:
94e5c3597852f0bd31494b60b463d3b88e922d59cfJavi Merino            return self._event_map[event], column, color
95bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh        except KeyError:
96c26a323210533d4ed3a8b4e62c33744236e3bedaJavi Merino            for trace in listify(self.traces):
97bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh
98c26a323210533d4ed3a8b4e62c33744236e3bedaJavi Merino                if event in trace.class_definitions:
99c26a323210533d4ed3a8b4e62c33744236e3bedaJavi Merino                    self._event_map[event] = trace.class_definitions[event]
100e5c3597852f0bd31494b60b463d3b88e922d59cfJavi Merino                    return self._event_map[event], column, color
101bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh
102bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh            raise ValueError(
103bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh                "Event: " +
104bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh                event +
1054f4b18adce159f73b112ab789d695918ba45ef2fJavi Merino                " not found in Trace Object")
106bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh
107bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh    def _describe_signals(self):
108bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh        """Internal Function for populating templates and columns
109bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh        from signals
110bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh        """
111bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh
112bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh        if "column" in self._attr or self.templates:
113bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh            raise ValueError("column/templates specified with values")
114bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh
115bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh        self._attr["column"] = []
116842150378505f3c227ccdc5233759e7eebb535efJavi Merino        self.templates = []
117e5c3597852f0bd31494b60b463d3b88e922d59cfJavi Merino        colors = []
11896602fc3cafea4e89a7b938e6d1363add1b9613fJohn Pocock
119bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh        for value in listify(self._attr["signals"]):
120e5c3597852f0bd31494b60b463d3b88e922d59cfJavi Merino            template, column, color = self._parse_value(value)
121bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh            self.templates.append(template)
122bb752f8828c8d170f6ab32c1b88a3792bb31f0aeKapileshwar Singh            self._attr["column"].append(column)
123e5c3597852f0bd31494b60b463d3b88e922d59cfJavi Merino            colors.append(color)
124e5c3597852f0bd31494b60b463d3b88e922d59cfJavi Merino
125e5c3597852f0bd31494b60b463d3b88e922d59cfJavi Merino        if any(colors):
126e5c3597852f0bd31494b60b463d3b88e922d59cfJavi Merino            self._attr["colors"] = colors
127