Using gaussian plots as a error bars in pyplot












0















I was wondering if it is possible to draw a scatter graph in matplotlib such that the error bars on each are represented as Gaussian distributions themselves.
Each scatter point had several repeats and a standard deviation, which I wanted to emphasize on the graph.
I thought this could be achieved by overlaying a separate, smaller plot over each point (scaled as appropriate), but I cannot find any help on StackOverflow or otherwise on the web.



I apologise if I was unclear, this is the first time I'm asking for help online.



Thank you very much in advance.










share|improve this question


















  • 2





    At which point are you stuck? How exactly do you envision this to look?

    – ImportanceOfBeingErnest
    Nov 25 '18 at 19:37











  • Would a violin plot would be appropriate? Matplotlib has a couple example in its gallery: matplotlib.org/gallery/statistics/…, matplotlib.org/gallery/statistics/…

    – Warren Weckesser
    Nov 25 '18 at 21:02
















0















I was wondering if it is possible to draw a scatter graph in matplotlib such that the error bars on each are represented as Gaussian distributions themselves.
Each scatter point had several repeats and a standard deviation, which I wanted to emphasize on the graph.
I thought this could be achieved by overlaying a separate, smaller plot over each point (scaled as appropriate), but I cannot find any help on StackOverflow or otherwise on the web.



I apologise if I was unclear, this is the first time I'm asking for help online.



Thank you very much in advance.










share|improve this question


















  • 2





    At which point are you stuck? How exactly do you envision this to look?

    – ImportanceOfBeingErnest
    Nov 25 '18 at 19:37











  • Would a violin plot would be appropriate? Matplotlib has a couple example in its gallery: matplotlib.org/gallery/statistics/…, matplotlib.org/gallery/statistics/…

    – Warren Weckesser
    Nov 25 '18 at 21:02














0












0








0








I was wondering if it is possible to draw a scatter graph in matplotlib such that the error bars on each are represented as Gaussian distributions themselves.
Each scatter point had several repeats and a standard deviation, which I wanted to emphasize on the graph.
I thought this could be achieved by overlaying a separate, smaller plot over each point (scaled as appropriate), but I cannot find any help on StackOverflow or otherwise on the web.



I apologise if I was unclear, this is the first time I'm asking for help online.



Thank you very much in advance.










share|improve this question














I was wondering if it is possible to draw a scatter graph in matplotlib such that the error bars on each are represented as Gaussian distributions themselves.
Each scatter point had several repeats and a standard deviation, which I wanted to emphasize on the graph.
I thought this could be achieved by overlaying a separate, smaller plot over each point (scaled as appropriate), but I cannot find any help on StackOverflow or otherwise on the web.



I apologise if I was unclear, this is the first time I'm asking for help online.



Thank you very much in advance.







python numpy matplotlib






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 25 '18 at 19:21









Franek PauwelsFranek Pauwels

41




41








  • 2





    At which point are you stuck? How exactly do you envision this to look?

    – ImportanceOfBeingErnest
    Nov 25 '18 at 19:37











  • Would a violin plot would be appropriate? Matplotlib has a couple example in its gallery: matplotlib.org/gallery/statistics/…, matplotlib.org/gallery/statistics/…

    – Warren Weckesser
    Nov 25 '18 at 21:02














  • 2





    At which point are you stuck? How exactly do you envision this to look?

    – ImportanceOfBeingErnest
    Nov 25 '18 at 19:37











  • Would a violin plot would be appropriate? Matplotlib has a couple example in its gallery: matplotlib.org/gallery/statistics/…, matplotlib.org/gallery/statistics/…

    – Warren Weckesser
    Nov 25 '18 at 21:02








2




2





At which point are you stuck? How exactly do you envision this to look?

– ImportanceOfBeingErnest
Nov 25 '18 at 19:37





At which point are you stuck? How exactly do you envision this to look?

– ImportanceOfBeingErnest
Nov 25 '18 at 19:37













Would a violin plot would be appropriate? Matplotlib has a couple example in its gallery: matplotlib.org/gallery/statistics/…, matplotlib.org/gallery/statistics/…

– Warren Weckesser
Nov 25 '18 at 21:02





Would a violin plot would be appropriate? Matplotlib has a couple example in its gallery: matplotlib.org/gallery/statistics/…, matplotlib.org/gallery/statistics/…

– Warren Weckesser
Nov 25 '18 at 21:02












1 Answer
1






active

oldest

votes


















1














I have some code lying around that does something similar to what you describe (EDIT: I cleaned up/improved the code significantly). The code provides a gaussianScatter function that can produce plots like these (the color bar and the error lines extending from each point are optional):



