Command Failure for External Command: XYZ is not callable

Hi,

i made a script wich runs fine a does what it needs to do but i get this error popup-window everytime i run it.

It seems that the issue is related to the XYZ’s at the moment i do UV-calculation and modification and then use them for raytracing.

But i can’t really figure out what exactly.

the script:

 # -- coding: UTF-8 -- 
 
# imports
import clr
clr.AddReference('RevitAPI')
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB import SpecTypeId
from System.Collections.Generic import List

from pyrevit import revit, script

# doc & appplication
doc = revit.doc
uidoc = revit.uidoc

# collect walls in model
walls = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls).WhereElementIsNotElementType().ToElements()
# dictionary containing all wall information: {wall:{faces:[], points:[], dir:[]}}
wall_info = {}

# WALLFACES

for wall in walls:
    # get exteriorface
    extside = HostObjectUtils.GetSideFaces(wall,ShellLayerType.Exterior)
    for e in extside:
        extface = wall.GetGeometryObjectFromReference(e)
        if extface == None:
            continue
        else:
            wall_info[wall] = {}
            wall_info[wall]['wall_faces'] = [extface]

# POINTS & DIRECTIONS

# determin precision of the check
precision = 3

for wall , info in wall_info.items():
    # create dictionary sublists for points and directions
    wall_info[wall]['points'] = []
    wall_info[wall]['directions']= []
    
    # iterate through the face to get points grid and directions
    for face in info['wall_faces']:
        # create list to store all points of each face in
        points = []
        point_dir = []
        # get min & max UV for each face and determin the interval based on the presicion
        bboxUV = face.GetBoundingBox()
        u_interval = (bboxUV.Max.U - bboxUV.Min.U) / (precision-1)
        v_interval = (bboxUV.Max.V - bboxUV.Min.V) / (precision-1)
        # create pointgrid for the face
        for i in range(precision):
            u = bboxUV.Min.U + i * u_interval
            for j in range(precision):
                v = bboxUV.Min.V + j * v_interval
                uv = UV(u, v)
                # check if points are on the face
                if face.IsInside(uv):
                    points.append(face.Evaluate(uv))
                    point_dir.append(face.ComputeNormal(uv))
                else:
                    # if the UV-point is outside the face, adjust it
                    for d in range (1, precision):
                        # Try moving the point towards the center of the face
                        adjusted_uv = UV(u - d * u_interval / precision, v - d * v_interval / precision)
                        if face.IsInside(adjusted_uv):
                            points.append(face.Evaluate(uv))
                            point_dir.append(face.ComputeNormal(uv))
                            break
        # add points of face to dict entry of the wall
        wall_info[wall]['points'].append(points)
        wall_info[wall]['directions'].append(point_dir)

# for wall,info in wall_info.items():
#     print(wall)
#     for i in info:
#         print(i)
#         for x in info[i]:
#             print(x)
#     print('------------')
    
# INTERSECTING   

# Get Raytracing view + settings
views = FilteredElementCollector(doc).OfClass(View).WhereElementIsNotElementType().ToElements()
for view in views:
    if view.Name == "Systemcheck":
        view = view
        break
ri = ReferenceIntersector(view)
ri.FindReferencesInRevitLinks = False

# Document UI Units
try:
	UIunit = Document.GetUnits(doc).GetFormatOptions(UnitType.UT_Length).DisplayUnits
except:
	UIunit = Document.GetUnits(doc).GetFormatOptions(SpecTypeId.Length).GetUnitTypeId()

# Dictionary to store wall thickness
wall_thickness = {}

# set wich all unique systems
systems = set()

# Raytrace for intersections with each point
for wall , info in wall_info.items():
    # append wall thickness to list
    if wall.Id not in wall_thickness:
        wall_thickness[wall.Id] = UnitUtils.ConvertFromInternalUnits(wall.WallType.Width, UIunit)

    for points, directions in zip(info['points'],info['directions']):
        for point, dir in zip(points,directions):
            # set both directions of a point
            directions = [dir, -dir]
            pointset = set()
            pointset.add(wall.Name)

            for direction in directions:
                # Define the Exclusion Filter and reset it for each direction
                filter_list = [wall.Id]
                filter = ExclusionFilter(List[ElementId](filter_list))
                ri.SetFilter(filter)
                
                # Distance tollarance of intersection: mm to ft (x3.281)
                if direction == dir:
                    distance_check = 150
                else:
                    distance_check = 150 + wall_thickness[wall.Id]
                
                # raytracing loop
                while True:
                    filter = ExclusionFilter(List[ElementId](filter_list))
                    ri.SetFilter(filter)
                    ref = ri.FindNearest(point, direction)
                    
                    # stop condition
                    if ref is None:
                        break
                    
                    # get ref information
                    refel = ref.GetReference()
                    refp = ref.GetReference().GlobalPoint
                    elem = doc.GetElement(refel.ElementId)
                    dist = UnitUtils.ConvertFromInternalUnits(point.DistanceTo(refp), UIunit) #mm (converted from internal ft)
                    
                    # check distance                    
                    if dist <= distance_check:
                        pointset.add(elem.Name)
                        filter_list.Add(refel.ElementId)
                        
                        # Get the thickness of the intersected wall
                        if elem.Id not in wall_thickness:
                            wall_thickness[elem.Id] = UnitUtils.ConvertFromInternalUnits(elem.WallType.Width, UIunit)
                        # modify check distance
                        distance_check = distance_check + wall_thickness[elem.Id]
						
                    else:
                        break
            pointset_f = frozenset(pointset)
            systems.add(pointset_f)

