Beispiel #1
0
 def _make_series_item(self, idx, item, dim_ordinal, display_schema, metrics, reference, color='#000'):
     metric_key = utils.slice_first(idx)
     return {
         'name': self._format_label(idx, dim_ordinal, display_schema, reference),
         'data': self._format_data(item),
         'tooltip': self._format_tooltip(display_schema['metrics'][metric_key]),
         'yAxis': metrics.index(utils.slice_first(idx)),
         'color': color,
         'dashStyle': 'Dot' if reference else 'Solid'
     }
Beispiel #2
0
    def _metrics_schema(self, metrics=(), operations=()):
        keys = list(metrics) + [
            metric for op in operations for metric in op.metrics()
        ]

        if not keys:
            raise SlicerException(
                'At least one metric is required requests.  Please add a metric.'
            )

        invalid_metrics = {utils.slice_first(key)
                           for key in keys} - set(self.slicer.metrics)
        if invalid_metrics:
            raise SlicerException('Invalid metrics included in request: '
                                  '[%s]' % ', '.join(invalid_metrics))

        schema_metrics = OrderedDict()
        for key in keys:
            schema_metric = self.slicer.metrics.get(key)

            for metric_key, definition in schema_metric.schemas():
                schema_metrics[
                    metric_key] = definition or self._default_metric_definition(
                        metric_key)

        return schema_metrics
Beispiel #3
0
    def _references_schema(self, references, dimensions):
        dimension_keys = {
            utils.slice_first(dimension)
            for dimension in dimensions
        }

        schema_references = OrderedDict()
        for reference in references:
            if reference.element_key not in dimension_keys:
                raise SlicerException(
                    'Unable to query with [{reference}]. '
                    'Dimension [{dimension}] is missing.'.format(
                        reference=str(reference),
                        dimension=reference.element_key))

            from .schemas import DatetimeDimension
            if not isinstance(self.slicer.dimensions[reference.element_key],
                              DatetimeDimension):
                raise SlicerException(
                    'Unable to query with [{reference}]. '
                    'Dimension [{dimension}] must be a DatetimeDimension.'.
                    format(reference=str(reference),
                           dimension=reference.element_key))

            schema_references[reference.key] = {
                'dimension': reference.element_key,
                'interval': reference.interval,
                'modifier': reference.modifier,
            }

        return schema_references
Beispiel #4
0
    def prevalidate_request(self, slicer, metrics, dimensions, metric_filters,
                            dimension_filters, references, operations):
        if not dimensions or not slicer.dimensions:
            raise TransformationException(MISSING_CONT_DIM_MESSAGE)

        from fireant.slicer import ContinuousDimension
        first_dimension = utils.slice_first(dimensions[0])
        dimension0 = slicer.dimensions[first_dimension]
        if not isinstance(dimension0, ContinuousDimension):
            raise TransformationException(MISSING_CONT_DIM_MESSAGE)
Beispiel #5
0
    def _get_and_transform_data(self, tx, metrics=(), dimensions=(),
                                metric_filters=(), dimension_filters=(),
                                references=(), operations=()):
        """
        Handles a request and applies a transformation to the result.  This is the implementation of all of the
        transformer manager methods, which are constructed in the __init__ function of this class for each transformer.

        The request is first validated with the transformer then the request is executed via the SlicerManager and then
        lastly the result is transformed and returned.

        :param tx:
            The transformer to use
        :param metrics:
            See ``fireant.slicer.SlicerManager``
            A list of metrics to include in the query.

        :param dimensions:
            See ``fireant.slicer.SlicerManager``
            A list of dimensions to include in the query.

        :param metric_filters:
            See ``fireant.slicer.SlicerManager``
            A list of metrics filters to apply to the query.

        :param dimension_filters:
            See ``fireant.slicer.SlicerManager``
            A list of dimension filters to apply to the query.

        :param references:
            See ``fireant.slicer.SlicerManager``
            A list of references to include in the query

        :param operations:
            See ``fireant.slicer.SlicerManager``
            A list of post-operations to apply to the result before transformation.

        :return:
            The transformed result of the request.
        """
        tx.prevalidate_request(self.manager.slicer, metrics=metrics, dimensions=[utils.slice_first(dimension)
                                                                                 for dimension in dimensions],
                               metric_filters=metric_filters, dimension_filters=dimension_filters,
                               references=references, operations=operations)

        # Loads data and transforms it with a given transformer.
        df = self.manager.data(metrics=metrics, dimensions=dimensions,
                               metric_filters=metric_filters, dimension_filters=dimension_filters,
                               references=references, operations=operations)

        display_schema = self.manager.display_schema(metrics, dimensions, references, operations)

        df = utils.correct_dimension_level_order(df, display_schema)

        return tx.transform(df, display_schema)
