Esempio n. 1
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())
Esempio n. 2
0
def initProgress(folder, rerun):

    try:
        xmlFile = getProgressFilenames(folder).xmlFile

        if not rerun:
            removeFile(xmlFile)

        # Create file if it does not exist
        if not os.path.exists(xmlFile):
            root = ET.Element("data")
            tree = ET.ElementTree(root)
            tree.write(xmlFile, encoding="utf-8", xml_declaration=True)
        else:
            # Open file for reading
            tree = ET.parse(xmlFile)
            root = tree.getroot()

        # Write scratch GDB to XML file if not already present
        scratchGDBNode = root.find('ScratchGDB')
        if scratchGDBNode is None:
            scratchGDBNode = createXMLNode(root, 'ScratchGDB')
            scratchGDBNode.text = str(arcpy.env.scratchGDB)

        try:
            # Save the XML file
            tree.write(xmlFile, encoding='utf-8', xml_declaration=True)

        except Exception:
            log.warning("Problem saving XML file " + str(xmlFile))
            raise

    except Exception:
        log.warning('Could not initialise progress.xml')
Esempio n. 3
0
def checkNegValue(nameValue, value, nameSoil):
    # Checks if the output is negative and returns a warning

    if value < 0.0:
        warningMsg = str(nameValue) + " is negative for " + str(nameSoil)
        log.warning(warningMsg)

        warningMsg2 = "Please check the results for " + str(nameSoil)
        log.warning(warningMsg2)
Esempio n. 4
0
def checkNegOutput(array, record):
    # Checks if the output is negative and returns a warning

    for output in array:

        if output < 0.0:
            warningFlag = 'Soil moisture value is negative for record ' + str(
                record)
            log.warning(warningFlag)
Esempio n. 5
0
def createXMLNode(parent, name):

    try:
        newNode = ET.Element(name)
        parent.append(newNode)

        return newNode

    except Exception:
        log.warning("Could not create node " + name)
        raise
Esempio n. 6
0
def checkBatjes(sand, silt, clay, carbon, carbContent, record):
    warningFlag = ''

    # log.info('DEBUG: checking for Batjes')

    if sand < 5.0:
        warningFlag = 'Sand less than 5'
        log.warning(
            'Batjes (1996) requires sand content to be at least 5 percent, check record: '
            + str(record))

    if silt < 5.0:
        warningFlag = 'Silt less than 5'
        log.warning(
            'Batjes (1996) requires silt content to be at least 5 percent, check record: '
            + str(record))

    if clay < 5.0:
        warningFlag = 'Clay less than 5'
        log.warning(
            'Batjes (1996) requires clay content to be at least 5 percent, check record: '
            + str(record))

    if carbon < 0.1:
        warningFlag = 'Carbon less than 0.1'
        log.warning(
            'Batjes (1996) requires carbon content to be at least 0.1 percent, check record: '
            + str(record))

    return warningFlag
Esempio n. 7
0
def getProgressFilenames(folder):

    try:

        class Files:
            ''' Declare filenames here '''
            def __init__(self):
                self.xmlFile = "progress.xml"

        return common.addPath(Files(), folder)

    except Exception:
        log.warning("Error occurred while generating filenames")
        raise
Esempio n. 8
0
def checkValue(name, value, record):
    warningFlag = ''

    # log.info('DEBUG: checking ' + str(name) + ' is not negative or over 100')

    if value < 0.0:
        warningFlag = str(name) + ' is negative'
        log.warning(
            str(name) + ' is negative, please check record: ' + str(record))

    if value > 100.0:
        warningFlag = str(name) + ' is over 100'
        log.warning(
            str(name) + ' is over 100, please check record: ' + str(record))

    return warningFlag
