Skip to content

Examples DemoBasicPandas

Truong Giang Vu edited this page Feb 14, 2026 · 2 revisions

Example: Data Analysis with Polars

Demo: Collect Revit data β†’ Analyze with Polars β†’ Visualize results
Script: data_analysis_script.py
Time: 2-3 minutes


What It Does

Complete workflow combining all three modules:

  1. CodeExecute - Auto-install Polars via PEP 723
  2. Logging - Structured output with syntax highlighting
  3. Visualization - Display outliers in 3D view

Key Pattern: PEP 723 Dependencies

# /// script
# dependencies = [
#     "polars==1.38.1",
# ]
# ///

When you click Execute:

  • CodeExecute checks if polars is installed
  • If missing, UV resolver installs it automatically (~5 seconds)
  • Script runs with full access to Polars DataFrame API

Key Pattern: Revit Data Collection

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

Key Pattern: DataFrame Analysis

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

Key Pattern: Geometry Visualization

# 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 color

Result:

  • Outlier walls highlighted in 3D view
  • Trace Panel shows IDs + areas
  • Clear visual feedback for analysis

Try It Yourself

  1. Open RevitDevTool panel
  2. Navigate to CodeExecute tab
  3. Load folder: source/RevitDevTool.PythonDemo/commands/
  4. Click data_analysis_script.py
  5. Watch dependencies install (first run only)
  6. See results in Trace Panel + 3D view

Full source: data_analysis_script.py


Related Examples


The Script: Wall Analysis Dashboard

Let's analyze wall dimensions across project levels and export results.

Script File: wall_analysis_script.py

# /// 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")

Expected Execution Trace

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

Behind the Scenes: Execution Flow

Phase 0: Discovery

CodeExecute scans project folder
└─ Finds: wall_analysis_script.py
└─ Creates ExecuteNode in tree

Phase 1: User Clicks Execute

User clicks script in tree + clicks "Execute" button

Phase 2: Check Dependencies (Silent)

[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

Phase 3: Show Install Dialog

[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

Phase 4: Initialize Python (First Time)

[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

Phase 5: Execute Script

[<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)

Phase 6: Display Output

[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

Key Learning Points

1. PEP 723 Dependency Declaration

# /// script
# dependencies = [
#     "pandas==1.5.3",
#     "numpy==1.24.0",
# ]
# ///
  • Declared at top of script
  • Comma-separated strings with version specifiers
  • No separate requirements.txt file needed
  • Used ONLY in this script (isolated)

2. Automatic Installation

  • First run: Script detects missing packages
  • Shows progress dialog (user can cancel)
  • Subsequent runs: Packages already present, skip install
  • Changed version? Re-installs automatically

3. Injected Globals

# 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)

4. Natural pandas Usage

# 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.

5. Revit Integration

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.


Running This Demo

  1. Copy script: Save wall_analysis_script.py to your scripts folder
  2. Load folder: In CodeExecute, click "Load Folder" β†’ select scripts folder
  3. Run script: Click script in tree β†’ "Execute" button
  4. Watch:
    • Dialog appears for package install (first time only)
    • Output streams in Trace panel
    • Results visible immediately after execution

Variations

Variation 1: Export Results to Excel

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}")

Variation 2: Filter by Level

# 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())

Variation 3: Visualize with Geometry

# /// 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!

Troubleshooting

Problem: Script shows error "ModuleNotFoundError: No module named 'pandas'"
Solution: Check:

  1. PEP 723 block is present (first 50 lines)
  2. Syntax is correct: dependencies = ["pandas==1.5.3"]
  3. Wait for install dialog and don't cancel

Problem: "Trace panel not showing output"
Solution:

  1. Open Trace panel: View menu β†’ "Trace"
  2. Ensure "Start Listener" is ON
  3. Check that print() is being called (not other output)

Problem: Script runs but no data displayed
Solution:

  1. Check if project is open
  2. Verify project actually has walls
  3. Add debug prints: print(f"Collected {len(walls)} walls")

Next Steps

For more information about Python execution and dependencies, see the main documentation.

Clone this wiki locally