In [1]:
%run basics
%matplotlib


Using matplotlib backend: Qt4Agg

In [2]:
def residuals_RHLRC_D(params,NEE,Fsd,D,D0,weighted,weight_type):
    alpha = params[0]
    beta = params[1]
    k = params[2]
    gamma = params[3]
    resid = NEE - NEE_RHLRC_D(Fsd,D,alpha,beta,k,D0,gamma)
    if weighted:
        weights = CalculateWeights(resid,weight_type=weight_type)
        return resid*weights
    else:
        return resid

def NEE_RHLRC_D(Fsd,D,alpha,beta,k,D0,gamma):
    NEE = -1*GPP_RHLRC_D(Fsd,D,alpha,beta,k,D0) + gamma
    return NEE

def GPP_RHLRC_D(Fsd,D,alpha,beta,k,D0):
    beta = beta*SHD_func_Lasslop(D,k,D0)
    GPP = alpha*beta*Fsd/(alpha*Fsd+beta)
    return GPP

def SHD_func_Lasslop(D,k,D0):
    SHD_func = numpy.ones(len(D))
    idx = numpy.where(D>D0)[0]
    SHD_func[idx] = numpy.exp(-k*(D[idx]-D0))
    return SHD_func

In [3]:
def irls_leastsq(func,p0,args=(),maxfev=3,weight_type='Huber',mode="quiet"):
    weighted = False
    popt,pcov = scipy.optimize.leastsq(func,p0,args=args+(weighted,weight_type))
    if mode!="quiet":
        print 'After non-weighted call to leastsq: ',popt
    n=1
    weighted = True
    while n<=maxfev:
        popt,pcov = scipy.optimize.leastsq(func,popt,args=args+(weighted,weight_type))
        if mode!="quiet":
            print 'Weighted call '+str(n)+' to leastsq: ',popt
        n = n + 1
    return popt,pcov

def CalculateWeights(resid,weight_type='Huber'):
    if weight_type.lower()=='tukey':
        weights = TukeyBiweight(MAD_scale(resid))
    elif weight_type.lower()=='huber':
        weights = HuberTWeight(MAD_scale(resid))
    elif weight_type.lower()=='ols':
        weights = OLSWeight(MAD_scale(resid))
    else:
        print "CalculateWeights: Unknown weight type, used Huber's t weight"
        weights = HuberTWeight(MAD_scale(resid))
    return weights

def TukeyBiweight(x):
    return ((numpy.abs(x)<1.0)*(1.0 - x**2)**2)

def HuberTWeight(x):
    weights = numpy.ones(len(x))
    idx = numpy.where(numpy.abs(x)>1.345)[0]
    weights[idx] = 1.345/numpy.abs(x[idx])
    return weights

def OLSWeight(x):
    weights = numpy.ones(len(x))
    return weights

def MAD_scale(resid):
    scale = numpy.median(numpy.abs(resid - numpy.median(resid))) / 0.6745
    return resid/scale

In [4]:
# get the netCDF file name
ncname = "../Sites/Whroo/Data/Portal/Whroo_L4.nc"
# read the contents into a data structure
ds = qcio.nc_read_series(ncname)
# get the datetime series
dt = ds.series["DateTime"]["Data"]

In [30]:
# open an Excel workbook for the results
xlname = ncname.replace(".nc","_RHLRC_WithD.xls")
xlfile = qcio.xl_open_write(xlname)

In [31]:
# rectangular hyperbolic LRC, with D function
# set the downwelling shortwave radiation and friction velocity thresholds
Fsd_threshold = 10
ustar_threshold = 0.40
VPD0 = 1.0
# add a sheet to the Excel workbook
xlsheet = xlfile.add_sheet("RHLRC_WithD")
# get the index of the first period at the start of the first whole month
si = qcutils.GetDateIndex(dt,str(dt[0]),match="startnextmonth")
# get the start datetime
start_date = dt[si]
# create a dictionary for the results
RHLRC_WithD = {"DateTime":{"data":[],"units":"-","format":"dd/mm/yyyy hh:mm"},
               "alpha":{"data":[],"units":"-","format":"0.0000"},
               "beta":{"data":[],"units":"-","format":"0.00"},
               "k":{"data":[],"units":"-","format":"0.000"},
               "gamma":{"data":[],"units":"-","format":"0.00"},
               "ER":{"data":[],"units":"-","format":"0.00"}}
