def l6qc(cf, ds5): ds6 = qcio.copy_datastructure(cf, ds5) # ds6 will be empty (logical false) if an error occurs in copy_datastructure # return from this routine if this is the case if not ds6: return ds6 # set some attributes for this level qcutils.UpdateGlobalAttributes(cf, ds6, "L6") # parse the control file qcrp.ParseL6ControlFile(cf, ds6) # check to see if we have any imports qcgf.ImportSeries(cf, ds6) # check units qcutils.CheckUnits(ds6, "Fc", "umol/m2/s", convert_units=True) ## filter Fc for night time and ustar threshold, write to ds as "ER" #result = qcrp.GetERFromFc(cf,ds6) #if result==0: return # apply the turbulence filter (if requested) qcck.ApplyTurbulenceFilter(cf, ds6) qcrp.GetERFromFc2(cf, ds6) # estimate ER using SOLO qcrp.ERUsingSOLO(cf, ds6) # estimate ER using FFNET qcrp.ERUsingFFNET(cf, ds6) # estimate ER using Lloyd-Taylor qcrp.ERUsingLloydTaylor(cf, ds6) # estimate ER using Lasslop et al qcrp.ERUsingLasslop(cf, ds6) # merge the estimates of ER with the observations qcts.MergeSeriesUsingDict(ds6, merge_order="standard") # calculate NEE from Fc and ER qcrp.CalculateNEE(cf, ds6) # calculate NEP from NEE qcrp.CalculateNEP(cf, ds6) # calculate ET from Fe qcrp.CalculateET(ds6) # partition NEE into GPP and ER qcrp.PartitionNEE(cf, ds6) # write the percentage of good data as a variable attribute qcutils.get_coverage_individual(ds6) # write the percentage of good data for groups qcutils.get_coverage_groups(ds6) # do the L6 summary qcrp.L6_summary(cf, ds6) return ds6
def l6qc(cf,ds5): ds6 = qcio.copy_datastructure(cf,ds5) # ds6 will be empty (logical false) if an error occurs in copy_datastructure # return from this routine if this is the case if not ds6: return ds6 # set some attributes for this level qcutils.UpdateGlobalAttributes(cf,ds6,"L6") # parse the control file qcrp.ParseL6ControlFile(cf,ds6) # check to see if we have any imports qcgf.ImportSeries(cf,ds6) # check units qcutils.CheckUnits(ds6,"Fc","umol/m2/s",convert_units=True) ## filter Fc for night time and ustar threshold, write to ds as "ER" #result = qcrp.GetERFromFc(cf,ds6) #if result==0: return # apply the turbulence filter (if requested) qcck.ApplyTurbulenceFilter(cf,ds6) qcrp.GetERFromFc2(cf,ds6) # estimate ER using SOLO qcrp.ERUsingSOLO(cf,ds6) # estimate ER using FFNET qcrp.ERUsingFFNET(cf,ds6) # estimate ER using Lloyd-Taylor qcrp.ERUsingLloydTaylor(cf,ds6) # estimate ER using Lasslop et al qcrp.ERUsingLasslop(cf,ds6) # merge the estimates of ER with the observations qcts.MergeSeriesUsingDict(ds6,merge_order="standard") # calculate NEE from Fc and ER qcrp.CalculateNEE(cf,ds6) # calculate NEP from NEE qcrp.CalculateNEP(cf,ds6) # calculate ET from Fe qcrp.CalculateET(ds6) # partition NEE into GPP and ER qcrp.PartitionNEE(cf,ds6) # write the percentage of good data as a variable attribute qcutils.get_coverage_individual(ds6) # write the percentage of good data for groups qcutils.get_coverage_groups(ds6) # do the L6 summary qcrp.L6_summary(cf,ds6) return ds6
def l5qc(cf, ds4): ds5 = qcio.copy_datastructure(cf, ds4) # ds4 will be empty (logical false) if an error occurs in copy_datastructure # return from this routine if this is the case if not ds5: return ds5 # set some attributes for this level qcutils.UpdateGlobalAttributes(cf, ds5, "L5") ds5.cf = cf # create a dictionary to hold the gap filling data ds_alt = {} # check to see if we have any imports qcgf.ImportSeries(cf, ds5) # re-apply the quality control checks (range, diurnal and rules) qcck.do_qcchecks(cf, ds5) # now do the flux gap filling methods label_list = qcutils.get_label_list_from_cf(cf) for label in label_list: # parse the control file for information on how the user wants to do the gap filling qcgf.GapFillParseControlFile(cf, ds5, label, ds_alt) # *** start of the section that does the gap filling of the fluxes *** # apply the turbulence filter (if requested) qcck.ApplyTurbulenceFilter(cf, ds5) # fill short gaps using interpolation qcgf.GapFillUsingInterpolation(cf, ds5) # do the gap filling using SOLO qcgfSOLO.GapFillUsingSOLO(cf, ds4, ds5) if ds5.returncodes["solo"] == "quit": return ds5 # gap fill using marginal distribution sampling qcgfMDS.GapFillFluxUsingMDS(cf, ds5) # gap fill using climatology qcgf.GapFillFromClimatology(ds5) # merge the gap filled drivers into a single series qcts.MergeSeriesUsingDict(ds5, merge_order="standard") # calculate Monin-Obukhov length qcts.CalculateMoninObukhovLength(ds5) # write the percentage of good data as a variable attribute qcutils.get_coverage_individual(ds5) # write the percentage of good data for groups qcutils.get_coverage_groups(ds5) return ds5
def l5qc(cf,ds4): ds5 = qcio.copy_datastructure(cf,ds4) # ds4 will be empty (logical false) if an error occurs in copy_datastructure # return from this routine if this is the case if not ds5: return ds5 # set some attributes for this level qcutils.UpdateGlobalAttributes(cf,ds5,"L5") ds5.cf = cf # create a dictionary to hold the gap filling data ds_alt = {} # check to see if we have any imports qcgf.ImportSeries(cf,ds5) # re-apply the quality control checks (range, diurnal and rules) qcck.do_qcchecks(cf,ds5) # now do the flux gap filling methods label_list = qcutils.get_label_list_from_cf(cf) for ThisOne in label_list: # parse the control file for information on how the user wants to do the gap filling qcgf.GapFillParseControlFile(cf,ds5,ThisOne,ds_alt) # *** start of the section that does the gap filling of the fluxes *** # apply the turbulence filter (if requested) qcck.ApplyTurbulenceFilter(cf,ds5) # fill short gaps using interpolation #qcgf.GapFillUsingInterpolation(cf,ds5) # do the gap filling using SOLO qcgf.GapFillUsingSOLO(cf,ds4,ds5) if ds5.returncodes["solo"]=="quit": return ds5 ## gap fill using marginal distribution sampling #qcgf.GapFillFluxUsingMDS(cf,ds5) ## gap fill using ratios #qcgf.GapFillFluxFromDayRatio(cf,ds5) # gap fill using climatology qcgf.GapFillFromClimatology(ds5) # merge the gap filled drivers into a single series qcts.MergeSeriesUsingDict(ds5,merge_order="standard") # write the percentage of good data as a variable attribute qcutils.get_coverage_individual(ds5) # write the percentage of good data for groups qcutils.get_coverage_groups(ds5) return ds5
def l6qc(cf,ds5): ds6 = qcio.copy_datastructure(cf,ds5) # ds6 will be empty (logical false) if an error occurs in copy_datastructure # return from this routine if this is the case if not ds6: return ds6 # set some attributes for this level qcutils.UpdateGlobalAttributes(cf,ds6,"L6") # parse the control file qcrp.ParseL6ControlFile(cf,ds6) # check to see if we have any imports qcgf.ImportSeries(cf,ds6) # filter Fc for night time and ustar threshold, write to ds as "Fre" #qcrp.GetFreIndicator(cf,ds6) qcrp.GetFreFromFc(cf,ds6) # estimate Reco using SOLO qcrp.FreUsingSOLO(cf,ds6) # estimate Reco using FFNET qcrp.FreUsingFFNET(cf,ds6) # estimate Reco using Lloyd-Taylor qcrp.FreUsingLloydTaylor(cf,ds6) # estimate Reco using Lasslop et al qcrp.FreUsingLasslop(cf,ds6) # merge the estimates of Reco with the observations qcts.MergeSeriesUsingDict(ds6,merge_order="standard") # calculate NEE from Fc and Fre qcrp.CalculateNEE(cf,ds6) # calculate NEP from NEE qcrp.CalculateNEP(cf,ds6) # calculate ET from Fe qcrp.CalculateET(ds6) # partition NEE into GPP and Reco qcrp.PartitionNEE(cf,ds6) # write the percentage of good data as a variable attribute qcutils.get_coverage_individual(ds6) # write the percentage of good data for groups qcutils.get_coverage_groups(ds6) # do the L6 summary qcrp.L6_summary(cf,ds6) return ds6
def l4qc(cf,ds3): # !!! code here to use existing L4 file # logic # if the L4 doesn't exist # - create ds4 by using copy.deepcopy(ds3) # if the L4 does exist and the "UseExistingL4File" option is False # - create ds4 by using copy.deepcopy(ds3) # if the L4 does exist and the "UseExistingL4File" option is True # - read the contents of the L4 netCDF file # - check the start and end dates of the L3 and L4 data # - if these are the same then tell the user there is nothing to do # - copy the L3 data to the L4 data structure # - replace the L3 data with the L4 data #ds4 = copy.deepcopy(ds3) ds4 = qcio.copy_datastructure(cf,ds3) # ds4 will be empty (logical false) if an error occurs in copy_datastructure # return from this routine if this is the case if not ds4: return ds4 # set some attributes for this level qcutils.UpdateGlobalAttributes(cf,ds4,"L4") ds4.cf = cf # calculate the available energy if "Fa" not in ds4.series.keys(): qcts.CalculateAvailableEnergy(ds4,Fa_out='Fa',Fn_in='Fn',Fg_in='Fg') # create a dictionary to hold the gap filling data ds_alt = {} # check to see if we have any imports qcgf.ImportSeries(cf,ds4) # re-apply the quality control checks (range, diurnal and rules) qcck.do_qcchecks(cf,ds4) # now do the meteorological driver gap filling for ThisOne in cf["Drivers"].keys(): if ThisOne not in ds4.series.keys(): log.error("Series "+ThisOne+" not in data structure"); continue # parse the control file for information on how the user wants to do the gap filling qcgf.GapFillParseControlFile(cf,ds4,ThisOne,ds_alt) # *** start of the section that does the gap filling of the drivers *** # fill short gaps using interpolation qcgf.GapFillUsingInterpolation(cf,ds4) # gap fill using climatology qcgf.GapFillFromClimatology(ds4) # do the gap filling using the ACCESS output qcgf.GapFillFromAlternate(cf,ds4,ds_alt) if ds4.returncodes["alternate"]=="quit": return ds4 # gap fill using SOLO qcgf.GapFillUsingSOLO(cf,ds3,ds4) if ds4.returncodes["solo"]=="quit": return ds4 # merge the first group of gap filled drivers into a single series qcts.MergeSeriesUsingDict(ds4,merge_order="prerequisite") # re-calculate the ground heat flux but only if requested in control file opt = qcutils.get_keyvaluefromcf(cf,["Options"],"CorrectFgForStorage",default="No",mode="quiet") if opt.lower()!="no": qcts.CorrectFgForStorage(cf,ds4,Fg_out='Fg',Fg_in='Fg_Av',Ts_in='Ts',Sws_in='Sws') # re-calculate the net radiation qcts.CalculateNetRadiation(cf,ds4,Fn_out='Fn',Fsd_in='Fsd',Fsu_in='Fsu',Fld_in='Fld',Flu_in='Flu') # re-calculate the available energy qcts.CalculateAvailableEnergy(ds4,Fa_out='Fa',Fn_in='Fn',Fg_in='Fg') # merge the second group of gap filled drivers into a single series qcts.MergeSeriesUsingDict(ds4,merge_order="standard") # re-calculate the water vapour concentrations qcts.CalculateHumiditiesAfterGapFill(ds4) # re-calculate the meteorological variables qcts.CalculateMeteorologicalVariables(ds4) # the Tumba rhumba qcts.CalculateComponentsFromWsWd(ds4) # check for any missing data qcutils.get_missingingapfilledseries(ds4) # write the percentage of good data as a variable attribute qcutils.get_coverage_individual(ds4) # write the percentage of good data for groups qcutils.get_coverage_groups(ds4) return ds4
def l4qc(cf, ds3): # !!! code here to use existing L4 file # logic # if the L4 doesn't exist # - create ds4 by using copy.deepcopy(ds3) # if the L4 does exist and the "UseExistingL4File" option is False # - create ds4 by using copy.deepcopy(ds3) # if the L4 does exist and the "UseExistingL4File" option is True # - read the contents of the L4 netCDF file # - check the start and end dates of the L3 and L4 data # - if these are the same then tell the user there is nothing to do # - copy the L3 data to the L4 data structure # - replace the L3 data with the L4 data #ds4 = copy.deepcopy(ds3) ds4 = qcio.copy_datastructure(cf, ds3) # ds4 will be empty (logical false) if an error occurs in copy_datastructure # return from this routine if this is the case if not ds4: return ds4 # set some attributes for this level qcutils.UpdateGlobalAttributes(cf, ds4, "L4") ds4.cf = cf # calculate the available energy if "Fa" not in ds4.series.keys(): qcts.CalculateAvailableEnergy(ds4, Fa_out='Fa', Fn_in='Fn', Fg_in='Fg') # create a dictionary to hold the gap filling data ds_alt = {} # check to see if we have any imports qcgf.ImportSeries(cf, ds4) # re-apply the quality control checks (range, diurnal and rules) qcck.do_qcchecks(cf, ds4) # now do the meteorological driver gap filling for ThisOne in cf["Drivers"].keys(): if ThisOne not in ds4.series.keys(): log.error("Series " + ThisOne + " not in data structure") continue # parse the control file for information on how the user wants to do the gap filling qcgf.GapFillParseControlFile(cf, ds4, ThisOne, ds_alt) # *** start of the section that does the gap filling of the drivers *** # fill short gaps using interpolation qcgf.GapFillUsingInterpolation(cf, ds4) # gap fill using climatology qcgf.GapFillFromClimatology(ds4) # do the gap filling using the ACCESS output qcgf.GapFillFromAlternate(cf, ds4, ds_alt) if ds4.returncodes["alternate"] == "quit": return ds4 # gap fill using SOLO qcgf.GapFillUsingSOLO(cf, ds3, ds4) if ds4.returncodes["solo"] == "quit": return ds4 # merge the first group of gap filled drivers into a single series qcts.MergeSeriesUsingDict(ds4, merge_order="prerequisite") # re-calculate the ground heat flux but only if requested in control file opt = qcutils.get_keyvaluefromcf(cf, ["Options"], "CorrectFgForStorage", default="No", mode="quiet") if opt.lower() != "no": qcts.CorrectFgForStorage(cf, ds4, Fg_out='Fg', Fg_in='Fg_Av', Ts_in='Ts', Sws_in='Sws') # re-calculate the net radiation qcts.CalculateNetRadiation(cf, ds4, Fn_out='Fn', Fsd_in='Fsd', Fsu_in='Fsu', Fld_in='Fld', Flu_in='Flu') # re-calculate the available energy qcts.CalculateAvailableEnergy(ds4, Fa_out='Fa', Fn_in='Fn', Fg_in='Fg') # merge the second group of gap filled drivers into a single series qcts.MergeSeriesUsingDict(ds4, merge_order="standard") # re-calculate the water vapour concentrations qcts.CalculateHumiditiesAfterGapFill(ds4) # re-calculate the meteorological variables qcts.CalculateMeteorologicalVariables(ds4) # the Tumba rhumba qcts.CalculateComponentsFromWsWd(ds4) # check for any missing data qcutils.get_missingingapfilledseries(ds4) # write the percentage of good data as a variable attribute qcutils.get_coverage_individual(ds4) # write the percentage of good data for groups qcutils.get_coverage_groups(ds4) return ds4