class GlobalKFunction(object): ### # Initialize the tool. ### def __init__(self): self.label = "Global K Function" self.description = "Uses a Global Network K Function to analyze clustering and dispersion trends in a set of crash points." self.canRunInBackground = False env.overwriteOutput = True self.kfHelper = KFunctionHelper() ### # Get input from the users. ### def getParameterInfo(self): # Input origin features. points = arcpy.Parameter( displayName="Input Points Feature Dataset", name="points", datatype="Feature Class", parameterType="Required", direction="Input") points.filter.list = ["Point"] # Network dataset. networkDataset = arcpy.Parameter( displayName="Input Network Dataset", name = "network_dataset", datatype="Network Dataset Layer", parameterType="Required", direction="Input") # Number of distance increments. numBands = arcpy.Parameter( displayName="Input Number of Distance Bands", name="num_dist_bands", datatype="Long", parameterType="Optional", direction="Input") # Beginning distance. begDist = arcpy.Parameter( displayName="Input Beginning Distance", name="beginning_distance", datatype="Double", parameterType="Required", direction="Input") begDist.value = 0 # Distance increment. distInc = arcpy.Parameter( displayName="Input Distance Increment", name="distance_increment", datatype="Double", parameterType="Required", direction="Input") distInc.value = 1000 # Snap distance. snapDist = arcpy.Parameter( displayName="Input Snap Distance", name="snap_distance", datatype="Double", parameterType="Required", direction="Input") snapDist.value = 25 # Output location. outNetKLoc = arcpy.Parameter( displayName="Output Location (Database Path)", name="out_location", datatype="DEWorkspace", parameterType="Required", direction="Input") outNetKLoc.value = arcpy.env.workspace # The raw ODCM data. outRawODCMFCName = arcpy.Parameter( displayName="Raw ODCM Data Table", name = "output_raw_odcm_feature_class", datatype="GPString", parameterType="Required", direction="Output") outRawODCMFCName.value = "Global_K_Raw_ODCM_Data" # The raw data feature class (e.g. observed and random point computations). outRawFCName = arcpy.Parameter( displayName="Raw Global-K Data Table (Raw Analysis Data)", name = "output_raw_analysis_feature_class", datatype="GPString", parameterType="Required", direction="Output") outRawFCName.value = "Global_K_Raw_Analysis_Data" # The analysis feature class. outAnlFCName = arcpy.Parameter( displayName="Global-K Summary Data (Plottable Data)", name = "output_analysis_feature_class", datatype="GPString", parameterType="Required", direction="Output") outAnlFCName.value = "Global_K_Summary_Data" # Confidence envelope (number of permutations). numPerms = arcpy.Parameter( displayName="Number of Random Point Permutations", name = "num_permutations", datatype="GPString", parameterType="Required", direction="Input") permKeys = self.kfHelper.getPermutationSelection().keys() numPerms.filter.list = permKeys numPerms.value = permKeys[0] # Projected coordinate system. outCoordSys = arcpy.Parameter( displayName="Output Network Dataset Length Projected Coordinate System", name="coordinate_system", datatype="GPSpatialReference", parameterType="Optional", direction="Input") # Number of points field. numPointsFieldName = arcpy.Parameter( displayName="Number of Points Field", name = "num_points_field", datatype="GPString", parameterType="Optional", direction="Input") return [points, networkDataset, numBands, begDist, distInc, snapDist, outNetKLoc, outRawODCMFCName, outRawFCName, outAnlFCName, numPerms, outCoordSys, numPointsFieldName] ### # Check if the tool is available for use. ### def isLicensed(self): # Network Analyst tools must be available. return arcpy.CheckExtension("Network") == "Available" ### # Set parameter defaults. ### def updateParameters(self, parameters): networkDataset = parameters[1].value outCoordSys = parameters[11].value # Default the coordinate system. if networkDataset is not None and outCoordSys is None: ndDesc = arcpy.Describe(networkDataset) # If the network dataset's coordinate system is a projected one, # use its coordinate system as the defualt. if (ndDesc.spatialReference.projectionName != "" and ndDesc.spatialReference.linearUnitName == "Meter" and ndDesc.spatialReference.factoryCode != 0): parameters[11].value = ndDesc.spatialReference.factoryCode # Set the source of the fields (the network dataset). if networkDataset is not None: parameters[12].filter.list = self.kfHelper.getEdgeSourceFieldNames(networkDataset) ### # If any fields are invalid, show an appropriate error message. ### def updateMessages(self, parameters): outCoordSys = parameters[11].value if outCoordSys is not None: if outCoordSys.projectionName == "": parameters[11].setErrorMessage("Output coordinate system must be a projected coordinate system.") elif outCoordSys.linearUnitName != "Meter": parameters[11].setErrorMessage("Output coordinate system must have a linear unit code of 'Meter.'") else: parameters[11].clearMessage() ### # Execute the tool. ### def execute(self, parameters, messages): points = parameters[0].valueAsText networkDataset = parameters[1].valueAsText numBands = parameters[2].value begDist = parameters[3].value distInc = parameters[4].value snapDist = parameters[5].value outNetKLoc = parameters[6].valueAsText outRawODCMFCName = parameters[7].valueAsText outRawFCName = parameters[8].valueAsText outAnlFCName = parameters[9].valueAsText numPermsDesc = parameters[10].valueAsText numPerms = self.kfHelper.getPermutationSelection()[numPermsDesc] outCoordSys = parameters[11].value numPointsFieldName = parameters[12].value ndDesc = arcpy.Describe(networkDataset) gkfSvc = GlobalKFunctionSvc() # Refer to the note in the NetworkDatasetLength tool. if outCoordSys is None: outCoordSys = ndDesc.spatialReference messages.addMessage("\nOrigin points: {0}".format(points)) messages.addMessage("Network dataset: {0}".format(networkDataset)) messages.addMessage("Number of distance bands: {0}".format(numBands)) messages.addMessage("Beginning distance: {0}".format(begDist)) messages.addMessage("Distance increment: {0}".format(distInc)) messages.addMessage("Snap distance: {0}".format(snapDist)) messages.addMessage("Output location (database path): {0}".format(outNetKLoc)) messages.addMessage("Raw ODCM data table: {0}".format(outRawODCMFCName)) messages.addMessage("Raw global-K data table (raw analysis data): {0}".format(outRawFCName)) messages.addMessage("Global-K summary data (plottable data): {0}".format(outAnlFCName)) messages.addMessage("Number of random permutations: {0}".format(numPerms)) messages.addMessage("Network dataset length projected coordinate system: {0}".format(outCoordSys.name)) messages.addMessage("Number of Points Field Name: {0}\n".format(numPointsFieldName)) # Calculate the length of the network. networkLength = self.kfHelper.calculateLength(networkDataset, outCoordSys) messages.addMessage("Total network length: {0}".format(networkLength)) # Count the number of crashes. numPoints = self.kfHelper.countNumberOfFeatures(os.path.join(outNetKLoc, points)) # Set up a cutoff lenght for the ODCM data if possible. (Optimization.) cutoff = gkfSvc.getCutoff(numBands, distInc, begDist) # The results of all the calculations end up here. netKCalculations = [] # Use a mutable container for the number of bands so that the below callback # can write to it. The "nonlocal" keyword not available in Python 2.x. numBandsCont = [numBands] # Callback function that does the Network K calculation on an OD cost matrix. def doNetKCalc(odDists, iteration): # Do the actual network k-function calculation. netKCalc = NetworkKCalculation(networkLength, numPoints, odDists, begDist, distInc, numBandsCont[0]) netKCalculations.append(netKCalc.getDistanceBands()) # If the user did not specifiy a number of distance bands explicitly, # store the number of bands. It's computed from the observed data. if numBandsCont[0] is None: numBandsCont[0] = netKCalc.getNumberOfDistanceBands() # Generate the ODCM permutations, including the ODCM for the observed data. # doNetKCalc is called on each iteration. randODCMPermSvc = RandomODCMPermutationsSvc() randODCMPermSvc.generateODCMPermutations("Global Analysis", points, points, networkDataset, snapDist, cutoff, outNetKLoc, outRawODCMFCName, numPerms, outCoordSys, numPointsFieldName, messages, doNetKCalc) # Store the raw analysis data. messages.addMessage("Writing raw analysis data.") gkfSvc.writeRawAnalysisData(outNetKLoc, outRawFCName, netKCalculations) # Analyze the data and store the results. messages.addMessage("Analyzing data.") gkfSvc.writeAnalysisSummaryData(numPerms, netKCalculations, outNetKLoc, outAnlFCName)
class CrossKFunction(object): ### # Initialize the tool. ### def __init__(self): self.label = "Cross K Function" self.description = "Uses a Cross K Function to analyze clustering and dispersion trends in a set of origin and destination points (for example, bridges and crashes)." self.canRunInBackground = False env.overwriteOutput = True self.kfHelper = KFunctionHelper() ### # Get input from the users. ### def getParameterInfo(self): # Input origin points features. srcPoints = arcpy.Parameter( displayName="Input Origin Points Feature Dataset (e.g. bridges)", name="srcPoints", datatype="Feature Class", parameterType="Required", direction="Input") srcPoints.filter.list = ["Point"] # Input destination origin features. destPoints = arcpy.Parameter( displayName= "Input Destination Points Feature Dataset (e.g. crashes)", name="destPoints", datatype="Feature Class", parameterType="Required", direction="Input") destPoints.filter.list = ["Point"] # Network dataset. networkDataset = arcpy.Parameter(displayName="Input Network Dataset", name="network_dataset", datatype="Network Dataset Layer", parameterType="Required", direction="Input") # Number of distance increments. numBands = arcpy.Parameter( displayName="Input Number of Distance Bands", name="num_dist_bands", datatype="Long", parameterType="Optional", direction="Input") # Beginning distance. begDist = arcpy.Parameter(displayName="Input Beginning Distance", name="beginning_distance", datatype="Double", parameterType="Required", direction="Input") begDist.value = 0 # Distance increment. distInc = arcpy.Parameter(displayName="Input Distance Increment", name="distance_increment", datatype="Double", parameterType="Required", direction="Input") distInc.value = 1000 # Snap distance. snapDist = arcpy.Parameter(displayName="Input Snap Distance", name="snap_distance", datatype="Double", parameterType="Required", direction="Input") snapDist.value = 25 # Output location. outNetKLoc = arcpy.Parameter( displayName="Output Location (Database Path)", name="out_location", datatype="DEWorkspace", parameterType="Required", direction="Input") outNetKLoc.value = arcpy.env.workspace # The raw ODCM data. outRawODCMFCName = arcpy.Parameter( displayName="Raw ODCM Data Table", name="output_raw_odcm_feature_class", datatype="GPString", parameterType="Required", direction="Output") outRawODCMFCName.value = "Cross_K_Raw_ODCM_Data" # The raw data feature class (e.g. observed and random point computations). outRawFCName = arcpy.Parameter( displayName="Raw Network-K Data Table (Raw Analysis Data)", name="output_raw_analysis_feature_class", datatype="GPString", parameterType="Required", direction="Output") outRawFCName.value = "Cross_K_Raw_Analysis_Data" # The analysis feature class. outAnlFCName = arcpy.Parameter( displayName="Network-K Summary Data (Plottable Data)", name="output_analysis_feature_class", datatype="GPString", parameterType="Required", direction="Output") outAnlFCName.value = "Cross_K_Summary_Data" # Confidence envelope (number of permutations). numPerms = arcpy.Parameter( displayName="Number of Random Point Permutations", name="num_permutations", datatype="GPString", parameterType="Required", direction="Input") permKeys = self.kfHelper.getPermutationSelection().keys() numPerms.filter.list = permKeys numPerms.value = permKeys[0] # Projected coordinate system. outCoordSys = arcpy.Parameter( displayName= "Output Network Dataset Length Projected Coordinate System", name="coordinate_system", datatype="GPSpatialReference", parameterType="Optional", direction="Input") # Number of points field. numPointsFieldName = arcpy.Parameter( displayName="Number of Points Field", name="num_points_field", datatype="GPString", parameterType="Optional", direction="Input") return [ srcPoints, destPoints, networkDataset, numBands, begDist, distInc, snapDist, outNetKLoc, outRawODCMFCName, outRawFCName, outAnlFCName, numPerms, outCoordSys, numPointsFieldName ] ### # Check if the tool is available for use. ### def isLicensed(self): # Network Analyst tools must be available. return arcpy.CheckExtension("Network") == "Available" ### # Set parameter defaults. ### def updateParameters(self, parameters): networkDataset = parameters[2].value outCoordSys = parameters[12].value # Default the coordinate system. if networkDataset is not None and outCoordSys is None: ndDesc = arcpy.Describe(networkDataset) # If the network dataset's coordinate system is a projected one, # use its coordinate system as the defualt. if (ndDesc.spatialReference.projectionName != "" and ndDesc.spatialReference.linearUnitName == "Meter" and ndDesc.spatialReference.factoryCode != 0): parameters[12].value = ndDesc.spatialReference.factoryCode # Set the source of the fields (the network dataset). if networkDataset is not None: parameters[13].filter.list = self.kfHelper.getEdgeSourceFieldNames( networkDataset) ### # If any fields are invalid, show an appropriate error message. ### def updateMessages(self, parameters): outCoordSys = parameters[12].value if outCoordSys is not None: if outCoordSys.projectionName == "": parameters[12].setErrorMessage( "Output coordinate system must be a projected coordinate system." ) elif outCoordSys.linearUnitName != "Meter": parameters[12].setErrorMessage( "Output coordinate system must have a linear unit code of 'Meter.'" ) else: parameters[12].clearMessage() ### # Execute the tool. ### def execute(self, parameters, messages): srcPoints = parameters[0].valueAsText destPoints = parameters[1].valueAsText networkDataset = parameters[2].valueAsText numBands = parameters[3].value begDist = parameters[4].value distInc = parameters[5].value snapDist = parameters[6].value outNetKLoc = parameters[7].valueAsText outRawODCMFCName = parameters[8].valueAsText outRawFCName = parameters[9].valueAsText outAnlFCName = parameters[10].valueAsText numPerms = self.kfHelper.getPermutationSelection()[ parameters[11].valueAsText] outCoordSys = parameters[12].value numPointsFieldName = parameters[13].value ndDesc = arcpy.Describe(networkDataset) gkfSvc = GlobalKFunctionSvc() # Refer to the note in the NetworkDatasetLength tool. if outCoordSys is None: outCoordSys = ndDesc.spatialReference messages.addMessage("\nOrigin points: {0}".format(srcPoints)) messages.addMessage("Destination points: {0}".format(destPoints)) messages.addMessage("Network dataset: {0}".format(networkDataset)) messages.addMessage("Number of distance bands: {0}".format(numBands)) messages.addMessage("Beginning distance: {0}".format(begDist)) messages.addMessage("Distance increment: {0}".format(distInc)) messages.addMessage("Snap distance: {0}".format(snapDist)) messages.addMessage( "Path to output cross-K feature class: {0}".format(outNetKLoc)) messages.addMessage( "Raw ODCM data table: {0}".format(outRawODCMFCName)) messages.addMessage( "Raw cross-K data table (raw analysis data): {0}".format( outRawFCName)) messages.addMessage( "Cross-K summary data (plottable data): {0}".format(outAnlFCName)) messages.addMessage( "Number of random permutations: {0}".format(numPerms)) messages.addMessage( "Network dataset length projected coordinate system: {0}".format( outCoordSys.name)) messages.addMessage( "Number of Points Field Name: {0}\n".format(numPointsFieldName)) # Calculate the length of the network. networkLength = self.kfHelper.calculateLength(networkDataset, outCoordSys) messages.addMessage("Total network length: {0}".format(networkLength)) # Count the number of crashes. numDests = self.kfHelper.countNumberOfFeatures( os.path.join(outNetKLoc, destPoints)) # Set up a cutoff lenght for the ODCM data if possible. (Optimization.) cutoff = gkfSvc.getCutoff(numBands, distInc, begDist) # The results of all the calculations end up here. netKCalculations = [] # Use a mutable container for the number of bands so that the below callback # can write to it. The "nonlocal" keyword not available in Python 2.x. numBandsCont = [numBands] # Callback function that does the Network K calculation on an OD cost matrix. def doNetKCalc(odDists, iteration): # Do the actual network k-function calculation. netKCalc = CrossKCalculation(networkLength, numDests, odDists, begDist, distInc, numBandsCont[0]) netKCalculations.append(netKCalc.getDistanceBands()) # If the user did not specifiy a number of distance bands explicitly, # store the number of bands. It's computed from the observed data. if numBandsCont[0] is None: numBandsCont[0] = netKCalc.getNumberOfDistanceBands() # Generate the ODCM permutations, including the ODCM for the observed data. # doNetKCalc is called on each iteration. randODCMPermSvc = RandomODCMPermutationsSvc() randODCMPermSvc.generateODCMPermutations( "Cross Analysis", srcPoints, destPoints, networkDataset, snapDist, cutoff, outNetKLoc, outRawODCMFCName, numPerms, outCoordSys, numPointsFieldName, messages, doNetKCalc) # Store the raw analysis data. messages.addMessage("Writing raw analysis data.") gkfSvc.writeRawAnalysisData(outNetKLoc, outRawFCName, netKCalculations) # Analyze the data and store the results. messages.addMessage("Analyzing data.") gkfSvc.writeAnalysisSummaryData(numPerms, netKCalculations, outNetKLoc, outAnlFCName)