I am looking to incorporate the FaceAnalysisDisplay.ByViewFacePointsAndValues node inside Python. Has anyone been on this journey? Now if you must ask why, to be brief, it would make my graph so much easier to deal with and more powerful as I have the bulk of my operations inside my Python node where I would ideally like to feed and get different iteration face analysis results to do other processes with.
With that said, here is what I’ve found/tried:
- Digging into the API, I couldn’t find anything to actually create a Face Analysis Display result in the Autodesk.Revit.DB.Analysis namespace.
- I’ve tried bringing in Designscript into my Python node to call the function FaceAnalysisDisplay.ByViewFacePointsAndValues, however that did not work.
- I dug into the code for the node, found: DynamoRevit/src/Libraries/RevitNodes/AnalysisDisplay/FaceAnalysisDisplay.cs at a4cd7f18d8d2f39da992b13354c704dfac4a2822 · DynamoDS/DynamoRevit · GitHub
however, it started to get difficult to follow as it used some functions like SurfaceData.BySurfacePointsAndValues() that I could not find anywhere. Can anyone help shed some light on this? Thank you.
Can you share what you have so far?
The first thing to do is isolate the issue of trying to get FaceAnalysis to work in Python. This is a very simple example (And yes all the inputs work on the normal Revit FaceAnalysisDisplay Node). When I call FaceAnalysisDisplay.ByViewFacePointsAndValues I get the error: Function has no attribute ByViewFacePointsAndValues.
When I try calling it with DS.FaceAnalysisDisplay.ByViewFacePointsAndValues (DS being the instantiation of DesignScript) I get the error:
Autodesk.DesignScript.Geometry has no attribute FaceAnalysisDisplay
but I can call the function in a codeblock.
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference("RevitAPIUI")
from Autodesk.Revit.UI import *
clr.AddReference("RevitServices")
import RevitServices
doc = DocumentManager.Instance.CurrentDBDocument
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
view = doc.ActiveView
srf = UnwrapElement(IN[0])
pts = [UnwrapElement(x) for x in IN[1]]
samples = [UnwrapElement(x) for x in IN[2]]
unitType = IN[3]
OUT = FaceAnalysisDisplay.ByViewFacePointsAndValues(view,srf,pts,samples,"NAME","DESCRIPTION",unitType)
The documentation you linked for the source code has the node under RevitNodes > AnalysisDisplay. It also shows the namespace as Revit.AnalysisDisplay. What happens when you use the full namespace in your code?
Initially I did have:
from Autodesk.Revit.DB.Analysis import*
however it does not seem to help unless I am calling it out incorrectly.
Hi,
here, an simple example using Autodesk.Revit.DB.Analysis namespace and AVF
in this example I used 3 pairs ‘points-values’ per face
- Face MinUV point → minimum value
- Face select point → maximum value
- Face MaxUV point → minimum value