# loop over periods until done
while start_date<dt[-1]:
    # get the end datetime for this pass
    end_date = start_date+dateutil.relativedelta.relativedelta(months=1)
    # indices of start and end datetimes
    si = qcutils.GetDateIndex(dt,str(start_date),default=0)
    ei = qcutils.GetDateIndex(dt,str(end_date),default=len(dt))
    # minimum number of points is 10%
    min_points = int(0.1*(ei-si))
    mi = int((si+ei)/2)
    # get the downwelling shortwave, CO2 flux and friction velocity
    Fsd,f,a = qcutils.GetSeriesasMA(ds,"Fsd",si=si,ei=ei)
    NEE,f,a = qcutils.GetSeriesasMA(ds,"Fc",si=si,ei=ei)
    ustar,f,a = qcutils.GetSeriesasMA(ds,"ustar",si=si,ei=ei)
    VPD,f,a = qcutils.GetSeriesasMA(ds,"VPD",si=si,ei=ei)
    T,f,a = qcutils.GetSeriesasMA(ds,"T",si=si,ei=ei)
    # mask out the night-time ...
    Fsd_day = numpy.ma.masked_where(Fsd<Fsd_threshold,Fsd)
    VPD_day = numpy.ma.masked_where(Fsd<Fsd_threshold,VPD)
    T_day = numpy.ma.masked_where(Fsd<Fsd_threshold,T)
    NEE_day = numpy.ma.masked_where(Fsd<Fsd_threshold,NEE)
    # get the mask across all data (one masked ==> all masked)
    ones = numpy.ma.ones(len(Fsd))
    for item in [Fsd_day,VPD_day,T_day,NEE_day]:
        mask = numpy.ma.mask_or(numpy.ma.getmaskarray(ones),
                                numpy.ma.getmaskarray(item),
                                copy=True)
    # remove masked elements
    for item in [Fsd_day,VPD_day,T_day,NEE_day]:
        item = numpy.ma.compressed(numpy.ma.masked_where(mask,item))
    # mask out the day-time conditions ...
    NEE_night = numpy.ma.masked_where(Fsd>=Fsd_threshold,NEE)
    T_night = numpy.ma.masked_where(Fsd>=Fsd_threshold,T)
    # get the mask across all data (one masked ==> all masked)
    ones = numpy.ma.ones(len(Fsd))
    for item in [NEE_night,T_night]:
        mask = numpy.ma.mask_or(numpy.ma.getmaskarray(ones),
                                numpy.ma.getmaskarray(item),
                                copy=True)
    # remove masked elements
    for item in [NEE_night,T_night]:
        item = numpy.ma.compressed(numpy.ma.masked_where(mask,item))
    # add the mid-period datetime to the results dictionary
    RHLRC_WithD["DateTime"]["data"].append(dt[mi])
    # call the optimisation if more than the minimum number of
    # points available, otherwise set results to missing value
    # set the priors
    rb_prior = numpy.ma.mean(NEE_night)
    beta_prior = numpy.abs(numpy.percentile(NEE_day,5)-numpy.percentile(NEE_day,95))
    print start_date,end_date,numpy.percentile(NEE_day,5),numpy.percentile(NEE_day,95)
    p0 = [0.01,20,0,2]
    if len(Fsd_day)>=min_points:
        #print start_date,end_date,numpy.max(NEE_day),numpy.min(NEE_day)
        #print start_date,end_date,numpy.max(Fsd_day),numpy.min(Fsd_day)
        #print start_date,end_date,numpy.max(VPD_day),numpy.min(VPD_day)
        popt,pcov = irls_leastsq(residuals_RHLRC_D,p0,
                                 args=(NEE_day,Fsd_day,VPD_day,VPD0),
                                 maxfev=3,weight_type='Huber')
    else:
        popt = [-9999,-9999,-9999,-9999]
    RHLRC_WithD["alpha"]["data"].append(popt[0])
    RHLRC_WithD["beta"]["data"].append(popt[1])
    RHLRC_WithD["k"]["data"].append(popt[2])
    RHLRC_WithD["gamma"]["data"].append(popt[3])
    # plot the data
    if popt[0]!=-9999:
        NEE_fit = NEE_RHLRC_D(Fsd_day,VPD_day,popt[0],popt[1],popt[2],VPD0,popt[3])
        fig=plt.figure()
        plt.plot(Fsd_day,NEE_day,'b.')
        plt.plot(Fsd_day,NEE_fit,'r+')
        plt.show()
    # get the average of the u*-filtered, nocturnal Fc
    NEE_night = numpy.ma.masked_where(ustar<=ustar_threshold,NEE_night)
    if len(NEE_night)>=min_points:
        RHLRC_WithD["ER"]["data"].append(numpy.ma.mean(NEE_night))
    else:
        RHLRC_WithD["ER"]["data"].append(-9999)
    start_date = end_date
