Пример #1
0
    def process(cls, widget, job, data):
        class ColInfo:
            def __init__(self, col, dataindex, axis):
                self.col = col
                self.dataindex = dataindex
                self.axis = axis

        all_cols = job.get_columns()

        # The category "key" column -- this is the column shown along the
        # bottom of the bar widget
        keycols = [c for c in all_cols if c.name in widget.options.keycols]

        # columns of '*' is a special case, just use all
        # defined columns other than time
        if widget.options.columns == '*' or widget.options.dynamic:
            cols = [c for c in all_cols if not c.iskey]
        else:
            # The value columns - one set of bars for each
            cols = [c for c in all_cols if c.name in widget.options.columns]

        axes = Axes(widget.options.axes)

        # Array of data series definitions yui3 style
        series = []

        # Array of axis definitions yui3 style
        catname = '-'.join([k.name for k in keycols])
        w_axes = {
            catname: {
                "keys": [catname],
                "position": "bottom",
                "styles": {
                    "label": {
                        "rotation": -60
                    }
                }
            }
        }

        # Map of column info by column name
        colmap = {}

        # Add keycols to the colmap
        for i, c in enumerate(all_cols):
            if c not in keycols:
                continue
            ci = ColInfo(c, i, axes.getaxis(c.name))
            colmap[c.name] = ci

        for i, c in enumerate(all_cols):
            # Rest of this is for data cols only
            if c not in cols:
                continue

            ci = ColInfo(c, i, axes.getaxis(c.name))
            colmap[c.name] = ci

            series.append({
                "xKey": '-'.join([k.name for k in keycols]),
                "xDisplayName": ','.join([k.label for k in keycols]),
                "yKey": c.name,
                "yDisplayName": c.label,
                "styles": {
                    "line": {
                        "weight": 1
                    },
                    "marker": {
                        "height": 6,
                        "width": 20
                    }
                }
            })

            # The rest compute axis min/max for datavalues, so skip keys
            if c.iskey:
                continue

            axis_name = 'axis' + str(ci.axis)
            if axis_name not in w_axes:
                w_axes[axis_name] = {
                    "type": "numeric",
                    "position": ("left" if (ci.axis == 0) else "right"),
                    "keys": []
                }

            w_axes[axis_name]['keys'].append(c.name)

        # Array of actual data yui3 style.  Each row is a dict of key->value
        rows = []

        # min/max values by axis 0/1
        minval = {}
        maxval = {}

        stacked = False  # XXXCJ

        for rawrow in data:
            row = {}
            rowmin = {}
            rowmax = {}

            # collect key values
            keyvals = []
            for c in colmap.values():
                if not c.col.iskey:
                    continue
                keyvals.append(rawrow[c.dataindex])
            row[catname] = ','.join(str(k) for k in keyvals)

            # collect the data values
            for c in colmap.values():
                if c.col.iskey:
                    continue

                # Set the value
                val = rawrow[c.dataindex]
                row[c.col.name] = val

                a = c.axis
                if c.axis not in rowmin:
                    rowmin[a] = val
                    rowmax[a] = val
                else:
                    rowmin[a] = ((rowmin[a] +
                                  val) if stacked else min(rowmin[a], val))
                    rowmax[a] = ((rowmax[a] +
                                  val) if stacked else max(rowmax[a], val))

            for a in rowmin.keys():
                minval[a] = rowmin[a] if (a not in minval) else min(
                    minval[a], rowmin[a])
                maxval[a] = rowmax[a] if (a not in maxval) else max(
                    maxval[a], rowmax[a])
            rows.append(row)

        # Build up axes
        for c in colmap.values():
            if c.col.iskey:
                continue

            axis_name = 'axis' + str(c.axis)

            if minval and maxval:
                n = NiceScale(minval[c.axis], maxval[c.axis])

                w_axes[axis_name]['minimum'] = "%.10f" % n.nicemin
                w_axes[axis_name]['maximum'] = "%.10f" % n.nicemax
                w_axes[axis_name]['tickExponent'] = math.log10(n.tickspacing)
                w_axes[axis_name]['styles'] = {
                    'majorUnit': {
                        'count': n.numticks
                    }
                }
            else:
                # empty data which would result in keyError above
                w_axes[axis_name]['minimum'] = "0"
                w_axes[axis_name]['maximum'] = "1"
                w_axes[axis_name]['tickExponent'] = 1
                w_axes[axis_name]['styles'] = {'majorUnit': {'count': 1}}

        data = {
            "chartTitle": widget.title.format(**job.actual_criteria),
            "type": widget.options.charttype,
            "categoryKey": catname,
            "dataProvider": rows,
            "seriesCollection": series,
            "axes": w_axes,
            "legend": {
                "position": "bottom",
                "fontSize": "8pt",
                "styles": {
                    "gap": 0
                }
            }
        }

        return data
