def Saxton_1986_BC(outputShp, PTFOption): log.info("Calculating Brooks-Corey using Saxton et al. (1986)") # Arrays to output warningArray = [] WC_resArray = [] WC_satArray = [] lambda_BCArray = [] hb_BCArray = [] # Get OID field OIDField = common.getOIDField(outputShp) reqFields = [OIDField, "Sand", "Clay"] checks_PTFs.checkInputFields(reqFields, outputShp) # Retrieve info from input record = [] sandPerc = [] clayPerc = [] with arcpy.da.SearchCursor(outputShp, reqFields) as searchCursor: for row in searchCursor: objectID = row[0] sand = row[1] clay = row[2] record.append(objectID) sandPerc.append(sand) clayPerc.append(clay) A_Array = [] B_Array = [] for x in range(0, len(record)): # Data checks warningFlag = checks_PTFs.checkValue("Clay", clayPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Sand", sandPerc[x], record[x]) warningArray.append(warningFlag) # Calculate values # WC_0kPa = WC_sat WC_sat = 0.332 - (7.251 * 10**(-4) * sandPerc[x]) + (0.1276 * math.log(clayPerc[x], 10.0)) WC_residual = 0 A_Saxton = 100 * math.exp(-4.396 - (0.0715 * clayPerc[x])- (0.000488 * sandPerc[x]**2) - (0.00004285 * sandPerc[x]**2 * clayPerc[x])) B_Saxton = -3.140 - (0.00222 * clayPerc[x]**2) - (0.00003484 * sandPerc[x]**2 * clayPerc[x]) hb_BC = A_Saxton * (WC_sat** B_Saxton) lambda_BC = -1.0 / float(B_Saxton) checks_PTFs.checkNegOutput([WC_sat, WC_residual], x) WC_satArray.append(WC_sat) WC_resArray.append(WC_residual) A_Array.append(A_Saxton) B_Array.append(B_Saxton) hb_BCArray.append(hb_BC) lambda_BCArray.append(lambda_BC) return warningArray, WC_resArray, WC_satArray, lambda_BCArray, hb_BCArray
def codeSuccessfullyRun(codeBlockName, folder, rerun): try: success = False xmlFile = getProgressFilenames(folder).xmlFile if rerun: try: # Open file for reading tree = ET.parse(xmlFile) root = tree.getroot() codeBlockNodes = root.findall('CodeBlock') except Exception: removeFile(xmlFile) else: codeBlockNames = [] for codeBlockNode in codeBlockNodes: names = codeBlockNode.findall('Name') for name in names: codeBlockNames.append(name.text) if codeBlockName in codeBlockNames: success = True if success: log.info('Skipping: ' + str(codeBlockName)) return success except Exception: log.warning('Could not check if code block was previously run') log.warning(traceback.format_exc())
def writeOutputCriticalWC(outputShp, wc_sat, wc_fc, wc_sic, wc_pwp, wc_DW, wc_RAW, wc_NRAW, wc_PAW): # Add fields arcpy.AddField_management(outputShp, "wc_satCalc", "DOUBLE", 10, 6) arcpy.AddField_management(outputShp, "wc_fcCalc", "DOUBLE", 10, 6) arcpy.AddField_management(outputShp, "wc_sicCalc", "DOUBLE", 10, 6) arcpy.AddField_management(outputShp, "wc_pwpCalc", "DOUBLE", 10, 6) arcpy.AddField_management(outputShp, "wc_DW", "DOUBLE", 10, 6) arcpy.AddField_management(outputShp, "wc_RAW", "DOUBLE", 10, 6) arcpy.AddField_management(outputShp, "wc_NRAW", "DOUBLE", 10, 6) arcpy.AddField_management(outputShp, "wc_PAW", "DOUBLE", 10, 6) wcFields = [ "wc_satCalc", "wc_fcCalc", "wc_sicCalc", "wc_pwpCalc", "wc_DW", "wc_RAW", "wc_NRAW", "wc_PAW" ] recordNum = 0 with arcpy.da.UpdateCursor(outputShp, wcFields) as cursor: for row in cursor: row[0] = wc_sat[recordNum] row[1] = wc_fc[recordNum] row[2] = wc_sic[recordNum] row[3] = wc_pwp[recordNum] row[4] = wc_DW[recordNum] row[5] = wc_RAW[recordNum] row[6] = wc_NRAW[recordNum] row[7] = wc_PAW[recordNum] cursor.updateRow(row) recordNum += 1 log.info( 'Water contents for critical thresholds written to output shapefile')
def writeWCCSV(outputFolder, soilName, pressureArray, WCArray, pressureTitle, WCTitle): import csv # This function writes a CSV containing pressure and WC # Loop through and reshape the array headings = [pressureTitle, WCTitle] outArray = [] for i in range(0, len(pressureArray)): pressure = pressureArray[i] waterContent = WCArray[i] dataPoint = [pressure, waterContent] outArray.append(dataPoint) # Write to output CSV outName = str(soilName) + '.csv' outCSV = os.path.join(outputFolder, outName) with open(outCSV, 'wb') as csv_file: writer = csv.writer(csv_file) writer.writerow(headings) for i in range(0, len(outArray)): row = outArray[i] writer.writerow(row) msg = 'Output CSV with water contents and pressure saved to: ' + str( outCSV) log.info(msg) csv_file.close()
def Cosby_1984_SSC_BC(outputShp, PTFOption): log.info("Calculating Brooks-Corey using Cosby et al. (1984) - Sand, Silt and Clay") # Arrays to output warningArray = [] WC_resArray = [] WC_satArray = [] lambda_BCArray = [] hb_BCArray = [] # Get OID field OIDField = common.getOIDField(outputShp) reqFields = [OIDField, "Sand", "Silt", "Clay"] checks_PTFs.checkInputFields(reqFields, outputShp) # Retrieve info from input record = [] sandPerc = [] siltPerc = [] clayPerc = [] with arcpy.da.SearchCursor(outputShp, reqFields) as searchCursor: for row in searchCursor: objectID = row[0] sand = row[1] silt = row[2] clay = row[3] record.append(objectID) sandPerc.append(sand) siltPerc.append(silt) clayPerc.append(clay) for x in range(0, len(record)): # Data checks warningFlag = checks_PTFs.checkSSC(sandPerc[x], siltPerc[x], clayPerc[x], record[x]) warningArray.append(warningFlag) # Calculate values WC_res = 0 WC_sat = (50.5 - (0.037 * clayPerc[x]) - (0.142 * sandPerc[x])) / 100.0 lambda_BC = 1.0 / (3.10 + (0.157 * clayPerc[x]) - (0.003 * sandPerc[x])) # Originally in cm hb_cm = 10.0 ** (1.54 - (0.0095 * sandPerc[x]) + (0.0063 * siltPerc[x])) hb_BC = hb_cm / 10.0 # Convert to kPa outValues = [WC_res, WC_sat] checks_PTFs.checkNegOutput(outValues, x) # Append to arrays WC_resArray.append(WC_res) WC_satArray.append(WC_sat) lambda_BCArray.append(lambda_BC) hb_BCArray.append(hb_BC) return warningArray, WC_resArray, WC_satArray, lambda_BCArray, hb_BCArray
def Jabro_1992(outputFolder, outputShp): # Returns these arrays warningArray = [] K_satArray = [] log.info('Calculating saturated hydraulic conductivity using Jabro (1992)') PTFInfo = PTFdatabase.checkPTF("Jabro_1992") PTFType = PTFInfo.PTFType PTFPressures = PTFInfo.PTFPressures PTFFields = PTFInfo.PTFFields # Requirements: sand and clay # Get OID field OIDField = common.getOIDField(outputShp) reqFields = [OIDField, "Silt", "Clay", "BD"] checks_PTFs.checkInputFields(reqFields, outputShp) # Retrieve info from input record = [] siltPerc = [] clayPerc = [] BDg_cm3 = [] with arcpy.da.SearchCursor(outputShp, reqFields) as searchCursor: for row in searchCursor: objectID = row[0] silt = row[1] clay = row[2] BD = row[3] record.append(objectID) siltPerc.append(silt) clayPerc.append(clay) BDg_cm3.append(BD) for x in range(0, len(record)): # Data checks warningFlag = checks_PTFs.checkValue("Silt", siltPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Clay", clayPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Bulk density", BDg_cm3[x], record[x]) warningArray.append(warningFlag) K_sat = 10**(9.56 - (0.81 * math.log(siltPerc[x], 10.0)) - (1.09 * math.log(clayPerc[x], 10.0)) - (4.64 * BDg_cm3[x])) * 10.0 checks_PTFs.checkValue("Ksat", K_sat, record[x]) K_satArray.append(K_sat) return warningArray, K_satArray
def Cosby_1984_SandC_BC(outputShp, PTFOption): log.info("Calculating Brooks-Corey using Cosby et al. (1984) - Sand and Clay") # Arrays to output warningArray = [] WC_resArray = [] WC_satArray = [] lambda_BCArray = [] hb_BCArray = [] # Get OID field OIDField = common.getOIDField(outputShp) reqFields = [OIDField, "Sand", "Clay"] checks_PTFs.checkInputFields(reqFields, outputShp) record = [] sandPerc = [] clayPerc = [] # Required: sand and clay with arcpy.da.SearchCursor(outputShp, reqFields) as searchCursor: for row in searchCursor: objectID = row[0] sand = row[1] clay = row[2] record.append(objectID) sandPerc.append(sand) clayPerc.append(clay) for x in range(0, len(record)): # Data checks warningFlag = checks_PTFs.checkValue("Clay", clayPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Sand", sandPerc[x], record[x]) warningArray.append(warningFlag) # Calculate values WC_res = 0 WC_sat = 0.489 - (0.00126 * sandPerc[x]) lambda_BC = 1.0 / (2.91 + (0.159 * clayPerc[x])) # Originally in cm hb_cm = 10.0 ** (1.88 - (0.013 * sandPerc[x])) hb_BC = hb_cm / 10.0 # Convert to kPa outValues = [WC_res, WC_sat] checks_PTFs.checkNegOutput(outValues, x) # Append to arrays WC_resArray.append(WC_res) WC_satArray.append(WC_sat) lambda_BCArray.append(lambda_BC) hb_BCArray.append(hb_BC) return warningArray, WC_resArray, WC_satArray, lambda_BCArray, hb_BCArray
def RawlsBrakensiek_1985_BC(outputShp, PTFOption): log.info("Calculating Brooks-Corey using Rawls and Brakensiek (1985)") # Arrays to output warningArray = [] WC_resArray = [] lambda_BCArray = [] hb_BCArray = [] # Get OID field OIDField = common.getOIDField(outputShp) reqFields = [OIDField, "Sand", "Clay", "WC_sat"] checks_PTFs.checkInputFields(reqFields, outputShp) # Retrieve info from input record = [] sandPerc = [] clayPerc = [] WC_satArray = [] with arcpy.da.SearchCursor(outputShp, reqFields) as searchCursor: for row in searchCursor: objectID = row[0] sand = row[1] clay = row[2] WCsat = row[3] record.append(objectID) sandPerc.append(sand) clayPerc.append(clay) WC_satArray.append(WCsat) for x in range(0, len(record)): # Data checks warningFlag = checks_PTFs.checkValue("Clay", clayPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Sand", sandPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Input saturation", WC_satArray[x], record[x]) warningArray.append(warningFlag) # Calculate values WC_residual = -0.0182482 + (0.00087269 * sandPerc[x]) + (0.00513488 * clayPerc[x]) + (0.02939286 * WC_satArray[x]) - (0.00015395 * clayPerc[x]**2) - (0.0010827 * sandPerc[x] * WC_satArray[x]) - (0.00018233 * clayPerc[x]**2 * WC_satArray[x]**2) + (0.00030703 * clayPerc[x]**2 * WC_satArray[x]) - (0.0023584 * WC_satArray[x]**2 * clayPerc[x]) # Originally in cm hb_cm = math.exp(5.3396738 + (0.1845038 * clayPerc[x]) - (2.48394546 * WC_satArray[x]) - (0.00213853 * clayPerc[x]**2) - (0.04356349 * sandPerc[x] * WC_satArray[x]) - (0.61745089 * clayPerc[x] * WC_satArray[x]) + (0.00143598 * sandPerc[x]**2 * WC_satArray[x]**2) - (0.00855375 * clayPerc[x]**2 * WC_satArray[x]**2) - (0.00001282 * sandPerc[x]**2 * clayPerc[x]) + (0.00895359 * clayPerc[x]**2 * WC_satArray[x]) - (0.00072472 * sandPerc[x]**2 * WC_satArray[x]) + (0.0000054 * clayPerc[x]**2 * sandPerc[x]) + (0.50028060 * WC_satArray[x]**2 * clayPerc[x])) hb_BC = hb_cm / 10.0 # Convert to kPa lambda_BC = math.exp(-0.7842831 + (0.0177544 * sandPerc[x]) - (1.062498 * WC_satArray[x]) - (0.00005304 * sandPerc[x]**2) - (0.00273493 * clayPerc[x]**2) + (1.11134946 * WC_satArray[x]**2) - (0.03088295 * sandPerc[x] * WC_satArray[x]) + (0.00026587 * sandPerc[x]**2 * WC_satArray[x]**2) - (0.00610522 * clayPerc[x]**2 * WC_satArray[x]**2) - (0.00000235 * sandPerc[x]**2 * clayPerc[x]) + (0.00798746 * clayPerc[x]**2 * WC_satArray[x]) - (0.00674491 * WC_satArray[x]**2 * clayPerc[x])) checks_PTFs.checkNegOutput([WC_residual], x) WC_resArray.append(WC_residual) hb_BCArray.append(hb_BC) lambda_BCArray.append(lambda_BC) return warningArray, WC_resArray, WC_satArray, lambda_BCArray, hb_BCArray
def MinasnyMcBratney_2000(outputFolder, outputShp): # Returns these arrays warningArray = [] K_satArray = [] log.info( 'Calculating saturated hydraulic conductivity using Minasny and McBratney (2000)' ) PTFInfo = PTFdatabase.checkPTF("MinasnyMcBratney_2000") PTFType = PTFInfo.PTFType PTFPressures = PTFInfo.PTFPressures PTFFields = PTFInfo.PTFFields # Get OID field OIDField = common.getOIDField(outputShp) # Requirements: WC @ Sat and WC @ FC reqFields = [OIDField, "wc_satCalc", "wc_fcCalc"] checks_PTFs.checkInputFields(reqFields, outputShp) # Retrieve info from input record = [] WC_satArray = [] WC_FCArray = [] with arcpy.da.SearchCursor(outputShp, reqFields) as searchCursor: for row in searchCursor: objectID = row[0] WC_sat = row[1] WC_FC = row[2] record.append(objectID) WC_satArray.append(WC_sat) WC_FCArray.append(WC_FC) for x in range(0, len(record)): # Data checks warningFlag = checks_PTFs.checkValue("WC at sat", WC_satArray[x], record[x]) warningFlag = checks_PTFs.checkValue("WC at FC", WC_FCArray[x], record[x]) warningArray.append(warningFlag) Eff_porosity = WC_satArray[x] - WC_FCArray[x] K_sat = 23190.55 * Eff_porosity**3.66 checks_PTFs.checkValue("Ksat", K_sat, record[x]) K_satArray.append(K_sat) return warningArray, K_satArray
def Cosby_1984(outputFolder, outputShp): # Returns these arrays warningArray = [] K_satArray = [] log.info( 'Calculating saturated hydraulic conductivity using Cosby et al. (1984)' ) PTFInfo = PTFdatabase.checkPTF("Cosby_1984") PTFType = PTFInfo.PTFType PTFPressures = PTFInfo.PTFPressures PTFFields = PTFInfo.PTFFields # Requirements: sand and clay # Get OID field OIDField = common.getOIDField(outputShp) reqFields = [OIDField, "Sand", "Clay"] checks_PTFs.checkInputFields(reqFields, outputShp) # Retrieve info from input record = [] sandPerc = [] clayPerc = [] with arcpy.da.SearchCursor(outputShp, reqFields) as searchCursor: for row in searchCursor: objectID = row[0] sand = row[1] clay = row[2] record.append(objectID) sandPerc.append(sand) clayPerc.append(clay) for x in range(0, len(record)): # Data checks warningFlag = checks_PTFs.checkValue("Sand", sandPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Clay", clayPerc[x], record[x]) warningArray.append(warningFlag) K_sat = 25.4 * 10**(-0.6 + (0.0126 * sandPerc[x]) - (0.0064 * clayPerc[x])) checks_PTFs.checkValue("Ksat", K_sat, record[x]) K_satArray.append(K_sat) return warningArray, K_satArray
def CampbellShiozawa_1994(outputFolder, outputShp): # Returns these arrays warningArray = [] K_satArray = [] log.info( 'Calculating saturated hydraulic conductivity using Campbell and Shiozawa (1994)' ) PTFInfo = PTFdatabase.checkPTF("CampbellShiozawa_1994") PTFType = PTFInfo.PTFType PTFPressures = PTFInfo.PTFPressures PTFFields = PTFInfo.PTFFields # Requirements: silt and clay # Get OID field OIDField = common.getOIDField(outputShp) reqFields = [OIDField, "Silt", "Clay"] checks_PTFs.checkInputFields(reqFields, outputShp) # Retrieve info from input record = [] siltPerc = [] clayPerc = [] with arcpy.da.SearchCursor(outputShp, reqFields) as searchCursor: for row in searchCursor: objectID = row[0] silt = row[1] clay = row[2] record.append(objectID) siltPerc.append(silt) clayPerc.append(clay) for x in range(0, len(record)): # Data checks warningFlag = checks_PTFs.checkValue("Silt", siltPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Clay", clayPerc[x], record[x]) warningArray.append(warningFlag) K_sat = 54.0 * math.exp((-0.07 * siltPerc[x]) - (0.167 * clayPerc[x])) checks_PTFs.checkValue("Ksat", K_sat, record[x]) K_satArray.append(K_sat) return warningArray, K_satArray
def FerrerJulia_2004_1(outputFolder, outputShp): # Returns these arrays warningArray = [] K_satArray = [] log.info( 'Calculating saturated hydraulic conductivity using Ferrer Julia et al. (2004) - Sand' ) PTFInfo = PTFdatabase.checkPTF("FerrerJulia_2004_1") PTFType = PTFInfo.PTFType PTFPressures = PTFInfo.PTFPressures PTFFields = PTFInfo.PTFFields # Requirements: sand # Get OID field OIDField = common.getOIDField(outputShp) reqFields = [OIDField, "Sand"] checks_PTFs.checkInputFields(reqFields, outputShp) # Retrieve info from input record = [] sandPerc = [] with arcpy.da.SearchCursor(outputShp, reqFields) as searchCursor: for row in searchCursor: objectID = row[0] sand = row[1] record.append(objectID) sandPerc.append(sand) for x in range(0, len(record)): # Data checks warningFlag = checks_PTFs.checkValue("Sand", sandPerc[x], record[x]) warningArray.append(warningFlag) K_sat = 0.920 * math.exp(0.0491 * sandPerc[x]) checks_PTFs.checkValue("Ksat", K_sat, record[x]) K_satArray.append(K_sat) return warningArray, K_satArray
def Puckett_1985(outputFolder, outputShp): # Returns these arrays warningArray = [] K_satArray = [] log.info( 'Calculating saturated hydraulic conductivity using Puckett et al. (1985)' ) PTFInfo = PTFdatabase.checkPTF("Puckett_1985") PTFType = PTFInfo.PTFType PTFPressures = PTFInfo.PTFPressures PTFFields = PTFInfo.PTFFields # Requirements: Clay # Get OID field OIDField = common.getOIDField(outputShp) reqFields = [OIDField, "Clay"] checks_PTFs.checkInputFields(reqFields, outputShp) # Retrieve info from input record = [] clayPerc = [] with arcpy.da.SearchCursor(outputShp, reqFields) as searchCursor: for row in searchCursor: objectID = row[0] clay = row[1] record.append(objectID) clayPerc.append(clay) for x in range(0, len(record)): # Data checks warningFlag = checks_PTFs.checkValue("Clay", clayPerc[x], record[x]) warningArray.append(warningFlag) K_sat = 156.96 * math.exp(-0.1975 * clayPerc[x]) checks_PTFs.checkValue("Ksat", K_sat, record[x]) K_satArray.append(K_sat) return warningArray, K_satArray
def checkInputFields(inputFields, inputShp): log.info('Checking if all required input fields are present in ' + str(inputShp)) # Checks if the input fields are present in the shapefile for param in inputFields: fieldPresent = False if common.CheckField(inputShp, param): fieldPresent = True else: log.error("Field " + str(param) + " not found in the input shapefile") log.error( "Please ensure this field present in the input shapefile") sys.exit()
def writeOutputWC(outputShp, WC_1kPaArray, WC_3kPaArray, WC_10kPaArray, WC_33kPaArray, WC_100kPaArray, WC_200kPaArray, WC_1000kPaArray, WC_1500kPaArray): # Write outputs of VG or BC equations to output shapefile # Add fields arcpy.AddField_management(outputShp, "WC_1kPa", "DOUBLE", 10, 6) arcpy.AddField_management(outputShp, "WC_3kPa", "DOUBLE", 10, 6) arcpy.AddField_management(outputShp, "WC_10kPa", "DOUBLE", 10, 6) arcpy.AddField_management(outputShp, "WC_33kPa", "DOUBLE", 10, 6) arcpy.AddField_management(outputShp, "WC_100kPa", "DOUBLE", 10, 6) arcpy.AddField_management(outputShp, "WC_200kPa", "DOUBLE", 10, 6) arcpy.AddField_management(outputShp, "WC_1000kPa", "DOUBLE", 10, 6) arcpy.AddField_management(outputShp, "WC_1500kPa", "DOUBLE", 10, 6) outputFields = [ "WC_1kPa", "WC_3kPa", "WC_10kPa", "WC_33kPa", "WC_100kPa", "WC_200kPa", "WC_1000kPa", "WC_1500kpa" ] recordNum = 0 with arcpy.da.UpdateCursor(outputShp, outputFields) as cursor: for row in cursor: row[0] = WC_1kPaArray[recordNum] row[1] = WC_3kPaArray[recordNum] row[2] = WC_10kPaArray[recordNum] row[3] = WC_33kPaArray[recordNum] row[4] = WC_100kPaArray[recordNum] row[5] = WC_200kPaArray[recordNum] row[6] = WC_1000kPaArray[recordNum] row[7] = WC_1500kPaArray[recordNum] cursor.updateRow(row) recordNum += 1 log.info("Water content at default pressures written to output shapefile")
def function(outputFolder, inputShp, PTFOption, fcVal, sicVal, pwpVal, carbContent, carbonConFactor): try: # Set temporary variables prefix = os.path.join(arcpy.env.scratchGDB, "soil_") # Set output filename outputShp = os.path.join(outputFolder, "soil_point_ptf.shp") # Copy the input shapefile to the output folder arcpy.CopyFeatures_management(inputShp, outputShp) #################################### ### Calculate the water contents ### #################################### # Get the nameArray nameArray = [] with arcpy.da.SearchCursor(outputShp, "LUCIname") as searchCursor: for row in searchCursor: name = row[0] nameArray.append(name) # Get PTF fields PTFxml = os.path.join(outputFolder, "ptfinfo.xml") PTFFields = common.readXML(PTFxml, 'PTFFields') PTFPressures = common.readXML(PTFxml, 'PTFPressures') PTFUnit = common.readXML(PTFxml, 'PTFUnit') # Call point-PTF here depending on PTFOption if PTFOption == "Nguyen_2014": results = point_PTFs.Nguyen_2014(outputFolder, outputShp, carbonConFactor, carbContent) elif PTFOption == "Adhikary_2008": results = point_PTFs.Adhikary_2008(outputFolder, outputShp) elif PTFOption == "Rawls_1982": results = point_PTFs.Rawls_1982(outputFolder, outputShp, carbonConFactor, carbContent) elif PTFOption == "Hall_1977_top": results = point_PTFs.Hall_1977_top(outputFolder, outputShp, carbonConFactor, carbContent) elif PTFOption == "Hall_1977_sub": results = point_PTFs.Hall_1977_sub(outputFolder, outputShp, carbonConFactor, carbContent) elif PTFOption == "GuptaLarson_1979": results = point_PTFs.GuptaLarson_1979(outputFolder, outputShp, carbonConFactor, carbContent) elif PTFOption == "Batjes_1996": results = point_PTFs.Batjes_1996(outputFolder, outputShp, carbonConFactor, carbContent) elif PTFOption == "SaxtonRawls_2006": results = point_PTFs.SaxtonRawls_2006(outputFolder, outputShp, carbonConFactor, carbContent) elif PTFOption == "Pidgeon_1972": results = point_PTFs.Pidgeon_1972(outputFolder, outputShp, carbonConFactor, carbContent) elif str(PTFOption[0:8]) == "Lal_1978": results = point_PTFs.Lal_1978(outputFolder, outputShp, PTFOption) elif PTFOption == "AinaPeriaswamy_1985": results = point_PTFs.AinaPeriaswamy_1985(outputFolder, outputShp) elif PTFOption == "ManriqueJones_1991": results = point_PTFs.ManriqueJones_1991(outputFolder, outputShp) elif PTFOption == "vanDenBerg_1997": results = point_PTFs.vanDenBerg_1997(outputFolder, outputShp, carbonConFactor, carbContent) elif PTFOption == "TomasellaHodnett_1998": results = point_PTFs.TomasellaHodnett_1998(outputFolder, outputShp, carbonConFactor, carbContent) elif PTFOption == "Reichert_2009_OM": results = point_PTFs.Reichert_2009_OM(outputFolder, outputShp, carbonConFactor, carbContent) elif PTFOption == "Reichert_2009": results = point_PTFs.Reichert_2009(outputFolder, outputShp) elif PTFOption == "Botula_2013": results = point_PTFs.Botula_2013(outputFolder, outputShp) elif PTFOption == "ShwethaVarija_2013": results = point_PTFs.ShwethaVarija_2013(outputFolder, outputShp) elif PTFOption == "Dashtaki_2010_point": results = point_PTFs.Dashtaki_2010(outputFolder, outputShp) elif PTFOption == "Santra_2018_OC": results = point_PTFs.Santra_2018_OC(outputFolder, outputShp, carbonConFactor, carbContent) elif PTFOption == "Santra_2018": results = point_PTFs.Santra_2018(outputFolder, outputShp) else: log.error("PTF option not recognised") sys.exit() # Plots plots.plotPTF(outputFolder, outputShp, PTFOption, nameArray, results) ###################################################### ### Calculate water content at critical thresholds ### ###################################################### satStatus = False fcStatus = False sicStatus = False pwpStatus = False wc_satCalc = [] wc_fcCalc = [] wc_sicCalc = [] wc_pwpCalc = [] if PTFOption == "Reichert_2009_OM": log.info( 'For Reichert et al. (2009) - Sand, silt, clay, OM, BD saturation is at 6kPa' ) satField = "WC_6kPa" else: satField = "WC_0" + str(PTFUnit) fcField = "WC_" + str(int(fcVal)) + str(PTFUnit) sicField = "WC_" + str(int(sicVal)) + str(PTFUnit) pwpField = "WC_" + str(int(pwpVal)) + str(PTFUnit) wcFields = [] wcArrays = [] if satField in PTFFields: # Saturation set to 0kPa # PTFs with 0kPa: ## Saxton_1986, Batjes_1996, SaxtonRawls_2006 ## Lal_1978_Group1, Lal_1978_Group2 ## TomasellaHodnett_1998 log.info('Field with WC at saturation found!') with arcpy.da.SearchCursor(outputShp, satField) as searchCursor: for row in searchCursor: wc_sat = row[0] if wc_sat > 1.0: log.warning('Water content at saturation over 1.0') wc_satCalc.append(wc_sat) satStatus = True wcFields.append("wc_satCalc") wcArrays.append(wc_satCalc) # Add sat field to output shapefile arcpy.AddField_management(outputShp, "wc_satCalc", "DOUBLE", 10, 6) recordNum = 0 with arcpy.da.UpdateCursor(outputShp, "wc_satCalc") as cursor: for row in cursor: row[0] = wc_satCalc[recordNum] cursor.updateRow(row) recordNum += 1 else: log.warning('Field with WC at saturation not found') satStatus = False if fcField in PTFFields: log.info('Field with WC at field capacity found!') with arcpy.da.SearchCursor(outputShp, fcField) as searchCursor: for row in searchCursor: wc_fc = row[0] wc_fcCalc.append(wc_fc) fcStatus = True wcFields.append("wc_fcCalc") wcArrays.append(wc_fcCalc) # Add FC field to output shapefile arcpy.AddField_management(outputShp, "wc_fcCalc", "DOUBLE", 10, 6) recordNum = 0 with arcpy.da.UpdateCursor(outputShp, "wc_fcCalc") as cursor: for row in cursor: row[0] = wc_fcCalc[recordNum] cursor.updateRow(row) recordNum += 1 else: log.warning('Field with WC at field capacity not found') fcStatus = False if sicField in PTFFields: log.info( 'Field with WC at water stress-induced stomatal closure found!' ) with arcpy.da.SearchCursor(outputShp, sicField) as searchCursor: for row in searchCursor: wc_sic = row[0] wc_sicCalc.append(wc_sic) sicStatus = True wcFields.append("wc_sicCalc") wcArrays.append(wc_sicCalc) # Add sic field to output shapefile arcpy.AddField_management(outputShp, "wc_sicCalc", "DOUBLE", 10, 6) recordNum = 0 with arcpy.da.UpdateCursor(outputShp, "wc_sicCalc") as cursor: for row in cursor: row[0] = wc_sicCalc[recordNum] cursor.updateRow(row) recordNum += 1 else: log.warning( 'Field with WC at water stress-induced stomatal closure not found' ) sicStatus = False if pwpField in PTFFields: log.info('Field with WC at permanent wilting point found!') with arcpy.da.SearchCursor(outputShp, pwpField) as searchCursor: for row in searchCursor: wc_pwp = row[0] if wc_pwp < 0.01: log.warning( 'WARNING: Water content at PWP is below 0.01') elif wc_pwp < 0.05: log.warning('Water content at PWP is below 0.05') wc_pwpCalc.append(wc_pwp) pwpStatus = True wcFields.append("wc_pwpCalc") wcArrays.append(wc_pwpCalc) # Add pwp field to output shapefile arcpy.AddField_management(outputShp, "wc_pwpCalc", "DOUBLE", 10, 6) recordNum = 0 with arcpy.da.UpdateCursor(outputShp, "wc_pwpCalc") as cursor: for row in cursor: row[0] = wc_pwpCalc[recordNum] cursor.updateRow(row) recordNum += 1 else: log.warning('Field with WC at permanent wilting point not found') pwpStatus = False drainWater = [] PAW = [] RAW = [] NRAW = [] if satStatus == True and fcStatus == True: # drainWater = wc_sat - wc_fc drainWater = point_PTFs.calcWaterContent(wc_satCalc, wc_fcCalc, 'drainable water', nameArray) log.info('Drainable water calculated') wcFields.append("wc_DW") wcArrays.append(drainWater) # Add DW field to output shapefile arcpy.AddField_management(outputShp, "wc_DW", "DOUBLE", 10, 6) recordNum = 0 with arcpy.da.UpdateCursor(outputShp, "wc_DW") as cursor: for row in cursor: row[0] = drainWater[recordNum] cursor.updateRow(row) recordNum += 1 if fcStatus == True and pwpStatus == True: # PAW = wc_fc - wc_pwp PAW = point_PTFs.calcWaterContent(wc_fcCalc, wc_pwpCalc, 'plant available water', nameArray) log.info('Plant available water calculated') wcFields.append("wc_PAW") wcArrays.append(PAW) # Add PAW field to output shapefile arcpy.AddField_management(outputShp, "wc_PAW", "DOUBLE", 10, 6) recordNum = 0 with arcpy.da.UpdateCursor(outputShp, "wc_PAW") as cursor: for row in cursor: row[0] = PAW[recordNum] cursor.updateRow(row) recordNum += 1 pawStatus = True if fcStatus == True and sicStatus == True: # readilyAvailWater = wc_fc - wc_sic RAW = point_PTFs.calcWaterContent(wc_fcCalc, wc_sicCalc, 'readily available water', nameArray) log.info('Readily available water calculated') wcFields.append("wc_RAW") wcArrays.append(RAW) # Add wc_RAW field to output shapefile arcpy.AddField_management(outputShp, "wc_RAW", "DOUBLE", 10, 6) recordNum = 0 with arcpy.da.UpdateCursor(outputShp, "wc_RAW") as cursor: for row in cursor: row[0] = RAW[recordNum] cursor.updateRow(row) recordNum += 1 elif pawStatus == True: # If PAW exists, get RAW = 0.5 * RAW PAW = point_PTFs.calcWaterContent(wc_fcCalc, wc_pwpCalc, 'plant available water', nameArray) RAW = [(float(i) * 0.5) for i in PAW] log.info('Readily available water calculated based on PAW') wcFields.append("wc_RAW") wcArrays.append(RAW) # Add wc_RAW field to output shapefile arcpy.AddField_management(outputShp, "wc_RAW", "DOUBLE", 10, 6) recordNum = 0 with arcpy.da.UpdateCursor(outputShp, "wc_RAW") as cursor: for row in cursor: row[0] = RAW[recordNum] cursor.updateRow(row) recordNum += 1 else: log.info('Readily available water not calculated') if sicStatus == True and pwpStatus == True: # notRAW = wc_sic - wc_pwp NRAW = point_PTFs.calcWaterContent(wc_sicCalc, wc_pwpCalc, 'not readily available water', nameArray) log.info('Not readily available water calculated') wcFields.append("wc_NRAW") wcArrays.append(NRAW) # Add sat field to output shapefile arcpy.AddField_management(outputShp, "wc_NRAW", "DOUBLE", 10, 6) recordNum = 0 with arcpy.da.UpdateCursor(outputShp, "wc_NRAW") as cursor: for row in cursor: row[0] = NRAW[recordNum] cursor.updateRow(row) recordNum += 1 log.info( 'Water contents at critical thresholds written to output shapefile' ) except Exception: arcpy.AddError("Point-PTFs function failed") raise finally: # Remove feature layers from memory try: for lyr in common.listFeatureLayers(locals()): arcpy.Delete_management(locals()[lyr]) exec(lyr + ' = None') in locals() except Exception: pass
def function(params): try: pText = common.paramsAsText(params) # Get inputs runSystemChecks = common.strToBool(pText[1]) outputFolder = pText[2] inputFolder = pText[3] # Get equation of choice Ksat = pText[4] carbonContent = pText[5] carbonConFactor = pText[6] # Create output folder if not os.path.exists(outputFolder): os.mkdir(outputFolder) # System checks and setup if runSystemChecks: common.runSystemChecks(outputFolder) # Set up logging output to file log.setupLogging(outputFolder) # Write input params to XML common.writeParamsToXML(params, outputFolder) # Set saturated hydraulic conductivity option if Ksat == 'Cosby et al. (1984)': KsatOption = 'Cosby_1984' elif Ksat == 'Puckett et al. (1985)': KsatOption = 'Puckett_1985' elif Ksat == 'Jabro (1992)': KsatOption = 'Jabro_1992' elif Ksat == 'Campbell and Shiozawa (1994)': KsatOption = 'CampbellShiozawa_1994' elif Ksat == 'Ferrer Julia et al. (2004) - Sand': KsatOption = 'FerrerJulia_2004_1' elif Ksat == 'Ferrer Julia et al. (2004) - Sand, clay, OM': KsatOption = 'FerrerJulia_2004_2' elif Ksat == 'Ahuja et al. (1989)': KsatOption = 'Ahuja_1989' elif Ksat == 'Minasny and McBratney (2000)': KsatOption = 'MinasnyMcBratney_2000' elif Ksat == 'Brakensiek et al. (1984)': KsatOption = 'Brakensiek_1984' elif Ksat == 'Wosten et al. (1999)': KsatOption = 'Wosten_1999' log.info( '===========================================================================' ) log.info( 'Wosten et al. (1999) already calculated Ksat in the previous step' ) log.info( 'Please check the output shapefile of the previous step for the K_sat field' ) log.info( '===========================================================================' ) sys.exit() else: log.error('Invalid Ksat option') sys.exit() # Set carbon content choice if carbonContent == 'Organic carbon': carbContent = 'OC' elif carbonContent == 'Organic matter': carbContent = 'OM' else: log.error('Invalid carbon content option') sys.exit() # Pull out PTFinfo PTFInfo = PTFdatabase.checkPTF(KsatOption) PTFType = PTFInfo.PTFType PTFUnit = PTFInfo.PTFUnit PTFOut = [("KsatOption", KsatOption), ("PTFType", PTFType), ("carbContent", carbContent)] # Write to XML file PTFXML = os.path.join(outputFolder, "ksat_ptfinfo.xml") common.writeXML(PTFXML, PTFOut) CalcKsat.function(outputFolder, inputFolder, KsatOption, carbContent, carbonConFactor) # Set output filename for display KsatOut = os.path.join(outputFolder, "Ksat.shp") arcpy.SetParameter(7, KsatOut) log.info( "Saturated hydraulic conductivity operations completed successfully" ) except Exception: log.exception("Saturated hydraulic conductivity tool failed") raise
def Wosten_1999(outputShp, VGOption, carbonConFactor, carbContent, MVGChoice): # Arrays to write to shapefile warningArray = [] K_satArray = [] WC_satArray = [] WC_residualArray = [] alpha_VGArray = [] n_VGArray = [] m_VGArray = [] l_MvGArray = [] log.info("Calculating van Genuchten parameters using Wosten et al. (1999)") # Requirements: sand, silt, clay, OM, and BD # Get OID field OIDField = common.getOIDField(outputShp) if carbContent == 'OC': reqFields = [ OIDField, "Sand", "Silt", "Clay", "OC", "BD", "LUCIname", "texture" ] elif carbContent == 'OM': reqFields = [ OIDField, "Sand", "Silt", "Clay", "OM", "BD", "LUCIname", "texture" ] carbonConFactor = 1.0 checks_PTFs.checkInputFields(reqFields, outputShp) # Retrieve info from input record = [] sandPerc = [] siltPerc = [] clayPerc = [] carbPerc = [] BDg_cm3 = [] nameArray = [] textureArray = [] with arcpy.da.SearchCursor(outputShp, reqFields) as searchCursor: for row in searchCursor: objectID = row[0] sand = row[1] silt = row[2] clay = row[3] carbon = row[4] BD = row[5] name = row[6] texture = row[7] record.append(objectID) sandPerc.append(sand) siltPerc.append(silt) clayPerc.append(clay) carbPerc.append(carbon) BDg_cm3.append(BD) nameArray.append(name) textureArray.append(texture) for x in range(0, len(record)): # Data checks warningFlag = checks_PTFs.checkSSC(sandPerc[x], siltPerc[x], clayPerc[x], record[x]) warningFlag = checks_PTFs.checkCarbon(carbPerc[x], carbContent, record[x]) warningFlag = checks_PTFs.checkValue("Bulk density", BDg_cm3[x], record[x]) warningArray.append(warningFlag) # Calculate VG parameters if clayPerc[x] < 18.0 and sandPerc[x] > 65.0: WC_residual = 0.025 else: WC_residual = 0.01 if VGOption == 'Wosten_1999_top': K_sat = (10.0 / 24.0) * math.exp( 7.755 + (0.0352 * siltPerc[x]) + (0.93 * 1) - (0.976 * BDg_cm3[x]**2) - (0.000484 * clayPerc[x]**2) - (0.000322 * siltPerc[x]**2) + (0.001 * siltPerc[x]**(-1)) - (0.0748 * (carbPerc[x] * float(carbonConFactor))**(-1)) - (0.643 * math.log(siltPerc[x])) - (0.0139 * BDg_cm3[x] * clayPerc[x]) - (0.167 * BDg_cm3[x] * carbPerc[x] * float(carbonConFactor)) + (0.0298 * 1 * clayPerc[x]) - (0.03305 * 1 * siltPerc[x])) WC_sat = 0.7919 + (0.001691 * clayPerc[x]) - ( 0.29619 * BDg_cm3[x]) - (0.000001491 * siltPerc[x]**2) + ( 0.0000821 * ((carbPerc[x] * float(carbonConFactor)))**2) + ( 0.02427 * clayPerc[x]**(-1.0) + (0.01113 * siltPerc[x]**(-1.0)) + (0.01472 * math.log(siltPerc[x])) - 0.0000733 * ((carbPerc[x] * float(carbonConFactor))) * clayPerc[x] ) - (0.000619 * BDg_cm3[x] * clayPerc[x]) - (0.001183 * BDg_cm3[x] * (carbPerc[x] * float(carbonConFactor)) ) - (0.0001664 * 1.0 * siltPerc[x]) # Alpha with 10.0 multiplier (convert alpha in cm-1 to kPa-1) alpha_cm = math.exp( -14.96 + (0.03135 * clayPerc[x]) + (0.0351 * siltPerc[x]) + (0.646 * (carbPerc[x] * float(carbonConFactor))) + (15.29 * BDg_cm3[x]) - (0.192 * 1.0) - (4.671 * BDg_cm3[x]**2.0) - (0.000781 * clayPerc[x]**2) - (0.00687 * (carbPerc[x] * float(carbonConFactor))**2.0) + (0.0449 * ((carbPerc[x] * float(carbonConFactor)))**(-1.0)) + (0.0663 * math.log(siltPerc[x])) + (0.1482 * math.log((carbPerc[x] * float(carbonConFactor)))) - (0.04546 * BDg_cm3[x] * siltPerc[x]) - (0.4852 * BDg_cm3[x] * (carbPerc[x] * float(carbonConFactor))) + (0.00673 * 1.0 * clayPerc[x])) alpha_VG = 10.0 * alpha_cm # Converted from cm-1 to kPa-1 for internal consistency n_VG = 1.0 + math.exp( -25.23 - (0.02195 * clayPerc[x]) + (0.0074 * siltPerc[x]) - (0.1940 * (carbPerc[x] * float(carbonConFactor))) + (45.5 * BDg_cm3[x]) - (7.24 * BDg_cm3[x]**2.0) + (0.0003658 * clayPerc[x]**2.0) + (0.002885 * ((carbPerc[x] * float(carbonConFactor)))**2.0) - (12.81 * (BDg_cm3[x])**(-1.0)) - (0.1524 * (siltPerc[x])**(-1.0)) - (0.01958 * ((carbPerc[x] * float(carbonConFactor)))**(-1.0)) - (0.2876 * math.log(siltPerc[x])) - (0.0709 * math.log((carbPerc[x] * float(carbonConFactor)))) - (44.6 * math.log(BDg_cm3[x])) - (0.02264 * BDg_cm3[x] * clayPerc[x]) + (0.0896 * BDg_cm3[x] * (carbPerc[x] * float(carbonConFactor))) + (0.00718 * 1.0 * clayPerc[x])) m_VG = 1.0 - (1.0 / float(n_VG)) l_MvG_norm = 0.0202 + (0.0006193 * clayPerc[x]**2) - ( 0.001136 * (carbPerc[x] * float(carbonConFactor))**2) - ( 0.2316 * math.log(carbPerc[x] * float(carbonConFactor)) ) - (0.03544 * BDg_cm3[x] * clayPerc[x]) + (0.00283 * BDg_cm3[x] * siltPerc[x]) + ( 0.0488 * BDg_cm3[x] * (carbPerc[x] * float(carbonConFactor))) l_MvG = 10 * (math.exp(l_MvG_norm) - 1) / (math.exp(l_MvG_norm) + 1) elif VGOption == 'Wosten_1999_sub': K_sat = (10.0 / 24.0) * math.exp( 7.755 + (0.0352 * siltPerc[x]) + (0.93 * 0) - (0.976 * BDg_cm3[x]**2) - (0.000484 * clayPerc[x]**2) - (0.000322 * siltPerc[x]**2) + (0.001 * siltPerc[x]**(-1)) - (0.0748 * (carbPerc[x] * float(carbonConFactor))**(-1)) - (0.643 * math.log(siltPerc[x])) - (0.0139 * BDg_cm3[x] * clayPerc[x]) - (0.167 * BDg_cm3[x] * carbPerc[x] * float(carbonConFactor)) + (0.0298 * 0 * clayPerc[x]) - (0.03305 * 0 * siltPerc[x])) WC_sat = 0.7919 + (0.001691 * clayPerc[x]) - ( 0.29619 * BDg_cm3[x]) - (0.000001491 * siltPerc[x]**2) + ( 0.0000821 * ((carbPerc[x] * float(carbonConFactor)))**2) + ( 0.02427 * clayPerc[x]**(-1.0) + (0.01113 * siltPerc[x]**(-1.0)) + (0.01472 * math.log(siltPerc[x])) - 0.0000733 * ((carbPerc[x] * float(carbonConFactor))) * clayPerc[x] ) - (0.000619 * BDg_cm3[x] * clayPerc[x]) - (0.001183 * BDg_cm3[x] * (carbPerc[x] * float(carbonConFactor)) ) - (0.0001664 * 0.0 * siltPerc[x]) # Wosten originally has alpha in cm-1 alpha_cm = math.exp( -14.96 + (0.03135 * clayPerc[x]) + (0.0351 * siltPerc[x]) + (0.646 * (carbPerc[x] * float(carbonConFactor))) + (15.29 * BDg_cm3[x]) - (0.192 * 0.0) - (4.671 * BDg_cm3[x]**2.0) - (0.000781 * clayPerc[x]**2) - (0.00687 * (carbPerc[x] * float(carbonConFactor))**2.0) + (0.0449 * ((carbPerc[x] * float(carbonConFactor)))**(-1.0)) + (0.0663 * math.log(siltPerc[x])) + (0.1482 * math.log((carbPerc[x] * float(carbonConFactor)))) - (0.04546 * BDg_cm3[x] * siltPerc[x]) - (0.4852 * BDg_cm3[x] * (carbPerc[x] * float(carbonConFactor))) + (0.00673 * 0.0 * clayPerc[x])) alpha_VG = 10.0 * alpha_cm # Converted from cm-1 to kPa-1 for internal consistency n_VG = 1.0 + math.exp( -25.23 - (0.02195 * clayPerc[x]) + (0.0074 * siltPerc[x]) - (0.1940 * (carbPerc[x] * float(carbonConFactor))) + (45.5 * BDg_cm3[x]) - (7.24 * BDg_cm3[x]**2.0) + (0.0003658 * clayPerc[x]**2.0) + (0.002885 * ((carbPerc[x] * float(carbonConFactor)))**2.0) - (12.81 * (BDg_cm3[x])**(-1.0)) - (0.1524 * (siltPerc[x])**(-1.0)) - (0.01958 * ((carbPerc[x] * float(carbonConFactor)))**(-1.0)) - (0.2876 * math.log(siltPerc[x])) - (0.0709 * math.log((carbPerc[x] * float(carbonConFactor)))) - (44.6 * math.log(BDg_cm3[x])) - (0.02264 * BDg_cm3[x] * clayPerc[x]) + (0.0896 * BDg_cm3[x] * (carbPerc[x] * float(carbonConFactor))) + (0.00718 * 0.0 * clayPerc[x])) m_VG = 1.0 - (1.0 / float(n_VG)) l_MvG_norm = 0.0202 + (0.0006193 * clayPerc[x]**2) - ( 0.001136 * (carbPerc[x] * float(carbonConFactor))**2) - ( 0.2316 * math.log(carbPerc[x] * float(carbonConFactor)) ) - (0.03544 * BDg_cm3[x] * clayPerc[x]) + (0.00283 * BDg_cm3[x] * siltPerc[x]) + ( 0.0488 * BDg_cm3[x] * (carbPerc[x] * float(carbonConFactor))) l_MvG = 10 * (math.exp(l_MvG_norm) - 1) / (math.exp(l_MvG_norm) + 1) WC_satArray.append(WC_sat) WC_residualArray.append(WC_residual) alpha_VGArray.append(alpha_VG) n_VGArray.append(n_VG) m_VGArray.append(m_VG) l_MvGArray.append(l_MvG) K_satArray.append(K_sat) # Write K_sat and warning results to output shapefile arcpy.AddField_management(outputShp, "warning", "TEXT") arcpy.AddField_management(outputShp, "K_sat", "DOUBLE", 10, 6) outputFields = ["warning", "K_sat"] recordNum = 0 with arcpy.da.UpdateCursor(outputShp, outputFields) as cursor: for row in cursor: row[0] = warningArray[recordNum] row[1] = K_satArray[recordNum] cursor.updateRow(row) recordNum += 1 return WC_residualArray, WC_satArray, alpha_VGArray, n_VGArray, m_VGArray, l_MvGArray, K_satArray
def SaxtonRawls_2006_BC(outputShp, PTFOption, carbonConFactor, carbContent): log.info("Calculating Brooks-Corey using Saxton and Rawls (2006)") # Arrays to output warningArray = [] WC_resArray = [] WC_satArray = [] lambda_BCArray = [] hb_BCArray = [] K_satArray = [] # Get OID field OIDField = common.getOIDField(outputShp) # Requirements: sand, clay, and OM if carbContent == 'OC': reqFields = [OIDField, "Sand", "Clay", "OC", "LUCIname"] elif carbContent == 'OM': reqFields = [OIDField, "Sand", "Clay", "OM", "LUCIname"] carbonConFactor = 1.0 checks_PTFs.checkInputFields(reqFields, outputShp) # Retrieve info from input record = [] sandPerc = [] clayPerc = [] carbPerc = [] name = [] with arcpy.da.SearchCursor(outputShp, reqFields) as searchCursor: for row in searchCursor: objectID = row[0] sand = row[1] clay = row[2] carbon = row[3] recName = row[4] record.append(objectID) sandPerc.append(sand) clayPerc.append(clay) carbPerc.append(carbon) name.append(recName) for x in range(0, len(record)): # Data checks warningFlag = checks_PTFs.checkValue("Clay", clayPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Sand", sandPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Carbon", carbPerc[x], record[x]) warningArray.append(warningFlag) # Calculate values WC_residual = 0 WC_33tkPa = (-0.00251 * sandPerc[x]) + (0.00195 * clayPerc[x]) + (0.00011 * carbPerc[x]*float(carbonConFactor)) + (0.0000006 * sandPerc[x] * carbPerc[x]*float(carbonConFactor)) - (0.0000027 * clayPerc[x] * carbPerc[x]*float(carbonConFactor)) + (0.0000452 * sandPerc[x] * clayPerc[x]) + 0.299 WC_33kPa = (1.283 * (WC_33tkPa)**(2)) + (0.626 * (WC_33tkPa)) - 0.015 WC_sat_33tkPa = (0.00278 * sandPerc[x]) + (0.00034 * clayPerc[x]) + (0.00022 * carbPerc[x]*float(carbonConFactor)) - (0.0000018 * sandPerc[x] * carbPerc[x]*float(carbonConFactor)) - (0.0000027 * clayPerc[x] * carbPerc[x]*float(carbonConFactor)) - (0.0000584 * sandPerc[x] * clayPerc[x]) + 0.078 WC_sat_33kPa = 1.636 * WC_sat_33tkPa - 0.107 ## WC_0kPa is now WC_sat WC_sat = WC_33kPa + WC_sat_33kPa - (0.00097 * sandPerc[x]) + 0.043 WC_1500tkPa = (-0.00024 * sandPerc[x]) + (0.00487 * clayPerc[x]) + (0.00006 * carbPerc[x]*float(carbonConFactor)) + (0.0000005 * sandPerc[x] * carbPerc[x]*float(carbonConFactor)) - (0.0000013 * clayPerc[x] * carbPerc[x]*float(carbonConFactor)) + (0.0000068 * sandPerc[x] * clayPerc[x]) + 0.031 WC_1500kPa = 1.14 * WC_1500tkPa - 0.02 # Need checks on WC_33kPa and WC_1500kPa wcError = False if WC_33kPa < 0.0: log.warning('WARNING: water content at 33kPa is negative for ' + str(name[x])) log.warning('WARNING: Cannot calculate lambda, setting it to -9999 for error catching') wcError = True if WC_1500kPa < 0.0: log.warning('WARNING: Water content at 1500kPa is negative for ' + str(name[x])) log.warning('WARNING: Cannot calculate lambda, setting it to -9999 for error catching') wcError = True if wcError == True: lambda_BC = -9999 hb_BC = -9999 else: B_SR = (math.log(1500.0) - math.log(33.0)) / (math.log(WC_33kPa) - math.log(WC_1500kPa)) lambda_BC = 1.0 / float(B_SR) hbt_BC = - (0.2167 * sandPerc[x]) - (0.2793 * clayPerc[x]) - (81.97 * WC_sat_33kPa) + (0.7112 * sandPerc[x] * WC_sat_33kPa) + (0.0829 * clayPerc[x] * WC_sat_33kPa) + (0.001405 * sandPerc[x] * clayPerc[x]) + 27.16 hb_BC = hbt_BC + (0.02 * hbt_BC ** 2) - (0.113 * hbt_BC) - 0.7 # If there is a valid lambda value if lambda_BC != -9999: K_sat = 1930.0 * ((WC_sat - WC_33kPa)**(3 - lambda_BC)) else: # If not valid, set K_sat to -9999 K_sat = -9999 WC_resArray.append(WC_residual) WC_satArray.append(WC_sat) lambda_BCArray.append(lambda_BC) hb_BCArray.append(hb_BC) K_satArray.append(K_sat) # Write K_sat to the output shapefile arcpy.AddField_management(outputShp, "K_sat", "DOUBLE", 10, 6) recordNum = 0 with arcpy.da.UpdateCursor(outputShp, "K_sat") as cursor: for row in cursor: row[0] = K_satArray[recordNum] cursor.updateRow(row) recordNum += 1 return warningArray, WC_resArray, WC_satArray, lambda_BCArray, hb_BCArray
def Vereecken_1989(outputShp, VGOption, carbonConFactor, carbContent): # Arrays to write to shapefile warningArray = [] WC_satArray = [] WC_residualArray = [] alpha_VGArray = [] n_VGArray = [] m_VGArray = [] log.info( "Calculating van Genuchten parameters using Vereecken et al. (1989)") # Get OID field OIDField = common.getOIDField(outputShp) if carbContent == 'OC': reqFields = [ OIDField, "Sand", "Clay", "OC", "BD", "LUCIname", "texture" ] carbonConFactor = 1.0 elif carbContent == 'OM': reqFields = [ OIDField, "Sand", "Clay", "OM", "BD", "LUCIname", "texture" ] checks_PTFs.checkInputFields(reqFields, outputShp) # Retrieve info from input record = [] sandPerc = [] clayPerc = [] carbPerc = [] BDg_cm3 = [] nameArray = [] textureArray = [] with arcpy.da.SearchCursor(outputShp, reqFields) as searchCursor: for row in searchCursor: objectID = row[0] sand = row[1] clay = row[2] carbon = row[3] BD = row[4] name = row[5] texture = row[6] record.append(objectID) sandPerc.append(sand) clayPerc.append(clay) carbPerc.append(carbon) BDg_cm3.append(BD) nameArray.append(name) textureArray.append(texture) for x in range(0, len(record)): # Data checks warningFlag = checks_PTFs.checkCarbon(carbPerc[x], carbContent, record[x]) warningFlag = checks_PTFs.checkValue("Sand", sandPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Clay", clayPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Bulk density", BDg_cm3[x], record[x]) warningArray.append(warningFlag) WC_sat = 0.81 - (0.283 * BDg_cm3[x]) + (0.001 * clayPerc[x]) WC_residual = 0.015 + (0.005 * clayPerc[x]) + (0.014 * carbPerc[x] * float(carbonConFactor)) # Vereecken et al. (1989) calculates alpha in cm-1 alpha_cm = math.exp(-2.486 + (0.025 * sandPerc[x]) - (0.351 * carbPerc[x] * float(carbonConFactor)) - (2.617 * BDg_cm3[x]) - (0.023 * clayPerc[x])) alpha_VG = 10.0 * alpha_cm # Converted from cm-1 to kPa-1 n_VG = math.exp(0.053 - (0.009 * sandPerc[x]) - (0.013 * clayPerc[x]) + (0.00015 * sandPerc[x]**2)) m_VG = 1.0 WC_satArray.append(WC_sat) WC_residualArray.append(WC_residual) alpha_VGArray.append(alpha_VG) n_VGArray.append(n_VG) m_VGArray.append(m_VG) common.writeWarning(outputShp, warningArray) return WC_residualArray, WC_satArray, alpha_VGArray, n_VGArray, m_VGArray
def CampbellShiozawa_1992_BC(outputShp, PTFOption): log.info("Calculating Brooks-Corey using Campbell and Shiozawa (1992)") # Arrays to output warningArray = [] WC_resArray = [] lambda_BCArray = [] hb_BCArray = [] # Get OID field OIDField = common.getOIDField(outputShp) reqFields = [OIDField, "Silt", "Clay", "BD", "WC_sat"] checks_PTFs.checkInputFields(reqFields, outputShp) # Retrieve info from input record = [] siltPerc = [] clayPerc = [] BDg_cm3 = [] WC_satArray = [] with arcpy.da.SearchCursor(outputShp, reqFields) as searchCursor: for row in searchCursor: objectID = row[0] silt = row[1] clay = row[2] BD = row[3] WCsat = row[4] record.append(objectID) siltPerc.append(silt) clayPerc.append(clay) BDg_cm3.append(BD) WC_satArray.append(WCsat) dg_CSArray = [] Sg_CSArray = [] hes_CSArray = [] b_CSArray = [] for x in range(0, len(record)): # Data checks warningFlag = checks_PTFs.checkValue("Clay", clayPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Silt", siltPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Bulk density", BDg_cm3[x], record[x]) warningFlag = checks_PTFs.checkValue("Input saturation", WC_satArray[x], record[x]) warningArray.append(warningFlag) # Calculate values WC_residual = 0 dg_CS = math.exp(-0.8 - (0.0317 * siltPerc[x]) - (0.0761 * clayPerc[x])) Sg_CS = (math.exp((0.133 * siltPerc[x]) + (0.477 * clayPerc[x]) - ((math.log(dg_CS))**2)))**0.5 hes_CS = 0.05/float((math.sqrt(dg_CS))) b_CS = (-20.0 * (-hes_CS)) + (0.2 * Sg_CS) # Originally in cm hb_cm = 100.0 * (hes_CS * ((BDg_cm3[x] / 1.3) ** (0.67* b_CS))) hb_BC = hb_cm / 10.0 # Convert to kPa lambda_BC = 1.0 /float(b_CS) checks_PTFs.checkNegOutput([WC_residual], x) WC_resArray.append(WC_residual) dg_CSArray.append(dg_CS) Sg_CSArray.append(Sg_CS) hes_CSArray.append(hes_CS) b_CSArray.append(b_CS) hb_BCArray.append(hb_BC) lambda_BCArray.append(lambda_BC) return warningArray, WC_resArray, WC_satArray, lambda_BCArray, hb_BCArray
def ZachariasWessolek_2007(outputShp, VGOption, carbonConFactor, carbContent): # Arrays to write to shapefile warningArray = [] WC_satArray = [] WC_residualArray = [] alpha_VGArray = [] n_VGArray = [] m_VGArray = [] log.info( "Calculating van Genuchten parameters using Zacharias and Wessolek (2007)" ) # Get OID field OIDField = common.getOIDField(outputShp) # Requirements: Sand, clay, and BD reqFields = [OIDField, "Sand", "Clay", "BD", "LUCIname", "texture"] checks_PTFs.checkInputFields(reqFields, outputShp) # Retrieve info from input record = [] sandPerc = [] clayPerc = [] BDg_cm3 = [] nameArray = [] textureArray = [] with arcpy.da.SearchCursor(outputShp, reqFields) as searchCursor: for row in searchCursor: objectID = row[0] sand = row[1] clay = row[2] BD = row[3] name = row[4] texture = row[5] record.append(objectID) sandPerc.append(sand) clayPerc.append(clay) BDg_cm3.append(BD) nameArray.append(name) textureArray.append(texture) for x in range(0, len(record)): # Data checks warningFlag = checks_PTFs.checkValue("Sand", sandPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Clay", clayPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Bulk density", BDg_cm3[x], record[x]) warningArray.append(warningFlag) if sandPerc[x] < 66.5: WC_residual = 0 WC_sat = 0.788 + (0.001 * clayPerc[x]) - (0.263 * BDg_cm3[x]) # Alpha in kPa-1 alpha_VG = math.exp(-0.648 + (0.023 * sandPerc[x]) + (0.044 * clayPerc[x]) - (3.168 * BDg_cm3[x])) n_VG = 1.392 - (0.418 * sandPerc[x]** (-0.024)) + (1.212 * clayPerc[x]**(-0.704)) m_VG = 1.0 - (1.0 / float(n_VG)) else: WC_residual = 0 WC_sat = 0.89 - (0.001 * clayPerc[x]) - (0.322 * BDg_cm3[x]) # Alpha in kPa-1 alpha_VG = math.exp(-4.197 + (0.013 * sandPerc[x]) + (0.076 * clayPerc[x]) - (0.276 * BDg_cm3[x])) n_VG = -2.562 + (7 * 10**(-9) * sandPerc[x]**4.004) + ( 3.75 * clayPerc[x]**(-0.016)) m_VG = 1.0 - (1.0 / float(n_VG)) WC_satArray.append(WC_sat) WC_residualArray.append(WC_residual) alpha_VGArray.append(alpha_VG) n_VGArray.append(n_VG) m_VGArray.append(m_VG) common.writeWarning(outputShp, warningArray) return WC_residualArray, WC_satArray, alpha_VGArray, n_VGArray, m_VGArray
def function(outputFolder, inputShp, VGOption, VGPressArray, MVGChoice, fcVal, sicVal, pwpVal, carbContent, carbonConFactor): try: # Set temporary variables prefix = os.path.join(arcpy.env.scratchGDB, "soil_") # Set output filename if MVGChoice == True: outputShp = os.path.join(outputFolder, "soil_mvg.shp") else: outputShp = os.path.join(outputFolder, "soil_vg.shp") # Copy the input shapefile to the output folder arcpy.CopyFeatures_management(inputShp, outputShp) ############################################## ### Calculate the van Genuchten parameters ### ############################################## # Get the nameArray nameArray = [] with arcpy.da.SearchCursor(outputShp, "LUCIname") as searchCursor: for row in searchCursor: name = row[0] nameArray.append(name) # Initialise the van Genuchten parameter arrays # All VG PTFs should return these arrays WC_residualArray = [] WC_satArray = [] alpha_VGArray = [] n_VGArray = [] m_VGArray = [] # Call VG PTF here depending on VGOption if str(VGOption[0:11]) == "Wosten_1999": # Has option to calculate Mualem-van Genuchten WC_residualArray, WC_satArray, alpha_VGArray, n_VGArray, m_VGArray, l_MvGArray, K_satArray = vg_PTFs.Wosten_1999(outputShp, VGOption, carbonConFactor, carbContent, MVGChoice) elif VGOption == "Vereecken_1989": WC_residualArray, WC_satArray, alpha_VGArray, n_VGArray, m_VGArray = vg_PTFs.Vereecken_1989(outputShp, VGOption, carbonConFactor, carbContent) elif VGOption == "ZachariasWessolek_2007": WC_residualArray, WC_satArray, alpha_VGArray, n_VGArray, m_VGArray = vg_PTFs.ZachariasWessolek_2007(outputShp, VGOption, carbonConFactor, carbContent) elif VGOption == "Weynants_2009": # Has option to calculate Mualem-van Genuchten WC_residualArray, WC_satArray, alpha_VGArray, n_VGArray, m_VGArray, l_MvGArray, K_satArray = vg_PTFs.Weynants_2009(outputShp, VGOption, carbonConFactor, carbContent, MVGChoice) elif VGOption == "Dashtaki_2010_vg": WC_residualArray, WC_satArray, alpha_VGArray, n_VGArray, m_VGArray = vg_PTFs.Dashtaki_2010(outputShp, VGOption, carbonConFactor, carbContent) elif VGOption == "HodnettTomasella_2002": WC_residualArray, WC_satArray, alpha_VGArray, n_VGArray, m_VGArray = vg_PTFs.HodnettTomasella_2002(outputShp, VGOption, carbonConFactor, carbContent) else: log.error("Van Genuchten option not recognised: " + str(VGOption)) sys.exit() # Write VG parameter results to output shapefile vanGenuchten.writeVGParams(outputShp, WC_residualArray, WC_satArray, alpha_VGArray, n_VGArray, m_VGArray) # Plot VG parameters vanGenuchten.plotVG(outputFolder, WC_residualArray, WC_satArray, alpha_VGArray, n_VGArray, m_VGArray, nameArray, fcVal, sicVal, pwpVal) ############################################### ### Calculate water content using VG params ### ############################################### # Calculate water content at default pressures WC_1kPaArray = [] WC_3kPaArray = [] WC_10kPaArray = [] WC_33kPaArray = [] WC_100kPaArray = [] WC_200kPaArray = [] WC_1000kPaArray = [] WC_1500kPaArray = [] for x in range(0, len(nameArray)): WC_1kPa = vanGenuchten.calcVGfxn(1.0, WC_residualArray[x], WC_satArray[x], alpha_VGArray[x], n_VGArray[x], m_VGArray[x]) WC_3kPa = vanGenuchten.calcVGfxn(3.0, WC_residualArray[x], WC_satArray[x], alpha_VGArray[x], n_VGArray[x], m_VGArray[x]) WC_10kPa = vanGenuchten.calcVGfxn(10.0, WC_residualArray[x], WC_satArray[x], alpha_VGArray[x], n_VGArray[x], m_VGArray[x]) WC_33kPa = vanGenuchten.calcVGfxn(33.0, WC_residualArray[x], WC_satArray[x], alpha_VGArray[x], n_VGArray[x], m_VGArray[x]) WC_100kPa = vanGenuchten.calcVGfxn(100.0, WC_residualArray[x], WC_satArray[x], alpha_VGArray[x], n_VGArray[x], m_VGArray[x]) WC_200kPa = vanGenuchten.calcVGfxn(200.0, WC_residualArray[x], WC_satArray[x], alpha_VGArray[x], n_VGArray[x], m_VGArray[x]) WC_1000kPa = vanGenuchten.calcVGfxn(1000.0, WC_residualArray[x], WC_satArray[x], alpha_VGArray[x], n_VGArray[x], m_VGArray[x]) WC_1500kPa = vanGenuchten.calcVGfxn(1500.0, WC_residualArray[x], WC_satArray[x], alpha_VGArray[x], n_VGArray[x], m_VGArray[x]) WC_1kPaArray.append(WC_1kPa) WC_3kPaArray.append(WC_3kPa) WC_10kPaArray.append(WC_10kPa) WC_33kPaArray.append(WC_33kPa) WC_100kPaArray.append(WC_100kPa) WC_200kPaArray.append(WC_200kPa) WC_1000kPaArray.append(WC_1000kPa) WC_1500kPaArray.append(WC_1500kPa) common.writeOutputWC(outputShp, WC_1kPaArray, WC_3kPaArray, WC_10kPaArray, WC_33kPaArray, WC_100kPaArray, WC_200kPaArray, WC_1000kPaArray, WC_1500kPaArray) # Write water content at user-input pressures # Initialise the pressure head array x = np.array(VGPressArray) vgPressures = x.astype(np.float) # For the headings headings = ['Name'] for pressure in vgPressures: headName = 'WC_' + str(pressure) + "kPa" headings.append(headName) wcHeadings = headings[1:] # Initialise water content arrays wcArrays = [] # Calculate soil moisture content at custom VG pressures for x in range(0, len(nameArray)): wcValues = vanGenuchten.calcPressuresVG(nameArray[x], WC_residualArray[x], WC_satArray[x], alpha_VGArray[x], n_VGArray[x], m_VGArray[x], vgPressures) wcArrays.append(wcValues) # Write to output CSV outCSV = os.path.join(outputFolder, 'WaterContent.csv') with open(outCSV, 'wb') as csv_file: writer = csv.writer(csv_file) writer.writerow(headings) for i in range(0, len(nameArray)): row = wcArrays[i] writer.writerow(row) msg = 'Output CSV with water content saved to: ' + str(outCSV) log.info(msg) csv_file.close() ################################################## ### Calculate water content at critical points ### ################################################## # Initialise water content arrays wc_satCalc = [] wc_fcCalc = [] wc_sicCalc = [] wc_pwpCalc = [] wc_DW = [] wc_RAW = [] wc_NRAW = [] wc_PAW = [] for i in range(0, len(nameArray)): wc_sat = vanGenuchten.calcVGfxn(0, WC_residualArray[i], WC_satArray[i], alpha_VGArray[i], n_VGArray[i], m_VGArray[i]) wc_fc = vanGenuchten.calcVGfxn(float(fcVal), WC_residualArray[i], WC_satArray[i], alpha_VGArray[i], n_VGArray[i], m_VGArray[i]) wc_sic = vanGenuchten.calcVGfxn(float(sicVal), WC_residualArray[i], WC_satArray[i], alpha_VGArray[i], n_VGArray[i], m_VGArray[i]) wc_pwp = vanGenuchten.calcVGfxn(float(pwpVal), WC_residualArray[i], WC_satArray[i], alpha_VGArray[i], n_VGArray[i], m_VGArray[i]) drainWater = wc_sat - wc_fc readilyAvailWater = wc_fc - wc_sic notRAW = wc_sic - wc_pwp PAW = wc_fc - wc_pwp checks_PTFs.checkNegValue("Drainable water", drainWater, nameArray[i]) checks_PTFs.checkNegValue("Readily available water", readilyAvailWater, nameArray[i]) checks_PTFs.checkNegValue("Not readily available water", notRAW, nameArray[i]) checks_PTFs.checkNegValue("Not readily available water", PAW, nameArray[i]) wc_satCalc.append(wc_sat) wc_fcCalc.append(wc_fc) wc_sicCalc.append(wc_sic) wc_pwpCalc.append(wc_pwp) wc_DW.append(drainWater) wc_RAW.append(readilyAvailWater) wc_NRAW.append(notRAW) wc_PAW.append(PAW) common.writeOutputCriticalWC(outputShp, wc_satCalc, wc_fcCalc, wc_sicCalc, wc_pwpCalc, wc_DW, wc_RAW, wc_NRAW, wc_PAW) ############################################ ### Calculate using Mualem-van Genuchten ### ############################################ if MVGChoice == True: if VGOption in ["Wosten_1999_top", "Wosten_1999_sub", "Weynants_2009"]: # Allow for calculation of MVG log.info("Calculating and plotting MVG") # Write l_MvGArray to outputShp arcpy.AddField_management(outputShp, "l_MvG", "DOUBLE", 10, 6) recordNum = 0 with arcpy.da.UpdateCursor(outputShp, "l_MvG") as cursor: for row in cursor: row[0] = l_MvGArray[recordNum] cursor.updateRow(row) recordNum += 1 # Plot MVG vanGenuchten.plotMVG(outputFolder, K_satArray, alpha_VGArray, n_VGArray, m_VGArray, l_MvGArray, WC_satArray, WC_residualArray, nameArray) # Calculate K at default pressures # Calculate at the pressures using the function K_1kPaArray = [] K_3kPaArray = [] K_10kPaArray = [] K_33kPaArray = [] K_100kPaArray = [] K_200kPaArray = [] K_1000kPaArray = [] K_1500kPaArray = [] for i in range(0, len(nameArray)): K_1kPa = vanGenuchten.calcKhfxn(1.0, K_satArray[i], alpha_VGArray[i], n_VGArray[i], m_VGArray[i], l_MvGArray[i]) K_3kPa = vanGenuchten.calcKhfxn(3.0, K_satArray[i], alpha_VGArray[i], n_VGArray[i], m_VGArray[i], l_MvGArray[i]) K_10kPa = vanGenuchten.calcKhfxn(10.0, K_satArray[i], alpha_VGArray[i], n_VGArray[i], m_VGArray[i], l_MvGArray[i]) K_33kPa = vanGenuchten.calcKhfxn(33.0, K_satArray[i], alpha_VGArray[i], n_VGArray[i], m_VGArray[i], l_MvGArray[i]) K_100kPa = vanGenuchten.calcKhfxn(100.0, K_satArray[i], alpha_VGArray[i], n_VGArray[i], m_VGArray[i], l_MvGArray[i]) K_200kPa = vanGenuchten.calcKhfxn(200.0, K_satArray[i], alpha_VGArray[i], n_VGArray[i], m_VGArray[i], l_MvGArray[i]) K_1000kPa = vanGenuchten.calcKhfxn(1000.0, K_satArray[i], alpha_VGArray[i], n_VGArray[i], m_VGArray[i], l_MvGArray[i]) K_1500kPa = vanGenuchten.calcKhfxn(1500.0, K_satArray[i], alpha_VGArray[i], n_VGArray[i], m_VGArray[i], l_MvGArray[i]) K_1kPaArray.append(K_1kPa) K_3kPaArray.append(K_3kPa) K_10kPaArray.append(K_10kPa) K_33kPaArray.append(K_33kPa) K_100kPaArray.append(K_100kPa) K_200kPaArray.append(K_200kPa) K_1000kPaArray.append(K_1000kPa) K_1500kPaArray.append(K_1500kPa) # Write to the shapefile MVGFields = ["K_1kPa", "K_3kPa", "K_10kPa", "K_33kPa", "K_100kPa", "K_200kPa", "K_1000kPa", "K_1500kPa"] # Add fields for field in MVGFields: arcpy.AddField_management(outputShp, field, "DOUBLE", 10, 6) recordNum = 0 with arcpy.da.UpdateCursor(outputShp, MVGFields) as cursor: for row in cursor: row[0] = K_1kPaArray[recordNum] row[1] = K_3kPaArray[recordNum] row[2] = K_10kPaArray[recordNum] row[3] = K_33kPaArray[recordNum] row[4] = K_100kPaArray[recordNum] row[5] = K_200kPaArray[recordNum] row[6] = K_1000kPaArray[recordNum] row[7] = K_1500kPaArray[recordNum] cursor.updateRow(row) recordNum += 1 log.info("Unsaturated hydraulic conductivity at default pressures written to output shapefile") # Calculate K at custom pressures # Initialise the pressure head array x = np.array(VGPressArray) vgPressures = x.astype(np.float) # For the headings headings = ['Name'] for pressure in vgPressures: headName = 'K_' + str(pressure) + "kPa" headings.append(headName) kHeadings = headings[1:] # Initialise K arrays kArrays = [] # Calculate K content at custom VG pressures for x in range(0, len(nameArray)): kValues = vanGenuchten.calcPressuresMVG(nameArray[x], K_satArray[x], alpha_VGArray[x], n_VGArray[x], m_VGArray[x], l_MvGArray[x], vgPressures) kArrays.append(kValues) # Write to output CSV outCSV = os.path.join(outputFolder, 'K_MVG.csv') with open(outCSV, 'wb') as csv_file: writer = csv.writer(csv_file) writer.writerow(headings) for i in range(0, len(nameArray)): row = kArrays[i] writer.writerow(row) msg = 'Output CSV with unsaturated hydraulic conductivity saved to: ' + str(outCSV) log.info(msg) csv_file.close() else: log.error("Selected PTF does not calculate Mualem-van Genuchten parameters") log.error("Please select a different PTF") sys.exit() except Exception: arcpy.AddError("van Genuchten function failed") raise finally: # Remove feature layers from memory try: for lyr in common.listFeatureLayers(locals()): arcpy.Delete_management(locals()[lyr]) exec(lyr + ' = None') in locals() except Exception: pass
def Weynants_2009(outputShp, VGOption, carbonConFactor, carbContent, MVGChoice): # Arrays to write to shapefile warningArray = [] K_satArray = [] WC_satArray = [] WC_residualArray = [] alpha_VGArray = [] n_VGArray = [] m_VGArray = [] l_MvGArray = [] log.info( "Calculating van Genuchten parameters using Weynants et al. (2009)") # Requirements: sand, clay, OC, and BD # Get OID field OIDField = common.getOIDField(outputShp) if carbContent == 'OC': reqFields = [ OIDField, "Sand", "Clay", "OC", "BD", "LUCIname", "texture" ] carbonConFactor = 1.0 elif carbContent == 'OM': reqFields = [ OIDField, "Sand", "Clay", "OM", "BD", "LUCIname", "texture" ] checks_PTFs.checkInputFields(reqFields, outputShp) # Retrieve info from input record = [] sandPerc = [] clayPerc = [] carbPerc = [] BDg_cm3 = [] nameArray = [] textureArray = [] with arcpy.da.SearchCursor(outputShp, reqFields) as searchCursor: for row in searchCursor: objectID = row[0] sand = row[1] clay = row[2] carbon = row[3] BD = row[4] name = row[5] texture = row[6] record.append(objectID) sandPerc.append(sand) clayPerc.append(clay) carbPerc.append(carbon) BDg_cm3.append(BD) nameArray.append(name) textureArray.append(texture) for x in range(0, len(record)): # Data checks warningFlag = checks_PTFs.checkCarbon(carbPerc[x], carbContent, record[x]) warningFlag = checks_PTFs.checkValue("Sand", sandPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Clay", clayPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Bulk density", BDg_cm3[x], record[x]) warningArray.append(warningFlag) WC_residual = 0 WC_sat = 0.6355 + (0.0013 * clayPerc[x]) - (0.1631 * BDg_cm3[x]) # Alpha in cm-1 alpha_cm = math.exp(-4.3003 - (0.0097 * clayPerc[x]) + (0.0138 * sandPerc[x]) - (0.0992 * carbPerc[x] * float(carbonConFactor))) alpha_VG = 10.0 * alpha_cm # Convert to kPa-1 n_VG = math.exp(-1.0846 - (0.0236 * clayPerc[x]) - (0.0085 * sandPerc[x]) + (0.0001 * sandPerc[x]**2)) + 1 m_VG = 1.0 - (1.0 / float(n_VG)) l_MvG = -1.8642 - (0.1317 * clayPerc[x]) + (0.0067 * sandPerc[x]) K_sat = math.exp(1.9582 + (0.0308 * sandPerc[x]) - (0.6142 * BDg_cm3[x]) - (0.1566 * (carbPerc[x] * float(carbonConFactor)))) * (10.0 / 24.0) WC_satArray.append(WC_sat) WC_residualArray.append(WC_residual) alpha_VGArray.append(alpha_VG) n_VGArray.append(n_VG) m_VGArray.append(m_VG) l_MvGArray.append(l_MvG) K_satArray.append(K_sat) common.writeWarning(outputShp, warningArray) return WC_residualArray, WC_satArray, alpha_VGArray, n_VGArray, m_VGArray, l_MvGArray, K_satArray
def runSystemChecks(folder=None, rerun=False): import LUCI_PTFs.lib.progress as progress # Set overwrite output arcpy.env.overwriteOutput = True # Check spatial analyst licence is available if arcpy.CheckExtension("Spatial") == "Available": arcpy.CheckOutExtension("Spatial") else: raise RuntimeError( "Spatial Analyst license not present or could not be checked out") ### Set workspaces so that temporary files are written to the LUCI scratch geodatabase ### if arcpy.ProductInfo() == "ArcServer": log.info('arcpy.env.scratchWorkspace on server: ' + str(arcpy.env.scratchWorkspace)) # Set current workspace arcpy.env.workspace = arcpy.env.scratchGDB else: # If rerunning a tool, check if scratch workspace has been set. If it has, use it as it is (with temporary rasters and feature classes from the previous run). scratchGDB = None if rerun: xmlFile = progress.getProgressFilenames(folder).xmlFile if os.path.exists(xmlFile): scratchGDB = readXML(xmlFile, 'ScratchGDB') if not arcpy.Exists(scratchGDB): log.error('Previous scratch GDB ' + str(scratchGDB) + ' does not exist. Tool cannot be rerun.') log.error('Exiting tool') sys.exit() if scratchGDB is None: # Set scratch path from values in user settings file if values present scratchPath = None try: if os.path.exists(configuration.userSettingsFile): tree = ET.parse(configuration.userSettingsFile) root = tree.getroot() scratchPath = root.find("scratchPath").text except Exception: pass # If any errors occur, ignore them. Just use the default scratch path. # Set scratch path if needed if scratchPath is None: scratchPath = configuration.scratchPath # Create scratch path folder if not os.path.exists(scratchPath): os.makedirs(scratchPath) # Remove old date/time stamped scratch folders if they exist and if they do not contain lock ArcGIS lock files. for root, dirs, files in os.walk(scratchPath): for dir in dirs: # Try to rename folder. If this is possible then no locks are held on it and it can then be removed. try: fullDirPath = os.path.join(scratchPath, dir) renamedDir = os.path.join(scratchPath, 'ready_for_deletion') os.rename(fullDirPath, renamedDir) except Exception: # import traceback # log.warning(traceback.format_exc()) pass else: try: shutil.rmtree(renamedDir) except Exception: # import traceback # log.warning(traceback.format_exc()) pass # Create new date/time stamped scratch folder for the scratch GDB to live in dateTimeStamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") scratchGDBFolder = os.path.join(scratchPath, 'scratch_' + dateTimeStamp) if not os.path.exists(scratchGDBFolder): os.mkdir(scratchGDBFolder) # Create scratch GDB scratchGDB = os.path.join(scratchGDBFolder, 'scratch.gdb') if not os.path.exists(scratchGDB): arcpy.CreateFileGDB_management(os.path.dirname(scratchGDB), os.path.basename(scratchGDB)) # Try to remove old scratch path if still exists try: shutil.rmtree(configuration.oldScratchPath, ignore_errors=True) except Exception: pass # Set scratch and current workspaces arcpy.env.scratchWorkspace = scratchGDB arcpy.env.workspace = scratchGDB # Scratch folder scratchFolder = arcpy.env.scratchFolder if not os.path.exists(scratchFolder): os.mkdir(scratchFolder) # Remove all in_memory data sets arcpy.Delete_management("in_memory") # Check disk space for disk with scratch workspace freeSpaceGb = 3 if getFreeDiskSpaceGb(arcpy.env.scratchWorkspace) < freeSpaceGb: log.warning("Disk containing scratch workspace has less than " + str(freeSpaceGb) + "Gb free space. This may cause this tool to fail.")
def Dashtaki_2010(outputShp, VGOption, carbonConFactor, carbContent): # Arrays to write to shapefile warningArray = [] K_satArray = [] WC_satArray = [] WC_residualArray = [] alpha_VGArray = [] n_VGArray = [] m_VGArray = [] log.info( "Calculating van Genuchten parameters using Dashtaki et al. (2010)") # Requirements: Sand, clay, and BD # Get OID field OIDField = common.getOIDField(outputShp) reqFields = [OIDField, "Sand", "Clay", "BD", "LUCIname", "texture"] checks_PTFs.checkInputFields(reqFields, outputShp) # Retrieve info from input record = [] sandPerc = [] clayPerc = [] BDg_cm3 = [] nameArray = [] textureArray = [] with arcpy.da.SearchCursor(outputShp, reqFields) as searchCursor: for row in searchCursor: objectID = row[0] sand = row[1] clay = row[2] BD = row[3] name = row[4] texture = row[5] record.append(objectID) sandPerc.append(sand) clayPerc.append(clay) BDg_cm3.append(BD) nameArray.append(name) textureArray.append(texture) for x in range(0, len(record)): # Data checks warningFlag = checks_PTFs.checkValue("Sand", sandPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Clay", clayPerc[x], record[x]) warningFlag = checks_PTFs.checkValue("Bulk density", BDg_cm3[x], record[x]) warningArray.append(warningFlag) # Calculate water content using Dashtaki et al. (2010) - Sand, Clay, BD WC_residual = 0.034 + (0.0032 * clayPerc[x]) WC_sat = 0.85 - (0.00061 * sandPerc[x]) - (0.258 * BDg_cm3[x]) # Alpha in cm-1 alpha_cm = abs(1 / (-476 - (4.1 * sandPerc[x]) + (499 * BDg_cm3[x]))) alpha_VG = 10.0 * alpha_cm # Converted from cm-1 to kPa-1 for internal consistency n_VG = 1.56 - (0.00228 * sandPerc[x]) m_VG = 1.0 - (1.0 / float(n_VG)) WC_satArray.append(WC_sat) WC_residualArray.append(WC_residual) alpha_VGArray.append(alpha_VG) n_VGArray.append(n_VG) m_VGArray.append(m_VG) common.writeWarning(outputShp, warningArray) return WC_residualArray, WC_satArray, alpha_VGArray, n_VGArray, m_VGArray
def function(params): try: pText = common.paramsAsText(params) # Get inputs runSystemChecks = common.strToBool(pText[1]) outputFolder = pText[2] inputShapefile = pText[3] VGChoice = pText[4] VGPressures = pText[5] fcVal = pText[6] sicVal = pText[7] pwpVal = pText[8] carbonContent = pText[9] carbonConFactor = pText[10] unitsPlot = pText[11] plotAxis = pText[12] MVGChoice = common.strToBool(pText[13]) # Create output folder if not os.path.exists(outputFolder): os.mkdir(outputFolder) common.runSystemChecks(outputFolder) # Set up logging output to file log.setupLogging(outputFolder) # Write input params to XML common.writeParamsToXML(params, outputFolder) # Simplify VGOption if VGChoice == "Wosten et al. (1999) topsoil": VGOption = "Wosten_1999_top" elif VGChoice == "Wosten et al. (1999) subsoil": VGOption = "Wosten_1999_sub" elif VGChoice == "Vereecken et al. (1989)": VGOption = "Vereecken_1989" elif VGChoice == "Zacharias and Wessolek (2007)": VGOption = "ZachariasWessolek_2007" elif VGChoice == "Weynants et al. (2009)": VGOption = "Weynants_2009" elif VGChoice == "Dashtaki et al. (2010)": VGOption = 'Dashtaki_2010_vg' elif VGChoice == "Hodnett and Tomasella (2002)": VGOption = 'HodnettTomasella_2002' else: log.error('Invalid PTF option') sys.exit() # Set carbon content choice if carbonContent == 'Organic carbon': carbContent = 'OC' elif carbonContent == 'Organic matter': carbContent = 'OM' else: log.error('Invalid carbon content option') sys.exit() # Unpack 'VG pressure heads' parameter if VGPressures is None: VGPressArray = [] else: VGPressArray = VGPressures.split(' ') # Pull out PTFinfo PTFInfo = PTFdatabase.checkPTF(VGOption) PTFType = PTFInfo.PTFType PTFUnit = PTFInfo.PTFUnit PTFOut = [("VGOption", VGOption), ("PTFType", PTFType), ("UserUnitPlot", unitsPlot), ("carbContent", carbContent)] # Write to XML file PTFXML = os.path.join(outputFolder, "ptfinfo.xml") common.writeXML(PTFXML, PTFOut) # Call van Genuchten function calc_vg.function(outputFolder, inputShapefile, VGOption, VGPressArray, MVGChoice, fcVal, sicVal, pwpVal, carbContent, carbonConFactor) # Loading shapefile automatically if MVGChoice == True: soilParamOut = os.path.join(outputFolder, "soil_mvg.shp") else: soilParamOut = os.path.join(outputFolder, "soil_vg.shp") arcpy.SetParameter(14, soilParamOut) log.info("van Genuchten operations completed successfully") except Exception: log.exception("van Genuchten tool failed") raise
def function(outputFolder, inputShp, PTFOption, BCPressArray, fcVal, sicVal, pwpVal, carbContent, carbonConFactor): try: # Set temporary variables prefix = os.path.join(arcpy.env.scratchGDB, "bc_") tempSoils = prefix + "tempSoils" # Set output filename outputShp = os.path.join(outputFolder, "BrooksCorey.shp") # Copy the input shapefile to the output folder arcpy.CopyFeatures_management(inputShp, outputShp) # Get the nameArray nameArray = [] with arcpy.da.SearchCursor(outputShp, "LUCIname") as searchCursor: for row in searchCursor: name = row[0] nameArray.append(name) # PTFs should return: WC_res, WC_sat, lambda_BC, hb_BC if PTFOption == "Cosby_1984_SandC_BC": warning, WC_res, WC_sat, lambda_BC, hb_BC = bc_PTFs.Cosby_1984_SandC_BC( outputShp, PTFOption) elif PTFOption == "Cosby_1984_SSC_BC": warning, WC_res, WC_sat, lambda_BC, hb_BC = bc_PTFs.Cosby_1984_SSC_BC( outputShp, PTFOption) elif PTFOption == "RawlsBrakensiek_1985_BC": warning, WC_res, WC_sat, lambda_BC, hb_BC = bc_PTFs.RawlsBrakensiek_1985_BC( outputShp, PTFOption) elif PTFOption == "CampbellShiozawa_1992_BC": warning, WC_res, WC_sat, lambda_BC, hb_BC = bc_PTFs.CampbellShiozawa_1992_BC( outputShp, PTFOption) elif PTFOption == "Saxton_1986_BC": warning, WC_res, WC_sat, lambda_BC, hb_BC = bc_PTFs.Saxton_1986_BC( outputShp, PTFOption) elif PTFOption == "SaxtonRawls_2006_BC": warning, WC_res, WC_sat, lambda_BC, hb_BC = bc_PTFs.SaxtonRawls_2006_BC( outputShp, PTFOption, carbonConFactor, carbContent) else: log.error("Brooks-Corey option not recognised: " + str(PTFOption)) sys.exit() # Write to shapefile brooksCorey.writeBCParams(outputShp, warning, WC_res, WC_sat, lambda_BC, hb_BC) log.info("Brooks-Corey parameters written to output shapefile") # Create plots brooksCorey.plotBrooksCorey(outputFolder, WC_res, WC_sat, hb_BC, lambda_BC, nameArray, fcVal, sicVal, pwpVal) ############################################### ### Calculate water content using BC params ### ############################################### # Check for any soils that we were not able to calculate BC parameters for # lambda_BC[i] == -9999 errors = [] for i in range(0, len(lambda_BC)): if lambda_BC[i] == -9999: log.warning('Invalid lambda found for ' + str(nameArray[i])) errors.append(i) # Calculate water content at default pressures WC_1kPaArray = [] WC_3kPaArray = [] WC_10kPaArray = [] WC_33kPaArray = [] WC_100kPaArray = [] WC_200kPaArray = [] WC_1000kPaArray = [] WC_1500kPaArray = [] for i in range(0, len(nameArray)): pressures = [1.0, 3.0, 10.0, 33.0, 100.0, 200.0, 1000.0, 1500.0] if lambda_BC[i] != -9999: bc_WC = brooksCorey.calcBrooksCoreyFXN(pressures, hb_BC[i], WC_res[i], WC_sat[i], lambda_BC[i]) else: bc_WC = [-9999] * len(pressures) WC_1kPaArray.append(bc_WC[0]) WC_3kPaArray.append(bc_WC[1]) WC_10kPaArray.append(bc_WC[2]) WC_33kPaArray.append(bc_WC[3]) WC_100kPaArray.append(bc_WC[4]) WC_200kPaArray.append(bc_WC[5]) WC_1000kPaArray.append(bc_WC[6]) WC_1500kPaArray.append(bc_WC[7]) common.writeOutputWC(outputShp, WC_1kPaArray, WC_3kPaArray, WC_10kPaArray, WC_33kPaArray, WC_100kPaArray, WC_200kPaArray, WC_1000kPaArray, WC_1500kPaArray) # Write water content at user-input pressures # Initialise the pressure head array x = np.array(BCPressArray) bcPressures = x.astype(np.float) # For the headings headings = ['Name'] for pressure in bcPressures: headName = 'WC_' + str(pressure) + "kPa" headings.append(headName) wcHeadings = headings[1:] wcArrays = [] # Calculate soil moisture content at custom VG pressures for i in range(0, len(nameArray)): if lambda_BC[i] != -9999: wcValues = brooksCorey.calcBrooksCoreyFXN( bcPressures, hb_BC[i], WC_res[i], WC_sat[i], lambda_BC[i]) else: wcValues = [-9999] * len(bcPressures) wcValues.insert(0, nameArray[i]) wcArrays.append(wcValues) # Write to output CSV outCSV = os.path.join(outputFolder, 'WaterContent.csv') with open(outCSV, 'wb') as csv_file: writer = csv.writer(csv_file) writer.writerow(headings) for i in range(0, len(nameArray)): row = wcArrays[i] writer.writerow(row) msg = 'Output CSV with water content saved to: ' + str(outCSV) log.info(msg) csv_file.close() ################################################## ### Calculate water content at critical points ### ################################################## # Initialise water content arrays wc_satCalc = [] wc_fcCalc = [] wc_sicCalc = [] wc_pwpCalc = [] wc_DW = [] wc_RAW = [] wc_NRAW = [] wc_PAW = [] wcCriticalPressures = [0.0, fcVal, sicVal, pwpVal] for x in range(0, len(nameArray)): if lambda_BC[x] != -9999: wcCriticals = brooksCorey.calcBrooksCoreyFXN( wcCriticalPressures, hb_BC[x], WC_res[x], WC_sat[x], lambda_BC[x]) wc_sat = wcCriticals[0] wc_fc = wcCriticals[1] wc_sic = wcCriticals[2] wc_pwp = wcCriticals[3] drainWater = wc_sat - wc_fc readilyAvailWater = wc_fc - wc_sic notRAW = wc_sic - wc_pwp PAW = wc_fc - wc_pwp checks_PTFs.checkNegValue("Drainable water", drainWater, nameArray[i]) checks_PTFs.checkNegValue("Readily available water", readilyAvailWater, nameArray[i]) checks_PTFs.checkNegValue("Not readily available water", notRAW, nameArray[i]) checks_PTFs.checkNegValue("Not readily available water", PAW, nameArray[i]) else: wc_sat = -9999 wc_fc = -9999 wc_sic = -9999 wc_pwp = -9999 drainWater = -9999 readilyAvailWater = -9999 notRAW = -9999 PAW = -9999 wc_satCalc.append(wc_sat) wc_fcCalc.append(wc_fc) wc_sicCalc.append(wc_sic) wc_pwpCalc.append(wc_pwp) wc_DW.append(drainWater) wc_RAW.append(readilyAvailWater) wc_NRAW.append(notRAW) wc_PAW.append(PAW) common.writeOutputCriticalWC(outputShp, wc_satCalc, wc_fcCalc, wc_sicCalc, wc_pwpCalc, wc_DW, wc_RAW, wc_NRAW, wc_PAW) except Exception: arcpy.AddError("Brooks-Corey function failed") raise finally: # Remove feature layers from memory try: for lyr in common.listFeatureLayers(locals()): arcpy.Delete_management(locals()[lyr]) exec(lyr + ' = None') in locals() except Exception: pass
def HodnettTomasella_2002(outputShp, VGOption, carbonConFactor, carbContent): # Arrays to write to shapefile warningArray = [] WC_satArray = [] WC_residualArray = [] alpha_VGArray = [] n_VGArray = [] m_VGArray = [] log.info( "Calculating van Genuchten parameters using Hodnett and Tomasella (2002)" ) # Requirements: Sand, Silt, Clay, OC, BD, CEC, pH # Get OID field OIDField = common.getOIDField(outputShp) if carbContent == 'OC': reqFields = [ OIDField, "Sand", "Silt", "Clay", "OC", "BD", "CEC", "pH", "LUCIname", "texture" ] carbonConFactor = 1.0 elif carbContent == 'OM': reqFields = [ OIDField, "Sand", "Silt", "Clay", "OC", "BD", "CEC", "pH", "LUCIname", "texture" ] checks_PTFs.checkInputFields(reqFields, outputShp) # Retrieve info from input record = [] sandPerc = [] siltPerc = [] clayPerc = [] carbPerc = [] BDg_cm3 = [] CECcmol_kg = [] pH = [] nameArray = [] textureArray = [] with arcpy.da.SearchCursor(outputShp, reqFields) as searchCursor: for row in searchCursor: objectID = row[0] sand = row[1] silt = row[2] clay = row[3] carbon = row[4] BD = row[5] CEC = row[6] pHValue = row[7] name = row[8] texture = row[9] record.append(objectID) sandPerc.append(sand) siltPerc.append(silt) clayPerc.append(clay) carbPerc.append(carbon) BDg_cm3.append(BD) CECcmol_kg.append(CEC) pH.append(pHValue) nameArray.append(name) textureArray.append(texture) for x in range(0, len(record)): # Data checks warningFlag = checks_PTFs.checkSSC(sandPerc[x], siltPerc[x], clayPerc[x], record[x]) warningFlag = checks_PTFs.checkCarbon(carbPerc[x], carbContent, record[x]) warningFlag = checks_PTFs.checkValue("Bulk density", BDg_cm3[x], record[x]) warningFlag = checks_PTFs.checkValue("CEC", CECcmol_kg[x], record[x]) warningFlag = checks_PTFs.checkValue("pH", pH[x], record[x]) warningArray.append(warningFlag) WC_sat = 0.81799 + (9.9 * 10**(-4) * clayPerc[x]) - ( 0.3142 * BDg_cm3[x]) + (1.8 * 10**(-4) * CECcmol_kg[x]) + ( 0.00451 * pH[x]) - (5 * 10**(-6) * sandPerc[x] * clayPerc[x]) WC_residual = 0.22733 - (0.00164 * sandPerc[x]) + ( 0.00235 * CECcmol_kg[x]) - (0.00831 * pH[x]) + ( 1.8 * 10**(-5) * clayPerc[x]**2) + (2.6 * 10**(-5) * sandPerc[x] * clayPerc[x]) # Original equation had values in kPa-1 # No internal conversion needed alpha_VG = math.exp(-0.02294 - (0.03526 * siltPerc[x]) + (0.024 * carbPerc[x] * float(carbonConFactor)) - (0.00076 * CECcmol_kg[x]) - (0.11331 * pH[x]) + (0.00019 * siltPerc[x]**2)) n_VG = math.exp(0.62986 - (0.00833 * clayPerc[x]) - (0.00529 * carbPerc[x] * float(carbonConFactor)) + (0.00593 * pH[x]) + (7 * 10**(-5) * clayPerc[x]**2) - (1.4 * 10**(-4) * sandPerc[x] * siltPerc[x])) m_VG = 1.0 - (1.0 / float(n_VG)) WC_satArray.append(WC_sat) WC_residualArray.append(WC_residual) alpha_VGArray.append(alpha_VG) n_VGArray.append(n_VG) m_VGArray.append(m_VG) common.writeWarning(outputShp, warningArray) return WC_residualArray, WC_satArray, alpha_VGArray, n_VGArray, m_VGArray
def function(outputFolder, inputFolder, KsatOption, carbContent, carbonConFactor): try: # Set temporary variables prefix = os.path.join(arcpy.env.scratchGDB, "moist_") # Set output filename outputShp = os.path.join(outputFolder, "Ksat.shp") ## From the input folder, pull the PTFinfo PTFxml = os.path.join(inputFolder, "ptfinfo.xml") if not os.path.exists(PTFxml): log.error( 'Please run the point-PTF or vg-PTF tool first before running this tool' ) sys.exit() else: PTFType = common.readXML(PTFxml, 'PTFType') if PTFType == "pointPTF": inputShp = os.path.join(inputFolder, "soil_point_ptf.shp") elif PTFType == "vgPTF": inputShp = os.path.join(inputFolder, "soil_vg.shp") else: log.error( 'Please run the point-PTF or vg-PTF tool first before running this tool' ) sys.exit() # Copy the input shapefile to the output folder arcpy.CopyFeatures_management(inputShp, outputShp) # Check if the K_sat field already exists in the shapefile if common.CheckField(outputShp, "K_sat"): log.error('K_sat field already present in the output shapefile') sys.exit() if KsatOption == 'Cosby_1984': warningArray, K_satArray = ksat_PTFs.Cosby_1984( outputFolder, outputShp) elif KsatOption == 'Puckett_1985': warningArray, K_satArray = ksat_PTFs.Puckett_1985( outputFolder, outputShp) elif KsatOption == 'Jabro_1992': warningArray, K_satArray = ksat_PTFs.Jabro_1992( outputFolder, outputShp) elif KsatOption == 'CampbellShiozawa_1994': warningArray, K_satArray = ksat_PTFs.CampbellShiozawa_1994( outputFolder, outputShp) elif KsatOption == 'FerrerJulia_2004_1': warningArray, K_satArray = ksat_PTFs.FerrerJulia_2004_1( outputFolder, outputShp) elif KsatOption == 'FerrerJulia_2004_2': warningArray, K_satArray = ksat_PTFs.FerrerJulia_2004_2( outputFolder, outputShp, carbonConFactor, carbContent) elif KsatOption == 'Ahuja_1989': warningArray, K_satArray = ksat_PTFs.Ahuja_1989( outputFolder, outputShp) elif KsatOption == 'MinasnyMcBratney_2000': warningArray, K_satArray = ksat_PTFs.MinasnyMcBratney_2000( outputFolder, outputShp) elif KsatOption == 'Brakensiek_1984': warningArray, K_satArray = ksat_PTFs.Brakensiek_1984( outputFolder, outputShp) else: log.error("Invalid KsatOption: " + str(KsatOption)) sys.exit() # Write results to output shapefile arcpy.AddField_management(outputShp, "warning", "TEXT") arcpy.AddField_management(outputShp, "K_sat", "DOUBLE", 10, 6) outputFields = ["warning", "K_sat"] recordNum = 0 with arcpy.da.UpdateCursor(outputShp, outputFields) as cursor: for row in cursor: row[0] = warningArray[recordNum] row[1] = K_satArray[recordNum] cursor.updateRow(row) recordNum += 1 log.info( "Results written to the output shapefile inside the output folder") except Exception: arcpy.AddError("Saturated hydraulic conductivity function failed") raise finally: # Remove feature layers from memory try: for lyr in common.listFeatureLayers(locals()): arcpy.Delete_management(locals()[lyr]) exec(lyr + ' = None') in locals() except Exception: pass