Esempio n. 9
0
def checkCarbon(carbon, carbContent, record):
    warningFlag = ''

    # log.info('DEBUG: checking if carbon is negative or over 100')

    if carbon < 0.0:
        warningFlag = 'Carbon negative'

        if carbContent == 'OC':
            msg = 'Organic carbon '
            field = 'OC'
        elif carbContent == 'OM':
            msg = 'Organic matter '
            field = 'OM'

        warningMsg1 = str(msg) + "content (percentage) is negative"
        log.warning(warningMsg1)
        warningMsg2 = "Please check the field " + str(
            field) + " in record " + str(record)
        log.warning(warningMsg2)

    ## ADD WARNING for carbon > 40

    ## ADD ERROR for carbon > 100

    if carbon > 100.0:

        warningFlag = 'OC or OM over 100'

        if carbContent == 'OC':
            msg = 'Organic carbon '
            field = 'OC'
        elif carbContent == 'OM':
            msg = 'Organic matter '
            field = 'OM'

        warningMsg1 = str(
            msg) + "content (percentage) is higher than 100 percent"
        log.warning(warningMsg1)
        warningMsg2 = "Please check the field " + str(
            field) + " in record " + str(record)
        log.warning(warningMsg2)

    return warningFlag
Esempio n. 10
0
def pressureFields(outputFolder, inputShp, fieldFC, fieldSIC, fieldPWP):

    # Check PTF information
    PTFxml = os.path.join(outputFolder, "ptfinfo.xml")
    PTFOption = common.readXML(PTFxml, 'VGOption')

    PTFInfo = PTFdatabase.checkPTF(PTFOption)
    PTFType = PTFInfo.PTFType
    PTFPressures = PTFInfo.PTFPressures

    # Get OIDField
    OIDField = arcpy.Describe(inputShp).OIDFieldName

    fcArray = []
    sicArray = []
    pwpArray = []

    # Check the field capacity field
    if common.CheckField(inputShp, fieldFC):

        with arcpy.da.SearchCursor(inputShp,
                                   [fieldFC, OIDField]) as searchCursor:
            for row in searchCursor:
                fc_kPa = row[0]

                if PTFType == 'vgPTF':
                    if fc_kPa < 6 or fc_kPa > 33:
                        log.warning("Field capacity for soil in row " +
                                    str(OIDField) +
                                    " should be between 6 to 33 kPa")

                    fcArray.append(fc_kPa)

                elif PTFType == 'pointPTF':
                    # Check if this pressure point is inside the array

                    if fc_kPa in PTFPressures:
                        fcArray.append(fc_kPa)

                    else:
                        log.error(
                            "Pressure for field capacity NOT present in point-PTF pressures"
                        )
                        log.error(
                            "Cannot calculate water content at this pressure for field capacity"
                        )
                        sys.exit()

                else:
                    log.error("PTF type not recognised: " + str(PTFType))

    else:
        log.error("Field for field capacity not found in input shapefle: " +
                  str(fieldFC))
        sys.exit()

    if fieldSIC is not None:
        if common.CheckField(inputShp, fieldSIC):

            with arcpy.da.SearchCursor(inputShp,
                                       [fieldSIC, OIDField]) as searchCursor:
                for row in searchCursor:
                    sic_kPa = row[0]

                    if PTFType == 'vgPTF':
                        ## TODO: Put in a check for the stoma closure pressure
                        ## TODO: Need to know what is a realistic range for the SIC presusre

                        sicArray.append(sic_kPa)

                    elif PTFType == 'pointPTF':
                        # Check if this pressure point is inside the array

                        if sic_kPa in PTFPressures:
                            sicArray.append(sic_kPa)

                        else:
                            log.error(
                                "Pressure for stoma closure due to water stress NOT present in point-PTF pressures"
                            )
                            log.error(
                                "Cannot calculate water content at this pressure for stoma closure due to water stress"
                            )
                            sys.exit()

                    else:
                        log.error("PTF type not recognised: " + str(PTFType))

        else:
            log.error(
                "Field for water stress-induced stomatal closure not found in input shapefle: "
                + str(fieldFC))

    else:
        log.warning(
            "Field for water stress-induced stomatal closure not specified")
        log.warning("Using default value of 100 kPa")
        defaultSIC = 100.0

        # Populate sicArray
        for i in range(0, len(fcArray)):
            sicArray.append(defaultSIC)

    if fieldPWP is not None:
        if common.CheckField(inputShp, fieldPWP):

            with arcpy.da.SearchCursor(inputShp,
                                       [fieldPWP, OIDField]) as searchCursor:
                for row in searchCursor:
                    pwp_kPa = row[0]

                    if PTFType == 'vgPTF':

                        if pwp_kPa > 1500:
                            log.warning(
                                "Permanent wilting point for soil in row " +
                                str(OIDField) + " exceeds 1500 kPa")

                            ## ASK B: vg not valid for over 1500 kPa?
                            log.warning(
                                "The van Genuchten equation is not valid for pressures greater than 1500 kPa"
                            )

                        pwpArray.append(pwp_kPa)

                    elif PTFType == 'pointPTF':
                        # Check if this pressure point is inside the array

                        if pwp_kPa in pwp_kPa:
                            pwpArray.append(pwp_kPa)

                        else:
                            log.error(
                                "Pressure for permanent wilting point NOT present in point-PTF pressures"
                            )
                            log.error(
                                "Cannot calculate water content at this pressure for permanent wilting point"
                            )
                            sys.exit()

                    else:
                        log.error("PTF type not recognised: " + str(PTFType))

        else:
            log.error(
                "Field for permanent wilting point not found in input shapefle: "
                + str(fieldFC))

    else:
        log.warning("Field for permanent wilting point not specified")
        log.warning("Using default value of 1500 kPa")
        defaultPWP = 1500.0

        # Populate pwpArray
        for i in range(0, len(fcArray)):
            pwpArray.append(defaultPWP)

    # log.info('DEBUG: fcArray: ' + str(fcArray))
    # log.info('DEBUG: sicArray: ' + str(sicArray))
    # log.info('DEBUG: pwpArray: ' + str(pwpArray))

    return fcArray, sicArray, pwpArray
