all right thank you everybody for coming
out tonight I want to thank the San
Francisco dynamo user group committee
for putting these presentations together
you know I've been coming to them
regularly I'm really happy to be able to
show dynamo with Python it's something
we use in our office and both Dennis and
I we really love it so so my name's I'll
go ahead and introduce myself
my name is Danny Bentley I worked at
Skidmore Owings and Merrill I'm a
structural BIM designer and drafter I'm
also a youtuber with channels for the
Revit API and getting started with
Python and dynamo and the code that I'll
be presenting today as well as the stuff
on my channel and even projects that I'm
working on is all available on my github
and you're welcome to check it out copy
stuff paste it tries things ask me about
it oh I'm sorry I also work at som as a
digital designer but in the architecture
department I'm a licensed architect
thanks for having us again I'm not
purging from the barre I'm a transplant
from DC it's nice to be able to they
didn't have that kind of thing in DC so
it's nice to be able to attend Spencer
alright so we're probably asking
ourselves why Python right like we just
got started with dynamo now we have the
whole new language that we have to learn
so the language is actually a great
language just to get started because the
syntax tweets really well it's a good
place to get started the other thing is
if you use it with Dinah more it
actually makes your flow a lot more
compact because a lot of times when I go
into somebody's dynamos script it's huge
and you can compact it by knowing a
little bit of Python the other the other
great thing is now that dynamos actually
matured as a product and it's been
around for a while we have the ability
to find a lot of samples and just
knowing how it's structured and the
syntax we can edit it and then bring it
and use it as our own so the language
was actually developed
or scripting so exactly what we're using
it for dynamo but since then it's
involved to be able to do full
applications without a problem so
hopefully today what we'll do is we'll
kind of do an introduction of the Python
language and then we'll do we'll walk
through the the syntax of the dynamo
Python node and then what we'll do is
we'll introduce the Revit API as well
and have some examples so python has
five datatypes and the very first data
type that it has our numbers and so as
integers long floats and complex numbers
and that number is actually that number
one is going from the right to the left
so that one is being assigned to the
number over there the other one that it
has a strings and strings are just texts
or series of characters the great thing
about Python is you don't need to
specify it can be either single quote or
double quote inside the string it
doesn't matter the other one is less so
everybody who's now worked with dynamo
is probably pretty familiar with list
list you can either merge them you can
remove stuff you can index them and
they're basically the same thing in in
in a Dinah and Python
the one other thing that does actually
have is called a tuple and the
difference between the list and the
tuple is that the tuple is read-only so
if you have something in your code that
you don't want to get manipulated you
can actually put it in there and the
syntax a little bit different what the
list has brackets the the tuple has
parenthesis so the very last one that it
has our dictionaries and dictionaries
have a unique key they're followed by a
colon and then a value separated each
one by a comma so the great part is you
can actually get
your value by looking up the key so I
use these actually a lot like this this
is an example of how I use it so we have
structural engineering software that has
a bunch of element IDs and what I do is
I use that as a key and in Revit we also
have we have parameters and I tie those
two element IDs as keys and then the
values R is applied flange sizes so then
I test the keys against each other and
then if they match then I test the
values against each other and if they
don't match if I have a wide flange from
the structural engineering software and
a Y flange in Revit that are different
then I swap them out so that brings us
to conditionals so conditionals are just
testing the code so here we're doing if
if the number is larger than 10 it'll
execute that line of code and that
little line of code needs that tab there
that indentation without that
indentation your your code will crash or
dynamo will actually give you a little
notification saying that your
indentation is is it'll give you a
little warning it says the indentation
is something about indentation the else
is is basically a default so if your if
condition isn't met you'll have an else
and that'll automatically be executed so
here if if my number is isn't larger
than 10 and that and that returns false
it'll automatically do the else
statement and run that and execute that
line a command line of code the eltz if
so here you can do the if statement and
test a condition and then if that
condition isn't met it'll check the next
condition so these are great if you're
if you're checking levels and want to
check the height of something if you're
trying to get certain pieces off of any
level you can always check the level
height using this conditionals or
anything actually you can check the
element name element IDs the the and so
these are these are two conditions and
they both have to be met in order the
for the line of code two
to execute so here if it has to be less
than ten and also greater than one so
this is kind of giving me a range and
since I'm feeding it a five it'll
execute that line of code the or does a
conditional or so it tests the first one
or the second one
and that's why python is great because
it just almost how you just you talk so
looping so you so if you have a list you
can execute a line of command for every
element in that list or item in that
list so this will execute until it runs
to the end of your list so here I have a
list of numbers 4 8 and 10 and I put
that in the node and the end
0 is the actual in 0 in my Python code
and I'm sending that list - my list now
I generate an empty list in order to put
the numbers that have got the executed
code into them so this will so for every
one of those it will add a 1 and dump it
into the new the new one and then and
then throw that out - to dynamo so the
while statement so this will test the
condition while something is running
true it'll it'll continuously execute so
while it's less than 9 it'll just
continuously run that code until it
matches until it hits 9 or let or until
it's equal or less than 9 it'll continue
to run so all right so a lot of times
we're writing we will be writing
something and we'll notice that we'll
write the same snippet of code two or
three times and you can actually take
this snippet of code out and put in a
little block of code called the
definition and the definitions the
syntax has def and then it could be by
you can put anything that your
definition is doing and the more
descriptive you are the better it is the
next time you come back and the and add
number is what what we call camel casing
and it's it's a
programming standard maybe not a
standard but it's commonplace because if
you put a space there that'll break so
you can't have any spaces but the only
way that you visually can recognize that
is by putting camel casing and then
inside the brackets I'll put two
arguments of what what things I'm
passing it in so it's exactly like the
node inside of dynamo we have the node
and on the left on the left hand side
we'll have the things that we're putting
into our node these are the exact same
thing actually that's what they are and
then I add the numbers and return the
sum so in so in Python then this is how
you would use it right so in in your
other snippet of code you would have
dynamo send in two numbers and then you
would then use your reusable code to add
those two numbers add them and it would
return the result to you and then you
can send that result out to to dynamo so
the all right this next part is it's
looking at the first half a page of the
dynamo node and I think a lot of times
what what makes people afraid of like
what what the note is is this first half
and the first half is actually is you
can copy and paste that code in because
it's so so many times you'll be using it
and it's basically the references or the
libraries from the Revit API from the
Dynamo API and from the dotnet framework
and these are these are what is given to
us from those developers to use in our
code so the very first thing that you'll
see in your Python node will be this
import CLR this is the common language
runtime and all it does is it turns your
dynamo script or your Python script into
machine language and the really great
part about this is you don't actually
have to do anything
dynamo does all the heavy lifting for
you and it'll just execute your your
your your node so the
one that you'll see is the Revit service
the Revit service is is what holds your
document manager or the instance or the
session that you're working in that that
Revit file is being held by by the Revit
services and this is how you call the
current document that you're working in
is with this library the other thing
that you do call with this is from Revit
services are the transactions the way
Revit works is it holds a queue of
everybody and as somebody gets put up on
the queue or in it at the beginning of
the line it'll execute that person's
code so if this allows you to get into
the queue and then if been 360's doing a
bunch of stuff on idling id8 products or
anybody's trying to talk to the Revit to
rev it at that time
it'll stop everybody during the command
that you're working while you execute
your line of code and and make a change
inside of Revit and then after you're
done you will close it off and Dennis
will go into a little bit more on that
as well if that's confusing so the next
thing that you'll import is the Revit
API and from Revit or Autodesk Revit
database you import and the asterisk
means that you're just gonna import the
whole library you you can import
individual pieces of it but but
sometimes it's just as easy just just do
the the asterisks in just so I'm just
gonna bring everything in but this will
the API allows you to do modification
create elements inside of Revit and then
the Revit a PI UI is all the push
buttons inside of Revit so the really
nice thing is that the developers have
allowed us to be able to push those
buttons programmatically if if you need
to so right now I'm working on a small
application for our office that we need
to hit that scene command and you know
that sync dialog that comes up and it
says if you want to sync it ok or if you
know it canceled well you can't actually
run that without pushing that button so
we
go through the Revit API UI and and then
push that button so okay the next thing
is the Revit node so the the this is
okay the Revit API is written in in in
feet and whole feet right and the the
Dynamo is written in meters so we got to
convert them but the really nice part
about it is that the developers have
already written in a library to do that
so we don't ever have to worry about
that this if you import this library you
can cast them back and forth as long as
you as long as you know if you're using
a point from Revit or a point from
Dinamo you can cast them back and forth
the other thing it does is a lot of the
elements that that you send in is called
there they're called boxed and you need
an unboxing so you'll be unwrapping and
that's in the and the the code the
snippet of code that you'll use is
called unwrapping so you'll send in all
your levels from Revit and they're all
wrapped or boxed and you need to unbox
them in order to work with them and this
this library actually will let you do
that with just typing in unwrapped the
the other ones the proto geometry which
has has everything that you need to
prototype in dynamo and we're all
probably well those of us who've been
working with dynamo are probably
familiar with all those great blue lines
so you can generate these through Python
as well with this library and then the
very last thing that you can import if
you like is the system and the system is
basically the dotnet the.net language
and this will allow you to do list
collections lambda expressions and other
other things so those are those are the
bulk of what you'll see the first half
of your note to be but you can also
reference a lot of other libraries
as such as excel and and and other
things if you want to tap into them
through their through their API so this
brings me to the revenue API so the
other nice nice part about the Revit API
is it's not written in Python it's
written in c-sharp and we have to talk
to it through through Python so the way
the Revit API is kind of structured is
that it it holds this sheet of reusable
code the the in Python we call
definitions and in in in c-sharp they're
called classes and each one of these
classes has properties which which allow
you to set set them there'll be like the
property of the long name while type and
they're there they're all the similar
properties as in Revit and then there's
the the methods which allow us to do or
perform an action on whatever that
element is as far as like flipping it or
or doing something like that so probably
the best way to to show you how Revit
interacts with or the Revit API in
c-sharp interacts with python is to to
walk through a really simple example in
python so what we'll do is we'll just
you see the syntax structure of creating
of just a real simple wall now I know
none of us would write this in Python
like like we wouldn't write it but it's
a good starting point even though even
the Dynamo flow is really simple right
like we have two points we're creating a
line or a curve and then in in there
we're gonna send that that curve to
generate a wall we're going to get some
inputs from the user of the base level
the top level and the wall type so this
this very first half or half a page is
is all the
all the references that we just that we
just got so we got the the Revit node
Revit service and the Revit API up there
so the very first thing that we're going
to get is the document from the the from
the rabbit services and we'll get the
instance of the current database
document which is the dot accession of
rabbit that were in in that file that
we're working in and then we're sending
it to to the left-hand side to that word
doc underneath that will be getting the
the input from from the Python node and
we'll have three inputs will will have a
base level a top level and a wall type
and these are Revit elements so in order
to work with them in this dynamo dynamo
node is we're gonna have to unwrap them
and that and that's where that Revit
node library comes in in order for us to
unlap it and then here we're actually
going to generate to Revit API X Y Z's
using the X the Y and the Z value and
then we're going to tell Revit that
we're going to do something we're going
to start a transaction inside of Revit
and here we'll use the document that
we've that we've gotten from our
document manager and we'll send that in
as an argument inside that to ensure in
transaction and then we'll generate a
curve or a line by sending our two
points in and it'll throw back a line
for us so here's where we create create
the wall and this is this is now Revit
API kind of working in dynamo the the
API from c-sharp there's a great
documentation that I use a lot called
the Revit API Docs and in there you can
look up stuff in order to find it
because every not everything is
as easy as you would think in the API
Python is easy the Revit API is a little
bit more complex so if you in order to
create a wall the you need a handful of
things we need the document that we so
we have the document from document
manager we we need a curve that we just
generated the curve we need an element
ID of the base level so we're going to
get the level that was sent in through
the the dynamo node and then we're going
to get a dot ID which which is our
parameter and then the very last thing
is asking for is a boolean value of
either if it's a structural wall or a
non structural wall and then we met
that's it'll generate a wall for us but
we need to set a couple parameters for
it
so here what we'll do is we'll set the
wall type and the they they've we've
sent it in through dynamo and we've also
we've also unwrapped it in order for us
to be able to use it so now we can just
send it in the the the other thing is we
need to get a parameter and the built-in
parameters are everything that the Revit
provides to us out of the box that has a
parameter and so all the wall parameters
that we would have out out of the box
Revit the the only problem is that when
the API was probably written they
weren't heavy Revit users so a lot of
the times what we know in our mind is
rabbit isn't exactly how they're labeled
in in C in the a and the Revit API so
again we go to the Revit Docs and just
for the top constraint the the actual
way they labeled it is called a wall
height type and that'll give you the the
top constraint for to set that so that
that top constraint is now parameter and
what you'll do is you'll do the dot set
and you'll send in the top level ID yes
we'll go into a little more detail on
parameters the later good thanks and
then the very last thing we'll do is
we'll close off our transaction that way
we're ensuring that the Revit knows that
we've finished and allow them to be able
to do something something else so this
is kind of what the syntax look like so
hopefully now that youyou kind of walked
slowly through this the next time you
see something like this you'll at least
know that the first half of it you can
probably you can probably just copy and
paste it in because it's all just
reusable code and then you'll know where
the inputs are where what's being sent
in and how it's being sent in and then
you'll know kind of a little bit what
they're trying to build and you know
exactly where the transaction is
happening or where the where where the
actual code that you want to concentrate
in as far as like building something so
accessing elements through the Revit API
so this this is the only way you can
access elements through the Revit API
and Dinamo's provided an incredibly good
note for it where you can just select
the category that you want and it will
just grab everything for you and send it
out but you can also do it in Python
pretty easy through the Revit API so
like I said that this would be the whole
piece of code it looks intimidating but
in reality this is everything that we're
really concerned about is this the the
rest of it like I said hold on to a txt
file go to my github I have a bunch of
those those references copy and paste
them in but what you do is you get the
document from the document manager and
then from the filter element collector
which is the the method that we're going
to use we'll go ahead and send the
document that we're using or the current
document that we're at and then from the
collector we're going to get the of
class and we're getting that wall and
then we'll just get all the
from from the project and that that's
how easy it is so the nice part about
this is is now that we know how to get
pieces from the from from rabbit we can
also use our looping and our conditional
if statements to check things so this is
this this one's exactly the same as the
node of category so what we'll do is
we'll do the filter element collector
again and we'll send in the document and
this time we'll do of a category and
then we'll get the built in category of
the walls and sometimes they're labeled
a bit different so it's good to go into
that Revit API Docs on their website and
look up the right name but now that we
have the whole list in that built in you
could iterate or loop over it and check
each one of those for the specific type
that you want you could check the length
and you could check just about anything
in that in that in that loop and then
the conditional if statement so here's
we'll do for every wall or W in our
built-in which is our list well we'll
check if the wall name equals SW 48
which in at som we call those shear wall
48 inches and then we'll append it or
add it to an empty list that we've
generated up top and at the very end
send those those walls out to dynamo in
order for us to do some other work with
it so this is this is why I love using
both of them you can kind of as you get
more comfortable with one or the other
you can really leverage eat one or the
other and then we have what what's the
filter element so the filter element
collector are collecting things in Revit
have two ways of collecting things you
can either do a quick quick quick
collection or what they call a slow
collection but both of these are
extremely fast and they're way faster
than doing it doing any other way and
then the the slowest way is the looping
over and testing each one through the
dotnet framework
so this the there's there's a lot of a
lot of them there's a lot of ways to do
the the slow filtering logic filters and
and and a lot of them but they would
discredit by itself be a whole other
topic but I thought I would introduce
you with just one which is filtering
where it passes so if I wanted to get to
two categories at the same time I can
build a list of categories and then I
can get the walls and the doors and then
I use the filter element multi category
filter and send in my list and now this
is a filter so inside a filter element
collector in in the document which I'm
actually working on I if it passes that
conditional of those two it'll put them
into an element and send them back to me
so that way I can get two categories at
the same time all right oh it I'll let
Dennis yes so so we have a lot of tools
here but a lot of what we want to do in
Revit is in the parameters right whether
that's the wall height or the mark of
the wall and so we're gonna go into a
little more detail and how you find
parameters for an object and how you set
those parameters and so most of you are
probably familiar with the ways that
that's done in dynamo you'd have your
item on the left here you used your
element parameters to find all the
parameters and then you can get a
certain parameter at whatever index you
want like the mark here at index 10
alternatively if you know the name of
your parameter you can use the get
parameter value by name input your your
mark string here and it gives you the
value of the parameter and so before we
get into actually the code of it I
thought I'd give kind of an overview
because it can be a little confusing so
we talked earlier about how things are
of classes right in in the API and so
classes as we said have properties and
you would think at first that the Letson
the height of a wall might be a property
of the wall class however tech a lot of
a lot of parameters are actually their
own classes so you might have a
parameter class that represents the wall
height or the mark there are some
properties sorry there are some
parameters that our property is like the
name but a lot of them are actually
classes so so how do we do that so here
let's say we have a wall a typical wall
class which you can see the similar
transition in dynamo there and so the
walls have a method called get
parameters so similar to in dynamo you
have this element parameters and in in
Python that will return you a list of
all the parameter classes that are
associated with this wall same isn't in
dynamo and then you'll select an item
from that list a parameter and the
parameter class has a method where you
can get its value so there's as string
method returns the string value of that
parameter and so there are actually
three common methods to find a parameter
for a certain class the easiest way is
to use this method called lookup
parameter so you basically take your
class in this case a wall class we use
the lookup parameter method and in
between the parentheses of the mat that
we put in a string representing the name
of the parameter and that will return to
us the first parameter that matches this
name and so this is obviously pretty
simple right as long as you know the
name of the parameter you're good
the second method is called get
parameters and also in parentheses you
return Nate you entered string
representing the name of the parameter
you
but this method actually returns to you
a list and so in this case you'll see I
have an index of zero to select the
first element in that list in most cases
this should return a list of just a
single element however let's say
somebody was doing something they
shouldn't have and they may be copied a
family from one project to another and
now you have two parameters with the
same name this could have multiple
values there could be multiple
parameters in this list in the last way
that Danny had mentioned earlier is this
get underscore parameter method and this
method this method is how you can get a
parameter that is built into Revit by
default something like the fire rating
or the mark the benefit of this this
method is that you can find it in the
you've got API Doc's online all the
built in parameters but the built in
parameter method is really stable so
like this the name of this parameter
isn't going to change through versions
but it could in like if you were to use
the lookup parameter additionally this
will work in any language whereas the
lookup parameter obviously only works in
English so this is a much more stable
way to find a parameter if you you know
needed to support multiple languages for
example and so all these three different
methods will return you the same thing
you get the same parameter no matter
what you use and so how do we get the
value of that parameter so there each
parameter has different methods
depending on what format of information
you want so if it's a string parameter
you could use the add string method the
as integer method will give you a whole
number the as double will give you a
float and a decimal number
so as double would be good for something
like an area which might have a number
of decimals yes no parameter is really
unique and you can use this
value string method and that will give
you a string that says either yes or no
to represent the yes or no parameter
okay so as an example I'll create an
empty list here called marks and I've
already created a filtered element
collector
it holds all the walls so we're going to
iterate through each wall in that
collector and we're going to find the
mark parameter and we're going to get
the value as a string and put it into
that marks list so this would output a
list of all the marks in in the the
walls and so so that's how you get a
parameter what about setting them so
setting them is pretty simple first you
have to find the parameter using the
same methods as before we here we use
lookup parameter or finding the mark and
then we just do dot set and in
parentheses we we tell wherever we tell
Python what we want to set that value to
and so you can see the same sort of
workflow in dynamo is you have your
element set parameter by name node and
you input your parameter name and your
value so transactions so as you
mentioned earlier transactions are how
you make changes to the model a lot of
you are probably familiar with
transactions you need to do use them in
DINO in order to change anything so you
have your transaction start node and
your transaction end node and as Danny
mentions the transactions are helpful as
to group changes together but they also
help Revit determine who's editing an
object so when you start transaction it
goes to like the central model and it
finds out if those elements are editable
yet and if they are you know it lets you
do that and so it creates a queue and it
goes through all the transactions to
make sure that nobody is editing the
same thing at the same time and so how
you do that in Python so in Python you
create an instance of the transaction
class so here we have T is equal to this
transaction class we feed it the current
Revit
document so we're not you know putting
the transaction in a separate model and
we give it a name this the name is
really more for your own reference but
as a bonus this name also appears in
your undo list so it's easier to
identify so then you'll you'll start the
transaction with the start method you'll
do whatever you want to do in this case
we're deleting element and then after
you're done you want to commit your
transaction with the commit command and
this you know finalizes your transaction
and then you'll want to dispose of it so
disposing of it is really just kind of
getting rid of it
in your computer's memory so that it can
use that memory to do other things it
doesn't you know it doesn't remove it
from your list your undo list like you
can still undo that transaction but it's
good practice to dispose of your
transactions after you're done with them
if you don't commit your transaction
you'll get a warning and you and python
won't let you actually finish what
you're doing that's a good question so
generally it's better to group
everything that you want to do into a
single transaction that includes things
both inside and outside of dinamo
usually usually you'll want to just
group everything in a single transaction
so it's easier to undo because otherwise
you'll have like you could have like
five different items on your undo list
and it could take a little while to
process everything there's easier just
to group it into one and so to further
expand on that you don't have to do your
transaction in Python you can start your
transaction in dynamo then run your
Python script and finish it in dynamo
notes so if you have if you have a bunch
of changes you're making both in dynamo
nodes and in Python you can just do it
outside and just have one start and end
note
when you earlier with causing other
transactions that would be cute sweet
sort of pause those the transaction not
really so what I was referring to there
is just like every time anybody edits a
model whether that's you know in Revit
itself whether that's in dynamo they
send a transaction to the central model
so it's like it's just how rabbit
handles changes to the model okay so I
thought I would go over an example now
that we have all these tools a simple
example that uses everything that we've
learned so far so I've recently come
into an issue where I've noticed the
number a lot of numbered dimension
styles in my project you see here this
is one two three four and apparently
three is duplicated I I think these get
into the model either through like I
heard they might get in through we're
having families or corrupted families
anyway this isn't something that the
users created but somehow these
dimension Styles get deleted and
unfortunately a lot of them I can't
purge out manually and there's no like
list of dimension styles in the browser
so it's difficult to remove them however
we can remove them pretty easily with
dynamo so why would you want to use
Python it instead of dynamo to do this
well this sort of transaction is a lot
easier to do with Python because we have
the ability to parse strings in dynamo
here you know you can get all your
dimension types you can find their name
but it's difficult to sort through the
parse the names like to say if this name
is only a number then keep it and will
delete it later but it's much easier to
do that sort of thing in dynamo see the
in Python and so so let's just go
through the code here so the first part
as Danny had mentioned is mostly just
references we're importing all these
different things
that won't go over it again so then
first will wanna do is will get the
current document so we know what we're
reading and we'll create a filter
element collector and in this case we
want to find the class dimension type to
get all the dimension types so the next
one we'll do is we'll create an empty
list to contain all the dimensions we
want to delete and then we'll iterate
through our filter element collector for
each of the dimension styles so for each
of these dimension styles we'll check
the name first so we'll do the we'll
look up the type name parameter of the
dimension style and we'll get that as a
string then we'll take that name and
we'll see this is actually some special
text processing that we can't do and I
know so what this does is that the name
is technically a string and so strings
in Python have a method called replace
which will allow us to replace this
space here with an empty string so it
basically removes that space and we're
doing this because I noticed these
dimension styles start with a space and
then the number and so in order to
convert it to a number I'm removing that
space first and strings also have a
method called is digit that will
determine if this this string can be
turned into a number and so if this is
true then we'll pend that dimension
style to our list to be deleted and so
then we want to start our transaction
using the document that we have we'll
give it a nice name and we'll start that
transaction then we want to iterate
through our dimensions to delete list
and for every dimension we'll just the
document that we grabbed earlier
actually has a method called delete and
it takes the element ID so most classes
in the API have a met a property called
ID which gives you the element ID so
that's what we're doing we're taking the
element ID and telling the document to
delete it and then we're committing that
that change and we're disposing of our
transaction and finally in the output
will output all the
of dimensions that we delete and so in
total this can be accomplished in about
sixty lines of a Python script which is
pretty simple and it's a really
effective way to get rid of things that
otherwise are difficult to remove so
that's kind of a kind of a boring
example I wanted to show something a
little more exciting so that this is
this is a problem that I had where
sometimes it can be difficult to
identify just in a regular elevation
what kind of window types you have so I
put together a script that goes through
all of the in this case curtain walls
and curtain panels and it will assign a
color just in this one elevation to
those windows based on their mark so
that I can visually see you know how
many different window types that we have
or if we forgot to apply a mark to a
certain window and so that would be also
difficult to do I think in dynamo you
can see this sprawling dynamo script
here I think the difficult part see it's
fairly easy to get our it's very easy to
get our walls and get our curtain panels
and you know combine them into a list
but I think it's difficult to filter out
the ones that don't have marks and then
it's it's difficult to assign to create
a color for each unique mark which is
what here and then it's I don't it's
difficult to override the surface
pattern of that element in a particular
view so rather than that we can do this
in dynamo so again we start by loading
all of our references so this I want to
call this out this is a function which
Danny mentioned earlier is our reusable
portion of code so something that we're
going to be doing a lot in this script
is creating a color and so we have this
function here called random color it
doesn't take any input but basically it
creates a color which is rich here
there's a in the Revit API there's a
method to create colors and so we're
feeding it
three random colors three random RGB
values at Python comes with a library
called random so here we're importing
that library random and it allows us to
the random library has a method called
random range the to randomly generate an
integer between two values in this case
0 and 255 it excludes 256 and so this
will create any color a random color for
us exactly this is exactly the same
thing as as the definitions in the
codebook okay and so then we first want
to start Oh
also mention um it's generally good
practice to put all of your definitions
at the front just as kind of listing out
everything that you'll need in the
beginning and then doing your actual
code later okay so then we want to get
the document again so we're working in
the right place we'll start by creating
a filter down and collector collecting
all the wall classes then we'll create
some empty list to contain all the
window families and a list to contain
all the marks so we know whether or not
a mark is already used okay so what
we'll do first is we'll iterate through
our wall all of our walls in the project
and we will first find the wall type so
the filter element collector here is
getting all the walls but in this case I
only want the curtain walls right
because they're the only pieces that'll
it'll be in my brazing schedule and so I
get the type of the wall by using this
here I have the wall class here I'm
using the get type ID method and that
will return to me the element ID of the
wall type but I want the actual wall
type itself and so
the document has a method called get
element that takes an element ID so
we're getting the element idea of the
wall type and where we're getting that
here so then what we want to do is we
want to check if that's a curtain wall
and wall types have a method called kind
which will tell us what type of wall it
is in this case you can see this in
spelled out in the Revit API Docs but in
this case there's a wall type called
curtain so we want to make sure that the
wall type is equal to that kind okay so
if that's true if we do have a curtain
wall we want to find the mark parameter
so we're using the lookup parameter
method define the mark parameter and
then it could be the case that a wall a
wall type does not have a mark maybe we
we don't want to intentionally don't
want to give it a mark because it's not
actually a window type or a wall type
that we want to we want to track so here
we're testing whether the parameter has
a market value so we want to make sure
that the parameter does have a mark
value and whoa or rather or the de mark
value actually has some was sorry we
want to make sure that the mark value
has some value other than like an empty
string so we're testing that it exists
and that it has a value and so if that's
true if it's a curtain wall and if it
has a mark value we want to add it to
our list of windows and then lastly what
we want to do is we want check if this
mark value is already in our list of
marks so we're gonna say it is the mark
value as a string not in our list of
unique marks so if this isn't a mark we
know about we want to add it to our list
so we have all the marks in the project
it's like a special python type yeah and
it basically is equal to like none or
null or nothing I'm not entirely sure it
might be with CLR yeah I think you
almost have it with just the lro
completely blanket still use those I
think it is yeah okay so then we want to
do a similar thing for the curtain
panels so we have a filter dominant
collector in this case there isn't a
class for walls a sorry they did in this
case there isn't a class for curtain
panels so I have to use the built in
category of OSD curtain panel walls and
then again will iterate through the list
of curtain panels in that collector will
get the parameter the mark parameter
will make sure that that parameter has a
value and that it isn't set that the
this is set to none and if that's true
then we'll add it to our list of window
so this list now contains both walls and
curtain panels and again we'll check
that parameter value to make sure that
it isn't it make sure that it is in our
marks and if it isn't in the marks then
we'll add it to our list of marks so we
have all the marks okay and so then so
so now what we'll do is we'll create
empty lists for the graphics overrides
and the colors so colors are pretty
obvious there's just a list of all the
colors that did correspond to each mark
value but the graphics overrides is this
there's actually a class called graphics
overrides that you know when you click
on a Revit element and you do override
graphics in view by element and then you
change let's say the transparency or you
give it like a different cut pattern so
that is its own class so we have to
create that class that will later apply
oh and this
in this particular case the one input to
this node is a hatch pattern that we
want to use to override it with so then
so then what we'll do is we'll go
through all of our unique marks in the
project will iterate through that list
will generate a color for that mark and
then so the graphics overrides is a
dictionary and so the value of these the
key of the dictionary is going to be the
mark so if this is the market this is d
let's say it's D and we're going to
assign the value of that mark to this
new overrides graphics class and so then
after we've created that class we want
to set the fill color here set
projection fill color to the color we
created earlier and then we'll set the
pattern to the pattern that we defined
in our input and so then we'll iterate
through that till we have a color for
each unique mark in the project and then
we'll start our transaction as we didn't
past and lastly we'll we want to get the
current view in the project which is a
property of the document and we'll then
we'll iterate through our list of
windows so this is this includes our
curtain wall types and our curtain
panels and we'll first find the mark
parameter again except this time it'll
be a string so we're getting looking up
that parameter as a string I mean then
we'll in the view for each window we
will use this method called set
overrides and that we input the the ID
the element ID of the window and the
graphics overrides of the mark so this
will return if it's mark D the key is
mark D we input that key and it returns
to us the color that that mark is
supposed to be and then once we have it
related to that we'll dispose of our
transaction and output the windows and
we get the schedule so this is about
what was it this is about 120 lines so
it's a little long but it's still pretty
manageable and so when you finish this
you know but is a colored diagram of all
the different glazing types
and so I didn't want to have to manually
define like a hundred different colors
so that's why I use the random colors
but I guess it's not affected that is
every time you run it is different you
get different colors yeah all right so I
was I was here I was here last month and
I saw somebody using a the Alexa with
with with was it the Microsoft database
and I thought like I bet you could write
that in a one-page of code in Python and
I'm not gonna walk through it since
we're at the end but you can you can
actually get a Lexus skill set then then
you can actually download this thing
called and rock and it's basically just
the tunnel it it gives you a kind of an
HTTP tunnel between your computer and
the Amazon Revit services and then you
can use an ass flask to translate the
JSON file from from a like Alexa skill
set to to Python and then from Python
you can then take it into using a CSV
file take it into dynamo so if my
computer back at work is still running
we can try to see if if we can get it to
run so all right
Alexa ask the architect ask the
architect to say hello ask the architect
yeah again Alexa ask the architect ask
the architect to create points
I am creating the points for the Janet
Ashland sculpture Alexa ask the
architect hello what would you like to
ask the architect ask the architect to
create lines between the points that
that's one page of Python code so this
is this is it this is the all that all
the code that was required to do that is
is this it's available on my on my
github if anybody wants to play around
with it I I don't think it's that
difficult the the Alexis skill set is um
is is free and training it is actually
pretty easy these are these are kind of
the things that you would you would ask
it to do and then any at the bottom here
is like what what people would say right
like you not every time somebody says
something they always say it the same
like you could say tell Revit to say
hello or whatever but then once you've
trained it then you can then you can go
in have this have this kind of working
and then you're tunneling through here
and you have your Python definition come
on and you have your Python kind of
automatically always listening for those
actions so as soon as one of those
actions and Alexa speaks to dynamo it
fires off into rabbit so anyways that's
that's our presentation
and questions I think how do one get
started learning Python cuz I mean
enrolling courses for Python but these
are for computer science and this is
very different to learn Python for
computer science that can you share how
you do
so yes the so learning Python is is you
can get started with like the very
basics and it's it's kind of once once
you even do design script or some of the
other things like understanding Python
is quite easy and even like the workflow
of dynamo how dynamo is structured is
exactly how you would write something
out I think the hard part is the API and
originally when I started the API like
digging into the API that's all in
c-sharp so that kind of left me to like
saying like you know what I bet people
would be interested to be able to do
really really simple things and then
later build on them so I've been slowly
kind of trying to build out a little um
like on YouTube really small samples of
how to do just things in dynamo that I
know can be frustrating that's one way
there's uh there's somebody else on on
there that has a whole couple pages
worth of stuff but you don't need to
know a lot of Python to be pretty
proficient at it in it with with dynamo
so yeah yep I'd agree with that I I took
like an online class to to learn a
little bit of Python but for a while it
was it was difficult to figure out what
how to use it there's a lot of good
resources online I think like Connor at
Saban has a lot of good examples part of
the what I did also is actually you can
take custom nodes and edit them and look
some of the custom nodes have Python
inside them
so like I took a couple of Conrad's
packages and edited his Oh edited those
nodes and looked at the Python inside to
see how it worked so finding a lot
examples really helps yeah yeah double
click on those nodes if you find a node
that you like you just double click into
it and all the Python know is all the
Python if they've written it in Python
comes up like so I guess what is your
way you just always write in time or you
like I use I use Visual Studio and I
have I think two versions of Visual
Studio on my machine and this this one
this one is really great because I have
Visual Studio community which is free
but in here if you could do like from
Auto desk
I got autocomplete on here which the IDE
in in in dynamo doesn't do and it drives
me insane so one thing I learned was
like if you get the community you can
actually like just go into here and it
has it has a preferences and in here in
these settings you can actually so don't
worry about everything on on on that
side if you if you if you use this you
can actually import the Revit API and UI
into into your visual Studios community
which you can download for free so uh
yeah yeah so so I have I I actually have
a video on exactly how to do this on my
youtube channel
right right no no no and that's his one
is exactly why I do this is because it
drives me like so so much of this stuff
if you like like no no no this Brian he
have a sound on this but oh no that's
overwriting graphics to be a visual
studio code I've used notepad plus plus
but that's not like it doesn't have
intellisense there's also a website I
can show but if you do a search for like
Python syntax it'll actually be a little
more helpful if their syntax issues like
it'll point out the line that those
issues are on that's the internet so if
you just there's a website that I don't
know the name of let's see if you type
in Python syntax I think it's like pi
Python lint that's what it is so if you
type your code in here it'll tell you
exactly what line you have issues on if
it's a syntax issue it doesn't help you
with a lot of other issues but it can be
useful yeah Python lint and we also need
to get onto the developers at Dynamo
totally update their IDE cuz it's like a
text box they can add like you know a
command liner or some sort of that but
because we can't see what's going on a
little I think it's happening last node
of the API is matured but it still
certainly occurs you you just have to
like with these version go through they
actually have like release notes of
what's changed in the API and check
through that but you know if you do a
Python no difference on something that's
no longer supported then you'll have to
update that
fortunately all right this guy he if he
publishes what's different in the API
from version to version and you just
look through his documentation and it's
beautiful so that but it does it does
change and when it and when it changes
from version version is really
frustrating yeah and I think it's what
happening less like you said
so I have a question yeah what happens
if you you know I do iterations of
simulation programs I I find the Python
sometimes to be a little bit more
efficient than then using the nodes just
the fact that you you have your and more
control of what what your what your
iterating over so but so you can filter
you can filter things out a lot faster
right if you know you're in control of
that Python node and then and then when
you iterate through using the.net
framework as always what slows you down
so I use it a lot of times with with
like mega high-rise buildings it's get
more so like we do you know thousands of
structural framing and then iterating
over that is very slow could take like
three to four minutes five minutes to
iterate over every one of them but if I
can start to like define like ranges of
height there you know scope of area or
things like that or just categories then
I can start to reduce it down real
quickly yeah it's not inherently slower
it just allows you more ability to
optimize your code to make it faster
yeah I was thinking all that earlier
like you mentioned all the combined
categories to sort of streamline that
scope we're talking about is that like
is that like a um okay so those those
filters or what they call what they call
slow filters but they're actually
incredibly fast the the you're talking
about the
[Music]
anyway I don't want to go on a rabbit
row I'm just thinking about bathroom the
this is the schedule filters as far as
like like going as using those admit I'm
not 100% sure but I bet they're using
that type of filtering because those are
incredibly fast and you can't iterate
over stuff and hope to be able to like
double click on it and see the whole
sheet of hundreds of things already
combined I would have to think that
they're going and using either some sort
of category or built in they got to be
using built-in parameters right yeah
there are the built-in filters I would I
would assume they are it's I mean behind
the scenes that that's possible but it's
not something that Revit exposes in
schedules to users in the in API I guess
that's probably more of limitation of
their UI and how they've designed it in
the API you can do as much as you want
too much the great thing about five on
two is that in schedules you can do or
run you're limited in your schedule
filtering to and like both of these have
to be true or right which you can use or
filters and Python which is much more
flexible to mention and we try to use
that script for your project you
probably have to change that process you
learn how to be efficient or you know
you just none of that so if I have to
start coding Python do I actually know
how programming language is set up do I
go watch use and try to know at first
and then I try to decode the script
that's being developed that I would say
yeah if you if you watch some lynda.com
or other online videos and then you you
could double click on people's Python
scripts
and kind of look to see what's
underneath the hood and then and then
you know I okay when I used to type
really type things out so it sort of
just copy and paste in and then I would
type things out just so I could kind of
memorize it but then I would also try to
see if I could change it a little bit
like try to just see if I could make
something do something slightly
different and then after a while I
started kind of understanding how how
flowed so same with dynamo I mean you
kind of you have to really play it like
you have to the way I think the way but
most of us probably learned dynamo was
probably by going in there and just like
trying to create little things right
just playing with the notes so some more
yeah a nice tip if you didn't know a lot
of public libraries have I guess I have
access to lynda.com if you get a public
library card you may be able to access
the comm through the public library card
if you didn't know that
so it's a very resource if you don't
have it I think San Francisco does that
yeah if you guys if I usually if if
somebody has like a question and
something that they're trying to do if I
can write it because usually I try to
record it like within 10 minutes and I
usually try to sit down and write write
it out as was posted like right now I
wasn't going to sit here and try to
write it while I was trying to talk but
at home I can just like type it out and
as on typing and kind of explain what
everything is so if any of you have a
question of something I can usually put
something together and walk you through
how how you would structure your code to
build that out yeah yeah okay we could
do a workshop for play down here yeah
that would be a good one
yeah but then the API lines using this I
see shot Python which which one's the
line the meant that nobody Python when
you're showing their code there the
lines will make the ID stop see shop not
quite enough like so
dynamo uses what's called ironpython
which allows you to access the dotnet
api which is what you sharp uses through
python so it's kind of like a mix
between the tailor the syntax is all
right it's all yeah I guess it is
company in the actual classes were from
the API which is that greater than all
the syntax and keywords yeah laughs yeah
it's still Python yeah yeah I think you
can use it's technically dotnet which
you can use like Visual Studio or
c-sharp check 2xs I believe uh yeah it's
like the operating system like next down
your machine then the source code into
beta plus and then will be revealed to
us an API they made it easier with
seizure great so very being they're
doing optimizations in C++ that we don't
want to care about like cleaning up
memory management so we just want to
like design so they made it easier with
Holly their dealings with us so yeah and
then we're adding an extra layer of
python python and python on top of it
with dynamo
all right well that way don't give up
pick up lost nor speakers
[Applause]