# write the results to the Excel workbook
qcio.xl_write_data(xlsheet,RHLRC_WithD,xlCol=0)


2012-01-01 00:30:00 2012-02-01 00:30:00 -9999.0 4.66453968049
2012-02-01 00:30:00 2012-03-01 00:30:00 -9999.0 4.74088633084
2012-03-01 00:30:00 2012-04-01 00:30:00 -11.6935826479 4.75551291
2012-04-01 00:30:00 2012-05-01 00:30:00 -9.76282724968 3.05611074233
2012-05-01 00:30:00 2012-06-01 00:30:00 -11.984396948 2.49565144819
2012-06-01 00:30:00 2012-07-01 00:30:00 -9999.0 3.3216780672
2012-07-01 00:30:00 2012-08-01 00:30:00 -9999.0 3.04056466812
2012-08-01 00:30:00 2012-09-01 00:30:00 -9999.0 2.68058810133
2012-09-01 00:30:00 2012-10-01 00:30:00 -9999.0 3.09080968471
2012-10-01 00:30:00 2012-11-01 00:30:00 -11.597478008 2.86808664161
2012-11-01 00:30:00 2012-12-01 00:30:00 -8.85205838693 3.30013662774
2012-12-01 00:30:00 2013-01-01 00:30:00 -9.39187758943 3.72260613306
2013-01-01 00:30:00 2013-02-01 00:30:00 -8.14584163021 3.1250638846
2013-02-01 00:30:00 2013-03-01 00:30:00 -10.6727930837 3.87657602326
2013-03-01 00:30:00 2013-04-01 00:30:00 -8.55814435748 3.59519017179
2013-04-01 00:30:00 2013-05-01 00:30:00 -9.0358135363 2.18988041342
2013-05-01 00:30:00 2013-06-01 00:30:00 -9999.0 2.44051437462
2013-06-01 00:30:00 2013-07-01 00:30:00 -9999.0 2.87662376323
2013-07-01 00:30:00 2013-08-01 00:30:00 -9999.0 2.46846836576
2013-08-01 00:30:00 2013-09-01 00:30:00 -9999.0 2.69387425131
2013-09-01 00:30:00 2013-10-01 00:30:00 -9999.0 3.20816824788
2013-10-01 00:30:00 2013-11-01 00:30:00 -13.7900777516 3.04143154835
2013-11-01 00:30:00 2013-12-01 00:30:00 -16.4342684479 2.85509581868
2013-12-01 00:30:00 2014-01-01 00:30:00 -9999.0 3.53227307318
2014-01-01 00:30:00 2014-02-01 00:30:00 -11.3724556637 3.71979086604
2014-02-01 00:30:00 2014-03-01 00:30:00 -9.31224167081 3.70469710246
2014-03-01 00:30:00 2014-04-01 00:30:00 -9999.0 3.0748586345
2014-04-01 00:30:00 2014-05-01 00:30:00 -9999.0 3.95147972724
2014-05-01 00:30:00 2014-06-01 00:30:00 -9999.0 3.76140544262
2014-06-01 00:30:00 2014-07-01 00:30:00 -9999.0 3.30088434826
2014-07-01 00:30:00 2014-08-01 00:30:00 -9999.0 2.37555952106
2014-08-01 00:30:00 2014-09-01 00:30:00 -9999.0 2.20046806183
2014-09-01 00:30:00 2014-10-01 00:30:00 -9999.0 3.15976090208
2014-10-01 00:30:00 2014-11-01 00:30:00 -14.9539411357 4.08369871307
2014-11-01 00:30:00 2014-12-01 00:30:00 -12.3939988159 3.42377661226
2014-12-01 00:30:00 2015-01-01 00:30:00 -9.38109298675 3.5691719222
2015-01-01 00:30:00 2015-02-01 00:30:00 -9999.0 4.77839855708
2015-02-01 00:30:00 2015-03-01 00:30:00 -8.88553634155 3.70801211016
2015-03-01 00:30:00 2015-04-01 00:30:00 -9.04617513634 3.13133032148
2015-04-01 00:30:00 2015-05-01 00:30:00 -9999.0 3.10056957965
2015-05-01 00:30:00 2015-06-01 00:30:00 -9999.0 2.76461741798
2015-06-01 00:30:00 2015-07-01 00:30:00 -9999.0 1.44826137411
2015-07-01 00:30:00 2015-08-01 00:30:00 -9999.0 -9999.0
2015-08-01 00:30:00 2015-09-01 00:30:00 -9999.0 1.74099734564
2015-09-01 00:30:00 2015-10-01 00:30:00 -9999.0 1.54820601388

In [29]:
xlfile.save(xlname)

In [ ]: