class PluginTool(ActionListener): def __init__(self, args): if len(args) != 0: self.execute(args) else: ''' Create a dialog for this tool to collect user-specified tool parameters.''' self.sd = ScriptDialog(pluginHost, descriptiveName, self) ''' Specifying the help file will display the html help // file in the help pane. This file should be be located // in the help directory and have the same name as the // class, with an html extension.''' self.sd.setHelpFile(name) ''' Specifying the source file allows the 'view code' // button on the tool dialog to be displayed.''' self.sd.setSourceFile(os.path.abspath(__file__)) # add some components to the dialog ''' self.sd.addDialogFile("Input DEM file", "Input DEM:", "open", "Raster Files (*.dep), DEP", True, False) self.sd.addDialogFile("Output DEM file", "Output DEM File:", "save", "Raster Files (*.dep), DEP", True, False) self.sd.addDialogDataInput("Neighbourhood size", "Neighbourhood Size (cells):", "", True, False) self.sd.addDialogDataInput("Slope threshold", "Slope threshold:", "15.0", True, False) # Resize the dialog to the standard size and display it ''' self.sd.setSize(800, 400) self.sd.visible = True def actionPerformed(self, event): if event.getActionCommand() == "ok": args = self.sd.collectParameters() t = Thread(target=lambda: self.execute(args)) t.start() ''' The execute function is the main part of the tool, where the actual work is completed.''' def execute(self, args): try: if len(args) != 4: pluginHost.showFeedback("Incorrect number of arguments given to tool.") return # read the input parameters inputfile = args[0] outputfile = args[1] filtersize = int(args[2]) if filtersize < 3: filtersize = 3 slopethreshold = float(args[3]) exe_path = pluginHost.getResourcesDirectory() + "plugins" + os.path.sep os.chdir(exe_path) (release, vendor, vminfo, osinfo) = jav() if "win" in osinfo[0].lower(): ext = '.exe' else: ext = '' cmd = "." + os.path.sep + "NativePlugins" + os.path.sep + "remove_off_terrain_objects{}".format(ext) cmd += ' -i=\"{}\"'.format(inputfile) cmd += ' -o=\"{}\"'.format(outputfile) cmd += ' -filter=\"{}\"'.format(filtersize) cmd += ' -slope=\"{}\"'.format(slopethreshold) cmd += ' -v' ps = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=1, universal_newlines=True) while True: line = ps.stdout.readline() if line != '': if "%" in line: str_array = line.split(" ") label = line.replace(str_array[len(str_array)-1], "") progress = int(str_array[len(str_array)-1].replace("%", "").strip()) pluginHost.updateProgress(label, progress) else: if "error" in line.lower(): pluginHost.showFeedback("Error: {}".format(line)) else: if not line.startswith("*"): pluginHost.updateProgress(line, 0) else: break # display the output image pluginHost.returnData(outputfile) except Exception, e: print e pluginHost.showFeedback("An error has occurred during operation. See log file for details.") pluginHost.logException("Error in " + descriptiveName, e) return finally:
class MyScript(ActionListener): def __init__(self, args): if len(args) != 0: ''' This will be followed if the parameters have already been set, e.g. if the tool was called from another script. ''' self.execute(args) else: ''' The script dialog is created here. The first parameter points the dialog to the Whitebox user interface. The second parameter is the title of the dialog. In most cases this should be set to the descriptive name of the tool. The third parameter is a listener for the OK button. When the user presses OK on the dialog, actionPerformed method of this class will be informed.''' self.sd = ScriptDialog(pluginHost, "My Script", self) ''' Sets the name of the helpfile, which should be an html file contained in the Help directory. Ideally, it has the same name as the tool's name.''' helpFile = self.__class__.__name__ self.sd.setHelpFile(helpFile) ''' This next line will enable the 'View Code' button on the dialog.''' self.sd.setSourceFile(os.path.abspath(__file__)) ''' Now add some components to the dialog. The following is a description of some of the most commonly used dialog components.''' ''' Use the addDialogFile method to add a File input/output component to the dialog. The method has six parameters: 1) String description, 2) String labelText, 3) String dialogMode ("open" or "save"), 4) String filter (commonly "Raster Files (*.dep), DEP", "Vector Files (*.shp), SHP", or "Whitebox Files (*.dep; *.shp), DEP, SHP"), 5) boolean showButton, 6) boolean makeOptional.''' self.sd.addDialogFile("Input raster file", "Input Raster File:", "open", "Raster Files (*.dep), DEP", True, False) self.sd.addDialogFile("Output rasterfile", "Output Raster File:", "save", "Raster Files (*.dep), DEP", True, False) self.sd.addDialogFile("Input vector file", "Input Vector File:", "open", "Vector Files (*.shp), SHP", True, False) self.sd.addDialogFile("Output vector file", "Output Vector File:", "save", "Vector Files (*.shp), SHP", True, False) ''' Use the addDialogMultiFile method to add a multi-file selection component to the dialog. This method has three parameters: 1) String description, 2) String labelText, 3) String filter (commonly "Raster Files (*.dep), DEP", "Vector Files (*.shp), SHP", or "Whitebox Files (*.dep; *.shp), DEP, SHP")''' #self.sd.addDialogMultiFile("This is a multifile input", "Choose some raster files:", "Raster Files (*.dep), DEP") ''' Use the addDialogDataInput method to add a data input component retrieving text strings or numbers from the user. This method has five parameters: 1) String description, 2) String labelText, 3) String initialText, 4) boolean numericalInput (text strings will not be accepted), 5) boolean makeOptional.''' self.sd.addDialogDataInput("Enter data here", "Enter a number", "1.3", True, False) ''' Use the addDialogCheckBox method to add a checkbox to the dialog. This method has three parameters: 1) String description, 2) String labelText, 3) boolean initialState''' self.sd.addDialogCheckBox("Do you want it to rain?", "Will it rain?", True) ''' Use the addDialogComboBox method to add a drop-down selection list to the dialog. This method has four parameters: 1) String description, 2) String labelText, 3) String[] (or ArrayList<>) listItems, 4) int defaultItem''' #self.sd.addDialogComboBox("Weather type", "Weather type:", ["rain", "snow", "sun", "hail"], 1) ''' Use the addDialogOption method to add a radio-button style option on the dialog. This method has four parameters: 1) String description, 2) String labelText, 3) String button1String, 4) String button2String''' #self.sd.addDialogOption("This is an option", "Choose one:", "Plants", "Animals") ''' Use the addDialogFieldSelector method to add a field selector component to the dialog. A field selector is a combination file input, specifically for selecting shapefiles, and a list selector for specifying a field within the shapefile's attribute table. This method has three parameters: 1) String description, 2) String labelText, 3) boolean allowMultipleSelection''' #self.sd.addDialogFieldSelector("A field selector", "Choose a field", True) ''' Use the addDialogLabel method to add a label to the dialog. This method has one parameter: 1) String text''' #self.sd.addDialogLabel("Model Parameters:") ''' Resize the dialog to the standard size and display it ''' self.sd.setSize(800, 400) self.sd.visible = True ''' This method is the main part of your script. It is were the main processing occurs and will be called on its own thread when the user presses the OK button on the dialog (see actionPerformed below).''' def execute(self, args): try: ''' Make sure that the args array has the expected number of parameters. If the script is being called by another script, this may not be the case, at which point, the script should inform the user of the error and then end gracefully.''' if len(args) != 6: pluginHost.showFeedback("Incorrect number of arguments given to tool.") return ''' Read in the parameters. All parameters are provided as strings and must be converted to their appropriate form for use, e.g. floats etc. ''' inputfile = args[0] outputfile = args[1] inputshapefile = args[2] outputshapefile = args[3] numericalData = float(args[4]) booleanValue = bool(args[5]) ''' The following is an example of how to call another Whitebox plugin from your script. simply create a list of strings to hold the parameters you wish to provide the plugin. Then call the runPlugin method of the pluginHost. pluginHost is a reference to the Whitebox user interface. The last two boolean variables in the runPlugin method are to indicate 1) whether the tool should be run on a dedicated thread, which is not advisable if you would like to run through a workflow sequentially (i.e. complete first task then move onto second task) and 2) whether upon completion, any data that would be automatically returned by the tool (e.g. a displayed image) should be suppressed.''' # args2 = [inputfile, outputfile, "0.0"] # pluginHost.runPlugin("FillDepressions", args2, False, True) ''' The following code sets up an input Whitebox raster for reading. It then reads the number of rows and columns and the nodata value.''' inputraster = WhiteboxRaster(inputfile, 'r') rows = inputraster.getNumberRows() cols = inputraster.getNumberColumns() nodata = inputraster.getNoDataValue() ''' The next line of code will create a new WhiteboxRaster of the name 'ouptutfile'. It will be the same dimensions and extent as the input file. The last parameter is the initial value of the raster grid, here set to nodata.''' outputraster = WhiteboxRaster(outputfile, "rw", inputfile, DataType.FLOAT, nodata) ''' This code can be used to scan through a raster grid. ''' oldprogress = -1 for row in xrange(0, rows): for col in xrange(0, cols): z = inputraster.getValue(row, col) if z != nodata: outputraster.setValue(row, col, z * 1000) else: outputraster.setValue(row, col, nodata) progress = (int)(100.0 * row / (rows - 1)) if progress > oldprogress: oldprogress = progress pluginHost.updateProgress(progress) if pluginHost.isRequestForOperationCancelSet(): pluginHost.showFeedback("Operation cancelled") return inputraster.close() outputraster.close() ''' Call the returnData method of pluginHost. You can return the file names of raster files and shapefiles and they will be automatically displayed. If you return a text string (other than a file name) it will be displayed in the textbox at the bottom of the Whitebox user interface. If you return html, it will be rendered in a window. If you return a JPanel, it will be placed in a JDialog and displayed.''' pluginHost.returnData(outputfile) ''' The following code is an example of how to work with vector data.''' ''' Open and existing shapefile''' input = ShapeFile(inputshapefile) shapetype = input.getShapeType() table = input.getAttributeTable() ''' reading from the records in a shapefile ''' r = 0 for record in input.records: shapegeometry = record.getGeometry() ''' Read the points into an array ''' points = shapegeometry.getPoints() # x = points[pointnum][0] # y = points[pointnum][1] ''' polylines and polygons can contain multiple parts. The 'parts' array can be used to identify the starting node from the points array for each part in the geometry. ''' parts = shapegeometry.getParts() ''' the following shows how you read the record's attributes and update an entry''' # recData = table.getRecord(r) # recData[recData.length - 1] = new Double(1.0) # table.updateRecord(r, recData) # r += 1 ''' The following code can be used to create a new shapefile. ''' ''' First, set up the fields within the attribute table. ''' field1 = DBFField() field1.setName("FID") field1.setDataType(DBFField.DBFDataType.NUMERIC) field1.setFieldLength(10) field1.setDecimalCount(0) field2 = DBFField() field2.setName("NAME") field2.setDataType(DBFField.DBFDataType.STRING) field2.setFieldLength(20) fields = [field1, field2] ''' Now create the shapefile, feeding the constructor the fields array. ''' output = ShapeFile(outputshapefile, ShapeType.POLYLINE, fields) # outputGeom = Point(x, y) # outputGeom = PolyLine(parts, points) # outputGeom = Polygon(parts, points) ''' Note that for ShapeTypes of M or Z dimensions, there are alternative constructors that allow for setting the M and Z data using a double array. ''' # Object[] rowData = new Object[2] # rowData[0] = (float)FID # rowData[1] = "New feature" # output.addRecord(outputGeom, rowData); output.write() except Exception, e: print e pluginHost.showFeedback("Error during script execution.") ''' alternatively, you many want to send the exception to the pluginHost.logException() method ''' return finally:
class PluginTool(ActionListener): def __init__(self, args): if len(args) != 0: self.execute(args) else: ''' Create a dialog for this tool to collect user-specified tool parameters.''' self.sd = ScriptDialog(pluginHost, descriptiveName, self) ''' Specifying the help file will display the html help // file in the help pane. This file should be be located // in the help directory and have the same name as the // class, with an html extension.''' self.sd.setHelpFile(name) ''' Specifying the source file allows the 'view code' // button on the tool dialog to be displayed.''' self.sd.setSourceFile(os.path.abspath(__file__)) # add some components to the dialog ''' self.sd.addDialogFile("Input LAS file", "Input LAS File:", "open", "LAS Files (*.las), LAS", True, False) self.sd.addDialogFile("Output LAS file", "Output LAS File:", "save", "LAS Files (*.las), LAS", True, False) self.sd.addDialogDataInput("Minimum elevation in z-units", "Minimum elevation (Optional):", "", True, True) self.sd.addDialogDataInput("Maximum elevation in z-units", "Maximum elevation (Optional):", "", True, True) self.sd.addDialogDataInput("In-slice class value (0-31)", "In-slice Class Value (Optional):", "", True, True) self.sd.addDialogDataInput("Out-of-slice class value (0-31)", "Out-of-slice Class Value (Optional):", "", True, True) # Resize the dialog to the standard size and display it ''' self.sd.setSize(800, 400) self.sd.visible = True def actionPerformed(self, event): if event.getActionCommand() == "ok": args = self.sd.collectParameters() t = Thread(target=lambda: self.execute(args)) t.start() ''' The execute function is the main part of the tool, where the actual work is completed.''' def execute(self, args): try: if len(args) != 6: pluginHost.showFeedback( "Incorrect number of arguments given to tool.") return # read the input parameters inputfile = args[0] outputfile = args[1] min_z = float('-inf') if args[2].lower() != "not specified": min_z = float(args[2]) max_z = float('inf') if args[3].lower() != "not specified": max_z = float(args[3]) in_class = -1 if args[4].lower() != "not specified": in_class = int(args[4]) out_class = -1 if args[5].lower() != "not specified": out_class = int(args[5]) if min_z == float('-inf') and max_z == float('inf'): pluginHost.showFeedback( "You must specify either a min. z, a max. z, or both.") return exe_path = pluginHost.getResourcesDirectory( ) + "plugins" + os.path.sep os.chdir(exe_path) (release, vendor, vminfo, osinfo) = jav() if "win" in osinfo[0].lower(): ext = '.exe' else: ext = '' tool_name = "lidar_elevation_slice" cmd = "." + os.path.sep + "NativePlugins" + os.path.sep + "{}{}".format( tool_name, ext) cmd += ' -i=\"{}\"'.format(inputfile) cmd += ' -o=\"{}\"'.format(outputfile) cmd += ' -minz=\"{}\"'.format(min_z) cmd += ' -maxz=\"{}\"'.format(max_z) if in_class >= 0 and out_class >= 0: cmd += ' -class' cmd += ' -inclassval=\"{}\"'.format(in_class) cmd += ' -outclassval=\"{}\"'.format(out_class) cmd += ' -v' ps = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=1, universal_newlines=True) while True: line = ps.stdout.readline() if line != '': if "%" in line: str_array = line.split(" ") label = line.replace(str_array[len(str_array) - 1], "") progress = int(str_array[len(str_array) - 1].replace( "%", "").strip()) pluginHost.updateProgress(label, progress) else: if "error" in line.lower(): pluginHost.showFeedback("Error: {}".format(line)) else: if not line.startswith("*"): pluginHost.updateProgress(line, 0) else: break # display the output image pluginHost.returnData(outputfile) except Exception, e: print e pluginHost.showFeedback( "An error has occurred during operation. See log file for details." ) pluginHost.logException("Error in " + descriptiveName, e) return finally:
class PluginTool(ActionListener): def __init__(self, args): if len(args) != 0: self.execute(args) else: ''' Create a dialog for this tool to collect user-specified tool parameters.''' self.sd = ScriptDialog(pluginHost, descriptiveName, self) ''' Specifying the help file will display the html help // file in the help pane. This file should be be located // in the help directory and have the same name as the // class, with an html extension.''' self.sd.setHelpFile(name) ''' Specifying the source file allows the 'view code' // button on the tool dialog to be displayed.''' self.sd.setSourceFile(os.path.abspath(__file__)) # add some components to the dialog ''' self.sd.addDialogFile("Input LAS file", "Input LAS File:", "open", "LAS Files (*.las), LAS", True, False) self.sd.addDialogFile("Output LAS file", "Output LAS File:", "save", "LAS Files (*.las), LAS", True, False) self.sd.addDialogDataInput( "Neighbourhood search distance (xy units)", "Search Distance (xy units):", "10.0", True, False) self.sd.addDialogDataInput( "Maximum allowable slope between neighbouring points", "Max. Slope Between Points:", "45.0", True, False) self.sd.addDialogDataInput( "Minimum height above ground (z units) for an off-terrain object", "Min. OTO Height:", "0.15", True, False) self.sd.addDialogDataInput( "The height above ground (z units) beyond which a point is considered to be an off-terrain object regardless of inter-point slopes.", "Max. Height Above Ground:", "2.5", True, False) self.sd.addDialogDataInput( "Elevation (z units) below which points are excluded from analysis (Optional).", "Min. Elevation:", "", True, True) self.sd.addDialogCheckBox("Classify ground points?", "Classify ground points?", False) # Resize the dialog to the standard size and display it ''' self.sd.setSize(800, 400) self.sd.visible = True def actionPerformed(self, event): if event.getActionCommand() == "ok": args = self.sd.collectParameters() t = Thread(target=lambda: self.execute(args)) t.start() ''' The execute function is the main part of the tool, where the actual work is completed.''' def execute(self, args): try: if len(args) != 8: pluginHost.showFeedback( "Incorrect number of arguments given to tool.") return # read the input parameters inputfile = args[0] outputfile = args[1] search_dist = float(args[2]) slope = float(args[3]) min_z_diff = float(args[4]) max_z_above_ground = float(args[5]) min_z_str = args[6] min_z = -999999.0 if min_z_str.lower() != "not specified": min_z = float(min_z) classify = False if args[7].lower() == 'true': classify = True exe_path = pluginHost.getResourcesDirectory( ) + "plugins" + os.path.sep os.chdir(exe_path) (release, vendor, vminfo, osinfo) = jav() if "win" in osinfo[0].lower(): ext = '.exe' else: ext = '' tool_name = "lidar_ground_point_separation" cmd = "." + os.path.sep + "NativePlugins" + os.path.sep + "{}{}".format( tool_name, ext) cmd += ' -i=\"{}\"'.format(inputfile) cmd += ' -o=\"{}\"'.format(outputfile) cmd += ' -dist=\"{}\"'.format(search_dist) cmd += ' -slope=\"{}\"'.format(slope) cmd += ' -minzdiff=\"{}\"'.format(min_z_diff) cmd += ' -maxzdiff=\"{}\"'.format(max_z_above_ground) if classify: cmd += ' -class' if min_z_str.lower() != "not specified": cmd += ' -minz=\"{}\"'.format(min_z) cmd += ' -v' ps = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=1, universal_newlines=True) while True: line = ps.stdout.readline() if line != '': if "%" in line: str_array = line.split(" ") label = line.replace(str_array[len(str_array) - 1], "") progress = int(str_array[len(str_array) - 1].replace( "%", "").strip()) pluginHost.updateProgress(label, progress) else: if "error" in line.lower(): pluginHost.showFeedback("Error: {}".format(line)) else: if not line.startswith("*"): pluginHost.updateProgress(line, 0) else: break # display the output image pluginHost.returnData(outputfile) except Exception, e: print e pluginHost.showFeedback( "An error has occurred during operation. See log file for details." ) pluginHost.logException("Error in " + descriptiveName, e) return finally:
class PluginTool(ActionListener): def __init__(self, args): if len(args) != 0: self.execute(args) else: ''' Create a dialog for this tool to collect user-specified tool parameters.''' self.sd = ScriptDialog(pluginHost, descriptiveName, self) ''' Specifying the help file will display the html help // file in the help pane. This file should be be located // in the help directory and have the same name as the // class, with an html extension.''' self.sd.setHelpFile(name) ''' Specifying the source file allows the 'view code' // button on the tool dialog to be displayed.''' self.sd.setSourceFile(os.path.abspath(__file__)) # add some components to the dialog ''' self.sd.addDialogFile("Input LAS file", "Input LAS File:", "open", "LAS Files (*.las), LAS", True, False) self.sd.addDialogFile("Output LAS file", "Output LAS File:", "save", "LAS Files (*.las), LAS", True, False) self.sd.addDialogDataInput("Detrending distance (xy units)", "Detrending Distance (xy units):", "20.0", True, False) self.sd.addDialogDataInput( "Neighbourhood search distance (xy units)", "Search Distance (xy units):", "10.0", True, False) self.sd.addDialogDataInput( "Maximum deviation (degrees) in normal vectors", "Max. Normal Vector Difference:", "10.0", True, False) self.sd.addDialogDataInput( "Maximum difference in elevation (z units) between neighbouring points of the same segment", "Max. Elevation Difference:", "0.15", True, False) self.sd.addDialogCheckBox("Classify ground segments?", "Classify ground segments?", False) # Resize the dialog to the standard size and display it ''' self.sd.setSize(800, 400) self.sd.visible = True def actionPerformed(self, event): if event.getActionCommand() == "ok": args = self.sd.collectParameters() t = Thread(target=lambda: self.execute(args)) t.start() ''' The execute function is the main part of the tool, where the actual work is completed.''' def execute(self, args): try: if len(args) != 7: pluginHost.showFeedback( "Incorrect number of arguments given to tool.") return # read the input parameters inputfile = args[0] outputfile = args[1] detrending_dist = float(args[2]) search_dist = float(args[3]) normal_dev = float(args[4]) elev_diff = float(args[5]) classify = False if args[6].lower() == 'true': classify = True exe_path = pluginHost.getResourcesDirectory( ) + "plugins" + os.path.sep os.chdir(exe_path) (release, vendor, vminfo, osinfo) = jav() if "win" in osinfo[0].lower(): ext = '.exe' else: ext = '' cmd = "." + os.path.sep + "NativePlugins" + os.path.sep + "lidar_segmentation{}".format( ext) cmd += ' -i=\"{}\"'.format(inputfile) cmd += ' -o=\"{}\"'.format(outputfile) cmd += ' -dist=\"{}\"'.format(search_dist) cmd += ' -detrend=\"{}\"'.format(detrending_dist) cmd += ' -max_norm_angle=\"{}\"'.format(normal_dev) cmd += ' -maxzdiff=\"{}\"'.format(elev_diff) if classify: cmd += ' -class' cmd += ' -v' ps = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=1, universal_newlines=True) while True: line = ps.stdout.readline() if line != '': if "%" in line: str_array = line.split(" ") label = line.replace(str_array[len(str_array) - 1], "") progress = int(str_array[len(str_array) - 1].replace( "%", "").strip()) pluginHost.updateProgress(label, progress) else: if "error" in line.lower(): pluginHost.showFeedback("Error: {}".format(line)) else: if not line.startswith("*"): pluginHost.updateProgress(line, 0) else: break # display the output image pluginHost.returnData(outputfile) except Exception, e: print e pluginHost.showFeedback( "An error has occurred during operation. See log file for details." ) pluginHost.logException("Error in " + descriptiveName, e) return finally:
class PluginTool(ActionListener): def __init__(self, args): if len(args) != 0: self.execute(args) else: ''' Create a dialog for this tool to collect user-specified tool parameters.''' self.sd = ScriptDialog(pluginHost, descriptiveName, self) ''' Specifying the help file will display the html help // file in the help pane. This file should be be located // in the help directory and have the same name as the // class, with an html extension.''' self.sd.setHelpFile(name) ''' Specifying the source file allows the 'view code' // button on the tool dialog to be displayed.''' self.sd.setSourceFile(os.path.abspath(__file__)) # add some components to the dialog ''' self.sd.addDialogFile("Input LAS file", "Input LAS File:", "open", "LAS Files (*.las), LAS", True, False) self.sd.addDialogFile("Output Raster file", "Output Raster File:", "save", "Raster Files (*.dep), DEP", True, False) self.sd.addDialogDataInput( "Output raster grid resolution (xy units)", "Grid Resolution (xy units):", "", True, False) # Resize the dialog to the standard size and display it ''' self.sd.setSize(800, 400) self.sd.visible = True def actionPerformed(self, event): if event.getActionCommand() == "ok": args = self.sd.collectParameters() t = Thread(target=lambda: self.execute(args)) t.start() ''' The execute function is the main part of the tool, where the actual work is completed.''' def execute(self, args): try: if len(args) != 3: pluginHost.showFeedback( "Incorrect number of arguments given to tool.") return # read the input parameters inputfile = args[0] outputfile = args[1] grid_resolution = float(args[2]) exe_path = pluginHost.getResourcesDirectory( ) + "plugins" + os.path.sep os.chdir(exe_path) (release, vendor, vminfo, osinfo) = jav() if "win" in osinfo[0].lower(): ext = '.exe' else: ext = '' tool_name = "lidar_flightline_overlap" # Hard coded exe directory only for testing. cmd = "/Users/johnlindsay/Documents/programming/Whitebox/trunk/whitebox_tools/target/release/{0}{1}".format( tool_name, ext) # cmd = "." + os.path.sep + "NativePlugins" + os.path.sep + "{0}{1}".format(tool_name, ext) cmd += ' -i=\"{}\"'.format(inputfile) cmd += ' -o=\"{}\"'.format(outputfile) cmd += ' -resolution=\"{}\"'.format(grid_resolution) cmd += ' -palette=\"light_quant.pal\"' cmd += ' -v' ps = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=1, universal_newlines=True) while True: line = ps.stdout.readline() if line != '': if "%" in line: str_array = line.split(" ") label = line.replace(str_array[len(str_array) - 1], "") progress = int(str_array[len(str_array) - 1].replace( "%", "").strip()) pluginHost.updateProgress(label, progress) else: # print line if "error" in line.lower(): pluginHost.showFeedback("Error: {}".format(line)) else: if not line.startswith("*"): pluginHost.updateProgress(line, 0) else: break # display the output image pluginHost.returnData(outputfile) except Exception, e: print e pluginHost.showFeedback( "An error has occurred during operation. See log file for details." ) pluginHost.logException("Error in " + descriptiveName, e) return finally:
class MyScript(ActionListener): def __init__(self, args): if len(args) != 0: ''' This will be followed if the parameters have already been set, e.g. if the tool was called from another script. ''' self.execute(args) else: ''' The script dialog is created here. The first parameter points the dialog to the Whitebox user interface. The second parameter is the title of the dialog. In most cases this should be set to the descriptive name of the tool. The third parameter is a listener for the OK button. When the user presses OK on the dialog, actionPerformed method of this class will be informed.''' self.sd = ScriptDialog(pluginHost, "My Script", self) ''' Sets the name of the helpfile, which should be an html file contained in the Help directory. Ideally, it has the same name as the tool's name.''' helpFile = self.__class__.__name__ self.sd.setHelpFile(helpFile) ''' This next line will enable the 'View Code' button on the dialog.''' self.sd.setSourceFile(os.path.abspath(__file__)) ''' Now add some components to the dialog. The following is a description of some of the most commonly used dialog components.''' ''' Use the addDialogFile method to add a File input/output component to the dialog. The method has six parameters: 1) String description, 2) String labelText, 3) String dialogMode ("open" or "save"), 4) String filter (commonly "Raster Files (*.dep), DEP", "Vector Files (*.shp), SHP", or "Whitebox Files (*.dep; *.shp), DEP, SHP"), 5) boolean showButton, 6) boolean makeOptional.''' self.sd.addDialogFile("Input raster file", "Input Raster File:", "open", "Raster Files (*.dep), DEP", True, False) self.sd.addDialogFile("Output rasterfile", "Output Raster File:", "save", "Raster Files (*.dep), DEP", True, False) self.sd.addDialogFile("Input vector file", "Input Vector File:", "open", "Vector Files (*.shp), SHP", True, False) self.sd.addDialogFile("Output vector file", "Output Vector File:", "save", "Vector Files (*.shp), SHP", True, False) ''' Use the addDialogMultiFile method to add a multi-file selection component to the dialog. This method has three parameters: 1) String description, 2) String labelText, 3) String filter (commonly "Raster Files (*.dep), DEP", "Vector Files (*.shp), SHP", or "Whitebox Files (*.dep; *.shp), DEP, SHP")''' #self.sd.addDialogMultiFile("This is a multifile input", "Choose some raster files:", "Raster Files (*.dep), DEP") ''' Use the addDialogDataInput method to add a data input component retrieving text strings or numbers from the user. This method has five parameters: 1) String description, 2) String labelText, 3) String initialText, 4) boolean numericalInput (text strings will not be accepted), 5) boolean makeOptional.''' self.sd.addDialogDataInput("Enter data here", "Enter a number", "1.3", True, False) ''' Use the addDialogCheckBox method to add a checkbox to the dialog. This method has three parameters: 1) String description, 2) String labelText, 3) boolean initialState''' self.sd.addDialogCheckBox("Do you want it to rain?", "Will it rain?", True) ''' Use the addDialogComboBox method to add a drop-down selection list to the dialog. This method has four parameters: 1) String description, 2) String labelText, 3) String[] (or ArrayList<>) listItems, 4) int defaultItem''' #self.sd.addDialogComboBox("Weather type", "Weather type:", ["rain", "snow", "sun", "hail"], 1) ''' Use the addDialogOption method to add a radio-button style option on the dialog. This method has four parameters: 1) String description, 2) String labelText, 3) String button1String, 4) String button2String''' #self.sd.addDialogOption("This is an option", "Choose one:", "Plants", "Animals") ''' Use the addDialogFieldSelector method to add a field selector component to the dialog. A field selector is a combination file input, specifically for selecting shapefiles, and a list selector for specifying a field within the shapefile's attribute table. This method has three parameters: 1) String description, 2) String labelText, 3) boolean allowMultipleSelection''' #self.sd.addDialogFieldSelector("A field selector", "Choose a field", True) ''' Use the addDialogLabel method to add a label to the dialog. This method has one parameter: 1) String text''' #self.sd.addDialogLabel("Model Parameters:") ''' Resize the dialog to the standard size and display it ''' self.sd.setSize(800, 400) self.sd.visible = True ''' This method is the main part of your script. It is were the main processing occurs and will be called on its own thread when the user presses the OK button on the dialog (see actionPerformed below).''' def execute(self, args): try: ''' Make sure that the args array has the expected number of parameters. If the script is being called by another script, this may not be the case, at which point, the script should inform the user of the error and then end gracefully.''' if len(args) != 6: pluginHost.showFeedback( "Incorrect number of arguments given to tool.") return ''' Read in the parameters. All parameters are provided as strings and must be converted to their appropriate form for use, e.g. floats etc. ''' inputfile = args[0] outputfile = args[1] inputshapefile = args[2] outputshapefile = args[3] numericalData = float(args[4]) booleanValue = bool(args[5]) ''' The following is an example of how to call another Whitebox plugin from your script. simply create a list of strings to hold the parameters you wish to provide the plugin. Then call the runPlugin method of the pluginHost. pluginHost is a reference to the Whitebox user interface. The last two boolean variables in the runPlugin method are to indicate 1) whether the tool should be run on a dedicated thread, which is not advisable if you would like to run through a workflow sequentially (i.e. complete first task then move onto second task) and 2) whether upon completion, any data that would be automatically returned by the tool (e.g. a displayed image) should be suppressed.''' # args2 = [inputfile, outputfile, "0.0"] # pluginHost.runPlugin("FillDepressions", args2, False, True) ''' The following code sets up an input Whitebox raster for reading. It then reads the number of rows and columns and the nodata value.''' inputraster = WhiteboxRaster(inputfile, 'r') rows = inputraster.getNumberRows() cols = inputraster.getNumberColumns() nodata = inputraster.getNoDataValue() ''' The next line of code will create a new WhiteboxRaster of the name 'ouptutfile'. It will be the same dimensions and extent as the input file. The last parameter is the initial value of the raster grid, here set to nodata.''' outputraster = WhiteboxRaster(outputfile, "rw", inputfile, DataType.FLOAT, nodata) ''' This code can be used to scan through a raster grid. ''' oldprogress = -1 for row in xrange(0, rows): for col in xrange(0, cols): z = inputraster.getValue(row, col) if z != nodata: outputraster.setValue(row, col, z * 1000) else: outputraster.setValue(row, col, nodata) progress = (int)(100.0 * row / (rows - 1)) if progress > oldprogress: oldprogress = progress pluginHost.updateProgress(progress) if pluginHost.isRequestForOperationCancelSet(): pluginHost.showFeedback("Operation cancelled") return inputraster.close() outputraster.close() ''' Call the returnData method of pluginHost. You can return the file names of raster files and shapefiles and they will be automatically displayed. If you return a text string (other than a file name) it will be displayed in the textbox at the bottom of the Whitebox user interface. If you return html, it will be rendered in a window. If you return a JPanel, it will be placed in a JDialog and displayed.''' pluginHost.returnData(outputfile) ''' The following code is an example of how to work with vector data.''' ''' Open and existing shapefile''' input = ShapeFile(inputshapefile) shapetype = input.getShapeType() table = input.getAttributeTable() ''' reading from the records in a shapefile ''' r = 0 for record in input.records: shapegeometry = record.getGeometry() ''' Read the points into an array ''' points = shapegeometry.getPoints() # x = points[pointnum][0] # y = points[pointnum][1] ''' polylines and polygons can contain multiple parts. The 'parts' array can be used to identify the starting node from the points array for each part in the geometry. ''' parts = shapegeometry.getParts() ''' the following shows how you read the record's attributes and update an entry''' # recData = table.getRecord(r) # recData[recData.length - 1] = new Double(1.0) # table.updateRecord(r, recData) # r += 1 ''' The following code can be used to create a new shapefile. ''' ''' First, set up the fields within the attribute table. ''' field1 = DBFField() field1.setName("FID") field1.setDataType(DBFField.DBFDataType.NUMERIC) field1.setFieldLength(10) field1.setDecimalCount(0) field2 = DBFField() field2.setName("NAME") field2.setDataType(DBFField.DBFDataType.STRING) field2.setFieldLength(20) fields = [field1, field2] ''' Now create the shapefile, feeding the constructor the fields array. ''' output = ShapeFile(outputshapefile, ShapeType.POLYLINE, fields) # outputGeom = Point(x, y) # outputGeom = PolyLine(parts, points) # outputGeom = Polygon(parts, points) ''' Note that for ShapeTypes of M or Z dimensions, there are alternative constructors that allow for setting the M and Z data using a double array. ''' # Object[] rowData = new Object[2] # rowData[0] = (float)FID # rowData[1] = "New feature" # output.addRecord(outputGeom, rowData); output.write() except Exception, e: print e pluginHost.showFeedback("Error during script execution.") ''' alternatively, you many want to send the exception to the pluginHost.logException() method ''' return finally: