Jump to content
Sign in to follow this  
spev

Compare difference between two networks

Recommended Posts

I have two scenes where one has had some changes. Is there a way to easily tell what changes have been made

Many thanks

Share this post


Link to post
Share on other sites

If you're comfortable with Python, the first thing that comes to mind for me is creating sets out of lists of the nodes in the networks and using the set boolean operations to compare them. The basic logic would be:

if network_a.issuperset(network_:
    net_diff = network_a.difference(network_
elif network_b.issuperset(network_a):
    net_diff = network_b.difference(network_a)
else:
    net_diff_a = network_a.difference(network_
    net_diff_b = network_b.difference(network_a)
    

Where network_a and network_b are the sets of node names. I'll see if I can cook up something a bit more substantial for you later on. 

  • Like 1

Share this post


Link to post
Share on other sites

Thanks jrockstad for your kind answer. I am not greatly familiar with python.. I was hoping there was a built in tool like diff on cmd line.

Share this post


Link to post
Share on other sites

Wrote up a little script, create a custom shelf tool and paste this in the Script tab to use it:


# Houdini Python shelf tool for comparing node networks
# Usage: Select first network, shift-select second network, launch tool

def node_names(networks):
    node_lists = ()
    for network in networks:
        nodes = network.glob('*')
        node_lists += (set([node.name() for node in nodes]),)
    return node_lists

def print_added_or_removed_nodes(a_or_r):
    if a_or_r == 'added':
        nodes = list(network_b.difference(network_a))
        message = "Nodes added to {}: \n".format(net_b_name)
    else:
        nodes = list(network_a.difference(network_)
        message = "Nodes removed in {}: \n".format(net_b_name)
        
    if nodes != []:
       nodes.sort()
    
    for node in nodes:
        message += node + '\n'
    return message
    
def print_added_and_removed_nodes():
    message = print_added_or_removed_nodes(a) + '\n' + \
              print_added_or_removed_nodes(r)
    return message    

networks = hou.selectedNodes()
net_b_name = networks[1].name()
network_a, network_b = node_names(networks)

nodes_added = network_b.issuperset(network_a)
nodes_removed = network_a.issuperset(network_

a = 'added'
r = 'removed'

if nodes_added:
    hou.ui.displayMessage(print_added_or_removed_nodes(a))
elif nodes_removed:
    hou.ui.displayMessage(print_added_or_removed_nodes(r))
else:
    hou.ui.displayMessage(print_added_and_removed_nodes())
      

Let me know if this works out for you.   :)

Edited by jrockstad
  • Like 2

Share this post


Link to post
Share on other sites

That's a nice script, but it doesn't tell you if things like parameters on nodes have changed. Using the "as code" method looks at everything in the networks. Using a list of nodes could work depending on the needs of the workflow.

Share this post


Link to post
Share on other sites

That's a nice script, but it doesn't tell you if things like parameters on nodes have changed. Using the "as code" method looks at everything in the networks. Using a list of nodes could work depending on the needs of the workflow.

 

Ah, yeah, looking back at the original post it's not perfectly clear if he's referring to differences in the overall node network, on parameters, or both. It seems like my current script could be a good jumping off point in any case, since it already has the ability to filter the list of nodes to check based on if they're shared between both networks. I definitely had fun writing that script so I'll see if I can tweak it a bit. 

  • Like 1

Share this post


Link to post
Share on other sites

Guys... Amazing answers.. Thank you both very much... I was hoping to find out the following .. Extra nodes, parameter changes and possibly dependencies too... Basically as much info as poss...

Thanks again I will try both options

Share this post


Link to post
Share on other sites

Modified version of my script, now including parameter changes:


# Houdini Python shelf tool for comparing node networks
# Prints changes in networks followed by changes in parameters

# Usage: Select first network, shift-select second network, launch tool

# Network comparison functions

def get_node_names(networks):
    node_lists = ()
    
    for network in networks:
        nodes = network.children()
        node_lists += (set([node.name() for node in nodes]),)
        
    return node_lists

def print_added_or_removed_nodes(a_or_r):
    if a_or_r == 'added':
        nodes = list(network_b.difference(network_a))
        message = "Nodes added to '{}': \n\n".format(net_b_name)
    else:
        nodes = list(network_a.difference(network_)
        message = "Nodes removed in '{}': \n\n".format(net_b_name)
        
    if nodes != []:
       nodes.sort()
    
    for node in nodes:
        message += "    " + node + '\n'
        
    return message
    
def print_added_and_removed_nodes():
    message = print_added_or_removed_nodes(a) + '\n' + \
              print_added_or_removed_nodes(r)
              
    return message

# Parameter comparison functions

def get_parms(networks, shared_nodes):
    parm_dicts = ()
    
    for network in networks:
        node_parms = {}
        nodes = network.children()
        for node in nodes:
            if node.name() in shared_nodes:
                parm_tuple = [(node.name(), node.parmTuples())]
                node_parms.update(parm_tuple)
        parm_dicts += (node_parms,)
                
    return parm_dicts
    
def compare_parms(parm_dicts, shared_nodes):
    message = ""
    a_parms, b_parms = parm_dicts
    
    for node in shared_nodes:
        a_parm_vals = []
        b_parm_vals = []
        parm_labels = []
        
        for parm_tuple in a_parms[node]:
            for parm in parm_tuple:
                a_parm_vals.append(parm.evalAsString())
                parm_labels.append(parm.name())
        for parm_tuple in b_parms[node]:
            for parm in parm_tuple:
                b_parm_vals.append(parm.evalAsString())
        
        if a_parm_vals != b_parm_vals:
            message += "Changed parameters in node {}:".format(node) + '\n\n'
            for val in range(0, len(parm_labels) - 1):
                if a_parm_vals[val] != b_parm_vals[val]:
                    message += "    Value in '{}' for '{}': {}".format \
                               (net_a_name, parm_labels[val], a_parm_vals[val]) + \
                               '\n' + \
                               "    Value in '{}' for '{}': {}".format \
                               (net_b_name, parm_labels[val], b_parm_vals[val]) + \
                               '\n\n'
                
    return message
    
# Script start

networks = hou.selectedNodes()
net_a_name = networks[0].name()
net_b_name = networks[1].name()
network_a, network_b = get_node_names(networks)

nodes_added = network_b.issuperset(network_a)
nodes_removed = network_a.issuperset(network_
shared_nodes = list(network_a.intersection(network_)

parm_dicts = get_parms(networks, shared_nodes)

a = 'added'
r = 'removed'

if nodes_added:
    hou.ui.displayMessage(print_added_or_removed_nodes(a))
elif nodes_removed:
    hou.ui.displayMessage(print_added_or_removed_nodes(r))
else:
    hou.ui.displayMessage(print_added_and_removed_nodes())
    
hou.ui.displayMessage(compare_parms(parm_dicts, shared_nodes)) 
   

There's definitely a lot of room to polish it up, and in particular I would like to add:

 

- Option for user to choose whether they want to see node changes, parameter changes, or both

- Option to print output to file 

- More efficient / readable output, especially for parameters

 

...but for now, it does exactly what it says on the tin.  :)

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites

@jrockstad

Hi I tried to use the code as is its throwing syntax errors

Quote

 

SyntaxError: ('invalid syntax', ('tool_6', 23, 15, '        message = "Nodes removed in \'{}\': \\n\\n".format(net_b_name)\n'))


 

 

I tried fixing it but got another syntax error....

(network_) to (network_b))

 

Quote

SyntaxError: ('invalid syntax', ('tool_6', 94, 12, 'shared_nodes = list(network_a.intersection(network_)\n'))

I tried fixing the second error

nodes_removed = network_a.issuperset(network_
shared_nodes = list(network_a.intersection(network_)

to...

nodes_removed = network_a.issuperset(network_b)
shared_nodes = list(network_a.intersection(network_b))

Now the code runs but shows empty message window...

Can you have a another look at this code...It will be very useful...

Thanks,

Rama.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×