Esempio n. 11
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
Esempio n. 12
0
def plotPTF(outputFolder, outputShp, PTFOption, nameArray, results):

    # For plotting point PTFs
    import matplotlib.pyplot as plt
    import numpy as np

    PTFInfo = PTFdatabase.checkPTF(PTFOption)
    PTFPressures = PTFInfo.PTFPressures
    PTFUnit = PTFInfo.PTFUnit

    # Remove warning
    results.pop(0)

    waterContents = []

    # Rearrange arrays
    for j in range(0, len(nameArray)):
        WC = []
        for i in range(0, len(PTFPressures)):
            water = results[i][j]
            WC.append(water)

        waterContents.append(WC)

    # log.info('DEBUG: waterContents: ')
    # log.info(waterContents)

    PTFInfo = PTFdatabase.checkPTF(PTFOption)
    WCheadings = PTFInfo.PTFFields
    WCheadings.pop(0) # remove warning

    for j in range(0, len(waterContents)):
        WC = waterContents[j]

        firstWCName = WCheadings[0]
        firstWCVal = WC[0]

        for i in range(1, len(WC)):
            if WC[i] > firstWCVal:
                log.warning('Water content in field ' + str(WCheadings[i]) + ' is higher than pressure at lowest water content (' + str(firstWCName) + ')')
                log.warning('Check this soil: ' + str(nameArray[j]))

    # Get units for plot
    unitPlots = common.getInputValue(outputFolder, "Pressure_units_plot")
    
    # Get critical thresholds
    fcValue = common.getInputValue(outputFolder, "FieldCapacity")
    sicValue = common.getInputValue(outputFolder, "SIC")
    pwpValue = common.getInputValue(outputFolder, "PWP")

    # Set up pressure vector
    psiArray = np.array(PTFPressures)
    psi_kPa = psiArray.astype(np.float)

    if unitPlots == 'kPa':
        psi_plot = psi_kPa
        fc_plot = float(fcValue) * -1.0
        sic_plot = float(sicValue) * -1.0
        pwp_plot = float(pwpValue) * -1.0
        xLimits = [-1600.0, 0.1]

    elif unitPlots == 'cm':
        psi_plot = 10.0 * psi_kPa
        fc_plot = float(fcValue) * -10.0
        sic_plot = float(sicValue) * -10.0
        pwp_plot = float(pwpValue) * -10.0
        xLimits = [-16000.0, 0.1]

    elif unitPlots == 'm':
        psi_plot = 0.1 * psi_kPa
        fc_plot = float(fcValue) * -0.1
        sic_plot = float(sicValue) * -0.1
        pwp_plot = float(pwpValue) * -0.1
        xLimits = [-160.0, 0.1]

    # Convert psi_plot to negative for plotting purposes
    psi_neg = -1.0 * psi_plot
 
    for i in range(0, len(nameArray)):
        outName = 'pointPTF_'  + str(nameArray[i]) + '.png'
        outPath = os.path.join(outputFolder, outName)
        title = 'Point-PTF plot for ' + str(nameArray[i])

        plt.scatter(psi_neg, waterContents[i], label=str(nameArray[i]), c='b')
        plt.xscale('symlog')
        plt.title(title)
        plt.xlabel('log Pressure (' + str(unitPlots) + ')')
        plt.ylabel('Volumetric water content')
        plt.xlim(xLimits)
        plt.axvline(x=fc_plot, color='g', linestyle='dashed', label='FC')
        plt.axvline(x=sic_plot, color='m', linestyle='dashed', label='SIC')
        plt.axvline(x=pwp_plot, color='r', linestyle='dashed', label='PWP')
        plt.legend(loc="upper left")
        plt.savefig(outPath, transparent=False)
        plt.close()
        log.info('Plot created for soil ' + str(nameArray[i]))
