Plots serveral Z, X and Y datasets as a 3d scatter plot with heatmaps of each axis pair in each dataset.

    Parameters
    ----------
    ZXYData : ndarray
        Array of arrays containing Z, X, Y data e.g. [[Z1, X1, Y1], [Z2, X2, Y2]]
    N : optional, int
        Number of time points to plot (Defaults to 1000)
    AxisOffset : optional, double
        Offset to add to each axis from the data - used to get a better view
        of the heat maps (Defaults to 0)
    LowLim : optional, double
        Lower limit of x, y and z axis
    HighLim : optional, double
        Upper limit of x, y and z axis
    show_fig : optional, bool
        Whether to show the produced figure before returning

    Returns
    -------
    fig : matplotlib.figure.Figure object
        The figure object created
    ax : matplotlib.axes.Axes object
        The subplot object created

def multi_plot_3d_dist(ZXYData, N=1000, AxisOffset=0, Angle=-40, LowLim=None, HighLim=None, ColorArray=None, alphaLevel=0.3, show_fig=True):
    """
    Plots serveral Z, X and Y datasets as a 3d scatter plot with heatmaps of each axis pair in each dataset.

    Parameters
    ----------
    ZXYData : ndarray
        Array of arrays containing Z, X, Y data e.g. [[Z1, X1, Y1], [Z2, X2, Y2]]
    N : optional, int
        Number of time points to plot (Defaults to 1000)
    AxisOffset : optional, double
        Offset to add to each axis from the data - used to get a better view
        of the heat maps (Defaults to 0)
    LowLim : optional, double
        Lower limit of x, y and z axis
    HighLim : optional, double
        Upper limit of x, y and z axis
    show_fig : optional, bool
        Whether to show the produced figure before returning

    Returns
    -------
    fig : matplotlib.figure.Figure object
        The figure object created
    ax : matplotlib.axes.Axes object
        The subplot object created
    """
    if ZXYData.shape[1] != 3:
        raise ValueError("Parameter ZXYData should be an array of length-3 arrays containing arrays of Z, X and Y data")
    if ColorArray != None:
        if ZXYData.shape[0] != len(ColorArray):
            raise ValueError("Parameter ColorArray should be the same lenth as ZXYData")
    else:
        ColorArray = list(mcolours.BASE_COLORS.keys())
        #ColorArray = ['b', 'g', 'r']
        #    ColorMapArray = [_plt.cm.Blues, _plt.cm.Greens, _plt.cm.Reds]
        if ZXYData.shape[0] > len(ColorArray):
            raise NotImplementedError("Only {} datasets can be plotted with automatic colors".format(len(ColorArray)))
        
    angle = Angle
    fig = _plt.figure(figsize=(8, 6))
    ax = fig.add_subplot(111, projection='3d')

    for datindx, ZXY in enumerate(ZXYData):
        y = ZXY[0][0:N]
        x = ZXY[1][0:N]
        z = ZXY[2][0:N]
        ax.scatter(x, y, z, alpha=alphaLevel, color=ColorArray[datindx])
        
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()
    zlim = ax.get_zlim()
    if LowLim != None:
        lowLim = LowLim - AxisOffset
    else:
        lowLim = min([xlim[0], ylim[0], zlim[0]]) - AxisOffset
    if HighLim != None:
        highLim = HighLim + AxisOffset
    else:
        highLim = max([xlim[1], ylim[1], zlim[1]]) + AxisOffset
    ax.set_xlim([lowLim, highLim])
    ax.set_ylim([lowLim, highLim])
    ax.set_zlim([lowLim, highLim])

    for datindx, ZXY in enumerate(ZXYData):
        y = ZXY[0][0:N]
        x = ZXY[1][0:N]
        z = ZXY[2][0:N]
        
        #h, yedges, zedges = _np.histogram2d(y, z, bins=50)
        #h = h.transpose()
        #normalized_map = ColorMapArray[datindx](h/h.max())
        #yy, zz = _np.meshgrid(yedges, zedges)
        xpos = lowLim # Plane of histogram
        #xflat = _np.full_like(yy, xpos) 
        #p = ax.plot_surface(xflat, yy, zz, facecolors=normalized_map, rstride=1, cstride=1, shade=False)
        xflat = _np.full_like(y, xpos) 
        ax.scatter(xflat, y, z, color=ColorArray[datindx], alpha=alphaLevel)
        
        #h, xedges, zedges = _np.histogram2d(x, z, bins=50)
        #h = h.transpose()
        #normalized_map = ColorMapArray[datindx](h/h.max())
        #xx, zz = _np.meshgrid(xedges, zedges)
        ypos = highLim # Plane of histogram
        #yflat = _np.full_like(xx, ypos) 
        #p = ax.plot_surface(xx, yflat, zz, facecolors=normalized_map, rstride=1, cstride=1, shade=False)
        yflat = _np.full_like(x, ypos) 
        ax.scatter(x, yflat, z, color=ColorArray[datindx], alpha=alphaLevel)
        
        #h, yedges, xedges = _np.histogram2d(y, x, bins=50)
        #h = h.transpose()
        #normalized_map = ColorMapArray[datindx](h/h.max())
        #yy, xx = _np.meshgrid(yedges, xedges)
        zpos = lowLim # Plane of histogram
        #zflat = _np.full_like(yy, zpos) 
        #p = ax.plot_surface(xx, yy, zflat, facecolors=normalized_map, rstride=1, cstride=1, shade=False)
        zflat = _np.full_like(y, zpos) 
        ax.scatter(x, y, zflat, color=ColorArray[datindx], alpha=alphaLevel)
    
    ax.set_xlabel("x")
    ax.set_ylabel("z")
    ax.set_zlabel("y")
    ax.view_init(30, angle)
    
    if show_fig == True:
        _plt.show()
    return fig, ax