enter image description here



You'll have to play around with the styling and such to adapt it to your needs, but it should get you started.



Here's the code I used to produce the example figure above:



import numpy as np

N = 10
testpoints = np.random.randint(0, 10, size=(2, N))
testnoise = np.random.uniform(.25, .75, size=(2, N))

fig,ax = gaussianScatter(*testpoints, *testnoise, docbar=True, doerrbar=True, c='C3')


and here's the complete implementation of gaussianScatter:



import numpy as np
from matplotlib.colors import ListedColormap, LinearSegmentedColormap
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import scipy.stats as sts

def cmapwhite(cmap, p=.05):
"""Modifies a named cmap so that its smallest values blend into white
"""
N = 256
Nold = int((1 - p)*N/p)

old = plt.cm.get_cmap(cmap)

cnames = ('red', 'green', 'blue')
wdict = {cname: [[0, 1, 1],
[.5, 1, 1],
[1, c, c]] for cname,c in zip(cnames, old(0))}
white = LinearSegmentedColormap(cmap + '_white', segmentdata=wdict, N=N)

colorComb = np.vstack((
white(np.linspace(0, 1, N)),
old(np.linspace(0, 1, Nold))
))
return ListedColormap(colorComb, name=cmap + '_white')

def datalimits(*data, err=None, pad=None):
if err is not None:
dmin,dmax = min((d - err).min() for d in data), max((d + err).max() for d in data)
else:
dmin,dmax = min(d.min() for d in data), max(d.max() for d in data)

if pad is not None:
spad = pad*(dmax - dmin)
dmin,dmax = dmin - spad, dmax + spad

return dmin,dmax

def getcov(xerr, yerr):
cov = np.array([
[xerr, 0],
[0, yerr]
])

return cov

def mvpdf(x, y, xerr, yerr, xlim, ylim):
"""Creates a grid of data that represents the PDF of a multivariate normal distribution (ie an ND Gaussian).

x, y: The center of the returned PDF
(xy)lim: The extent of the returned PDF
(xy)err: The noise the PDF is meant to represent. Will scale pdf in the appropriate direction

returns: X, Y, PDF. X and Y hold the coordinates of the PDF.
"""
# create the coordinate grids
X,Y = np.meshgrid(np.linspace(*xlim), np.linspace(*ylim))

# stack them into the format expected by the multivariate pdf
XY = np.stack([X, Y], 2)

# get the covariance matrix with the appropriate transforms
cov = getcov(xerr, yerr)

# generate the data grid that represents the PDF
PDF = sts.multivariate_normal([x, y], cov).pdf(XY)

return X, Y, PDF

def gaussianScatter(x, y, xerr, yerr, xlim=None, ylim=None, cmap='Blues', fig=None, ax=None, docbar=False, doerrbar=False, doclines=False, donorm=False, cfkwargs=None, **pltkwargs):
"""
x,y: sequence of coordinates to be plotted
(x,y)err: sequence of error/noise associated with each plotted coordinate
(x,y)lim: sequence of (start, end). Determines extents of data displayed in plot
cmap: str of named cmap, or cmap instance
fig: the figure to be plotted on
ax: the axes to be plotted on
docbar: add a color bar
doerrbar: plot the error bars associated with each point as lines
doclines: plot the contour lines of the gaussians
donorm: normalize each plotted gaussian so that its largest value is 1
cfkwargs: a dict of arguments that will be passed to the `contourf` function used to plot the gaussians
pltkwargs: a dict of arguments that will be passed to the `plot` function used to plot the xy points
"""
if xlim is None: xlim = datalimits(x, err=2*xerr)
if ylim is None: ylim = datalimits(y, err=2*yerr)
if cfkwargs is None: cfkwargs = {}

if fig is None:
fig = plt.figure(figsize=(8,8))
ax = fig.add_axes([0, 0, 1, 1])
elif ax is None:
ax = fig.add_axes([0, 0, 1, 1])

if isinstance(cmap, str):
cmap = cmapwhite(cmap)

cfDefault = {'cmap': cmap, 'levels': 100}
pltDefault = {'marker': '.', 'ms': 20, 'ls': 'None', 'c': 'C1'}

# plot gaussians
PDFs =
for _x,_y,_xeta,_yeta in zip(x, y, xerr, yerr):
X, Y, PDF = mvpdf(_x, _y, _xeta, _yeta, xlim, ylim)
PDFs.append(PDF)

