Example #1
0
def variance(
    data,
    binsize=300,
    limit=1000,
    inTime=True,
    returnfield=False,
    continuous=False,
    power=False,
    vertbin=5,
    nbins=20,
    **kwargs
):
    """
    Compute boundary layer/aerosol layer depth by evaluating temporal variance
    under the assumption that sufficient smoothing will result in variations
    of boundary layer top being apparent.
    """
    if data == "about":
        return "110Variance"
    field, time, height = u._ComputeFieldMeans(
        data, binsize, inTime=inTime, continuous=continuous, vertbin=vertbin, power=power
    )
    # Now, to preserve shape, I am going to do a running calculation of STDev
    field = runstd(field, nbins) ** 2

    if returnfield:
        return (field, time, height)
    depth = u._MaxDepth(field, height, limit=limit)
    return (depth, time)
Example #2
0
def threshold(
    data, threshold=-7.6, cloud=-5, returnfield=False, binsize=0, inTime=True, continuous=False, vertbin=5, **kwargs
):
    """
    for a formatted backsctter dataset, determine a timeseries of the lowest incidence
    of the specified backscatter value, regardless of mathematical base.
    
    Parameters
    ----------
    threshold: float, optional
        specify the cutoff value for the threshold to be determined from the bottom up
        
    data: numpy 2-d array
        the dataset from which the thresholds are determined 
    """
    if data == "about":
        "Then something just wants an info string about the method, so spit it out"
        return "010Threshold"
    if binsize == 0:
        "no binning or averaging or whatnot is to be done."
        z = data["height"]
        t = data["time"]
        data = data["bs"]
    else:
        data, t, z = u._ComputeFieldMeans(data, binsize, inTime=inTime, continuous=continuous, vertbin=vertbin)
    if returnfield:
        return (data, t, z)
    depth = u._ThresholdLT(data, z, threshold, limit=1200)
    del data
    return (depth, t)
Example #3
0
def ipm(
    data, limit=1000, binsize=300, inTime=True, eval_dist=20, continuous=False, returnfield=False, vertbin=5, **kwargs
):
    """
    determine mixed layer/aerosol depth by determinng the maximum decrease 
    (this is not the second gradient method)

    Known as the inflection point method (IPM)
    
    note, if inTime is false, a time value is still required!!!
    """
    if data == "about":
        return "110Inflection Point Method"
    bs, times, z = u._ComputeFieldMeans(
        data, binsize, inTime=inTime, continuous=continuous, vertbin=vertbin, power=True
    )
    # Compute the gradient of the gradient'
    # FIXME - do i want negative or positive gradients!?!!'
    field = np.gradient(np.gradient(bs, eval_dist)[1], eval_dist)[1]
    field[field >= 0.0] = np.NAN
    field = np.log10(-1 * field)
    if returnfield:
        field[np.isnan(field)] = np.nanmin(field)
        return (field, times, z)
    field = field[:, 20:]
    z = z[20:]
    # We need to compute the max above 200m.
    depth = u._MaxDepth(field, z, limit=limit)
    return (depth, times)
Example #4
0
def gradient(
    data,
    window=20,
    cloud=-5,
    limit=1500,
    binsize=300,
    inTime=True,
    continuous=False,
    multiple=False,
    returnfield=False,
    eval_distance=20,
    vertbin=5,
    minmax=-9.7,
    **kwargs
):
    """
    determine mixed layer/aerosol depth by determinng the maximum decrease 
    (this is not the second gradient method)
    """
    if data == "about":
        return "110Gradient"
    bs, times, z = u._ComputeFieldMeans(
        data, binsize, inTime=inTime, continuous=continuous, vertbin=vertbin, power=True
    )
    del data
    "Compute the vertical gradient!"
    field = np.gradient(bs, eval_distance)[1]
    field[field >= 0.0] = np.nan
    "this line, though it is undone in 3 lines, is to protect log10"
    field = np.log10(-1 * field)
    if returnfield:
        field[np.isnan(field)] = np.nanmin(field)
        return (field, times, z)
    "get rid of field data which is beyond the limit of what gets computed"
    field = field[:, z <= limit]
    z = z[z <= limit]
    tops = np.zeros(len(field))
    bottoms = np.zeros(len(field))

    "///////////////////  DETERMINISTIC SECTION  /////////////////////////////"
    if not multiple:
        "FIXME - this should pick the max depth within the largest contiguous"
        "first loop through and identify the largest contiguous non-zero aera"
        i = 0
        field[:, 0] = np.nan
        depth = np.zeros(len(field))
        for prof in np.isnan(field):
            "we get a list of true/false"
            keys = np.arange(len(prof))[prof]
            "=[0,1,2,5,6]"
            "compute the diff of this field"
            kd = np.diff(keys)
            "=[1,1,3,1]"
            startkey = keys[kd == max(kd)][0]
            "=2"
            "the endkey is the next item in keys after startkeys"
            endkey = keys[keys > startkey][0]
            tops[i] = z[endkey]
            bottoms[i] = z[startkey]
            if startkey + 1 == endkey:
                "then there really is no data... weird"
                i += 1
                continue

            zs = z[startkey + 1 : endkey]
            fd = field[i, startkey + 1 : endkey]
            "pick the LAST match, rather than the first"
            depth[i] = zs[fd == np.nanmax(fd)][-1]

            i += 1
    else:
        """
        Multiple levels should be returned, with the 
        """
        depth = u._LocalMaxDepths(field, z, window, 4, limit=limit, minmax=minmax)
    del field
    return (depth, times, tops, bottoms)
