Example #1
0
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
Example #2
0
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())
Example #3
0
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')
Example #4
0
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()
Example #5
0
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
Example #6
0
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
Example #7
0
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
Example #8
0
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
Example #9
0
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
Example #10
0
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
Example #11
0
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
Example #12
0
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
Example #13
0
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
Example #14
0
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()
Example #15
0
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")
Example #16
0
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
Example #17
0
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
Example #18
0
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
Example #19
0
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
Example #20
0
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
Example #21
0
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
Example #22
0
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
Example #23
0
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
Example #24
0
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
Example #25
0
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.")
Example #26
0
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
Example #27
0
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
Example #28
0
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
Example #29
0
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
Example #30
0
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