if donorm:
# norm the individual PDFs
PDFs = [(PDF - PDF.min())/(PDF.max() - PDF.min()) for PDF in PDFs]

# combine PDFs by treating them like 3D structures. At each xy point, we pick the "tallest" one
PDFcomb = np.max(PDFs, axis=0)

# plot the filled contours that will represent the gaussians.
cfDefault.update(cfkwargs)
cfs = ax.contourf(X, Y, PDFcomb, **cfDefault)

if doclines:
# plot and label the contour lines of the 2D gaussian
cs = ax.contour(X, Y, PDFcomb, levels=6, colors='w', alpha=.5)
ax.clabel(cs, fmt='%.3f', fontsize=12)

# plot scatter
pltDefault.update(pltkwargs)
if doerrbar:
ax.errorbar(x, y, xerr=xerr, yerr=yerr, **pltDefault)
else:
ax.plot(x, y, **pltDefault)

# ensure that x vs y scaling doesn't disrupt the transforms applied to the 2D gaussian
ax.set_aspect('equal', 'box')

if docbar:
# create the colorbar
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.2)
cbar = fig.colorbar(cfs, ax=ax, cax=cax, format='%.2f')
cbar.set_ticks(np.linspace(0, PDFcomb.max(), num=6))

return fig,ax





