ICM InfoWorks by Autodesk Innovyze is a complicated program with many parts and a state-of-the-art 1D and 2D engine. One way to deal with the complexity is to automate complicated or repetitive tasks with SQL and Ruby. In this blog, we will use SQL and Ruby to automate the process of assigning Watershed outlet nodes for ICM SWMM Networks.
What are we hoping to achieve by Combining Ruby with ICM SWMM Networks?
- We want to find the outlet ID for the closest node to a Subcatchment in an ICM SWMM Network.
- Ruby will use the Geometry tools of ICM to find the closest node.
- What is an ICM SWMM Network? It is a Network in ICM that uses SWMM 5.1.015 data and most/many of the tools of the ICM GUI. ICM of course also has InfoWorks Networks.
- What am I showing in the Post header image? Autodesk has Subscription versions of ICM (Standard and Ultimate), but I am showing the Thales versions of ICM which are both 32bit and 64bit, and comingled ICM InfoWorks and ICM SWMM Networks. I also use InfoWater Pro (Arc GIS Pro) and InfoSWMM which uses Arc Map and has a direct import into an ICM SWMM Network.
ICM SWMM Network Data in the Autodesk Innvovyze ICM GUI
Why use Ruby for InfoWorks ICM SWMM Networks?
Why Ruby - it is part of ICM and easy to understand with a lot of Modeling features. It is part of Network Menu Commands. You can use a new Script or a past used script so it is easy to find.
What is an InfoWorks ICM SWMM Network?
What is an example of Ruby Scripts?
net=WSApplication.current_network puts 'Running ruby for SWMM Networks' nodes=Array.new net.row_object_collection('sw_node').each do |n| if n.selected? temp=Array.new temp << n.id temp << n.x temp << n.y nodes << temp end end net.transaction_begin net.row_object_collection('sw_subcatchment').each do |s| if s.selected? sx = s.x sy = s.y nearest_distance = 999999999.9 (0...nodes.size).each do |i| nx = nodes[i][1] ny = nodes[i][2] n_id = nodes[i][0] distance=((sx-nx)*(sx-nx))+((sy-ny)*(sy-ny)) if distance < nearest_distance nearest_distance=distance s.outlet_id = n_id end end else puts 'You forgot to select anything' end s.write end puts 'Ending ruby' net.transaction_commit
Where can I find the Ruby Scripts?
Innovyze has a Github that you can use to copy or download dozens of Ruby and SQL scripts. If registered on our Portal, you can find Salesforce Knowledge Base articles and many other sources of help. at https://github.com/innovyze/Open-Source-Support. SQL and Ruby functionality exist to be used by users with knowledge of programming languages. We provide resources to assist customers in building their scripts through the existing self-help frameworks, including documentation on Ruby, help files, and more recently a wealth of GitHub examples - link above.
How do I use Ruby Scripts?
Easy - Go to the Network Menu and choose Run Ruby Scripts or Recent Ruby Scripts
Do I need to use SQL?
It helps if you have a simple global grid command and you do not want to edit the grid. Here is a simple SQL that sets the SWMM Network OUTLET_ID to blank. You can save the SQL on the project explorer window and click to activate the dialog.
What does each line of the Ruby Script represent and what does it perform for the ICM SWMM Network?
The annotated snippet below shows the steps used in the script. ICM SWMM Networks are sw_ whereas ICM InfoWorks Networks are hw_ (for reference)
net=WSApplication.current_network # Opens the current network on the ICM Geoplan puts 'Running ruby for SWMM Networks' # Tell the user some actions are being done by the script nodes=Array.new # Makes a new array - uses swmm nodes or sw_node net.row_object_collection('sw_node').each do |n| if n.selected? temp=Array.new temp << n.id temp << n.x temp << n.y nodes << temp end end # Save the id, x coordinate, y coordinate to the nodes array of SELECTED Elements net.transaction_begin # start finding the nodes to set to the outlet of the subcatchment net.row_object_collection('sw_subcatchment').each do |s| # use swmm subcatchments or sw_subcatchment if s.selected? # use the SELECTED Elements sx = s.x sy = s.y # use the centroid of the subcatchment nearest_distance = 999999999.9 (0...nodes.size).each do |i| nx = nodes[i][1] ny = nodes[i][2] n_id = nodes[i][0] # for each node find the x and y coordinates distance=((sx-nx)*(sx-nx))+((sy-ny)*(sy-ny)) # compute the node to subcatchment distance if distance < nearest_distance nearest_distance=distance s.outlet_id = n_id # We have found the closed node and set the outlet ID to the node ID end end else puts 'You forgot to select anything' # message to remind ourself we forget to select any nodes or subcatchments end s.write end puts 'Ending ruby' # Tell the user some actions were by the script net.transaction_commit # commit our new found ID to the current network (ICM SWMM Network)
I'm attaching a YouTube video that explains the previous stages. It is for ICM SWMM Networks, which utilizes SQL to remove or set the SWMM Subcatchment's OUTLET ID to Null and Ruby to determine the closest node to the Subcatchment's centroid and assign it as the OUTLET ID. I made a mistake and ran Ruby without using ICM to pick any items, which resulted in nothing being done, but at least I received a notice about not choosing any components.