Esempio n. 13
0
def checkSSC(sand, silt, clay, record):
    warningFlag = ''

    # log.info('DEBUG: checking sand, silt, clay (negative and sum)')

    if sand < 0.0:
        warningFlag = 'Sand is negative'
        log.warning('Sand content is negative')
        log.warning('Please check record: ' + str(record))

    if silt < 0.0:
        warningFlag = 'Silt is negative'
        log.warning('Silt content is negative')
        log.warning('Please check record: ' + str(record))

    if clay < 0.0:
        warningFlag = 'Clay is negative'
        log.warning('Clay content is negative')
        log.warning('Please check record: ' + str(record))

    SSC = sand + silt + clay

    # log.info('DEBUG: SSC: ' + str(SSC))

    if SSC < 99.0:
        warningFlag = 'SSC less than 99'
        log.warning('Sand, silt, clay sum up to less than 99 percent')
        log.warning('Please check record: ' + str(record))

    if SSC > 101.0:
        warningFlag = 'SSC more than 101'
        log.warning('Sand, silt, clay sum up to more than 100')
        log.warning('Please check record: ' + str(record))

    return warningFlag
Esempio n. 14
0
def function(params):

    try:
        pText = common.paramsAsText(params)

        # Get inputs
        runSystemChecks = common.strToBool(pText[1])
        outputFolder = pText[2]
        inputShapefile = pText[3]
        PTFChoice = pText[4]
        BCPressures = pText[5]
        fcVal = pText[6]
        sicVal = pText[7]
        pwpVal = pText[8]
        carbonContent = pText[9]
        carbonConFactor = pText[10]
        unitsPlot = pText[11]
        axisChoice = pText[12]

        # 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)

        if PTFChoice == 'Cosby et al. (1984) - Sand and Clay':
            PTFOption = 'Cosby_1984_SandC_BC'

        elif PTFChoice == 'Cosby et al. (1984) - Sand, Silt and Clay':
            PTFOption = 'Cosby_1984_SSC_BC'

        elif PTFChoice == 'Rawls and Brakensiek (1985)':
            PTFOption = 'RawlsBrakensiek_1985_BC'
            log.warning("Rawls and Brakensiek (1985) requires water content at saturation")
            log.warning("Please ensure the WC_sat field is present in the shapefile")

        elif PTFChoice == 'Campbell and Shiozawa (1992)':
            PTFOption = 'CampbellShiozawa_1992_BC'
            log.warning("Campbell and Shiozava (1992) requires water content at saturation")
            log.warning("Please ensure the WC_sat field is present in the shapefile")

        elif PTFChoice == 'Saxton et al. (1986)':
            PTFOption = 'Saxton_1986_BC'
            
        elif PTFChoice == 'Saxton and Rawls (2006)':
            PTFOption = 'SaxtonRawls_2006_BC'

        else:
            log.error('Choice for Brooks-Corey calculation not recognised')
            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 'BC pressure heads' parameter
        if BCPressures is None:
            BCPressArray = []
        else:
            BCPressArray = BCPressures.split(' ')

        # Pull out PTFinfo
        PTFInfo = PTFdatabase.checkPTF(PTFOption)
        PTFType = PTFInfo.PTFType
        PTFUnit = PTFInfo.PTFUnit

        PTFOut = [("BCOption", PTFOption),
                  ("PTFType", PTFType),
                  ("UserUnitPlot", unitsPlot),
                  ("carbContent", carbContent)]

        # Write to XML file
        PTFXML = os.path.join(outputFolder, "ptfinfo.xml")
        common.writeXML(PTFXML, PTFOut)

        # Call Brooks-Corey function
        brooks_corey.function(outputFolder, inputShapefile, PTFOption,
                              BCPressArray, fcVal, sicVal, pwpVal,
                              carbContent, carbonConFactor)

        # Set output filename for display
        BCOut = os.path.join(outputFolder, "BrooksCorey.shp")
        arcpy.SetParameter(13, BCOut)

        log.info("Brooks-Corey operations completed successfully")

    except Exception:
        log.exception("Brooks-Corey tool failed")
        raise