Пример #2
0
    def process(cls, widget, job, data):
        class ColInfo:
            def __init__(self, col, dataindex, axis):
                self.col = col
                self.dataindex = dataindex
                self.axis = axis

        all_cols = job.get_columns()

        # The category "key" column -- this is the column shown along the
        # bottom of the bar widget
        keycols = [c for c in all_cols if c.name in widget.options.keycols]

        # columns of '*' is a special case, just use all
        # defined columns other than time
        if widget.options.columns == '*' or widget.options.dynamic:
            cols = [c for c in all_cols if not c.iskey]
        else:
            # The value columns - one set of bars for each
            cols = [c for c in all_cols if c.name in widget.options.columns]

        axes = Axes(widget.options.axes)

        # Array of data series definitions yui3 style
        series = []

        # Array of axis definitions yui3 style
        catname = '-'.join([k.name for k in keycols])
        w_axes = {catname: {"keys": [catname],
                            "position": "bottom",
                            "styles": {"label": {"rotation": -60}}}}

        # Map of column info by column name
        colmap = {}

        # Add keycols to the colmap
        for i, c in enumerate(all_cols):
            if c not in keycols:
                continue
            ci = ColInfo(c, i, axes.getaxis(c.name))
            colmap[c.name] = ci

        for i, c in enumerate(all_cols):
            # Rest of this is for data cols only
            if c not in cols:
                continue

            ci = ColInfo(c, i, axes.getaxis(c.name))
            colmap[c.name] = ci

            series.append({"xKey": '-'.join([k.name for k in keycols]),
                           "xDisplayName": ','.join([k.label
                                                     for k in keycols]),
                           "yKey": c.name,
                           "yDisplayName": c.label,
                           "styles": {"line": {"weight": 1},
                                      "marker": {"height": 6,
                                                 "width": 20}}})

            # The rest compute axis min/max for datavalues, so skip keys
            if c.iskey:
                continue

            axis_name = 'axis' + str(ci.axis)
            if axis_name not in w_axes:
                w_axes[axis_name] = {"type": "numeric",
                                     "position": ("left" if (ci.axis == 0)
                                                  else "right"),
                                     "keys": []}

            w_axes[axis_name]['keys'].append(c.name)

        # Array of actual data yui3 style.  Each row is a dict of key->value
        rows = []

        # min/max values by axis 0/1
        minval = {}
        maxval = {}

        stacked = False  # XXXCJ

        for rawrow in data:
            row = {}
            rowmin = {}
            rowmax = {}

            # collect key values
            keyvals = []
            for c in colmap.values():
                if not c.col.iskey:
                    continue
                keyvals.append(rawrow[c.dataindex])
            row[catname] = ','.join(str(k) for k in keyvals)

            # collect the data values
            for c in colmap.values():
                if c.col.iskey:
                    continue

                # Set the value
                val = rawrow[c.dataindex]
                row[c.col.name] = val

                a = c.axis
                if c.axis not in rowmin:
                    rowmin[a] = val
                    rowmax[a] = val
                else:
                    rowmin[a] = ((rowmin[a] + val) if stacked
                                 else min(rowmin[a], val))
                    rowmax[a] = ((rowmax[a] + val) if stacked
                                 else max(rowmax[a], val))

            for a in rowmin.keys():
                minval[a] = rowmin[a] if (a not in minval) else min(minval[a],
                                                                    rowmin[a])
                maxval[a] = rowmax[a] if (a not in maxval) else max(maxval[a],
                                                                    rowmax[a])
            rows.append(row)

        # Build up axes
        for c in colmap.values():
            if c.col.iskey:
                continue

            axis_name = 'axis' + str(c.axis)

            if minval and maxval:
                n = NiceScale(minval[c.axis], maxval[c.axis])

                w_axes[axis_name]['minimum'] = "%.10f" % n.nicemin
                w_axes[axis_name]['maximum'] = "%.10f" % n.nicemax
                w_axes[axis_name]['tickExponent'] = math.log10(n.tickspacing)
                w_axes[axis_name]['styles'] = {
                    'majorUnit': {'count': n.numticks}
                }
            else:
                # empty data which would result in keyError above
                w_axes[axis_name]['minimum'] = "0"
                w_axes[axis_name]['maximum'] = "1"
                w_axes[axis_name]['tickExponent'] = 1
                w_axes[axis_name]['styles'] = {'majorUnit': {'count': 1}}

        data = {
            "chartTitle": widget.title.format(**job.actual_criteria),
            "type": widget.options.charttype,
            "categoryKey": catname,
            "dataProvider": rows,
            "seriesCollection": series,
            "axes": w_axes,
            "legend": {"position": "bottom",
                       "fontSize": "8pt",
                       "styles": {"gap": 0}}
        }

        return data
