# Setting Compound Layer Function (Python Script)

**URL:** <https://forum.dynamobim.com/t/setting-compound-layer-function-python-script/18106>\
**Category:** Revit\
**Tags:** clockwork, python\
**Created:** [January 12, 2018, 9:41pm UTC](https://forum.dynamobim.com/t/setting-compound-layer-function-python-script/18106 "2018-01-12T21:41:47Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Chad\_Clary](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/chad_clary/32/10510_2.png) [@Chad\_Clary](https://forum.dynamobim.com/u/Chad_Clary)\
**Post date:** [January 12, 2018, 9:41pm UTC](https://forum.dynamobim.com/t/setting-compound-layer-function-python-script/18106/1 "2018-01-12T21:41:47Z")

</div>

I’m trying to put together a graph to set the function of layers in compound families (walls, roofs, floors, ceilings) and am stuck on the actual implementation of setting the function. I’ve shamelessly hacked up the **FamilyType.SetCompoundLayerMaterial** node from Clockwork and managed to restructure the node itself (woo!) and have managed to get the python to set the function **IF** I force it using MaterialFunctionAssignment.Substrate (or Finish1, Structure, etc.) However, that isn’t very useful long-term since the function might need to be something different depending on the family.

So - I’m obviously missing something in the Python code itself on how to allow the Layer Function to be an input and then executed based on the input but I’m stumped. Long term goal with this is to be able to filter everything by the material (i.e. 1/2" Metal Furring) and have all layers that have that material be set to a particular function (i.e. Substrate); however the application could easily go in a variety of other directions.

Stuff I’ve looked through that helped some:

> **[MaterialFunctionAssignment Enumeration](https://www.revitapidocs.com/2018.1/1cbeb006-f7a2-f6d2-491f-faa0b9a006fc.htm)**
>
> Online Documentation for Autodesk's Revit API: 2015, 2016, 2017, 2017.1, 2018

> [@Set Wall Compound Layers Function](https://forum.dynamobim.com/t/set-wall-compound-layers-function/4028):
>
> Hello, I was wondering if someone has already run into this topic. I am currently trying to automate the process of changing Wall Compound Layer functions to be able to change them from Finish to Membrane. I am currently using the clockwork nodes FamilyType.SetCompoundLayerMaterial and FamilyType.SetCompoundLayerWidth, nevertheless there is no node to set the Function of the layer. I have tried to modify the FamilyType.SetCompoundLayerWidth node to change the Function of the layer instead of t…

The overall graph (currently only worrying about the function, the Substrate text in the code block doesn’t do anything at the moment.)

 ![SetCompountLayerFunctionGraph](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/d/7/d762c218c3ba68253e08927899c3fb6e1120e602.png)

The hacked-up node:

 ![SetCompountLayerFunction](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/2/a/2aaa53835a99bade34112b8bc2291a0a46954b7e.png)

The even more hacked up Python:

 ![SetCompountLayerFunctionPython](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/4/c/4cc9e167a718416c643002f62cf5deba9712ff39.png)

The code itself:

```
#from FamilyType.SetCompountLayerWidth
#Clockwork Package
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument
famtypes = UnwrapElement(IN[0])
indices = IN[1]
function = IN[2]
booleans = list()
counter = 0

TransactionManager.Instance.EnsureInTransaction(doc)
for ft in famtypes:
	try:
		cs = ft.GetCompoundStructure()
		cs.SetLayerFunction(indices[counter],MaterialFunctionAssignment.Substrate)
		ft.SetCompoundStructure(cs)
		booleans.append(True)
	except:
		booleans.append(False)
	counter += 1	
TransactionManager.Instance.TransactionTaskDone()

OUT = (famtypes,booleans)

```

TL;DR: How can I make the **MaterialFunctionAssignment** an input that will read a value (probably a string?), and pass it through the Python to modify the family?

🍻

---

<div class="post-metadata">

**Author:** ![Tomasz](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/tomasz/32/66785_2.png) [@Tomasz](https://forum.dynamobim.com/u/Tomasz)\
**Post date:** [January 13, 2018, 9:30am UTC](https://forum.dynamobim.com/t/setting-compound-layer-function-python-script/18106/2 "2018-01-13T09:30:37Z")

</div>

```
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import MaterialFunctionAssignment

material_function_string = IN[0]

if material_function_string == '0':
    material_function = MaterialFunctionAssignment.Structure

OUT = material_function
```

---

<div class="post-metadata">

**Author:** ![Chad\_Clary](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/chad_clary/32/10510_2.png) [@Chad\_Clary](https://forum.dynamobim.com/u/Chad_Clary)\
**Post date:** [January 15, 2018, 3:20pm UTC](https://forum.dynamobim.com/t/setting-compound-layer-function-python-script/18106/3 "2018-01-15T15:20:03Z")

</div>

Thanks.  
After stumbling around this for a while I’m a bit lost (my python knowledge is… limited); I’ll try and work on it a bit more today and come back with some actual questions rather than just stating I’m lost.

🍻

---

<div class="post-metadata">

**Author:** ![Chad\_Clary](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/chad_clary/32/10510_2.png) [@Chad\_Clary](https://forum.dynamobim.com/u/Chad_Clary)\
**Post date:** [January 15, 2018, 10:34pm UTC](https://forum.dynamobim.com/t/setting-compound-layer-function-python-script/18106/4 "2018-01-15T22:34:43Z")

</div>

A couple questions/thoughts:

1. What’s the benefit of using IF rather than TRY in this instance? I looked them up and it seems the main reason to use one or the other has to do with error handling, but I don’t quite have a full grasp on it.
2. Does the IF nest inside of the TRY statement or is it a replacement? I’ve tried both but haven’t had much luck…
3. The 0 in the _if material\_function\_string == ‘0’_ string corresponds to the 0 in the _IN[0]_ statement correct? So if I have multiple inputs that could be a 2, as long as both of them are 2?
4. The bigger issue I’m running into is your code still forces the assignment by using _MaterialFunctionAssignment.Structure_. In theory what I want to achieve is MaterialFunctionAssignment.(material\_function\_string), where the (material\_function\_string) could be Structure, or Substrate, or FInish1, etc.

In the attached version I fumbled through the Python (script from string) and at least managed to get it to not error, but the OUT on the node returns the name of the wall, rather than the function, which probably relates to item 3 above…

🍻

 ![WallLayerFunction](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/1/b/1b214fd073ec9325c53b52b2a12833ca0cfe880c.png)  
[Walls-Layers-Function.dyn](https://forum.dynamobim.com/uploads/short-url/3MD2ZEYLWbxjgMqiOR9PeWilAEe.dyn) (6.9 KB)  
[FamilyType.SetCompoundLayerFunction\_chad.dyf](https://forum.dynamobim.com/uploads/short-url/AdCnJJefNbIFhq0M9XOHJACLzUp.dyf) (13.4 KB)

---

<div class="post-metadata">

**Author:** ![Tomasz](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/tomasz/32/66785_2.png) [@Tomasz](https://forum.dynamobim.com/u/Tomasz)\
**Post date:** [January 16, 2018, 9:23am UTC](https://forum.dynamobim.com/t/setting-compound-layer-function-python-script/18106/5 "2018-01-16T09:23:46Z")

</div>

1.The benefit of using ‘if’ is creating a conditional statement. We want to assign _MaterialFunctionAssignment.Structure_ to _material\_function_ if the given **string** on the input is equal “0” (as a letter). You can change “0” to “structure” for example. Then you can add another if statement:

```
if material_function_string == 'structure':
    material_function = MaterialFunctionAssignment.Structure
if material_function_string == 'finish':
    material_function = MaterialFunctionAssignment.Finish1

```

2 - Both ‘if’ and ‘try’ can be nested inside each other but they have two different purposes. Please see Python documentation.

3 - No, it does not correspond. The IN[0] is assigned here:

`material_function_string = IN[0]`

Wherever you see ‘material\_function\_string’ you shoud read it as ‘IN[0]’. You only change value you feed to input.

4 - See point 2.

---

<div class="post-metadata">

**Author:** ![Tomasz](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/tomasz/32/66785_2.png) [@Tomasz](https://forum.dynamobim.com/u/Tomasz)\
**Post date:** [January 16, 2018, 9:39am UTC](https://forum.dynamobim.com/t/setting-compound-layer-function-python-script/18106/6 "2018-01-16T09:39:04Z")

</div>

Try:

 ![simple](https://us1.discourse-cdn.com/flex022/uploads/dynamobim/original/3X/d/8/d80fcba49491ba576e617b5a612a902d2d878eea.png)

---

<div class="post-metadata">

**Author:** ![Andreas\_Dieckmann](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.dynamobim.com/andreas_dieckmann/32/365_2.png) [@Andreas\_Dieckmann](https://forum.dynamobim.com/u/Andreas_Dieckmann)\
**Post date:** [January 16, 2018, 10:28am UTC](https://forum.dynamobim.com/t/setting-compound-layer-function-python-script/18106/7 "2018-01-16T10:28:11Z")

</div>

Regarding if/else vs. try/except:

> <https://stackoverflow.com/questions/6186340/how-to-decide-between-using-if-else-vs-try-catch>