Esempio n. 15
0
def plotBrooksCorey(outputFolder, WC_resArray, WC_satArray, hbArray,
                    lambdaArray, nameArray, fcValue, sicValue, pwpValue):
    # Create Brooks-Corey plots
    import matplotlib.pyplot as plt
    import numpy as np

    # Check what unit the user wants to output
    PTFUnit = common.getInputValue(outputFolder, 'Pressure_units_plot')

    # Check what axis was chosen
    AxisChoice = common.getInputValue(outputFolder, 'Plot_axis')

    # Check for any soils that we were not able to calculate BC parameters for
    errors = []
    for i in range(0, len(lambdaArray)):
        if lambdaArray[i] == -9999:
            log.warning('Invalid lambda found for ' + str(nameArray[i]))
            errors.append(i)

    # Define output folder for CSVs
    outFolder = os.path.join(outputFolder, 'BC_waterContents')
    if not os.path.exists(outFolder):
        os.mkdir(outFolder)

    ################################
    ### Plot 0: individual plots ###
    ################################

    # Plot 0: pressure on the y-axis and water content on the x-axis
    for i in [x for x in range(0, len(nameArray)) if x not in errors]:

        outName = 'bc_' + str(nameArray[i]) + '.png'
        outPath = os.path.join(outputFolder, outName)
        title = 'Brooks-Corey plot for ' + str(nameArray[i])

        # Set pressure vector
        psi_kPa = np.linspace(0.0, 1500.0, 1501)

        # Calculate WC over that pressure vector
        bc_WC = calcBrooksCoreyFXN(psi_kPa, hbArray[i], WC_resArray[i],
                                   WC_satArray[i], lambdaArray[i])

        common.writeWCCSV(outFolder, nameArray[i], psi_kPa, bc_WC,
                          'Pressures_kPa', 'WaterContents')

        ## Figure out what to do about multipliers
        if PTFUnit == 'kPa':
            pressureUnit = 'kPa'
            psi_plot = psi_kPa

            fc_plot = float(fcValue) * -1.0
            sic_plot = float(sicValue) * -1.0
            pwp_plot = float(pwpValue) * -1.0

        elif PTFUnit == 'cm':
            pressureUnit = 'cm'
            psi_plot = 10.0 * psi_kPa

            fc_plot = float(fcValue) * -10.0
            sic_plot = float(sicValue) * -10.0
            pwp_plot = float(pwpValue) * -10.0

        elif PTFUnit == 'm':
            pressureUnit = 'm'
            psi_plot = 0.1 * psi_kPa

            fc_plot = float(fcValue) * -0.1
            sic_plot = float(sicValue) * -0.1
            pwp_plot = float(pwpValue) * -0.1

        # Convert psi_plot to negative for plotting
        psi_neg = -1.0 * psi_plot

        if AxisChoice == 'Y-axis':
            plt.plot(psi_neg, bc_WC, label=str(nameArray[i]))
            plt.xscale('symlog')
            plt.axvline(x=fc_plot, color='g', linestyle='dashed', label='FC')
            plt.axvline(x=sic_plot, color='m', linestyle='dashed', label='SIC')
            plt.axvline(x=pwp_plot, color='r', linestyle='dashed', label='PWP')
            plt.legend(loc="best")
            plt.title(title)
            plt.xlabel('Pressure (' + str(pressureUnit) + ')')
            plt.ylabel('Volumetric water content')
            plt.savefig(outPath, transparent=False)
            plt.close()
            log.info('Plot created for soil ' + str(nameArray[i]))

        elif AxisChoice == 'X-axis':
            plt.plot(bc_WC, psi_neg, label=str(nameArray[i]))
            plt.yscale('symlog')
            plt.axhline(y=fc_plot, color='g', linestyle='dashed', label='FC')
            plt.axhline(y=sic_plot, color='m', linestyle='dashed', label='SIC')
            plt.axhline(y=pwp_plot, color='r', linestyle='dashed', label='PWP')
            plt.legend(loc="best")
            plt.title(title)
            plt.ylabel('Pressure (' + str(pressureUnit) + ')')
            plt.xlabel('Volumetric water content')
            plt.savefig(outPath, transparent=False)
            plt.close()
            log.info('Plot created for soil ' + str(nameArray[i]))

        else:
            log.error(
                'Invalid choice for axis plotting, please select Y-axis or X-axis'
            )
            sys.exit()

    #########################
    ### Plot 1: all soils ###
    #########################

    outPath = os.path.join(outputFolder, 'plotBC_logPressure.png')
    title = 'Brooks-Corey plots of ' + str(
        len(nameArray)) + ' soils (log scale)'

    # Define pressure vector
    psi_kPa = np.linspace(0.0, 1500.0, 1501)

    for i in [x for x in range(0, len(nameArray)) if x not in errors]:

        # Calculate WC over pressure vector
        bc_WC = calcBrooksCoreyFXN(psi_kPa, hbArray[i], WC_resArray[i],
                                   WC_satArray[i], lambdaArray[i])

        if PTFUnit == 'kPa':
            pressureUnit = 'kPa'
            psi_plot = psi_kPa

        elif PTFUnit == 'cm':
            pressureUnit = 'cm'
            psi_plot = 10.0 * psi_kPa

        elif PTFUnit == 'm':
            pressureUnit = 'm'
            psi_plot = 0.1 * psi_kPa

        # Convert psi to negative for plotting purposes
        psi_neg = -1.0 * psi_plot

        plt.plot(psi_neg, bc_WC, label=str(nameArray[i]))

    if AxisChoice == 'Y-axis':
        plt.xscale('symlog')
        plt.title(title)
        plt.axvline(x=fc_plot, color='g', linestyle='dashed', label='FC')
        plt.axvline(x=sic_plot, color='m', linestyle='dashed', label='SIC')
        plt.axvline(x=pwp_plot, color='r', linestyle='dashed', label='PWP')
        plt.ylabel('Water content')
        plt.xlabel('Pressure (' + str(pressureUnit) + ')')
        plt.legend(ncol=2, fontsize=12, loc="best")
        plt.savefig(outPath, transparent=False)
        plt.close()
        log.info('Plot created with water content on the y-axis')

    elif AxisChoice == 'X-axis':
        plt.yscale('symlog')
        plt.title(title)
        plt.axhline(y=fc_plot, color='g', linestyle='dashed', label='FC')
        plt.axhline(y=sic_plot, color='m', linestyle='dashed', label='SIC')
        plt.axhline(y=pwp_plot, color='r', linestyle='dashed', label='PWP')
        plt.xlabel('Water content')
        plt.ylabel('Pressure (' + str(pressureUnit) + ')')
        plt.legend(ncol=2, fontsize=12, loc="best")
        plt.savefig(outPath, transparent=False)
        plt.close()
        log.info('Plot created with water content on the y-axis')

    else:
        log.error(
            'Invalid choice for axis plotting, please select Y-axis or X-axis')
        sys.exit()
