Example #1
0
def plotxy(
    data,
    xerrors=None,
    yerrors=None,
    xlimits=None,
    ylimits=None,
    xscale=1,
    yscale=None,
    xlogscale=False,
    ylogscale=False,
    c="k",
    alpha=1,
    xtitle="x",
    ytitle="y",
    title="",
    titleSize=None,
    ec=None,
    lc="k",
    lw=2,
    line=True,
    dashed=False,
    splined=False,
    marker=None,
    ms=None,
    mc=None,
    ma=None,
):
    """Draw a 2D plot of variable x vs y.

    :param list data: input format can be [allx, ally] or [(x1,y1), (x2,y2), ...]

    :param list xerrors: set uncertainties for the x variable, shown as error bars.
    :param list yerrors: set uncertainties for the y variable, shown as error bars.
    :param list xlimits: set limits to the range for the x variable
    :param list ylimits: set limits to the range for the y variable
    :param float xscale: set scaling factor in x. Default is 1.
    :param float yscale: set scaling factor in y. Automatically calculated to get
        a reasonable aspect ratio. Scaling factor is saved in `info['yscale']`.

    :param bool xlogscale: set x logarithmic scale.
    :param bool ylogscale: set y logarithmic scale.
    :param str c: color of frame and text.
    :param float alpha: opacity of frame and text.
    :param str xtitle: title label along x-axis.
    :param str ytitle: title label along y-axis.
    :param str title: histogram title on top.
    :param float titleSize: size of title
    :param str ec: color of error bar, by default the same as marker color
    :param str lc: color of line
    :param float lw: width of line
    :param bool line: join points with line
    :param bool dashed: use a dashed line style
    :param bool splined: spline the line joining the point as a countinous curve
    :param str,int marker: use a marker shape for the data points
    :param float ms: marker size.
    :param str mc: color of marker
    :param float ma: opacity of marker

    |plotxy| |plotxy.py|_
    """
    if len(data) == 2 and len(data[0]) > 1 and len(data[0]) == len(data[1]):
        #format is [allx, ally], convert it:
        data = np.c_[data[0], data[1]]

    if xlimits is not None:
        cdata = []
        x0lim = xlimits[0]
        x1lim = xlimits[1]
        for d in data:
            if d[0] > x0lim and d[0] < x1lim:
                cdata.append(d)
        data = cdata
        if not len(data):
            colors.printc("Error in plotxy(): no points within xlimits", c=1)
            return None

    if ylimits is not None:
        cdata = []
        y0lim = ylimits[0]
        y1lim = ylimits[1]
        for d in data:
            if d[1] > y0lim and d[1] < y1lim:
                cdata.append(d)
        data = cdata
        if not len(data):
            colors.printc("Error in plotxy(): no points within ylimits", c=1)
            return None

    data = np.array(data)[:, [0, 1]]

    if xlogscale:
        data[:, 0] = np.log(data[:, 0])

    if ylogscale:
        data[:, 1] = np.log(data[:, 1])

    x0, y0 = np.min(data, axis=0)
    x1, y1 = np.max(data, axis=0)

    if yscale is None:
        yscale = (x1 - x0) / (y1 - y0) * 0.75  # default 3/4 aspect ratio
        yscale = float(utils.precision(yscale, 1))
        if abs(yscale - 1) > 0.2:
            ytitle += " *" + str(yscale)
            y0 *= yscale
            y1 *= yscale
        else:
            yscale = 1

    scale = np.array([[xscale, yscale]])
    data = np.multiply(data, scale)

    acts = []
    if dashed:
        l = shapes.DashedLine(data, lw=lw, spacing=20)
        acts.append(l)
    elif splined:
        l = shapes.KSpline(data).lw(lw).c(lc)
        acts.append(l)
    elif line:
        l = shapes.Line(data, lw=lw, c=lc)
        acts.append(l)

    if marker:
        if ms is None:
            ms = (x1 - x0) / 75.0
        if mc is None:
            mc = lc
        mk = shapes.Marker(marker, s=ms, alpha=ma)
        pts = shapes.Points(data)
        marked = shapes.Glyph(pts, glyphObj=mk, c=mc)
        acts.append(marked)

    if ec is None:
        if mc is not None:
            ec = mc
        else:
            ec = lc
        offs = (x1 - x0) / 1000

    if yerrors is not None:
        if len(yerrors) != len(data):
            colors.printc(
                "Error in plotxy(yerrors=...): mismatched array length.", c=1)
            return None
        errs = []
        for i in range(len(data)):
            xval, yval = data[i]
            yerr = yerrors[i] / 2 * yscale
            errs.append(
                shapes.Line((xval, yval - yerr, offs),
                            (xval, yval + yerr, offs)))
        myerrs = merge(errs).c(ec).lw(lw).alpha(alpha)
        acts.append(myerrs)

    if xerrors is not None:
        if len(xerrors) != len(data):
            colors.printc(
                "Error in plotxy(xerrors=...): mismatched array length.", c=1)
            return None
        errs = []
        for i in range(len(data)):
            xval, yval = data[i]
            xerr = xerrors[i] / 2
            errs.append(
                shapes.Line((xval - xerr, yval, offs),
                            (xval + xerr, yval, offs)))
        mxerrs = merge(errs).c(ec).lw(lw).alpha(alpha)
        acts.append(mxerrs)

    x0lim = x0
    x1lim = x1
    y0lim = y0 * yscale
    y1lim = y1 * yscale
    if xlimits is not None or ylimits is not None:
        if xlimits is not None:
            x0lim = min(xlimits[0], x0)
            x1lim = max(xlimits[1], x1)
        if ylimits is not None:
            y0lim = min(ylimits[0] * yscale, y0)
            y1lim = max(ylimits[1] * yscale, y1)
        rec = shapes.Rectangle([x0lim, y0lim, 0], [x1lim, y1lim, 0])
        rec.alpha(0).wireframe()
        acts.append(rec)

    if title:
        if titleSize is None:
            titleSize = (x1lim - x0lim) / 40.0
        tit = shapes.Text(
            title,
            s=titleSize,
            c=c,
            depth=0,
            alpha=alpha,
            pos=((x1lim + x0lim) / 2.0, y1lim, 0),
            justify="bottom-center",
        )
        tit.pickable(False)
        acts.append(tit)

    settings.xtitle = xtitle
    settings.ytitle = ytitle
    asse = Assembly(acts)
    asse.info["yscale"] = yscale
    return asse