Beispiel #6
0
 def _make_series_item(self, idx, item, dim_ordinal, display_schema, metrics, reference, color='#000'):
     metric_key = utils.slice_first(idx)
     return {
         'name': self._format_label(idx, dim_ordinal, display_schema, reference),
         'data': [_format_data_point(x)
                  for x in item
                  if not (isinstance(x, (float, int)) and np.isnan(x))],
         'tooltip': self._format_tooltip(display_schema['metrics'][metric_key]),
         'yAxis': metrics.index(metric_key),
         'color': color,
     }
Beispiel #7
0
 def _make_series_item(self,
                       idx,
                       item,
                       dim_ordinal,
                       display_schema,
                       metrics,
                       reference,
                       color='#000'):
     metric_key = utils.slice_first(idx)
     return {
         'name': self._format_label(idx, dim_ordinal, display_schema,
                                    reference),
         'data': self._format_data(item),
         'tooltip':
         self._format_tooltip(display_schema['metrics'][metric_key]),
         'color': color
     }
Beispiel #8
0
    def _display_dimensions(self, dimensions):
        req_dimension_keys = [utils.slice_first(dimension)
                              for dimension in dimensions]

        display_dims = OrderedDict()
        for key in req_dimension_keys:
            dimension = self.slicer.dimensions[key]
            display_dim = {'label': dimension.label}

            if hasattr(dimension, 'display_options'):
                display_dim['display_options'] = {opt.key: opt.label
                                                  for opt in dimension.display_options}

            if hasattr(dimension, 'display_field'):
                display_dim['display_field'] = '%s_display' % dimension.key

            display_dims[key] = display_dim

        return display_dims
Beispiel #9
0
    def _totals_schema(self, dimensions, operations):
        dimension_set = set(
            utils.slice_first(dimension) for dimension in dimensions)
        totals, missing_dimensions = [], set()

        for operation in operations:
            if operation.key != Totals.key:
                continue

            missing_dimensions |= set(operation.dimension_keys) - dimension_set
            totals += [[
                level for level in self.slicer.dimensions[dimension].levels()
            ] for dimension in operation.dimension_keys]

        if missing_dimensions:
            raise SlicerException("Missing dimensions with keys: {}".format(
                ", ".join(missing_dimensions)))

        return totals
Beispiel #10
0
    def _joins_schema(self, keys, elements):
        """

        :param keys:
            The keys of the schema elements to retrieve joins for.
        :param elements:
            The elements to retrieve the joins from, either slicer.metrics or slicer.dimensions.
        :return:
            A `set` of join schemas containing the join table and the join criterion.
        """
        joins = set()

        for key in keys:
            schema_metric = elements.get(utils.slice_first(key))
            if schema_metric.joins:
                joins |= set(schema_metric.joins)

        return {(self.slicer.joins[key].table,
                 self.slicer.joins[key].criterion,
                 self.slicer.joins[key].join_type)
                for key in joins}
Beispiel #11
0
 def _make_series_item(self,
                       idx,
                       item,
                       dim_ordinal,
                       display_schema,
                       metrics,
                       reference,
                       color='#000'):
     """
     Overriding the parent class' _make_series_item to remove the yAxis key as area charts
     only really make sense on a single y axis
     """
     metric_key = utils.slice_first(idx)
     return {
         'name': self._format_label(idx, dim_ordinal, display_schema,
                                    reference),
         'data': self._format_data(item),
         'tooltip':
         self._format_tooltip(display_schema['metrics'][metric_key]),
         'color': color,
         'dashStyle': 'Dot' if reference else 'Solid'
     }
Beispiel #12
0
    def _dimensions_schema(self, keys):
        invalid_dimensions = {utils.slice_first(key)
                              for key in keys} - set(self.slicer.dimensions)
        if invalid_dimensions:
            raise SlicerException('Invalid dimensions included in request: '
                                  '[%s]' % ', '.join(invalid_dimensions))

        dimensions = OrderedDict()
        for dimension in keys:
            # unpack tuples for args
            if isinstance(dimension, (list, tuple)):
                dimension, args = dimension[0], dimension[1:]
            else:
                args = []

            schema_dimension = self.slicer.dimensions.get(dimension)

            for key, definition in schema_dimension.schemas(
                    *args, database=self.slicer.database):
                dimensions[
                    key] = definition or self._default_dimension_definition(
                        key)

        return dimensions