def plotSpotDist(mLabels,spots,outPath,subtractMean):
    colors = ['r', 'g', 'b', 'y','k']
    nColors = len(colors)
    # go to nm
    mLabelsNm = mLabels *  1e9
    mSetSpots = sorted(set(spots))
    labelsBySpot = []
    rawBySpot = []
    flattenedFromMean = []
    # first, get the spot-wise labelling
    for i,spot in enumerate(mSetSpots):
        # get the indices of the spots
        spotIdx = np.where(abs((spots - spot)) < 1e-9)[0]
        thisSpotLabels = mLabelsNm[spotIdx]
        meanV = np.mean(thisSpotLabels)
        if (subtractMean):
            thisSpotLabels -= meanV
        labelsBySpot.append(thisSpotLabels)
        flattenedFromMean.extend(thisSpotLabels)
        if (subtractMean):
            rawBySpot.append(thisSpotLabels + meanV)
        else:
            rawBySpot.append(thisSpotLabels)        
    #  get the min and max from the labelsBySpot array
    bins = np.linspace(min(flattenedFromMean),max(flattenedFromMean),10)
    fig = pPlotUtil.figure(xSize=12,ySize=12)
    ax = fig.add_subplot(111, projection='3d',)
    for i,thisSpotLabels in enumerate(labelsBySpot):
        mColor = colors[i % nColors]
        height,left = np.histogram(thisSpotLabels,bins=bins)
        ax.bar(left[:-1], height, zs=i,zdir='y', color=mColor, alpha=0.7,
               edgecolor="none",linewidth=0)
    xStr = r'$\Delta$ from Expected Surface Loc. [nm]'
    pPlotUtil.lazyLabel(xStr,
                        "Surface Position (arb)",
                    "Dependence of Surface Location Distribution on Position",
                        zlab="Count")
    pPlotUtil.savefig(fig,outPath + "AllSpots.png")
    # get a figure showing the mean surface location, assuming
    # we reshape into an Nx(whatever) array
    N = 5
    # -1: infer dimension
    meanVals = [np.mean(mList) for mList in rawBySpot]
    meanSurf = np.reshape(meanVals,(-1,N))
    meanSurf -= np.min(meanSurf)
    fig = pPlotUtil.figure(ySize=14,xSize=10)
    ax = fig.add_subplot(111, projection='3d')
    # convert to nm (XXX assuming grid is 1micron for each)
    Nx = N
    Ny = meanSurf.shape[0]
    x = np.linspace(0, Nx, Nx) * 1e3
    y = np.linspace(0, Ny, Ny) * 1e3
    xv, yv = np.meshgrid(x, y)
    ax.plot_wireframe(xv,yv,meanSurf)
    pPlotUtil.lazyLabel("X Location [nm]","Y Location [nm]",
                        "Surface Position Varies with height")
    pPlotUtil.zlabel("Surface height (relative to min)")
    pPlotUtil.savefig(fig,outPath + "Surface.png")
    fig = pPlotUtil.figure(ySize=14,xSize=10)
    plt.subplot(2,1,1)
    nPoints = len(flattenedFromMean)
    vals,edges,_=plt.hist(flattenedFromMean,bins=bins)
    # add a 'fudge' factor to make plotting better,
    fudgeX = (max(edges)-min(edges))*0.05
    xlim = [min(edges)-fudgeX,max(edges)+fudgeX]
    yLim = [0,max(vals)]
    pPlotUtil.lazyLabel(xStr,
                        "Number of counts",
                        "Algorithm finds surface within 10nm, >98%, N={:d}".\
                        format(nPoints))
    normed = [0,max(vals)/sum(vals)]
    plt.xlim(xlim)
    propAx = pPlotUtil.secondAxis(plt.gca(),"Proportion",normed,yColor="Red")
    propAx.axhline("0.05",color='r',
                   label="5% of Curves",linestyle='--',linewidth=4.0)
    pPlotUtil.legend()
    # plot the CDF 
    plt.subplot(2,1,2)
    # add a zero at the start, so the plot matches the PDF
    cdf = np.zeros(edges.size)
    cdf[1:] = np.cumsum(vals/sum(vals))
    mX = edges
    plt.plot(mX,cdf,linestyle='--',linewidth=4,color='k')
    plt.xlim(xlim)
    pPlotUtil.lazyLabel(xStr,
                        "Cummulative Proportion",
                        ("Cummulative Density Function," +
                         "Surface Detection Performance"))
    plt.gca().fill_between(mX, 0, cdf,alpha=0.3)
    pPlotUtil.savefig(fig,outPath + "FlatSpots.png")