1e81fdcb135d0325e3bc22fae0583555d20aae280Brendan Jackman#    Copyright 2015-2017 ARM Limited
2ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh#
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
16ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh"""Trigger is a representation of the following:
17ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh
18d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    - Event(s) (:mod:`trappy.base.Base`)
19d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    - An associated value
20d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh        - scalar
21d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh        - vector
22d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    - A set of filters
23d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh        - value based
24d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh        - function based
25ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh"""
26ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh
27ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singhimport types
28b95a4c5504771224bfe6a4abec759c00d2612a73Javi Merinofrom trappy.utils import listify
291ddd9d3bb4633c4fe48ebb8658d6c6449c7fab44Kapileshwar Singhimport pandas as pd
30ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh
31ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh
32ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singhclass Trigger(object):
33d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    """Trigger is an event-value relationship which
34c26a323210533d4ed3a8b4e62c33744236e3bedaJavi Merino    accepts a trace object to "generate" qualified data
35ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh
36c26a323210533d4ed3a8b4e62c33744236e3bedaJavi Merino    :param trace: A trappy FTrace object
37c26a323210533d4ed3a8b4e62c33744236e3bedaJavi Merino    :type trace: :mod:`trappy.trace.FTrace`
38ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh
39d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    :param template: A trappy Event to act as a trigger
40d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    :type template: trappy.Base
41d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh
42d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    :param filters: Key value filter pairs
43d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    :type filters: dict
44d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh
45d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    The filter can either have a function:
46d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    ::
47d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh
48d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh        def function_based_filter(elem):
49ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh            if condition:
50ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh                return True
51ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh            else:
52ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh                return False
53ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh
54d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    or a value/list of values
55d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    ::
56ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh
57d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh        f = {}
58d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh        f["data_column_a"] = function_based_filter
59d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh        f["data_column_b"] = value
60d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh
61f703d77cfc6f8f36051d6e5944370974326afddfJavi Merino    function_based_filter is anything that behaves like a function,
62f703d77cfc6f8f36051d6e5944370974326afddfJavi Merino    i.e. a callable.
63f703d77cfc6f8f36051d6e5944370974326afddfJavi Merino
64d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    :param value: Value can be a string or a numeric
65d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    :type value: str, int, float
66d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh
67d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    :param pivot: This is the column around which the data will be
68d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh        pivoted
69d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    :type pivot: str
70ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh    """
71ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh
72c26a323210533d4ed3a8b4e62c33744236e3bedaJavi Merino    def __init__(self, trace, template, filters, value, pivot):
73ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh
74ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh        self.template = template
75ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh        self._filters = filters
761ddd9d3bb4633c4fe48ebb8658d6c6449c7fab44Kapileshwar Singh        self._value = value
77ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh        self._pivot = pivot
78c26a323210533d4ed3a8b4e62c33744236e3bedaJavi Merino        self.trace = trace
79ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh
80ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh    def generate(self, pivot_val):
81ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh        """Generate the trigger data for a given pivot value
82c26a323210533d4ed3a8b4e62c33744236e3bedaJavi Merino        and a trace index
83ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh
84d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh        :param pivot_val: The pivot to generate data for
85d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh        :type pivot_val: hashable
86ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh        """
87ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh
88c26a323210533d4ed3a8b4e62c33744236e3bedaJavi Merino        trappy_event = getattr(self.trace, self.template.name)
89435457c8af9d69383ba45e0bd7da022d967a8deaJavi Merino        data_frame = trappy_event.data_frame
9005ffbccfb2eaec7ad8a1b6f4c1b8ef2706854089Javi Merino        data_frame = data_frame[data_frame[self._pivot] == pivot_val]
9105ffbccfb2eaec7ad8a1b6f4c1b8ef2706854089Javi Merino
9205ffbccfb2eaec7ad8a1b6f4c1b8ef2706854089Javi Merino        mask = [True for _ in range(len(data_frame))]
93ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh
94adeb9ab49aa913d381ebe1f7000b677c0dd15b4fJavi Merino        for key, value in self._filters.iteritems():
95f703d77cfc6f8f36051d6e5944370974326afddfJavi Merino            if hasattr(value, "__call__"):
96adeb9ab49aa913d381ebe1f7000b677c0dd15b4fJavi Merino                mask = mask & (data_frame[key].apply(value))
97ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh            else:
98ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh                mask = apply_filter_kv(key, value, data_frame, mask)
99ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh
1001ddd9d3bb4633c4fe48ebb8658d6c6449c7fab44Kapileshwar Singh        data_frame = data_frame[mask]
1011ddd9d3bb4633c4fe48ebb8658d6c6449c7fab44Kapileshwar Singh
1021ddd9d3bb4633c4fe48ebb8658d6c6449c7fab44Kapileshwar Singh        if isinstance(self._value, str):
1031ddd9d3bb4633c4fe48ebb8658d6c6449c7fab44Kapileshwar Singh            return data_frame[value]
1041ddd9d3bb4633c4fe48ebb8658d6c6449c7fab44Kapileshwar Singh        else:
1051ddd9d3bb4633c4fe48ebb8658d6c6449c7fab44Kapileshwar Singh            return pd.Series(self._value, index=data_frame.index)
106ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh
107ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh
108ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singhdef apply_filter_kv(key, value, data_frame, mask):
109ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh    """Internal function to apply a key value
110d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    filter to a data_frame and update the initial
111d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    condition provided in mask.
112d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh
113d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    :param value: The value to checked for
114d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh
115d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    :param data_frame: The data to be filtered
116d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    :type data_frame: :mod:`pandas.DataFrame`
117d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh
118d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    :param mask: Initial Condition Mask
119d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    :type mask: :mod:`pandas.Series`
120ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh
121d8fed2c6e783de0b42606177cd062fa265befff2Kapileshwar Singh    :return: A **mask** to index the data frame
122ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh    """
123ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh
124ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh    value = listify(value)
125ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh    if key not in data_frame.columns:
126ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh        return mask
127ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh    else:
128ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh        for val in value:
129ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh            mask = mask & (data_frame[key] == val)
130ca7994692ab5cf454c5b9742a556f24c5dbd8136Kapileshwar Singh        return mask
131