Esempio n. 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
Esempio n. 17
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
Esempio n. 18
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.")
Esempio n. 19
0
def function(outputFolder, inputShp, fieldFC, fieldPWP, fieldSat, RAWoption,
             RAWfrac, fieldCrit, RDchoice, rootingDepth):

    try:
        # Set temporary variables
        prefix = os.path.join(arcpy.env.scratchGDB, "moist_")

        tempSoils = prefix + "tempSoils"

        # Set output filename
        outputShp = os.path.join(outputFolder, "soilMoisture.shp")

        # Check fields are present in the input shapefile
        reqFields = ['OBJECTID', fieldFC, fieldPWP, fieldSat]

        if RAWoption == 'CriticalPoint':
            reqFields.append(fieldCrit)

        checkInputFields(reqFields, inputShp)

        # Copy the input shapefile to the output folder
        arcpy.CopyFeatures_management(inputShp, tempSoils)

        # Retrieve information from input shapefile
        record = []
        volFC = []
        volPWP = []
        volSat = []
        volCrit = []

        with arcpy.da.SearchCursor(tempSoils, reqFields) as searchCursor:
            for row in searchCursor:
                objectID = row[0]
                WC_FC = row[1]
                WC_PWP = row[2]
                WC_Sat = row[3]

                record.append(objectID)
                volFC.append(WC_FC)
                volPWP.append(WC_PWP)
                volSat.append(WC_Sat)

                if RAWoption == 'CriticalPoint':
                    WC_Crit = row[4]
                    volCrit.append(WC_Crit)

        volPAW = []
        volDW = []
        volTWC = []
        volRAW = []

        mmPAW = []
        mmDW = []
        mmTWC = []
        mmRAW = []

        for x in range(0, len(record)):

            # Calculate PAW
            PAW = volFC[x] - volPWP[x]

            if PAW < 0:
                log.warning('Negative PAW (vol) calculated for record ' +
                            str(record[x]))

            volPAW.append(PAW)

            # Calculate drainable water
            DW = volSat[x] - volFC[x]

            if DW < 0:
                log.warning(
                    'Negative drainable water (vol) calculated for record ' +
                    str(record[x]))

            volDW.append(DW)

            # Calculate total water content
            TWC = volSat[x] - volPWP[x]

            if TWC < 0:
                log.warning(
                    'Negative total water content (vol) calculated for record '
                    + str(record[x]))

            volTWC.append(TWC)

            if RAWoption == 'CriticalPoint':
                RAW = volFC[x] - volCrit[x]

                RAWfrac = RAW / float(PAW)

                if frac <= 0.2 or frac >= 0.8:
                    log.warning('Fraction of RAW to PAW is below 0.2 or 0.8')

                volRAW.append(RAW)

            elif RAWoption == 'Fraction':

                RAW = float(RAWfrac) * float(PAW)
                volRAW.append(RAW)

            if RDchoice == True:
                mm_PAW = PAW * float(rootingDepth)
                mm_DW = DW * float(rootingDepth)
                mm_TWC = TWC * float(rootingDepth)
                mm_RAW = RAW * float(rootingDepth)

                mmPAW.append(mm_PAW)
                mmDW.append(mm_DW)
                mmTWC.append(mm_TWC)
                mmRAW.append(mm_RAW)

        outFields = ['volPAW', 'volDW', 'volTWC', 'volRAW']

        # Write outputs to shapefile
        arcpy.AddField_management(tempSoils, "volPAW", "DOUBLE", 10, 6)
        arcpy.AddField_management(tempSoils, "volDW", "DOUBLE", 10, 6)
        arcpy.AddField_management(tempSoils, "volTWC", "DOUBLE", 10, 6)
        arcpy.AddField_management(tempSoils, "volRAW", "DOUBLE", 10, 6)

        if RDchoice == True:
            arcpy.AddField_management(tempSoils, "mmPAW", "DOUBLE", 10, 6)
            arcpy.AddField_management(tempSoils, "mmDW", "DOUBLE", 10, 6)
            arcpy.AddField_management(tempSoils, "mmTWC", "DOUBLE", 10, 6)
            arcpy.AddField_management(tempSoils, "mmRAW", "DOUBLE", 10, 6)

            outFields.append('mmPAW')
            outFields.append('mmDW')
            outFields.append('mmTWC')
            outFields.append('mmRAW')

        recordNum = 0
        with arcpy.da.UpdateCursor(tempSoils, outFields) as cursor:
            for row in cursor:
                row[0] = volPAW[recordNum]
                row[1] = volDW[recordNum]
                row[2] = volTWC[recordNum]
                row[3] = volRAW[recordNum]

                if RDchoice == True:
                    row[4] = mmPAW[recordNum]
                    row[5] = mmDW[recordNum]
                    row[6] = mmTWC[recordNum]
                    row[7] = mmRAW[recordNum]

                cursor.updateRow(row)
                recordNum += 1

        # Clean fields
        outFields.append('OBJECTID')
        common.CleanFields(tempSoils, outFields)

        arcpy.CopyFeatures_management(tempSoils, outputShp)

    except Exception:
        arcpy.AddError("Soil moisture 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