import clr
import sys
import math
import System
from System.Collections.Generic import List
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Analysis import *
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.UI import *
from Autodesk.Revit.UI.Selection import *
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
uidoc = uiapp.ActiveUIDocument
import traceback
def create_AvfDisplayStyle3(view):
filter = System.Predicate[System.Object](lambda x : x.Name == "Paint_Preview")
analysisDisplayStyle = List[Element](FilteredElementCollector(doc).OfClass(AnalysisDisplayStyle).ToElements()).Find(filter)
if view.AnalysisDisplayStyleId == ElementId.InvalidElementId or analysisDisplayStyle is None :
t = Transaction(doc, "Paint_Preview")
t.Start()
coloredSurfaceSettings = AnalysisDisplayColoredSurfaceSettings()
coloredSurfaceSettings.ShowGridLines = True
colorSettings = AnalysisDisplayColorSettings()
legendSettings = AnalysisDisplayLegendSettings()
legendSettings.ShowLegend = False
analysisDisplayStyle = AnalysisDisplayStyle.CreateAnalysisDisplayStyle( doc, "Paint_Preview", coloredSurfaceSettings, colorSettings, legendSettings )
view.AnalysisDisplayStyleId = analysisDisplayStyle.Id
t.Commit()
return view
def surfaceAnalysisSelection(view):
"""Pick points on the face with preview with AVF"""
create_AvfDisplayStyle3(view)
sfm = SpatialFieldManager.GetSpatialFieldManager(doc.ActiveView)
if sfm is None:
sfm = SpatialFieldManager.CreateSpatialFieldManager(doc.ActiveView, 1)
sfm.Clear()
resultSchema = AnalysisResultSchema("Schema Name" , "Preview_Selection")
schemaIndex = sfm.RegisterResult(resultSchema)
flag = True
error = None
outgpoints = []
TaskDialog.Show("Selection", "Select points on face, tap Esc to Finish")
while flag:
try:
reference = uidoc.Selection.PickObject(ObjectType.Face, "Select points on face, tap Esc to Finish")
selectface = doc.GetElement(reference).GetGeometryObjectFromReference(reference)
outgpoints.append(reference.GlobalPoint.ToPoint() )
interResult = selectface.Project(reference.GlobalPoint)
# code for only paint select surface
idx = sfm.AddSpatialFieldPrimitive(reference)
uvPts = List[UV]()
bbuv = selectface.GetBoundingBox()
uvPts.Add(bbuv.Min)
# uvPts.Add((bbuv.Min + bbuv.Max) * 0.5)
# OR
uvPts.Add(interResult.UVPoint)
uvPts.Add(bbuv.Max)
pnts = FieldDomainPointsByUV(uvPts)
#
doubleListA = List[System.Double]([10.0])
doubleListB = List[System.Double]([0.0])
vals = FieldValues(List[ValueAtPoint]([ValueAtPoint(doubleListA), ValueAtPoint(doubleListB), ValueAtPoint(doubleListA)]))
sfm.UpdateSpatialFieldPrimitive(idx, pnts, vals, schemaIndex)
except:
import traceback
error = traceback.format_exc()
flag = False
print(error)
break
return outgpoints, error
OUT = surfaceAnalysisSelection(doc.ActiveView)
3 Likes
You’re confusing the Revit API and the Dynamo Revit Nodes.
Using the API is the best option (see Cyril’s examples below). Typically there is no reason to use nodes over the API when in python, but in this case the node is much more streamlined than the API (and you were asking about the node).
To use the Dynamo (node) version within python you need to use the method from the Dynamo namespace: Revit.AnalysisDisplay.FaceAnalysisDisplay.ByViewFacePointsAndValues(). That’s what’s referenced in the source documentation. It’s the same as using it in DesignScript, you just have to import or use the full namespace here.
2 Likes
Thanks @c.poupin and @Nick_Boyts
I’ll check both suggestions later as they sound promising. Nick, I am well aware of the difference between the two hence I listed the separate approaches listed in my first post. In my examples as shown I was just struggling to find the right syntax to get the designscript in python which was clearly requested.
@Nick_Boyts
In the function: Revit.AnalysisDisplay.FaceAnalysisDisplay.ByViewFacePointsAndValues(), input sampleLocations takes in a UV array. This is what I have however I get an error: Expected Array[UV], got Array[UV].
import System
from System import Array
from System.Collections.Generic import List
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference("RevitAPIUI")
from Autodesk.Revit.UI import *
clr.AddReference("RevitServices")
import RevitServices
doc = DocumentManager.Instance.CurrentDBDocument
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
pts = [Autodesk.Revit.DB.UV(pt.X, pt.Y) for pt in IN[1]]
ptsArray = Array[UV](pts)
A list of Points is input into IN[1]. Any idea why I get the exception expected Array[UV], got Array[UV]? Thanks!
Your initial response was about loading a Revit API namespace while I was suggesting you use the extended Dynamo namespace with the DesignScript method. That’s what I was trying to clarify. Revit doesn’t have a FaceAnalysisDisplay.ByViewFacePointsAndValues() method.
This is always a confusing one because it sounds like the error is saying they’re the same. In actuality, you’re mixing up Revit and Dynamo objects. You’re using the Dynamo method but creating Revit UVs. You need to use Dynamo objects when using the Dynamo method and Revit objects when using the Revit method.
AnalysisDisplay is located in the RevitNodes assembly
here an example
however, it seems that AnalysisDisplayStyle cannot be created with the RevitNodes wrapper.

import clr
import sys
import System
#import net library
from System import Array
from System.Collections.Generic import List, IList, Dictionary
#
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS
#import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
clr.AddReference('RevitNodes')
import Revit
from Revit import AnalysisDisplay
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.GeometryReferences)
#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
import numpy as np
surface = IN[0]
view = IN[1]
array = np.random.rand(10, 2)
values = System.Array[System.Double]([x for x in np.random.rand(10)])
array_UV = System.Array[DS.UV]([DS.UV.ByCoordinates(x, y) for x, y in array])
analysis_display = AnalysisDisplay.FaceAnalysisDisplay.ByViewFacePointsAndValues(view,
surface,
array_UV,
values,
"test2",
"test2",
None)
OUT = analysis_display
2 Likes