Пример #3
0
    def process(cls, widget, job, data):
        class ColInfo:
            def __init__(self,
                         col,
                         dataindex,
                         axis,
                         istime=False,
                         isdate=False):
                self.col = col
                self.key = cleankey(col.name)
                self.dataindex = dataindex
                self.axis = axis
                self.istime = istime
                self.isdate = isdate

        t_cols = job.get_columns()
        colinfo = {}  # map by widget key

        # columns of None is a special case, just use all
        # defined columns other than time
        if widget.options.columns is None:
            valuecolnames = [
                col.name for col in t_cols
                if not col.istime() and not col.isdate()
            ]
        else:
            valuecolnames = widget.options.columns

        # Column keys are the 'cleaned' column names
        w_keys = [cleankey(n) for n in valuecolnames]

        # Retrieve the desired value columns
        # ...and the indices for the value values
        # (as the 'data' has *all* columns)
        time_colinfo = None
        for i, c in enumerate(t_cols):
            if c.istime():
                ci = ColInfo(c, i, -1, istime=True)
                time_colinfo = ci
            elif c.isdate():
                ci = ColInfo(c, i, -1, isdate=True)
                time_colinfo = ci
            elif c.name in valuecolnames:
                if c.isnumeric():
                    ci = ColInfo(c, i, -1, istime=False, isdate=False)
                else:
                    raise KeyError(
                        "Cannot graph non-numeric data in timeseries widget: "
                        "column {0}".format(c.name))

            colinfo[ci.key] = ci

        if widget.options.altaxis:
            altaxis = widget.options.altaxis
            axes_def = {
                '0': {
                    'position': 'left',
                    'columns':
                    [col for col in valuecolnames if col not in altaxis]
                },
                '1': {
                    'position': 'right',
                    'columns':
                    [col for col in valuecolnames if col in altaxis]
                }
            }
        else:
            axes_def = {'0': {'position': 'left', 'columns': valuecolnames}}
        w_series = []
        axes = Axes(axes_def)

        # Setup the time axis
        w_axes = {
            "time": {
                "keys": ["time"],
                "position": "bottom",
                "type": "time",
                "styles": {
                    "label": {
                        "fontSize": "8pt",
                        "rotation": "-45"
                    }
                }
            }
        }

        # Create a better time format depending on t0/t1
        t_dataindex = time_colinfo.dataindex

        t0 = data[0][t_dataindex]
        t1 = data[-1][t_dataindex]
        if not hasattr(t0, 'utcfromtimestamp'):
            t0 = timeutils.sec_string_to_datetime(t0)
            t1 = timeutils.sec_string_to_datetime(t1)

        total_seconds = timeutils.timedelta_total_seconds(t1 - t0)
        if total_seconds < 2:
            w_axes['time']['formatter'] = 'formatTimeMs'
        elif total_seconds < 120:
            w_axes['time']['labelFormat'] = '%k:%M:%S'
        elif total_seconds < (24 * 60 * 60):
            w_axes['time']['labelFormat'] = '%k:%M'
        elif time_colinfo.isdate:
            w_axes['time']['formatter'] = 'formatDate'
        else:
            w_axes['time']['labelFormat'] = '%D %k:%M'

        # Setup the other axes, checking the axis for each column
        for w_key in w_keys:
            # Need to interate the valuecolnames array to preserve order
            ci = colinfo[w_key]

            w_series.append({
                "xKey": "time",
                "xDisplayName": "Time",
                "yKey": ci.key,
                "yDisplayName": ci.col.label,
                "styles": {
                    "line": {
                        "weight": 1
                    },
                    "marker": {
                        "height": 3,
                        "width": 3
                    }
                }
            })

            ci.axis = axes.getaxis(ci.col.name)
            axis_name = 'axis' + str(ci.axis)
            if axis_name not in w_axes:
                w_axes[axis_name] = {
                    "type": "numeric",
                    "position": axes.position(ci.axis),
                    "keys": []
                }

            w_axes[axis_name]['keys'].append(ci.key)

        # Output row data
        rows = []

        # min/max values by axis 0/1
        minval = {}
        maxval = {}

        stacked = widget.options.stacked
        # Iterate through all rows if input data
        for rawrow in data:
            t = rawrow[t_dataindex]
            try:
                t = timeutils.datetime_to_microseconds(t) / 1000
            except AttributeError:
                t = t * 1000

            row = {'time': t}
            rowmin = {}
            rowmax = {}
            for ci in colinfo.values():
                if ci.istime or ci.isdate:
                    continue
                a = ci.axis
                val = rawrow[ci.dataindex]
                row[ci.key] = val if val != '' else None

                # If stacked and there is only one value, use that
                # value as the rowmin.  If stacked and there is more than
                # one value for the axis, use a floor of 0 to give proper
                # context.
                if a not in rowmin:
                    rowmin[a] = val if val != '' else 0
                    rowmax[a] = val if val != '' else 0
                else:
                    rowmin[a] = (0 if stacked else min(rowmin[a], val))
                    rowmax[a] = ((rowmax[a] +
                                  val) if stacked else max(rowmax[a], val))

            for a in rowmin.keys():
                minval[a] = rowmin[a] if (a not in minval) else min(
                    minval[a], rowmin[a])
                maxval[a] = rowmax[a] if (a not in maxval) else max(
                    maxval[a], rowmax[a])

            rows.append(row)

        # Setup the scale values for the axes
        for ci in colinfo.values():
            if ci.istime or ci.isdate:
                continue

            axis_name = 'axis' + str(ci.axis)

            if minval and maxval:
                n = NiceScale(minval[ci.axis], maxval[ci.axis])

                w_axes[axis_name]['minimum'] = "%.10f" % n.nicemin
                w_axes[axis_name]['maximum'] = "%.10f" % n.nicemax
                w_axes[axis_name]['tickExponent'] = math.log10(n.tickspacing)
                w_axes[axis_name]['styles'] = {
                    'majorUnit': {
                        'count': n.numticks
                    }
                }
            else:
                # empty data which would result in keyError above
                w_axes[axis_name]['minimum'] = "0"
                w_axes[axis_name]['maximum'] = "1"
                w_axes[axis_name]['tickExponent'] = 1
                w_axes[axis_name]['styles'] = {'majorUnit': {'count': 1}}

            if ci.col.units == ci.col.UNITS_PCT:
                w_axes[axis_name]['formatter'] = 'formatPct'
            else:
                w_axes[axis_name]['formatter'] = 'formatMetric'

        if stacked:
            charttype = "area"
        elif widget.options.bar:
            charttype = "column"
        else:
            charttype = "combo"

        data = {
            "chartTitle": widget.title.format(**job.actual_criteria),
            "type": charttype,
            "stacked": stacked,
            "dataProvider": rows,
            "seriesCollection": w_series,
            "axes": w_axes,
            "legend": {
                "position": "bottom",
                "fontSize": "8pt",
                "styles": {
                    "gap": 0
                }
            },
            "interactionType": "planar"
        }

        # logger.debug("data:\n\n%s\n" % data)
        return data
Пример #4
0
    def process(cls, widget, job, data):
        class ColInfo:
            def __init__(self, col, dataindex, axis,
                         istime=False, isdate=False):
                self.col = col
                self.key = cleankey(col.name)
                self.dataindex = dataindex
                self.axis = axis
                self.istime = istime
                self.isdate = isdate
        t_cols = job.get_columns()
        colinfo = {}  # map by widget key

        # columns of None is a special case, just use all
        # defined columns other than time
        if widget.options.columns is None:
            valuecolnames = [col.name for col in t_cols
                             if not col.istime() and not col.isdate()]
        else:
            valuecolnames = widget.options.columns

        # Column keys are the 'cleaned' column names
        w_keys = [cleankey(n) for n in valuecolnames]

        # Retrieve the desired value columns
        # ...and the indices for the value values
        # (as the 'data' has *all* columns)
        time_colinfo = None
        for i, c in enumerate(t_cols):
            if c.istime():
                ci = ColInfo(c, i, -1, istime=True)
                time_colinfo = ci
            elif c.isdate():
                ci = ColInfo(c, i, -1, isdate=True)
                time_colinfo = ci
            elif c.name in valuecolnames:
                if c.isnumeric():
                    ci = ColInfo(c, i, -1, istime=False, isdate=False)
                else:
                    raise KeyError(
                        "Cannot graph non-numeric data in timeseries widget: "
                        "column {0}".format(c.name))

            colinfo[ci.key] = ci

        if widget.options.altaxis:
            altaxis = widget.options.altaxis
            axes_def = {'0': {'position': 'left',
                              'columns': [col for col in valuecolnames
                                          if col not in altaxis]},
                        '1': {'position': 'right',
                              'columns': [col for col in valuecolnames
                                          if col in altaxis]}
                        }
        else:
            axes_def = {'0': {'position': 'left',
                              'columns': valuecolnames}}
        w_series = []
        axes = Axes(axes_def)

        # Setup the time axis
        w_axes = {"time": {"keys": ["time"],
                           "position": "bottom",
                           "type": "time",
                           "styles": {"label": {"fontSize": "8pt",
                                                "rotation": "-45"}}}}

        # Create a better time format depending on t0/t1
        t_dataindex = time_colinfo.dataindex

        t0 = data[0][t_dataindex]
        t1 = data[-1][t_dataindex]
        if not hasattr(t0, 'utcfromtimestamp'):
            t0 = timeutils.sec_string_to_datetime(t0)
            t1 = timeutils.sec_string_to_datetime(t1)

        total_seconds = timeutils.timedelta_total_seconds(t1 - t0)
        if total_seconds < 2:
            w_axes['time']['formatter'] = 'formatTimeMs'
        elif total_seconds < 120:
            w_axes['time']['labelFormat'] = '%k:%M:%S'
        elif total_seconds < (24 * 60 * 60):
            w_axes['time']['labelFormat'] = '%k:%M'
        elif time_colinfo.isdate:
            w_axes['time']['formatter'] = 'formatDate'
        else:
            w_axes['time']['labelFormat'] = '%D %k:%M'

        # Setup the other axes, checking the axis for each column
        for w_key in w_keys:
            # Need to interate the valuecolnames array to preserve order
            ci = colinfo[w_key]

            w_series.append({"xKey": "time",
                             "xDisplayName": "Time",
                             "yKey": ci.key,
                             "yDisplayName": ci.col.label,
                             "styles": {"line": {"weight": 1},
                                        "marker": {"height": 3,
                                                   "width": 3}}})

            ci.axis = axes.getaxis(ci.col.name)
            axis_name = 'axis' + str(ci.axis)
            if axis_name not in w_axes:
                w_axes[axis_name] = {"type": "numeric",
                                     "position": axes.position(ci.axis),
                                     "keys": []
                                     }

            w_axes[axis_name]['keys'].append(ci.key)

        # Output row data
        rows = []

        # min/max values by axis 0/1
        minval = {}
        maxval = {}

        stacked = widget.options.stacked
        # Iterate through all rows if input data
        for rawrow in data:
            t = rawrow[t_dataindex]
            try:
                t = timeutils.datetime_to_microseconds(t) / 1000
            except AttributeError:
                t = t * 1000

            row = {'time': t}
            rowmin = {}
            rowmax = {}
            for ci in colinfo.values():
                if ci.istime or ci.isdate:
                    continue
                a = ci.axis
                val = rawrow[ci.dataindex]
                row[ci.key] = val if val != '' else None

                # If stacked and there is only one value, use that
                # value as the rowmin.  If stacked and there is more than
                # one value for the axis, use a floor of 0 to give proper
                # context.
                if a not in rowmin:
                    rowmin[a] = val if val != '' else 0
                    rowmax[a] = val if val != '' else 0
                else:
                    rowmin[a] = (0 if stacked
                                 else min(rowmin[a], val))
                    rowmax[a] = ((rowmax[a] + val) if stacked
                                 else max(rowmax[a], val))

            for a in rowmin.keys():
                minval[a] = rowmin[a] if (a not in minval) else min(minval[a],
                                                                    rowmin[a])
                maxval[a] = rowmax[a] if (a not in maxval) else max(maxval[a],
                                                                    rowmax[a])

            rows.append(row)

        # Setup the scale values for the axes
        for ci in colinfo.values():
            if ci.istime or ci.isdate:
                continue

            axis_name = 'axis' + str(ci.axis)

            if minval and maxval:
                n = NiceScale(minval[ci.axis], maxval[ci.axis])

                w_axes[axis_name]['minimum'] = "%.10f" % n.nicemin
                w_axes[axis_name]['maximum'] = "%.10f" % n.nicemax
                w_axes[axis_name]['tickExponent'] = math.log10(n.tickspacing)
                w_axes[axis_name]['styles'] = {
                    'majorUnit': {'count': n.numticks}
                }
            else:
                # empty data which would result in keyError above
                w_axes[axis_name]['minimum'] = "0"
                w_axes[axis_name]['maximum'] = "1"
                w_axes[axis_name]['tickExponent'] = 1
                w_axes[axis_name]['styles'] = {'majorUnit': {'count': 1}}

            if ci.col.units == ci.col.UNITS_PCT:
                w_axes[axis_name]['formatter'] = 'formatPct'
            else:
                w_axes[axis_name]['formatter'] = 'formatMetric'

        if stacked:
            charttype = "area"
        elif widget.options.bar:
            charttype = "column"
        else:
            charttype = "combo"

        data = {
            "chartTitle": widget.title.format(**job.actual_criteria),
            "type": charttype,
            "stacked": stacked,
            "dataProvider": rows,
            "seriesCollection": w_series,
            "axes": w_axes,
            "legend": {"position": "bottom",
                       "fontSize": "8pt",
                       "styles": {"gap": 0}},
            "interactionType": "planar"
        }

        # logger.debug("data:\n\n%s\n" % data)
        return data