Example #5
0
def idealized_multiple(
    data,
    binsize=300,
    returnfield=False,
    inTime=True,
    savebin=False,
    continuous=False,
    guessmean=False,
    guessheight=False,
    vertbin=5,
    limit=1000,
    background=-8.2,
    threshold=-7.6,
    **kwargs
):
    """
    Use the idealized backscatter method to identify the top of the aerosol layer.
    
    This routine will use the -7.6 threshold method as a first guess, and will 
    then minimize the defined function to determine the function coefficients 
    
    This is from the method proposed by Eresmaa et al 2012
    
    Parameters
    ----------
    
    data: list
        The produced output from the slice for ceilometer data for the time 
        period analyzed
    binsize: int, optional
        the length in SECONDS for bins to be produced. Longer bins increase 
        the chance of success
    returnfield: bool, optional
        return only the field analyzed, not very useful for this operation.
    inTime: bool, optional
        specify if the provided time dimension is actually epoch time stamps, 
        or just bin numbers
    savebin: str, optional
        only save a demonstrative figure of a single bin. A possibly useful 
        demonstration operation. 
    background: float, optional
        set the background (low value) approximation. The current value is -8.2,
        which is sufficient for Vaisala CL31 ceilometer backscatter in (m*sr)^-1
        units.
   
    """
    l.warning("The mutli-layer idealized profile method has not been implemented")
    exit()
    if data == "about":
        "Then something just wants an info string about the method, so spit it out"
        return "100Idealized Profile"
    from scipy import optimize, special

    bs, times, z = u._ComputeFieldMeans(data, binsize, inTime=inTime, continuous=continuous, vertbin=vertbin)
    bs, z = bs[:, : limit / 10], z[: limit / 10]
    "no, this method will not use power"
    if returnfield:
        return (bs, times, z)
    if guessmean and guessheight:
        "A fixed guess mean has been assigned"
        first_guesses = [guessheight for x in times]
        first_guess_mean = [guessmean for x in times]
    else:
        print "Applying threshold theory"
        first_guesses = u._ThresholdLT(bs, z, threshold)
        "compute the low-level means from the 5th ob up to the guess height"
        guess_mean_func = lambda x: np.mean(bs[x][z <= first_guesses[x]])
        first_guess_mean = map(guess_mean_func, range(len(first_guesses)))

    "now, for each time bin, we will run the optimization"
    outH = np.zeros(len(times))
    outdH = np.zeros(len(times))
    for i in range(len(times)):
        """
        make first guesses and fix the two variables
        """
        b = bs[i]  # the backscatter profile
        h = first_guesses[i]  # first guess height (a very good guess)]
        dh = 100.0  # guess value of dh, based on observation
        "for now we are always assuming a 100m transition layer until told otherwise"
        p0 = [h, dh]
        if h == 0:
            continue
        bm = first_guess_mean[i]  # approximation for boundary layer intensity
        bu = background  # approximation for free atmosphere intensity
        "There are two coefficients, A1 and A2, and one is fixed for the fitting"
        a1 = (bm + bu) / 2.0
        a2 = (bm - bu) / 2.0
        fitfunc = lambda p, z: a1 - a2 * special.erf((z - p[0]) / p[1])
        errfunc = lambda p, z, bs: np.sum((fitfunc(p, z) - bs) ** 2)
        # print errfunc(p0,height,b)
        p1 = optimize.fmin(errfunc, p0, args=(z, b))
        print p1
        outH[i] = p1[0]
        outdH[i] = p1[1]

        if savebin:
            "this code can just save an example bin plot."
            import matplotlib.pyplot as plt

            plt.plot(fitfunc(p1, z), z)
            plt.plot(b, z)
            plt.xlabel("Bakscatter ($m^{-1}sr^{-1}$)")
            plt.ylabel("Height AGL (m)")
            plt.savefig(savebin)
            "in this case, this is the only operation engaged by the code."
            return True
    "this can solve to some bizzaro solutions, so we need to filter realistic values"
    outH[(outH > limit) | (outH < 0)] = 0
    outdH[(outdH > limit) | (outdH < -limit)] = 0
    return (outH, times, outdH, first_guess_mean)