Example #2
0
def histogram(
    values,
    xtitle="",
    ytitle="",
    bins=25,
    vrange=None,
    logscale=False,
    yscale=None,
    fill=True,
    gap=0.02,
    c="olivedrab",
    alpha=1,
    outline=True,
    lw=2,
    lc="black",
    errors=False,
):
    """
    Build a histogram from a list of values in n bins.
    The resulting object is a 2D actor.

    :param int bins: number of bins.
    :param list vrange: restrict the range of the histogram.
    :param bool logscale: use logscale on y-axis.
    :param bool fill: fill bars woth solid color `c`.
    :param float gap: leave a small space btw bars.
    :param bool outline: show outline of the bins.
    :param bool errors: show error bars.

    |histogram| |histogram.py|_
    """
    if xtitle:
        from vtkplotter import settings

        settings.xtitle = xtitle
    if ytitle:
        from vtkplotter import settings

        settings.ytitle = ytitle

    fs, edges = np.histogram(values, bins=bins, range=vrange)
    if logscale:
        fs = np.log10(fs + 1)
    mine, maxe = np.min(edges), np.max(edges)
    binsize = edges[1] - edges[0]

    rs = []
    if fill:
        if outline:
            gap = 0
        for i in range(bins):
            p0 = (edges[i] + gap * binsize, 0, 0)
            p1 = (edges[i + 1] - gap * binsize, fs[i], 0)
            r = shapes.Rectangle(p0, p1)
            r.color(c).alpha(alpha).lighting("ambient")
            rs.append(r)

    if outline:
        lns = [[mine, 0, 0]]
        for i in range(bins):
            lns.append([edges[i], fs[i], 0])
            lns.append([edges[i + 1], fs[i], 0])
        lns.append([maxe, 0, 0])
        rs.append(shapes.Line(lns, c=lc, alpha=alpha, lw=lw))

    if errors:
        errs = np.sqrt(fs)
        for i in range(bins):
            x = (edges[i] + edges[i + 1]) / 2
            el = shapes.Line(
                [x, fs[i] - errs[i] / 2, 0.1 * binsize],
                [x, fs[i] + errs[i] / 2, 0.1 * binsize],
                c=lc,
                alpha=alpha,
                lw=lw,
            )
            pt = shapes.Point([x, fs[i], 0.1 * binsize],
                              r=7,
                              c=lc,
                              alpha=alpha)
            rs.append(el)
            rs.append(pt)

    asse = Assembly(rs)
    if yscale is None:
        yscale = 10 / np.sum(fs) * (maxe - mine)
    asse.scale([1, yscale, 1])
    return asse
