-
Notifications
You must be signed in to change notification settings - Fork 0
Examples DemoBasicPandas
Demo: Collect Revit data β Analyze with Polars β Visualize results
Script: data_analysis_script.py
Time: 2-3 minutes
Complete workflow combining all three modules:
- CodeExecute - Auto-install Polars via PEP 723
- Logging - Structured output with syntax highlighting
- Visualization - Display outliers in 3D view
# /// script
# dependencies = [
# "polars==1.38.1",
# ]
# ///When you click Execute:
- CodeExecute checks if
polarsis installed - If missing, UV resolver installs it automatically (~5 seconds)
- Script runs with full access to Polars DataFrame API
from Autodesk.Revit.DB import FilteredElementCollector, Wall
doc = __revit__.ActiveUIDocument.Document
walls = FilteredElementCollector(doc).OfClass(Wall).ToElements()
data = []
for wall in walls:
data.append({
"Id": wall.Id.IntegerValue,
"Name": wall.Name,
"Area": wall.get_Parameter(BuiltInParameter.HOST_AREA_COMPUTED).AsDouble(),
})Output in Trace Panel:
Collecting wall data...
Collected 127 walls
import polars as pl
df = pl.DataFrame(data)
# Statistical analysis
stats = df.select(pl.col("Area").describe())
print(stats)
# Find outliers (area > 2 std deviations)
mean_area = df["Area"].mean()
std_area = df["Area"].std()
outliers = df.filter(pl.col("Area") > mean_area + 2 * std_area)Output in Trace Panel:
Wall Area Statistics:
ββββββββββββ¬βββββββββββββ
β statisticβ value β
ββββββββββββΌβββββββββββββ€
β count β 127.0 β
β mean β 245.8 β
β std β 78.3 β
β min β 12.5 β
β max β 892.1 β
ββββββββββββ΄βββββββββββββ
Found 3 outlier walls
# Get walls from outlier IDs
outlier_ids = [ElementId(id) for id in outliers["Id"]]
outlier_walls = [doc.GetElement(id) for id in outlier_ids]
# Print geometry β auto-visualized in 3D
for wall in outlier_walls:
curve = wall.Location.Curve
print(f"Wall {wall.Id}: Area={wall_area:.1f} sq ft")
print(curve) # Appears in 3D view with colorResult:
- Outlier walls highlighted in 3D view
- Trace Panel shows IDs + areas
- Clear visual feedback for analysis
- Open RevitDevTool panel
- Navigate to CodeExecute tab
-
Load folder:
source/RevitDevTool.PythonDemo/commands/ -
Click
data_analysis_script.py - Watch dependencies install (first run only)
- See results in Trace Panel + 3D view
Full source: data_analysis_script.py
-
Logging tests β
logging_format_script.py -
Visualization tests β
visualization_curve_script.py -
Dashboard UI β
dashboard_script.py
Let's analyze wall dimensions across project levels and export results.
# /// script
# dependencies = [
# "pandas==1.5.3",
# "numpy==1.24.0",
# ]
# ///
"""
Wall Analysis Script
Demonstrates:
- PEP 723 dependency declaration
- Revit element collection
- pandas DataFrame analysis
- Output to Trace panel
"""
import numpy as np
import pandas as pd
from Autodesk.Revit import DB
print("=" * 60)
print("WALL ANALYSIS SCRIPT")
print("=" * 60)
# Get current document
doc = __revit__.ActiveUIDocument.Document
print(f"\\n1. Opening document: {doc.Title}")
# Collect all walls
print("\\n2. Collecting walls from model...")
collector = DB.FilteredElementCollector(doc)
all_elements = list(collector.OfClass(DB.Wall).ToElements())
print(f" Found {len(all_elements)} walls")
# Extract wall data
print("\\n3. Extracting wall properties...")
wall_data = []
for wall in all_elements:
try:
# Get dimensions
wall_type = wall.WallType
width = wall_type.Width # In feet
height = None
# Try to get height
if hasattr(wall, "Height"):
height = wall.Height
# Convert to feet
wall_data.append({
"Id": wall.Id.IntegerValue,
"Name": wall.Name,
"Type": wall_type.Name,
"Level": wall.LevelName,
"Height_ft": height if height else 0,
"Thickness_in": round(width * 12, 2), # Convert to inches
"Family": wall_type.Family.Name if wall_type.Family else "Unknown",
})
except Exception as e:
print(f" Warning: Couldn't extract data for wall {wall.Id}: {e}")
print(f" Extracted data for {len(wall_data)} walls")
# Create DataFrame
print("\\n4. Creating DataFrame...")
df = pd.DataFrame(wall_data)
print(f" DataFrame shape: {df.shape[0]} rows, {df.shape[1]} columns")
# Analysis 1: Count by Level
print("\\n5. ANALYSIS: Walls by Level")
print(" " + "-" * 40)
by_level = pd.crosstab(df["Level"], "Count")
print(by_level.to_string())
print(f" Total: {by_level.values.sum()} walls")
# Analysis 2: Average thickness by type
print("\\n6. ANALYSIS: Average Thickness by Type")
print(" " + "-" * 40)
by_type = df.groupby("Type").agg(
Count=("Type", "count"),
Avg_Thickness_in=("Thickness_in", "mean"),
Min_Thickness_in=("Thickness_in", "min"),
Max_Thickness_in=("Thickness_in", "max"),
).round(2)
print(by_type.to_string())
# Analysis 3: Statistics
print("\\n7. STATISTICS: All Walls")
print(" " + "-" * 40)
stats = df[["Height_ft", "Thickness_in"]].describe().round(2)
print(stats.to_string())
# Analysis 4: Top 5 most common types
print("\\n8. TOP 5 MOST COMMON TYPES")
print(" " + "-" * 40)
top_types = df["Type"].value_counts().head(5)
for i, (wall_type, count) in enumerate(top_types.items(), 1):
percentage = (count / len(df)) * 100
print(f" {i}. {wall_type}: {count} ({percentage:.1f}%)")
# Summary
print("\\n" + "=" * 60)
print("SUMMARY")
print("=" * 60)
print(f"Total Walls Analyzed: {len(df)}")
print(f"Levels: {df['Level'].nunique()}")
print(f"Wall Types: {df['Type'].nunique()}")
print(f"Average Thickness: {df['Thickness_in'].mean():.2f} inches")
print("=" * 60 + "\\n")When you run wall_analysis_script.py in RevitDevTool, you'll see this in the Trace Panel:
[INFO] ============================================================
[INFO] WALL ANALYSIS SCRIPT
[INFO] ============================================================
[INFO]
[INFO] 1. Opening document: MyProject.rvt
[INFO]
[INFO] 2. Collecting walls from model...
[INFO] Found 47 walls
[INFO]
[INFO] 3. Extracting wall properties...
[INFO] Extracted data for 47 walls
[INFO]
[INFO] 4. Creating DataFrame...
[INFO] DataFrame shape: 47 rows, 7 columns
[INFO]
[INFO] 5. ANALYSIS: Walls by Level
[INFO] ----------------------------------------
[INFO] Level Count
[INFO] Ground Floor 12
[INFO] Level 1 15
[INFO] Level 2 14
[INFO] Roof 6
[INFO] Total: 47 walls
[INFO]
[INFO] 6. ANALYSIS: Average Thickness by Type
[INFO] ----------------------------------------
[INFO] Count Avg_Thickness_in Min_Thickness_in Max_Thickness_in
[INFO] Exterior 15 12.50 8.75 20.00
[INFO] Interior 18 9.38 6.00 12.00
[INFO] Curtain 12 6.25 6.25 6.25
[INFO] Shear 2 20.00 20.00 20.00
[INFO]
[INFO] 7. STATISTICS: All Walls
[INFO] ----------------------------------------
[INFO] Height_ft Thickness_in
[INFO] count 47.00 47.00
[INFO] mean 12.50 9.88
[INFO] std 2.30 4.15
[INFO] min 10.00 6.00
[INFO] 25% 10.00 6.25
[INFO] 50% 12.00 9.38
[INFO] 75% 15.00 12.00
[INFO] max 15.00 20.00
[INFO]
[INFO] 8. TOP 5 MOST COMMON TYPES
[INFO] ----------------------------------------
[INFO] 1. Interior: 18 (38.3%)
[INFO] 2. Exterior: 15 (31.9%)
[INFO] 3. Curtain: 12 (25.5%)
[INFO] 4. Shear: 2 (4.3%)
[INFO]
[INFO] ============================================================
[INFO] SUMMARY
[INFO] ============================================================
[INFO] Total Walls Analyzed: 47
[INFO] Levels: 4
[INFO] Wall Types: 4
[INFO] Average Thickness: 9.88 inches
[INFO] ============================================================
[β] Script executed successfully
CodeExecute scans project folder
ββ Finds: wall_analysis_script.py
ββ Creates ExecuteNode in tree
User clicks script in tree + clicks "Execute" button
[1ms] Pep723Parser reads script header
ββ Extracts: ["pandas==1.5.3", "numpy==1.24.0"]
[500ms] PythonDependencyManager dry-run check
ββ uv pip install --dry-run pandas==1.5.3 numpy==1.24.0 --python <path>
ββ Output: "Would install: pandas numpy"
ββ Decision: Needs installation? YES
[User sees Modal Dialog]
βββββββββββββββββββββββββββββββββββββββ
β Installing Packages β
βββββββββββββββββββββββββββββββββββββββ€
β Installing: pandas==1.5.3 β
β [ββββββββββββββββββββββββββ 50%] β
β β
β [Cancel] β
βββββββββββββββββββββββββββββββββββββββ
[~10 sec] uv pip install runs
ββ Downloads pandas (2MB) + numpy (3MB) + dependencies
ββ Progress reported line-by-line
ββ "Installed 8 packages"
ββ Dialog closes
[50ms] Create Python scope
ββ Inject __revit__, __file__, __root__
[<1ms] Inject Reset.py
ββ Clear previous module cache
ββ Clear import caches
[<1ms] Inject Setup.py
ββ Import Revit assemblies
ββ Override print() for Trace capture
ββ Redirect stdout/stderr
[<100ms] scope.Exec(script_code)
ββ Python interpreter runs script
ββ All print() output β __log_func__ β Trace panel
ββ All imports use fresh disk loads
ββ GIL held for duration (Revit thread-safe)
[Real-time] As print() runs, output appears in Trace
ββ Line-by-line as script executes
ββ Colored by log level ([INFO], [ERROR], etc.)
ββ Fully searchable in Trace panel
# /// script
# dependencies = [
# "pandas==1.5.3",
# "numpy==1.24.0",
# ]
# ///- Declared at top of script
- Comma-separated strings with version specifiers
- No separate
requirements.txtfile needed - Used ONLY in this script (isolated)
- First run: Script detects missing packages
- Shows progress dialog (user can cancel)
- Subsequent runs: Packages already present, skip install
- Changed version? Re-installs automatically
# These are available automatically:
__revit__ # UIApplication for Revit API
__file__ # Path to current script
__root__ # Path to script folder
print() # Redirected to Trace panel (captured)# Works perfectly - no workarounds needed!
df = pd.DataFrame(data)
df.groupby("Level").sum()
df.describe()Unlike pyRevit (IronPython 2.7), modern Python packages just work.
from Autodesk.Revit import DB
doc = __revit__.ActiveUIDocument.Document
collector = DB.FilteredElementCollector(doc)
walls = collector.OfClass(DB.Wall).ToElements()Direct API access - no wrapper layers needed.
-
Copy script: Save
wall_analysis_script.pyto your scripts folder - Load folder: In CodeExecute, click "Load Folder" β select scripts folder
- Run script: Click script in tree β "Execute" button
-
Watch:
- Dialog appears for package install (first time only)
- Output streams in Trace panel
- Results visible immediately after execution
Add to script:
# /// script
# dependencies = [
# "pandas==1.5.3",
# "numpy==1.24.0",
# "openpyxl==3.1.5",
# ]
# ///
# ... analysis code ...
# Export to Excel
import openpyxl
wb = openpyxl.Workbook()
ws = wb.active
# Write headers
for col, header in enumerate(df.columns, 1):
ws.cell(row=1, column=col).value = header
# Write data
for row, record in enumerate(df.to_dict("records"), 2):
for col, value in enumerate(record.values(), 1):
ws.cell(row=row, column=col).value = value
# Save
output_path = f"{__root__}/wall_analysis_output.xlsx"
wb.save(output_path)
print(f"β Exported to: {output_path}")# Add to script
# Analyze specific level
target_level = "Level 1"
level_walls = df[df["Level"] == target_level]
print(f"\\nWalls on {target_level}: {len(level_walls)}")
print(level_walls[["Name", "Type", "Thickness_in"]].to_string())# /// script
# dependencies = [
# "pandas==1.5.3",
# "numpy==1.24.0",
# ]
# ///
# ... collect walls ...
# Visualize in 3D
from Autodesk.Revit.DB import *
print("\\nVisualizing walls in 3D view...")
for wall in all_elements:
# Get and display geometry
geometry_elem = wall.get_Geometry(Options())
for geo_obj in geometry_elem:
if isinstance(geo_obj, Solid):
print(geo_obj) # Draws in Revit 3D view!Problem: Script shows error "ModuleNotFoundError: No module named 'pandas'"
Solution: Check:
- PEP 723 block is present (first 50 lines)
- Syntax is correct:
dependencies = ["pandas==1.5.3"] - Wait for install dialog and don't cancel
Problem: "Trace panel not showing output"
Solution:
- Open Trace panel: View menu β "Trace"
- Ensure "Start Listener" is ON
- Check that
print()is being called (not other output)
Problem: Script runs but no data displayed
Solution:
- Check if project is open
- Verify project actually has walls
- Add debug prints:
print(f"Collected {len(walls)} walls")
For more information about Python execution and dependencies, see the main documentation.