Infoworks Ruby Scripting - Using Ruby with the open data import centre
Don't have six minutes to read the article and want to get your hands on the finished script? Scroll to the bottom for a link to download it!
InfoWorks includes the ability to run Ruby scripts both within the user interface and through the command line in a standard alone product, InfoWorks Exchange.
While Ruby scripts and InfoWorks Exchange will now let us create digital twins that build, update and run themselves; this probably won't be the first task you try to automate if you're brand new to using Ruby in InfoWorks.
I'm going to walk you through the steps to create a script to automate the import of GIS data into InfoWorks through the Open Data Import Centre (ODIC). While this task may not take you too long manually, it can be prone to error if you don't have every set up correctly.
By the end of this tutorial, we will have a Ruby script you can assign to a button in InfoWorks and share with your modelling team.
I will be using InfoWorks WS Pro in my examples below; however, with minor modifications on the table names, the same code can be used with InfoWorks ICM.
Running your first Ruby script
To run a Ruby script in InfoWorks, click Network > Run Ruby Script in the toolbar and then select a .rb file. Let's look at a simple example below.
We start by setting the variable open_net to the currently open network, and we then get a list of all hydrants in the network.
Using the each_with_index function, we can loop through each hydrant in the list and output information about them with the puts function.
Scripting the Open Data Import Centre
To run the ODIC from a script, we use the odic_import_ex function on the open_net variable.
For importing shapefiles, there are five parameters you need to include in the function, one of which is a Ruby hash which you can set additional options. For information on how to import other file types and other options, check the documentation listed at the end of the article.
As this is just a single function, you could copy and paste this for each of the different layers.
However, repeating the same code over can lead to problems and can make your code more difficult to maintain. If you ever need to do updates to your script, you would have to find all the places you copied your code.
Configuration variables
Lets set up some configuration variables at the top of the script. First, we create two variables to store the directory of the shapefiles and config files.
We then make a Ruby hash that will contain each of the layers we want to import and their field mapping config file and shapefile locations. We can prefix the file locations with the folder variables we created earlier.
Compare the code above against the output. See how we use a hash to lookup values and loop through the results.
Try modifying and running the code to see how you can access the data within a hash.
Looping through the build
Let's adapt the code we had previously and take the options variable and odic_import_ex function and place it in the loop using the configuration variables.
Now we can make changes to the configuration of our script at the top of the file. If we need to update the directories or import more layers, it's all in one place.
Filtering features from being imported
If you have assets in your GIS data that you don't want to import, you can filter them out during the import. Let's add a new parameter to the options hash that points to a script file that will run during the import. For InfoWorks WS Pro this will be a VBScript .bas file, and for InfoWorks ICM you link to a Ruby .rb file.
For more details on these scripts, I recommend looking up 'Using a script to control import of network data' within the InfoWorks help file. Below is a simple example where we filter out any abandoned assets by looking up the operation field and also make sure we only import polygons of type DMA.
Choosing the import location
While things are looking good, it's probably not practical to get all the modellers to edit the Ruby script before they import their model.
Lets instead bring up a user prompt to let the user pick a folder to import files. Use the folder_dialog function to get this information.
While we're at it, we can also set the location of the config files dynamically. You probably want to keep the config files in the same location as your script. We can use the script_file property to get the file path of the script and then strip it back to just the directory with the FileUtils library. Don't forget to include require 'FileUtils' at the top of your script!
We can now place these three lines into our previous script, if the data or the location of the scripts move, the import will still work!
Error handling
If we let the user pick the import folder, there is a chance that they may not have included all the files required for the build. If this happens, InfoWorks will stop the script and display a cryptic error to your user.
Let's add some extra lines to check if the file exists before importing. Below we are using an if statement to see if the file exists and if not we write a message saying which layer failed and move onto the next shapefile.
Including the error log in the console
If there are any issues in the import of individual features in the ODIC import, then your users won't get any error message, they all get logged to the error file you specify.
Let's add a few lines of code to open the error file and copy anything within it straight to the script output.
As we are using the same error file for all the shapefiles, let's add another line after the odic_import_ex function that appends a message to the end of the error file after each import completes so we know which shapefiles are causing any errors.
Running the script from the toolbar
If you think you will be using a script often, you can assign it a button on the user actions toolbar. To add a new custom action, select user custom actions under the master database settings in the toolbar
Give your new action a name and include the location of the script. You can now quickly import a new model from the toolbar.
See it in action
Download a copy of the script
If you want a copy of these scripts I've saved them on Github, click the code or link below to be taken over to GitHub where you can make a copy and start playing around with it yourself.
Click here to go to GitHub and download a copy of the Ruby script
Further reading
If you want to learn more about Ruby scripting in InfoWorks I recommend you look up the Exchange documentation on the Innovyze product download pages.
If you're still new to Ruby scripting, then download and work through their 'Introduction to Ruby Scripting' document.
I hope this script can save you and your modelling team time by streamlining the import of data into InfoWorks.
Let me know how you get along and if you have any questions!
Autodesk Water Technologist for Storm Sewer and Flood | Expert in ICM InfoWorks ICM SWMM/Ruby | 18 Years at Innovyze/Autodesk | 52 Years with EPASWMM TAC for CIMM.ORG SWMM5+
1 年For some reason when I search for Ruby on Linkedin it is at the top of the found articles. Great work and I have used some of your ideas,. I will note that :open data import centre is now open data import center at Autodesk.
Technical Authority / Principal Engineer @ AtkinsRealis | Water and Environment
5 年Building some routines for pressure sewer systems...property level details.
Technical Authority / Principal Engineer @ AtkinsRealis | Water and Environment
5 年Assigning subcatchment to nodes currently its done manually or using other routine in mapinfo. Again, some sensible rules.
Technical Authority / Principal Engineer @ AtkinsRealis | Water and Environment
5 年Is it possible to fill missing data based on some rules..e.g automated interpolation of storm /combined network/pipe invert levels (but sensible). Same for cover levels, pipe sizes eyc...with simple routine. I mean at once at network level.