Example #3
0
def plotxy(
    data,
    xlimits=None,
    ylimits=None,
    xscale=1,
    yscale=None,
    xlogscale=False,
    ylogscale=False,
    c="k",
    alpha=1,
    xtitle="x",
    ytitle="y",
    title="",
    titleSize=None,
    lc="k",
    lw=2,
    dashed=False,
    splined=False,
    marker=None,
    ms=None,
    mc=None,
    ma=None,
):
    """Draw a 2D plot of variable x vs y.

    """

    if len(data) == 2 and len(data[0]) > 1 and len(data[0]) == len(data[1]):
        data = np.c_[data[0], data[1]]

    if xlimits is not None:
        cdata = []
        x0lim = xlimits[0]
        x1lim = xlimits[1]
        for d in data:
            if d[0] > x0lim and d[0] < x1lim:
                cdata.append(d)
        data = cdata
        if not len(data):
            colors.printc("Error in plotxy(): no points within xlimits", c=1)
            return None

    if ylimits is not None:
        cdata = []
        y0lim = ylimits[0]
        y1lim = ylimits[1]
        for d in data:
            if d[1] > y0lim and d[1] < y1lim:
                cdata.append(d)
        data = cdata
        if not len(data):
            colors.printc("Error in plotxy(): no points within ylimits", c=1)
            return None

    data = np.array(data)[:, [0, 1]]

    if xlogscale:
        data[:, 0] = np.log(data[:, 0])

    if ylogscale:
        data[:, 1] = np.log(data[:, 1])

    x0, y0 = np.min(data, axis=0)
    x1, y1 = np.max(data, axis=0)

    if yscale is None:
        yscale = (x1 - x0) / (y1 - y0) * 0.75  # default 3/4 aspect ratio
        yscale = float(utils.precision(yscale, 1))
        if abs(yscale - 1) > 0.2:
            ytitle += " *" + str(yscale)
            y0 *= yscale
            y1 *= yscale
        else:
            yscale = 1

    scale = np.array([[xscale, yscale]])
    data = np.multiply(data, scale)

    acts = []
    if dashed:
        l = shapes.DashedLine(data, lw=lw, spacing=20)
    elif splined:
        l = shapes.KSpline(data).lw(lw).c(lc)
    else:
        l = shapes.Line(data, lw=lw, c=lc)
    acts.append(l)

    if marker:
        if ms is None:
            ms = (x1 - x0) / 75.0
        if mc is None:
            mc = lc
        mk = shapes.Marker(marker, s=ms, alpha=ma)
        pts = shapes.Points(data)
        marked = shapes.Glyph(pts, glyphObj=mk, c=mc)
        acts.append(marked)

    x0lim = x0
    x1lim = x1
    y0lim = y0 * yscale
    y1lim = y1 * yscale
    if xlimits is not None or ylimits is not None:
        if xlimits is not None:
            x0lim = min(xlimits[0], x0)
            x1lim = max(xlimits[1], x1)
        if ylimits is not None:
            y0lim = min(ylimits[0] * yscale, y0)
            y1lim = max(ylimits[1] * yscale, y1)
        rec = shapes.Rectangle([x0lim, y0lim, 0], [x1lim, y1lim, 0])
        rec.alpha(0).wireframe()
        acts.append(rec)

    if title:
        if titleSize is None:
            titleSize = (x1lim - x0lim) / 40.0
        tit = shapes.Text(
            title,
            s=titleSize,
            c=c,
            depth=0,
            alpha=alpha,
            pos=((x1lim + x0lim) / 2.0, y1lim, 0),
            justify="bottom-center",
        )
        tit.pickable(False)
        acts.append(tit)

    settings.xtitle = xtitle
    settings.ytitle = ytitle
    asse = Assembly(acts)
    asse.info["yscale"] = yscale
    return asse