E-mail | SIS | Moodle | Helpdesk | Knihovny | cuni.cz | CIS Více

česky | english Přihlášení



Points_source

Python Source icon Points_source.py — Python Source, 9 KB (9964 bytes)

Obsah souboru

# -*- coding: utf-8 -*-

# First script for plot input data into triangular graph
# Author: Sukhdorj Ganbaatar (student), s.ganbaatar@seznam.cz
# Department of Geoinformatics, Palacky University in Olomouc

# Modification by Alexandra Mondekova (student), alexandra@mondek.eu
# Department of Demography and Geodemography, Faculty of Science, Charles University
# Addition of work with time
# Last update: June 2022

import arcpy as ap
import math
ap.env.overwriteOutput = True

# Parametric input layer, 3 fields from attribute table for calculation and variables
input = ap.GetParameterAsText(0)
if ap.Exists(input):
    sheetName = ap.GetParameterAsText(1)
    C1 = ap.GetParameterAsText(2)
    C2 = ap.GetParameterAsText(3)
    C3 = ap.GetParameterAsText(4)

    createLines = ap.GetParameterAsText(7)

    checkTuples = []

    # First check: entered fields shouldn't be used more than once
    if C1 == C2 or C2 == C3 or C3 == C1:
        ap.AddError(u" -- Process cannot be completed.")
        ap.AddError(u" -- You have chosen one field many times. Please repeat the operation.")

    # Generate field names of 3-column data
    fields = ap.ListFields(input)
    lastTuple = ()
    for field in fields:
        if field.name.split("$.")[0]+"$" != sheetName:
            continue
        splitField = field.baseName.split("_")
        if len(splitField) < 3:
            continue
        if len(lastTuple) == 0 and splitField[2] == C1:
            lastTuple = (field.name,)
        elif len(lastTuple) == 1 and splitField[2] == C2:
            lastTuple = lastTuple + (field.name,)
        elif len(lastTuple) == 2 and splitField[2] == C3:
            lastTuple = lastTuple + (field.name, splitField[1])
            checkTuples.append(lastTuple)
            lastTuple = ()
        else:
            lastTuple = ()

    if not checkTuples:
        ap.AddError(u" -- Unable to find usable 3-column data. Check category names.")

    ap.AddWarning(u" -- Input layer: Ok")

    # Second check: generated fields shouldn't be used more than once
    if C1 == C2 or C2 == C3 or C3 == C1:
        ap.AddError(u" -- Process cannot be completed.")
        ap.AddError(u" -- You have chosen one field many times. Please repeat the operation.")
    else:
        point = ap.Point()      # create a point instance
        vyska = 86.6            # variable for height of triangle
        pointList = []          # array for hold new points
        featureList = []        # array for hold new lines

        # FOR loop to iterate rows
        for checkTuple in checkTuples:
            F1 = checkTuple[0]
            F2 = checkTuple[1]
            F3 = checkTuple[2]
            period = checkTuple[3]
            F1sum = 0
            F2sum = 0
            F3sum = 0
            rowsCount = 0
            checkRows = 0  # variable for check purpose
            tuplePointList = []

            # Create a cursor object
            rows = ap.SearchCursor(input)
            lineNum = 1
            for row in rows:

                # Check: values of fields shouldn't be negative
                if row.isNull(F1) or row.isNull(F2) or row.isNull(F3):
                    ap.AddWarning(u" -- Row data with number " + str(lineNum) + u" contains negative value.")
                    checkRows += 1
                elif row.getValue(F1) < 0 or row.getValue(F2) < 0 or row.getValue(F3) < 0:
                    ap.AddWarning(u" -- Row data with number " + str(lineNum) + u" contains negative value.")
                    checkRows += 1
                else:

                    # Calculate a sum of fields and check its value
                    sumFields = row.getValue(F1) + row.getValue(F2) + row.getValue(F3)
                    if sumFields == 0:
                        ap.AddWarning(u" -- Input values for row with number " + str(lineNum) + u" are negative or all are equal zero.")
                        checkRows += 1
                    else:

                        # Get reference category
                        REFERENCE_ID = row.getValue(ap.GetParameterAsText(5))

                        # Calculate a percentage value of three variable phenomenon.
                        # Variable sumFields is sums of input value
                        P1_per = row.getValue(F1) * 100.0 / sumFields
                        P2_per = row.getValue(F2) * 100.0 / sumFields
                        P3_per = row.getValue(F3) * 100.0 / sumFields

                        # Auxiliary calculations for further usage
                        F1sum += P1_per
                        F2sum += P2_per
                        F3sum += P3_per
                        rowsCount += 1

                        # Calculate a X, Y coordiantes and save them to the points
                        coordX = P1_per + (P2_per * 0.5)
                        coordY = P2_per * (vyska)/100.0
                        point.X = coordX
                        point.Y = coordY

                        # Save a point instance to array
                        bod = ap.Multipoint(point)
                        tuplePointList.append((bod, REFERENCE_ID, period))
                        lineNum += 1

            # Check a checking variables
            pointList = pointList + tuplePointList
            ap.AddWarning(u" -- Input variables of three-structured data: Ok")

            # Create auxiliary lines
            if createLines != "":
                F1avg = F1sum/rowsCount
                F2avg = F2sum/rowsCount
                F3avg = F3sum/rowsCount
                Favg = [F2avg,F1avg,F3avg]

                # Calculate X,Y of lines
                # Linie 1 -> reprezents avg value of 2nd part (F2)
                Y1 = F2avg*math.sin(math.radians(60))
                # Linie 2 -> reprezents avg value of 1st part (F1)
                pom1 = F1avg*math.sin(math.radians(60))
                Y2 = pom1*math.sin(math.radians(30))
                X2 = pom1*math.sin(math.radians(60))
                # Linie 3 -> reprezents avg value of 3rd part (F3)
                pom2 = F3avg*math.sin(math.radians(60))
                Y3 = pom2*math.sin(math.radians(30))
                X3 = pom2*math.sin(math.radians(60))

                coordsList = [[[0,Y1],[100,Y1]],
                              [[X2,0-Y2],[X2+50,0-Y2+vyska]],
                              [[100-X3,0-Y3],[100-X3-50,0-Y3+vyska]]]

                # Variables to hold points and coordinates of lines
                point2 = ap.Point()
                array2 = ap.Array()

                # Save coordinates to points
                a = 0
                for linie in coordsList:
                    for bod in linie:
                        point2.X = bod[0]
                        point2.Y = bod[1]
                        array2.add(point2)

                    # Create parts of lines and sav them to featurelist
                    polyline = ap.Polyline(array2)
                    array2.removeAll()
                    featureList.append((polyline, Favg[a], period))
                    a += 1

            ap.AddWarning("\n" + u"Summary:")
            ap.AddWarning(u"Successfully created basic layers to construct a triangular graph for input data:")
            ap.AddWarning(str(input) + "\n")

            if checkRows != 0:
                ap.AddWarning("\n" + u"Summary:")
                ap.AddWarning(u"Calculation for " + str(input) + u" finished but not completely because of invalid input data." + "\n")

        # Create a base triangle
        createTriangle = ap.GetParameterAsText(8)
        if createTriangle != "":
            point3 = ap.Point()
            array3 = ap.Array()
            posunY = 0.001
            coordsList = [[0.0-posunY*2,0.0-posunY],[100.0+posunY*2,0.0-posunY],[50.0,vyska+0.002236]]
            for XY in coordsList:
                point3.X = XY[0]
                point3.Y = XY[1]
                array3.add(point3)
            polygon = ap.Polygon(array3)
            ap.CopyFeatures_management(polygon, createTriangle)

        # Save created points
        ap.AddWarning(u"Path to created points:")
        pointsName = ap.GetParameterAsText(6)

        points = []
        referenceIds = []
        periods = []
        for pointEntry in pointList:
            points.append(pointEntry[0])
            referenceIds.append(pointEntry[1])
            periods.append(pointEntry[2])
        ap.CopyFeatures_management(points, pointsName)
        ap.AddField_management(pointsName, "Ref_ID", "Text")
        ap.AddField_management(pointsName, "Period", "Long")
        a = 0
        rows2 = ap.UpdateCursor(pointsName)
        for row2 in rows2:
            row2.setValue("Ref_ID", referenceIds[a])
            row2.setValue("Period", periods[a])
            rows2.updateRow(row2)
            a += 1

        # List of created points
        ap.AddWarning(str(pointsName) + "\n")

        # Create line file if specified
        if createLines != "":
            polylines = []
            favgs = []
            periods = []
            for featureEntry in featureList:
                polylines.append(featureEntry[0])
                favgs.append(featureEntry[1])
                periods.append(featureEntry[2])
            ap.CopyFeatures_management(polylines, createLines)
            ap.AddField_management(createLines, "TGavg", "Float")
            ap.AddField_management(createLines, "Period", "Long")
            a = 0
            rows2 = ap.UpdateCursor(createLines)
            for row2 in rows2:
                row2.setValue("TGavg", favgs[a])
                row2.setValue("Period", periods[a])
                rows2.updateRow(row2)
                a += 1

else:
    ap.AddError(u" -- Input layer wasn't found.")

Akce dokumentů