share|improve this answer

























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53471028%2fusing-gaussian-plots-as-a-error-bars-in-pyplot%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    I have some code lying around that does something similar to what you describe (EDIT: I cleaned up/improved the code significantly). The code provides a gaussianScatter function that can produce plots like these (the color bar and the error lines extending from each point are optional):



    enter image description here



    You'll have to play around with the styling and such to adapt it to your needs, but it should get you started.



    Here's the code I used to produce the example figure above:



    import numpy as np

    N = 10
    testpoints = np.random.randint(0, 10, size=(2, N))
    testnoise = np.random.uniform(.25, .75, size=(2, N))

    fig,ax = gaussianScatter(*testpoints, *testnoise, docbar=True, doerrbar=True, c='C3')


    and here's the complete implementation of gaussianScatter:



    import numpy as np
    from matplotlib.colors import ListedColormap, LinearSegmentedColormap
    import matplotlib.pyplot as plt
    from mpl_toolkits.axes_grid1 import make_axes_locatable
    import scipy.stats as sts

    def cmapwhite(cmap, p=.05):
    """Modifies a named cmap so that its smallest values blend into white
    """
    N = 256
    Nold = int((1 - p)*N/p)

    old = plt.cm.get_cmap(cmap)

    cnames = ('red', 'green', 'blue')
    wdict = {cname: [[0, 1, 1],
    [.5, 1, 1],
    [1, c, c]] for cname,c in zip(cnames, old(0))}
    white = LinearSegmentedColormap(cmap + '_white', segmentdata=wdict, N=N)

    colorComb = np.vstack((
    white(np.linspace(0, 1, N)),
    old(np.linspace(0, 1, Nold))
    ))
    return ListedColormap(colorComb, name=cmap + '_white')

    def datalimits(*data, err=None, pad=None):
    if err is not None:
    dmin,dmax = min((d - err).min() for d in data), max((d + err).max() for d in data)
    else:
    dmin,dmax = min(d.min() for d in data), max(d.max() for d in data)

    if pad is not None:
    spad = pad*(dmax - dmin)
    dmin,dmax = dmin - spad, dmax + spad

    return dmin,dmax

    def getcov(xerr, yerr):
    cov = np.array([
    [xerr, 0],
    [0, yerr]
    ])

    return cov

    def mvpdf(x, y, xerr, yerr, xlim, ylim):
    """Creates a grid of data that represents the PDF of a multivariate normal distribution (ie an ND Gaussian).

    x, y: The center of the returned PDF
    (xy)lim: The extent of the returned PDF
    (xy)err: The noise the PDF is meant to represent. Will scale pdf in the appropriate direction

    returns: X, Y, PDF. X and Y hold the coordinates of the PDF.
    """
    # create the coordinate grids
    X,Y = np.meshgrid(np.linspace(*xlim), np.linspace(*ylim))

    # stack them into the format expected by the multivariate pdf
    XY = np.stack([X, Y], 2)

    # get the covariance matrix with the appropriate transforms
    cov = getcov(xerr, yerr)

    # generate the data grid that represents the PDF
    PDF = sts.multivariate_normal([x, y], cov).pdf(XY)

    return X, Y, PDF

    def gaussianScatter(x, y, xerr, yerr, xlim=None, ylim=None, cmap='Blues', fig=None, ax=None, docbar=False, doerrbar=False, doclines=False, donorm=False, cfkwargs=None, **pltkwargs):
    """
    x,y: sequence of coordinates to be plotted
    (x,y)err: sequence of error/noise associated with each plotted coordinate
    (x,y)lim: sequence of (start, end). Determines extents of data displayed in plot
    cmap: str of named cmap, or cmap instance
    fig: the figure to be plotted on
    ax: the axes to be plotted on
    docbar: add a color bar
    doerrbar: plot the error bars associated with each point as lines
    doclines: plot the contour lines of the gaussians
    donorm: normalize each plotted gaussian so that its largest value is 1
    cfkwargs: a dict of arguments that will be passed to the `contourf` function used to plot the gaussians
    pltkwargs: a dict of arguments that will be passed to the `plot` function used to plot the xy points
    """
    if xlim is None: xlim = datalimits(x, err=2*xerr)
    if ylim is None: ylim = datalimits(y, err=2*yerr)
    if cfkwargs is None: cfkwargs = {}

    if fig is None:
    fig = plt.figure(figsize=(8,8))
    ax = fig.add_axes([0, 0, 1, 1])
    elif ax is None:
    ax = fig.add_axes([0, 0, 1, 1])

    if isinstance(cmap, str):
    cmap = cmapwhite(cmap)

    cfDefault = {'cmap': cmap, 'levels': 100}
    pltDefault = {'marker': '.', 'ms': 20, 'ls': 'None', 'c': 'C1'}

    # plot gaussians
    PDFs =
    for _x,_y,_xeta,_yeta in zip(x, y, xerr, yerr):
    X, Y, PDF = mvpdf(_x, _y, _xeta, _yeta, xlim, ylim)
    PDFs.append(PDF)

    if donorm:
    # norm the individual PDFs
    PDFs = [(PDF - PDF.min())/(PDF.max() - PDF.min()) for PDF in PDFs]

    # combine PDFs by treating them like 3D structures. At each xy point, we pick the "tallest" one
    PDFcomb = np.max(PDFs, axis=0)

    # plot the filled contours that will represent the gaussians.
    cfDefault.update(cfkwargs)
    cfs = ax.contourf(X, Y, PDFcomb, **cfDefault)

    if doclines:
    # plot and label the contour lines of the 2D gaussian
    cs = ax.contour(X, Y, PDFcomb, levels=6, colors='w', alpha=.5)
    ax.clabel(cs, fmt='%.3f', fontsize=12)

    # plot scatter
    pltDefault.update(pltkwargs)
    if doerrbar:
    ax.errorbar(x, y, xerr=xerr, yerr=yerr, **pltDefault)
    else:
    ax.plot(x, y, **pltDefault)

    # ensure that x vs y scaling doesn't disrupt the transforms applied to the 2D gaussian
    ax.set_aspect('equal', 'box')

    if docbar:
    # create the colorbar
    divider = make_axes_locatable(ax)
    cax = divider.append_axes("right", size="5%", pad=0.2)
    cbar = fig.colorbar(cfs, ax=ax, cax=cax, format='%.2f')
    cbar.set_ticks(np.linspace(0, PDFcomb.max(), num=6))

    return fig,ax





    share|improve this answer






























      1














      I have some code lying around that does something similar to what you describe (EDIT: I cleaned up/improved the code significantly). The code provides a gaussianScatter function that can produce plots like these (the color bar and the error lines extending from each point are optional):



      enter image description here



      You'll have to play around with the styling and such to adapt it to your needs, but it should get you started.



      Here's the code I used to produce the example figure above:



      import numpy as np

      N = 10
      testpoints = np.random.randint(0, 10, size=(2, N))
      testnoise = np.random.uniform(.25, .75, size=(2, N))

      fig,ax = gaussianScatter(*testpoints, *testnoise, docbar=True, doerrbar=True, c='C3')


      and here's the complete implementation of gaussianScatter:



      import numpy as np
      from matplotlib.colors import ListedColormap, LinearSegmentedColormap
      import matplotlib.pyplot as plt
      from mpl_toolkits.axes_grid1 import make_axes_locatable
      import scipy.stats as sts

      def cmapwhite(cmap, p=.05):
      """Modifies a named cmap so that its smallest values blend into white
      """
      N = 256
      Nold = int((1 - p)*N/p)

      old = plt.cm.get_cmap(cmap)

      cnames = ('red', 'green', 'blue')
      wdict = {cname: [[0, 1, 1],
      [.5, 1, 1],
      [1, c, c]] for cname,c in zip(cnames, old(0))}
      white = LinearSegmentedColormap(cmap + '_white', segmentdata=wdict, N=N)

      colorComb = np.vstack((
      white(np.linspace(0, 1, N)),
      old(np.linspace(0, 1, Nold))
      ))
      return ListedColormap(colorComb, name=cmap + '_white')

      def datalimits(*data, err=None, pad=None):
      if err is not None:
      dmin,dmax = min((d - err).min() for d in data), max((d + err).max() for d in data)
      else:
      dmin,dmax = min(d.min() for d in data), max(d.max() for d in data)

      if pad is not None:
      spad = pad*(dmax - dmin)
      dmin,dmax = dmin - spad, dmax + spad

      return dmin,dmax

      def getcov(xerr, yerr):
      cov = np.array([
      [xerr, 0],
      [0, yerr]
      ])

      return cov

      def mvpdf(x, y, xerr, yerr, xlim, ylim):
      """Creates a grid of data that represents the PDF of a multivariate normal distribution (ie an ND Gaussian).

      x, y: The center of the returned PDF
      (xy)lim: The extent of the returned PDF
      (xy)err: The noise the PDF is meant to represent. Will scale pdf in the appropriate direction

      returns: X, Y, PDF. X and Y hold the coordinates of the PDF.
      """
      # create the coordinate grids
      X,Y = np.meshgrid(np.linspace(*xlim), np.linspace(*ylim))

      # stack them into the format expected by the multivariate pdf
      XY = np.stack([X, Y], 2)

      # get the covariance matrix with the appropriate transforms
      cov = getcov(xerr, yerr)

      # generate the data grid that represents the PDF
      PDF = sts.multivariate_normal([x, y], cov).pdf(XY)

      return X, Y, PDF

      def gaussianScatter(x, y, xerr, yerr, xlim=None, ylim=None, cmap='Blues', fig=None, ax=None, docbar=False, doerrbar=False, doclines=False, donorm=False, cfkwargs=None, **pltkwargs):
      """
      x,y: sequence of coordinates to be plotted
      (x,y)err: sequence of error/noise associated with each plotted coordinate
      (x,y)lim: sequence of (start, end). Determines extents of data displayed in plot
      cmap: str of named cmap, or cmap instance
      fig: the figure to be plotted on
      ax: the axes to be plotted on
      docbar: add a color bar
      doerrbar: plot the error bars associated with each point as lines
      doclines: plot the contour lines of the gaussians
      donorm: normalize each plotted gaussian so that its largest value is 1
      cfkwargs: a dict of arguments that will be passed to the `contourf` function used to plot the gaussians
      pltkwargs: a dict of arguments that will be passed to the `plot` function used to plot the xy points
      """
      if xlim is None: xlim = datalimits(x, err=2*xerr)
      if ylim is None: ylim = datalimits(y, err=2*yerr)
      if cfkwargs is None: cfkwargs = {}

      if fig is None:
      fig = plt.figure(figsize=(8,8))
      ax = fig.add_axes([0, 0, 1, 1])
      elif ax is None:
      ax = fig.add_axes([0, 0, 1, 1])

      if isinstance(cmap, str):
      cmap = cmapwhite(cmap)

      cfDefault = {'cmap': cmap, 'levels': 100}
      pltDefault = {'marker': '.', 'ms': 20, 'ls': 'None', 'c': 'C1'}

      # plot gaussians
      PDFs =
      for _x,_y,_xeta,_yeta in zip(x, y, xerr, yerr):
      X, Y, PDF = mvpdf(_x, _y, _xeta, _yeta, xlim, ylim)
      PDFs.append(PDF)

      if donorm:
      # norm the individual PDFs
      PDFs = [(PDF - PDF.min())/(PDF.max() - PDF.min()) for PDF in PDFs]

      # combine PDFs by treating them like 3D structures. At each xy point, we pick the "tallest" one
      PDFcomb = np.max(PDFs, axis=0)

      # plot the filled contours that will represent the gaussians.
      cfDefault.update(cfkwargs)
      cfs = ax.contourf(X, Y, PDFcomb, **cfDefault)

      if doclines:
      # plot and label the contour lines of the 2D gaussian
      cs = ax.contour(X, Y, PDFcomb, levels=6, colors='w', alpha=.5)
      ax.clabel(cs, fmt='%.3f', fontsize=12)

      # plot scatter
      pltDefault.update(pltkwargs)
      if doerrbar:
      ax.errorbar(x, y, xerr=xerr, yerr=yerr, **pltDefault)
      else:
      ax.plot(x, y, **pltDefault)

      # ensure that x vs y scaling doesn't disrupt the transforms applied to the 2D gaussian
      ax.set_aspect('equal', 'box')

      if docbar:
      # create the colorbar
      divider = make_axes_locatable(ax)
      cax = divider.append_axes("right", size="5%", pad=0.2)
      cbar = fig.colorbar(cfs, ax=ax, cax=cax, format='%.2f')
      cbar.set_ticks(np.linspace(0, PDFcomb.max(), num=6))

      return fig,ax





      share|improve this answer




























        1












        1








        1







        I have some code lying around that does something similar to what you describe (EDIT: I cleaned up/improved the code significantly). The code provides a gaussianScatter function that can produce plots like these (the color bar and the error lines extending from each point are optional):



        enter image description here



        You'll have to play around with the styling and such to adapt it to your needs, but it should get you started.



        Here's the code I used to produce the example figure above:



        import numpy as np

        N = 10
        testpoints = np.random.randint(0, 10, size=(2, N))
        testnoise = np.random.uniform(.25, .75, size=(2, N))

        fig,ax = gaussianScatter(*testpoints, *testnoise, docbar=True, doerrbar=True, c='C3')


        and here's the complete implementation of gaussianScatter:



        import numpy as np
        from matplotlib.colors import ListedColormap, LinearSegmentedColormap
        import matplotlib.pyplot as plt
        from mpl_toolkits.axes_grid1 import make_axes_locatable
        import scipy.stats as sts

        def cmapwhite(cmap, p=.05):
        """Modifies a named cmap so that its smallest values blend into white
        """
        N = 256
        Nold = int((1 - p)*N/p)

        old = plt.cm.get_cmap(cmap)

        cnames = ('red', 'green', 'blue')
        wdict = {cname: [[0, 1, 1],
        [.5, 1, 1],
        [1, c, c]] for cname,c in zip(cnames, old(0))}
        white = LinearSegmentedColormap(cmap + '_white', segmentdata=wdict, N=N)

        colorComb = np.vstack((
        white(np.linspace(0, 1, N)),
        old(np.linspace(0, 1, Nold))
        ))
        return ListedColormap(colorComb, name=cmap + '_white')

        def datalimits(*data, err=None, pad=None):
        if err is not None:
        dmin,dmax = min((d - err).min() for d in data), max((d + err).max() for d in data)
        else:
        dmin,dmax = min(d.min() for d in data), max(d.max() for d in data)

        if pad is not None:
        spad = pad*(dmax - dmin)
        dmin,dmax = dmin - spad, dmax + spad

        return dmin,dmax

        def getcov(xerr, yerr):
        cov = np.array([
        [xerr, 0],
        [0, yerr]
        ])

        return cov

        def mvpdf(x, y, xerr, yerr, xlim, ylim):
        """Creates a grid of data that represents the PDF of a multivariate normal distribution (ie an ND Gaussian).

        x, y: The center of the returned PDF
        (xy)lim: The extent of the returned PDF
        (xy)err: The noise the PDF is meant to represent. Will scale pdf in the appropriate direction

        returns: X, Y, PDF. X and Y hold the coordinates of the PDF.
        """
        # create the coordinate grids
        X,Y = np.meshgrid(np.linspace(*xlim), np.linspace(*ylim))

        # stack them into the format expected by the multivariate pdf
        XY = np.stack([X, Y], 2)

        # get the covariance matrix with the appropriate transforms
        cov = getcov(xerr, yerr)

        # generate the data grid that represents the PDF
        PDF = sts.multivariate_normal([x, y], cov).pdf(XY)

        return X, Y, PDF

        def gaussianScatter(x, y, xerr, yerr, xlim=None, ylim=None, cmap='Blues', fig=None, ax=None, docbar=False, doerrbar=False, doclines=False, donorm=False, cfkwargs=None, **pltkwargs):
        """
        x,y: sequence of coordinates to be plotted
        (x,y)err: sequence of error/noise associated with each plotted coordinate
        (x,y)lim: sequence of (start, end). Determines extents of data displayed in plot
        cmap: str of named cmap, or cmap instance
        fig: the figure to be plotted on
        ax: the axes to be plotted on
        docbar: add a color bar
        doerrbar: plot the error bars associated with each point as lines
        doclines: plot the contour lines of the gaussians
        donorm: normalize each plotted gaussian so that its largest value is 1
        cfkwargs: a dict of arguments that will be passed to the `contourf` function used to plot the gaussians
        pltkwargs: a dict of arguments that will be passed to the `plot` function used to plot the xy points
        """
        if xlim is None: xlim = datalimits(x, err=2*xerr)
        if ylim is None: ylim = datalimits(y, err=2*yerr)
        if cfkwargs is None: cfkwargs = {}

        if fig is None:
        fig = plt.figure(figsize=(8,8))
        ax = fig.add_axes([0, 0, 1, 1])
        elif ax is None:
        ax = fig.add_axes([0, 0, 1, 1])

        if isinstance(cmap, str):
        cmap = cmapwhite(cmap)

        cfDefault = {'cmap': cmap, 'levels': 100}
        pltDefault = {'marker': '.', 'ms': 20, 'ls': 'None', 'c': 'C1'}

        # plot gaussians
        PDFs =
        for _x,_y,_xeta,_yeta in zip(x, y, xerr, yerr):
        X, Y, PDF = mvpdf(_x, _y, _xeta, _yeta, xlim, ylim)
        PDFs.append(PDF)

        if donorm:
        # norm the individual PDFs
        PDFs = [(PDF - PDF.min())/(PDF.max() - PDF.min()) for PDF in PDFs]

        # combine PDFs by treating them like 3D structures. At each xy point, we pick the "tallest" one
        PDFcomb = np.max(PDFs, axis=0)

        # plot the filled contours that will represent the gaussians.
        cfDefault.update(cfkwargs)
        cfs = ax.contourf(X, Y, PDFcomb, **cfDefault)

        if doclines:
        # plot and label the contour lines of the 2D gaussian
        cs = ax.contour(X, Y, PDFcomb, levels=6, colors='w', alpha=.5)
        ax.clabel(cs, fmt='%.3f', fontsize=12)

        # plot scatter
        pltDefault.update(pltkwargs)
        if doerrbar:
        ax.errorbar(x, y, xerr=xerr, yerr=yerr, **pltDefault)
        else:
        ax.plot(x, y, **pltDefault)

        # ensure that x vs y scaling doesn't disrupt the transforms applied to the 2D gaussian
        ax.set_aspect('equal', 'box')

        if docbar:
        # create the colorbar
        divider = make_axes_locatable(ax)
        cax = divider.append_axes("right", size="5%", pad=0.2)
        cbar = fig.colorbar(cfs, ax=ax, cax=cax, format='%.2f')
        cbar.set_ticks(np.linspace(0, PDFcomb.max(), num=6))

        return fig,ax





        share|improve this answer















        I have some code lying around that does something similar to what you describe (EDIT: I cleaned up/improved the code significantly). The code provides a gaussianScatter function that can produce plots like these (the color bar and the error lines extending from each point are optional):



        enter image description here



        You'll have to play around with the styling and such to adapt it to your needs, but it should get you started.



        Here's the code I used to produce the example figure above:



        import numpy as np

        N = 10
        testpoints = np.random.randint(0, 10, size=(2, N))
        testnoise = np.random.uniform(.25, .75, size=(2, N))

        fig,ax = gaussianScatter(*testpoints, *testnoise, docbar=True, doerrbar=True, c='C3')


        and here's the complete implementation of gaussianScatter:



        import numpy as np
        from matplotlib.colors import ListedColormap, LinearSegmentedColormap
        import matplotlib.pyplot as plt
        from mpl_toolkits.axes_grid1 import make_axes_locatable
        import scipy.stats as sts

        def cmapwhite(cmap, p=.05):
        """Modifies a named cmap so that its smallest values blend into white
        """
        N = 256
        Nold = int((1 - p)*N/p)

        old = plt.cm.get_cmap(cmap)

        cnames = ('red', 'green', 'blue')
        wdict = {cname: [[0, 1, 1],
        [.5, 1, 1],
        [1, c, c]] for cname,c in zip(cnames, old(0))}
        white = LinearSegmentedColormap(cmap + '_white', segmentdata=wdict, N=N)

        colorComb = np.vstack((
        white(np.linspace(0, 1, N)),
        old(np.linspace(0, 1, Nold))
        ))
        return ListedColormap(colorComb, name=cmap + '_white')

        def datalimits(*data, err=None, pad=None):
        if err is not None:
        dmin,dmax = min((d - err).min() for d in data), max((d + err).max() for d in data)
        else:
        dmin,dmax = min(d.min() for d in data), max(d.max() for d in data)

        if pad is not None:
        spad = pad*(dmax - dmin)
        dmin,dmax = dmin - spad, dmax + spad

        return dmin,dmax

        def getcov(xerr, yerr):
        cov = np.array([
        [xerr, 0],
        [0, yerr]
        ])

        return cov

        def mvpdf(x, y, xerr, yerr, xlim, ylim):
        """Creates a grid of data that represents the PDF of a multivariate normal distribution (ie an ND Gaussian).

        x, y: The center of the returned PDF
        (xy)lim: The extent of the returned PDF
        (xy)err: The noise the PDF is meant to represent. Will scale pdf in the appropriate direction

        returns: X, Y, PDF. X and Y hold the coordinates of the PDF.
        """
        # create the coordinate grids
        X,Y = np.meshgrid(np.linspace(*xlim), np.linspace(*ylim))

        # stack them into the format expected by the multivariate pdf
        XY = np.stack([X, Y], 2)

        # get the covariance matrix with the appropriate transforms
        cov = getcov(xerr, yerr)

        # generate the data grid that represents the PDF
        PDF = sts.multivariate_normal([x, y], cov).pdf(XY)

        return X, Y, PDF

        def gaussianScatter(x, y, xerr, yerr, xlim=None, ylim=None, cmap='Blues', fig=None, ax=None, docbar=False, doerrbar=False, doclines=False, donorm=False, cfkwargs=None, **pltkwargs):
        """
        x,y: sequence of coordinates to be plotted
        (x,y)err: sequence of error/noise associated with each plotted coordinate
        (x,y)lim: sequence of (start, end). Determines extents of data displayed in plot
        cmap: str of named cmap, or cmap instance
        fig: the figure to be plotted on
        ax: the axes to be plotted on
        docbar: add a color bar
        doerrbar: plot the error bars associated with each point as lines
        doclines: plot the contour lines of the gaussians
        donorm: normalize each plotted gaussian so that its largest value is 1
        cfkwargs: a dict of arguments that will be passed to the `contourf` function used to plot the gaussians
        pltkwargs: a dict of arguments that will be passed to the `plot` function used to plot the xy points
        """
        if xlim is None: xlim = datalimits(x, err=2*xerr)
        if ylim is None: ylim = datalimits(y, err=2*yerr)
        if cfkwargs is None: cfkwargs = {}

        if fig is None:
        fig = plt.figure(figsize=(8,8))
        ax = fig.add_axes([0, 0, 1, 1])
        elif ax is None:
        ax = fig.add_axes([0, 0, 1, 1])

        if isinstance(cmap, str):
        cmap = cmapwhite(cmap)

        cfDefault = {'cmap': cmap, 'levels': 100}
        pltDefault = {'marker': '.', 'ms': 20, 'ls': 'None', 'c': 'C1'}

        # plot gaussians
        PDFs =
        for _x,_y,_xeta,_yeta in zip(x, y, xerr, yerr):
        X, Y, PDF = mvpdf(_x, _y, _xeta, _yeta, xlim, ylim)
        PDFs.append(PDF)

        if donorm:
        # norm the individual PDFs
        PDFs = [(PDF - PDF.min())/(PDF.max() - PDF.min()) for PDF in PDFs]

        # combine PDFs by treating them like 3D structures. At each xy point, we pick the "tallest" one
        PDFcomb = np.max(PDFs, axis=0)

        # plot the filled contours that will represent the gaussians.
        cfDefault.update(cfkwargs)
        cfs = ax.contourf(X, Y, PDFcomb, **cfDefault)

        if doclines:
        # plot and label the contour lines of the 2D gaussian
        cs = ax.contour(X, Y, PDFcomb, levels=6, colors='w', alpha=.5)
        ax.clabel(cs, fmt='%.3f', fontsize=12)

        # plot scatter
        pltDefault.update(pltkwargs)
        if doerrbar:
        ax.errorbar(x, y, xerr=xerr, yerr=yerr, **pltDefault)
        else:
        ax.plot(x, y, **pltDefault)

        # ensure that x vs y scaling doesn't disrupt the transforms applied to the 2D gaussian
        ax.set_aspect('equal', 'box')

        if docbar:
        # create the colorbar
        divider = make_axes_locatable(ax)
        cax = divider.append_axes("right", size="5%", pad=0.2)
        cbar = fig.colorbar(cfs, ax=ax, cax=cax, format='%.2f')
        cbar.set_ticks(np.linspace(0, PDFcomb.max(), num=6))

        return fig,ax






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 26 '18 at 22:23

























        answered Nov 25 '18 at 21:17









        teltel

        7,43621431




        7,43621431
































            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53471028%2fusing-gaussian-plots-as-a-error-bars-in-pyplot%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Create new schema in PostgreSQL using DBeaver

            Deepest pit of an array with Javascript: test on Codility

            Costa Masnaga