# int = 1
# for set in systems:
#     print("set"+ str(int))
#     for i in set:
#         print(i)
#     print('-----')
#     int = int +1

output = script.get_output()

data = []
typenr = 1
for set in systems:
    dataset = []
    dataset.append(typenr)
    for i in set:
        dataset.append(i)
    typenr = typenr+1
    data.append(dataset)

headers = ["System Nr"]
longest_set = len(max(systems, key=len))
for i in range(longest_set):
    headers.append("Materiaal " + str(i+1))

output.print_table(table_data = data,
                   title="Wallsystems",
                   columns= headers,
                   formats=['', '', '', ''],)

output.log_success('script succesfull')

is your boundingBox of type DB.BoundingBoxUV?

Quickly reading it seems your are getting a ‘regular’ BB that return XYZ points as Min and Max, But not in front of a computer to test it.

The difference being Min and Man with X,Y or Zs or U,Vs

I commented out a few things so I could run it in RevitPythonShell.
First run is fine - no error.
Second run returns an error related to the dictionary not being callable.

Don’t know if this helps:

As far i a know i’m pretty sure it returns the UV’s. and not the XYZ.
Because after calling for the boundingbox i then generate u and v-interval based on the uv-max and min values.

@aaronrumple
I need to make the pointset a frozenset to be able to nest the pointset into the systems-set.
U can’t nest set into another set without it being a frozenset.
This does mean that the set can’t be manipulated anymore onces it frozen.

The reason i do this nesting is to avoid duplicates (first on the wall-level and then on an overal level)

But this pointset exctualy includes the walls(names) i find via the tracing and not the XYZ points.
Those are stored in the wall_info[wall][points] dictionary-location

So the frozenset doesn’t really have anything to do with the XYZ error that i’m getting (that’s my analyses).

But i can see you are get a kind of simullar error but frozenser related…
In the view that you are tracing do u only have walls active and nothing else?

Maybe i need to build in some safety so that the tracing only takes walls into account no matter the view settings?

@aaronrumple and @Jean-Marc,

i traced the issue down to these lines of code (around lines 112-115):

    for points, directions in zip(info['points'],info['directions']):
        for point, dir in zip(points,directions):
            # set both directions of a point
            directions = [dir, -dir]

could it have to do with the way i create a inverted vector (-dir)?

Yes. Just walls in the view. It bonked out when I had other elements.

In an other script i get the same error on:
Here the error is shorter just :
image

and it gets triggered at the FindNearest Method itself.
so could this be that traced point just go up in smoke?
altho i check for that in the next line.

Also in this case the script keeps on working but it fails in the end to commit the transaction where i set the retrieved values to the annotation instances.

# tracing settings
ri = ReferenceIntersector(view_sel)     # view to trace on
ri.FindReferencesInRevitLinks = True    # Use Links to bounce on
directions = [XYZ(0,0,1),XYZ(0,0,-1)]   # raytrace Directions

#Document UI Units
try:
	UIunit = Document.GetUnits(doc).GetFormatOptions(UnitType.UT_Length).DisplayUnits
except:
	UIunit = Document.GetUnits(doc).GetFormatOptions(SpecTypeId.Length).GetUnitTypeId()
 
# Print the desired annotations
with revit.Transaction("BB: FreeHeight", swallow_errors=True) as t:
    for anno in filtered_annotations:
        # trace location
        location = anno.Location.Point

        z_values = []
        vloerpas = 0
        for dir in directions:
            # trace
            ref = ri.FindNearest(location, dir)
            if ref is not None:
                refp = ref.GetReference().GlobalPoint
                # Unit conversion from internal units
                refp_Z = UnitUtils.ConvertFromInternalUnits(refp.Z,UIunit)

I found the error for both case (scripts).

dir is also a built-in Python function, which returns a list of the attributes and methods of any object. If you try to overwrite dir with an XYZ object and then use dir as a function, you’ll get the error i’m having that says that XYZ is not callable.

solution: don’t use dir as a variable name…

        for dir in directions:
            # trace
            ref = ri.FindNearest(location, dir)
1 Like