Models API
TreeScape’s data model consists of TreeScapeModel (collection of runs) and Run (individual performance measurements).
TreeScapeModel
- class TreeScapeModel(reader, updated_list=None)
Collection of Run objects representing performance data across multiple runs.
Extends Python’s list class, so all list operations are supported.
- Parameters:
import treescape as ts # Create from reader reader = ts.CaliReader("/path/to/files") model = ts.TreeScapeModel(reader) # Create from filtered runs filtered_runs = [r for r in model if r.metadata["problem_size"] > 100] new_model = ts.TreeScapeModel(reader, filtered_runs)
Attributes:
- childrenMap
Global mapping of parent nodes to their children.
model = ts.TreeScapeModel(reader) print(model.childrenMap["main"]) # Output: ["initialization", "computation", "finalization"]
- meta_globals
Metadata type information for all runs.
print(model.meta_globals) # Output: {"launchdate": "int", "problem_size": "int", "test": "string"}
Methods:
- get_meta_globals()
Get metadata type information.
meta = model.get_meta_globals() if meta["launchdate"] == "int": print("Launch date is numeric")
- get_children_map()
Get the global children map.
children_map = model.get_children_map() for parent, children in children_map.items(): print(f"{parent} -> {children}")
- update(new_tsm_list)
Replace the runs in the model with a new list.
# Filter and update fast_runs = [r for r in model if r.perftree["main"]["avg"] < 10.0] model.update(fast_runs)
- get_entire_tsm()
Get the complete model as a dictionary.
- Returns:
Dictionary with nodes, childrenMap, and meta_globals
- Return type:
data = model.get_entire_tsm() print(data.keys()) # dict_keys(['nodes', 'childrenMap', 'meta_globals'])
- sort(metadata_key)
Sort runs by a metadata key (in-place).
- Parameters:
metadata_key (str) – Metadata field to sort by
model.sort("launchdate") # Sort by date model.sort("problem_size") # Sort by size
List Operations:
Since TreeScapeModel extends list, you can use standard list operations:
model = ts.TreeScapeModel(reader) # Length print(f"Number of runs: {len(model)}") # Indexing first_run = model[0] last_run = model[-1] # Slicing first_ten = model[:10] last_five = model[-5:] # Iteration for run in model: print(run.metadata) # List comprehension large_runs = [r for r in model if r.metadata["problem_size"] > 1000] # Filtering recent = [r for r in model if r.metadata["launchdate"] > 1609459200] # Sorting (returns new list) sorted_runs = sorted(model, key=lambda r: r.metadata["launchdate"]) # Check membership if first_run in model: print("Run found")
Run
- class Run(metadata, perftree, reader, childrenMap=None)
Represents a single performance run.
- Parameters:
Attributes:
- metadata
Dictionary of metadata for this run.
- Type:
- Common metadata keys:
launchdate/launchday: Timestamp of the runproblem_size: Problem size parameterjobsize: Number of MPI ranks or threadstest: Test name or identifierCustom fields from your Caliper instrumentation
run = model[0] print(run.metadata["launchdate"]) print(run.metadata["problem_size"]) print(run.metadata.get("custom_field", "default"))
- perftree
Dictionary mapping node names to their performance metrics.
- Each node’s metrics include:
sum: Total inclusive timeavg: Average inclusive timemin: Minimum inclusive timemax: Maximum inclusive time
run = model[0] main_metrics = run.perftree["main"] print(f"Average time: {main_metrics['avg']}") print(f"Total time: {main_metrics['sum']}") print(f"Min time: {main_metrics['min']}") print(f"Max time: {main_metrics['max']}")
- childrenMap
Dictionary mapping parent nodes to their children for this run.
Methods:
- getMetaData(key)
Get a metadata value by key.
- Parameters:
key (str) – Metadata key to retrieve
- Returns:
Metadata value
- Return type:
any
run = model[0] date = run.getMetaData("launchdate") size = run.getMetaData("problem_size")
- getPerfTree(node, metric)
Get a specific metric for a node.
- Parameters:
- Returns:
Metric value
- Return type:
run = model[0] avg_time = run.getPerfTree("main", "avg") max_time = run.getPerfTree("compute", "max")
- to_dict()
Convert the run to a dictionary.
- Returns:
Dictionary with metadata, perftree, and childrenMap
- Return type:
run = model[0] data = run.to_dict() print(data.keys()) # dict_keys(['metadata', 'perftree', 'childrenMap'])
Common Patterns
Filtering Runs
import treescape as ts
reader = ts.CaliReader("/path/to/data")
model = ts.TreeScapeModel(reader)
# Filter by problem size
large = [r for r in model if r.metadata.get("problem_size", 0) > 1000]
# Filter by date range
import datetime
start = datetime.datetime(2024, 1, 1).timestamp()
end = datetime.datetime(2024, 12, 31).timestamp()
year_2024 = [r for r in model
if start <= r.metadata["launchdate"] <= end]
# Filter by multiple criteria
filtered = [
r for r in model
if r.metadata.get("jobsize") == 64
and r.metadata.get("test") == "baseline"
and "main" in r.perftree
]
# Create new model from filtered data
new_model = ts.TreeScapeModel(reader, filtered)
Sorting Runs
# Sort by date (ascending)
by_date = sorted(model, key=lambda r: r.metadata["launchdate"])
# Sort by problem size (descending)
by_size = sorted(model, key=lambda r: r.metadata["problem_size"], reverse=True)
# Sort by performance
by_perf = sorted(model, key=lambda r: r.perftree.get("main", {}).get("avg", 0))
# Multi-level sort
sorted_runs = sorted(
model,
key=lambda r: (r.metadata["test"], r.metadata["launchdate"])
)
Extracting Data
# Get all unique test names
tests = set(r.metadata.get("test", "unknown") for r in model)
# Get time series data for a node
times = [
(r.metadata["launchdate"], r.perftree["main"]["avg"])
for r in model
if "main" in r.perftree
]
# Calculate statistics
import statistics
avg_times = [r.perftree["main"]["avg"] for r in model if "main" in r.perftree]
mean_time = statistics.mean(avg_times)
median_time = statistics.median(avg_times)
std_dev = statistics.stdev(avg_times)
Grouping Runs
from collections import defaultdict
# Group by test name
by_test = defaultdict(list)
for run in model:
test_name = run.metadata.get("test", "unknown")
by_test[test_name].append(run)
# Group by problem size
by_size = defaultdict(list)
for run in model:
size = run.metadata.get("problem_size")
by_size[size].append(run)
# Create models for each group
test_models = {
test: ts.TreeScapeModel(model.reader, runs)
for test, runs in by_test.items()
}
Analyzing Performance
# Find slowest runs
slowest = sorted(
model,
key=lambda r: r.perftree.get("main", {}).get("avg", 0),
reverse=True
)[:10]
# Find runs with high variance
high_variance = [
r for r in model
if "main" in r.perftree
and (r.perftree["main"]["max"] - r.perftree["main"]["min"]) > 10.0
]
# Compare baseline vs optimized
baseline = [r for r in model if r.metadata.get("version") == "baseline"]
optimized = [r for r in model if r.metadata.get("version") == "optimized"]
baseline_avg = statistics.mean(
r.perftree["main"]["avg"] for r in baseline if "main" in r.perftree
)
optimized_avg = statistics.mean(
r.perftree["main"]["avg"] for r in optimized if "main" in r.perftree
)
speedup = baseline_avg / optimized_avg
print(f"Speedup: {speedup:.2f}x")
Integration with Pandas
import pandas as pd
import treescape as ts
reader = ts.CaliReader("/path/to/data")
model = ts.TreeScapeModel(reader)
# Convert to DataFrame
data = []
for run in model:
row = {**run.metadata} # Start with all metadata
# Add performance metrics for key nodes
if "main" in run.perftree:
row["main_avg"] = run.perftree["main"]["avg"]
row["main_sum"] = run.perftree["main"]["sum"]
data.append(row)
df = pd.DataFrame(data)
# Now use pandas operations
print(df.describe())
print(df.groupby("test")["main_avg"].mean())
# Filter with pandas
fast_runs_df = df[df["main_avg"] < 10.0]
# Convert back to model
fast_run_indices = fast_runs_df.index.tolist()
fast_runs = [model[i] for i in fast_run_indices]
fast_model = ts.TreeScapeModel(reader, fast_runs)
See Also
Readers API - Loading data with CaliReader and ThicketReader
Visualizations API - Creating visualizations from models
Examples - Practical examples of working with models