coordination-metrics 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- coordination_metrics-0.1.0/.gitignore +38 -0
- coordination_metrics-0.1.0/LICENSE +21 -0
- coordination_metrics-0.1.0/PKG-INFO +257 -0
- coordination_metrics-0.1.0/README.md +231 -0
- coordination_metrics-0.1.0/examples/full_dashboard.py +78 -0
- coordination_metrics-0.1.0/examples/navisworks_workflow.py +75 -0
- coordination_metrics-0.1.0/examples/output/coordination_report.html +233 -0
- coordination_metrics-0.1.0/examples/output/coordination_report.json +326 -0
- coordination_metrics-0.1.0/examples/quick_start.py +56 -0
- coordination_metrics-0.1.0/examples/sample_data/clash_round1.xml +99 -0
- coordination_metrics-0.1.0/examples/sample_data/clash_round2.xml +103 -0
- coordination_metrics-0.1.0/examples/sample_data/clash_round3.xml +79 -0
- coordination_metrics-0.1.0/examples/sample_data/meeting_minutes.csv +38 -0
- coordination_metrics-0.1.0/examples/sample_data/rfi_register.csv +101 -0
- coordination_metrics-0.1.0/examples/sample_data/submittal_register.csv +52 -0
- coordination_metrics-0.1.0/pyproject.toml +42 -0
- coordination_metrics-0.1.0/src/coordination_metrics/__init__.py +84 -0
- coordination_metrics-0.1.0/src/coordination_metrics/approval_rates.py +152 -0
- coordination_metrics-0.1.0/src/coordination_metrics/benchmarks.py +215 -0
- coordination_metrics-0.1.0/src/coordination_metrics/clash_trajectory.py +413 -0
- coordination_metrics-0.1.0/src/coordination_metrics/cli.py +120 -0
- coordination_metrics-0.1.0/src/coordination_metrics/core.py +237 -0
- coordination_metrics-0.1.0/src/coordination_metrics/cross_correlation.py +155 -0
- coordination_metrics-0.1.0/src/coordination_metrics/dashboard.py +629 -0
- coordination_metrics-0.1.0/src/coordination_metrics/ecv.py +188 -0
- coordination_metrics-0.1.0/src/coordination_metrics/exporters.py +151 -0
- coordination_metrics-0.1.0/src/coordination_metrics/mcp_server.py +309 -0
- coordination_metrics-0.1.0/src/coordination_metrics/meeting_decisions.py +421 -0
- coordination_metrics-0.1.0/src/coordination_metrics/parsers/__init__.py +27 -0
- coordination_metrics-0.1.0/src/coordination_metrics/parsers/bcf.py +237 -0
- coordination_metrics-0.1.0/src/coordination_metrics/parsers/bim360.py +89 -0
- coordination_metrics-0.1.0/src/coordination_metrics/parsers/csv_register.py +75 -0
- coordination_metrics-0.1.0/src/coordination_metrics/parsers/navisworks.py +70 -0
- coordination_metrics-0.1.0/src/coordination_metrics/parsers/solibri.py +144 -0
- coordination_metrics-0.1.0/src/coordination_metrics/recurring_clashes.py +446 -0
- coordination_metrics-0.1.0/src/coordination_metrics/rfi_distribution.py +362 -0
- coordination_metrics-0.1.0/src/coordination_metrics/visualizations.py +260 -0
- coordination_metrics-0.1.0/tests/conftest.py +159 -0
- coordination_metrics-0.1.0/tests/test_approval_rates.py +80 -0
- coordination_metrics-0.1.0/tests/test_benchmarks.py +128 -0
- coordination_metrics-0.1.0/tests/test_clash_trajectory.py +99 -0
- coordination_metrics-0.1.0/tests/test_cross_correlation.py +168 -0
- coordination_metrics-0.1.0/tests/test_ecv.py +204 -0
- coordination_metrics-0.1.0/tests/test_meeting_decisions.py +101 -0
- coordination_metrics-0.1.0/tests/test_recurring_clashes.py +103 -0
- coordination_metrics-0.1.0/tests/test_rfi_distribution.py +74 -0
- coordination_metrics-0.1.0/tests/test_statistical_improvements.py +637 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Environment
|
|
2
|
+
.env
|
|
3
|
+
.venv/
|
|
4
|
+
__pycache__/
|
|
5
|
+
*.pyc
|
|
6
|
+
*.pyo
|
|
7
|
+
|
|
8
|
+
# IDE
|
|
9
|
+
.vscode/
|
|
10
|
+
.idea/
|
|
11
|
+
*.swp
|
|
12
|
+
*.swo
|
|
13
|
+
|
|
14
|
+
# uv
|
|
15
|
+
.python-version
|
|
16
|
+
|
|
17
|
+
# Data (local state, not source)
|
|
18
|
+
data/
|
|
19
|
+
packages/mastermind-mcp/data/
|
|
20
|
+
NUL
|
|
21
|
+
.claude/
|
|
22
|
+
|
|
23
|
+
# Obsidian
|
|
24
|
+
vault/.obsidian/workspace.json
|
|
25
|
+
vault/.obsidian/workspace-mobile.json
|
|
26
|
+
vault/.obsidian/graph.json
|
|
27
|
+
|
|
28
|
+
# OS
|
|
29
|
+
Thumbs.db
|
|
30
|
+
.DS_Store
|
|
31
|
+
|
|
32
|
+
# Build
|
|
33
|
+
dist/
|
|
34
|
+
*.egg-info/
|
|
35
|
+
|
|
36
|
+
# SSH Keys
|
|
37
|
+
*.key
|
|
38
|
+
*.pub
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Houssame E. Hsain
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: coordination-metrics
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: 5 metrics that predict design coordination failure before it hits site. For BIM managers, design coordinators, and digital engineering leads.
|
|
5
|
+
Author-email: "Houssame E. Hsain" <houssameeddinehsain@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: AEC,BIM,clash-detection,construction,coordination,design-management
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering
|
|
13
|
+
Requires-Python: >=3.10
|
|
14
|
+
Requires-Dist: matplotlib>=3.7
|
|
15
|
+
Requires-Dist: numpy>=1.24
|
|
16
|
+
Requires-Dist: pandas>=2.0
|
|
17
|
+
Provides-Extra: all
|
|
18
|
+
Requires-Dist: fastmcp>=3.0; extra == 'all'
|
|
19
|
+
Requires-Dist: openpyxl>=3.1; extra == 'all'
|
|
20
|
+
Requires-Dist: scipy>=1.10; extra == 'all'
|
|
21
|
+
Provides-Extra: mcp
|
|
22
|
+
Requires-Dist: fastmcp>=3.0; extra == 'mcp'
|
|
23
|
+
Provides-Extra: scipy
|
|
24
|
+
Requires-Dist: scipy>=1.10; extra == 'scipy'
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# coordination-metrics
|
|
28
|
+
|
|
29
|
+
**5 Metrics That Predict Design Coordination Failure Before It Hits Site**
|
|
30
|
+
|
|
31
|
+
[](https://www.python.org/downloads/)
|
|
32
|
+
[](https://opensource.org/licenses/MIT)
|
|
33
|
+
[](https://pypi.org/project/coordination-metrics/)
|
|
34
|
+
|
|
35
|
+
A Python toolkit that extracts leading indicators of coordination failure from standard AEC project data — Navisworks clash exports, submittal registers, RFI logs, and meeting minutes. Designed for BIM managers, design coordinators, and digital engineering leads who need to catch problems weeks before they reach site.
|
|
36
|
+
|
|
37
|
+
## Why These Metrics
|
|
38
|
+
|
|
39
|
+
Design coordination on complex buildings is where projects are won or lost:
|
|
40
|
+
|
|
41
|
+
- **70% of construction defects originate in design** (GIRI, 2019) — most are coordination failures between disciplines, not individual design errors.
|
|
42
|
+
- **Rework costs 5-15% of total project value** (CII) — and the majority traces back to information that was available but never surfaced at the right time.
|
|
43
|
+
|
|
44
|
+
The standard practice of counting open clashes tells you where you are, not where you're heading. These 5 metrics are the *derivatives* — they tell you whether coordination is improving or deteriorating, while there's still time to act.
|
|
45
|
+
|
|
46
|
+
## Quick Start
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install git+https://github.com/houssameehsain/coordination-metrics.git
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from coordination_metrics import build_trajectory, compute_trajectory_slope
|
|
54
|
+
|
|
55
|
+
summaries = build_trajectory(["round1.xml", "round2.xml", "round3.xml"])
|
|
56
|
+
result = compute_trajectory_slope(summaries)
|
|
57
|
+
print(f"Slope: {result['slope']:+.1f} clashes/day — {result['interpretation']}")
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## The 5 Metrics
|
|
61
|
+
|
|
62
|
+
| # | Metric | What It Measures | Healthy | Critical |
|
|
63
|
+
|---|--------|-----------------|---------|----------|
|
|
64
|
+
| 1 | **Clash Trajectory Slope** | Rate of change in total hard clashes across detection rounds | Negative slope (clashes decreasing) | Positive slope > 2/day |
|
|
65
|
+
| 2 | **Recurring Clash Rate** | Percentage of resolved clashes that reappear near the same location | < 10% | > 25% |
|
|
66
|
+
| 3 | **First-Submission Approval Rate** | Submittals approved on the first attempt, by discipline | > 75% | < 50% |
|
|
67
|
+
| 4 | **RFI Response Time P90** | 90th percentile response time — exposes the long tail | P90 < 7 days | P90 > 14 days |
|
|
68
|
+
| 5 | **Meeting Decision Rate** | Fraction of agenda items that reach a decision, correlated with attendance | > 70% | < 45% |
|
|
69
|
+
|
|
70
|
+
## Metric Maturity
|
|
71
|
+
|
|
72
|
+
| Metric | Status | Notes |
|
|
73
|
+
|--------|--------|-------|
|
|
74
|
+
| Clash Trajectory | **Stable** | Exponential decay model validated against sample data |
|
|
75
|
+
| Recurring Clashes | **Beta** | Works well with BCF/GUID data; spatial matching has known limitations in dense MEP zones |
|
|
76
|
+
| Approval Rates | **Stable** | Requires column mapping for your specific platform export |
|
|
77
|
+
| RFI Distribution | **Stable** | Most reliable metric; survival analysis handles open RFIs |
|
|
78
|
+
| Meeting Decisions | **Experimental** | Requires custom CSV data; <10% of teams produce this format today |
|
|
79
|
+
| ECV | **Beta** | Novel metric; S-curve shape is configurable but defaults may not suit all project types |
|
|
80
|
+
| Benchmarks | **Indicative** | Based on published research + author estimates; not empirical percentile distributions |
|
|
81
|
+
|
|
82
|
+
## Full Dashboard
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
from coordination_metrics import CoordinationHealthDashboard
|
|
86
|
+
|
|
87
|
+
dashboard = CoordinationHealthDashboard(data_dir="./project_data/")
|
|
88
|
+
health = dashboard.run()
|
|
89
|
+
|
|
90
|
+
print(f"Overall: {health.overall_health:.0f}/100 ({health.health_level.value})")
|
|
91
|
+
dashboard.generate_html_report(health, output_path="report.html")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Data Sources
|
|
95
|
+
|
|
96
|
+
| Source | Format | Metrics Supported |
|
|
97
|
+
|--------|--------|-------------------|
|
|
98
|
+
| **Navisworks** Clash Detective | XML export | Clash trajectory, recurring clashes |
|
|
99
|
+
| **Solibri** | BCF / CSV results | Clash-based metrics |
|
|
100
|
+
| **BIM 360 / ACC** | CSV export | Clashes, issues (as RFIs) |
|
|
101
|
+
| **Procore** | CSV export | Submittals, RFIs |
|
|
102
|
+
| **Aconex** | CSV export | Submittals, RFIs, correspondence |
|
|
103
|
+
| **Manual registers** | CSV / Excel | All 5 metrics |
|
|
104
|
+
|
|
105
|
+
## AI Integration (MCP Server)
|
|
106
|
+
|
|
107
|
+
Connect to Claude Code as an MCP server for natural-language analysis:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
claude mcp add --scope project coordination-metrics -- \
|
|
111
|
+
python -m coordination_metrics.mcp_server
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Then ask Claude:
|
|
115
|
+
|
|
116
|
+
> "Analyse the clash trajectory from the exports in `./data/` and tell me which
|
|
117
|
+
> disciplines are falling behind."
|
|
118
|
+
|
|
119
|
+
Available tools: `analyse_clash_trajectory`, `detect_recurring_clashes`, `analyse_submittal_rates`, `analyse_rfi_distribution`, `analyse_meeting_decisions`, `generate_coordination_health_report`, `compute_earned_coordination_value`, `compare_to_benchmarks`, `discover_cross_correlations_tool`.
|
|
120
|
+
|
|
121
|
+
## Earned Coordination Value (ECV)
|
|
122
|
+
|
|
123
|
+
A novel composite metric analogous to Earned Value Management (EVM), adapted for design coordination. It answers: "Are we resolving coordination issues fast enough to meet the project milestone?"
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
from datetime import date
|
|
127
|
+
from coordination_metrics.ecv import ECVConfig, compute_ecv
|
|
128
|
+
|
|
129
|
+
config = ECVConfig(
|
|
130
|
+
project_start=date(2026, 1, 1),
|
|
131
|
+
coordination_deadline=date(2026, 7, 1),
|
|
132
|
+
total_expected_clashes=200,
|
|
133
|
+
total_expected_rfis=100,
|
|
134
|
+
total_expected_submittals=80,
|
|
135
|
+
total_expected_meetings=24,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
ecv = compute_ecv(
|
|
139
|
+
config=config,
|
|
140
|
+
measurement_date=date(2026, 4, 1),
|
|
141
|
+
clashes_resolved=120,
|
|
142
|
+
rfis_answered=55,
|
|
143
|
+
submittals_approved=45,
|
|
144
|
+
decisions_made=60,
|
|
145
|
+
)
|
|
146
|
+
print(f"CPI: {ecv.cpi:.2f} — {ecv.status}")
|
|
147
|
+
# CPI > 1.0 = ahead, CPI = 1.0 = on track, CPI < 1.0 = behind
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Benchmark Comparisons
|
|
151
|
+
|
|
152
|
+
Compare your project's metrics against industry benchmarks derived from published research (Navigant, GIRI, CII, Chahrour et al.):
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
from coordination_metrics.benchmarks import compare_to_benchmark
|
|
156
|
+
|
|
157
|
+
result = compare_to_benchmark("recurring_clash_rate", 12.5)
|
|
158
|
+
print(f"{result['insight']}")
|
|
159
|
+
# "Your Recurring clash rate (%) of 12.5 is at the 55th percentile."
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Supported benchmarks: `clash_reduction_rate_per_round`, `recurring_clash_rate`, `first_submission_approval_rate`, `rfi_response_p90_days`, `rfi_no_response_rate`, `meeting_decision_rate`.
|
|
163
|
+
|
|
164
|
+
## Cross-Metric Correlations
|
|
165
|
+
|
|
166
|
+
The correlation engine discovers relationships between the 5 metrics that reveal systemic coordination failures:
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
from coordination_metrics.cross_correlation import discover_cross_correlations
|
|
170
|
+
|
|
171
|
+
insights = discover_cross_correlations(
|
|
172
|
+
clash_trajectory_data={"health": "stalled"},
|
|
173
|
+
recurrence_data={"recurrence_rate_pct": 18.0},
|
|
174
|
+
approval_data={},
|
|
175
|
+
rfi_data={"no_response_pct": 25},
|
|
176
|
+
meeting_data={"avg_decision_rate_pct": 40, "critical_absence": "Mechanical"},
|
|
177
|
+
)
|
|
178
|
+
for i in insights:
|
|
179
|
+
print(f"[{'ACTION' if i.actionable else 'INFO'}] {i.insight}")
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Architecture
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
coordination_metrics/
|
|
186
|
+
core.py # Data models: ClashRoundSummary, CoordinationHealth, etc.
|
|
187
|
+
clash_trajectory.py # Metric 1: slope + exponential decay + zero-clash projection
|
|
188
|
+
recurring_clashes.py # Metric 2: 3D spatial recurrence detection
|
|
189
|
+
approval_rates.py # Metric 3: first-submission approval by discipline
|
|
190
|
+
rfi_distribution.py # Metric 4: response time P90 + bottleneck flagging
|
|
191
|
+
meeting_decisions.py # Metric 5: decision rate + attendance correlation
|
|
192
|
+
ecv.py # Earned Coordination Value (CPI for coordination)
|
|
193
|
+
benchmarks.py # Industry benchmark database and comparison
|
|
194
|
+
cross_correlation.py # Cross-metric correlation engine
|
|
195
|
+
dashboard.py # Unified health score + benchmark + insight integration
|
|
196
|
+
visualizations.py # Dark-themed matplotlib charts
|
|
197
|
+
exporters.py # HTML report, JSON, chart images
|
|
198
|
+
mcp_server.py # FastMCP server for Claude Code integration
|
|
199
|
+
cli.py # Command-line interface
|
|
200
|
+
parsers/
|
|
201
|
+
navisworks.py # Navisworks Clash Detective XML parser
|
|
202
|
+
solibri.py # Solibri BCF/results parser
|
|
203
|
+
bim360.py # BIM 360 / ACC export parser
|
|
204
|
+
csv_register.py # Generic CSV/Excel with auto-detection
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Installation
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
# Core (pandas, numpy, matplotlib)
|
|
211
|
+
pip install git+https://github.com/houssameehsain/coordination-metrics.git
|
|
212
|
+
|
|
213
|
+
# With MCP server support
|
|
214
|
+
pip install "coordination-metrics[mcp] @ git+https://github.com/houssameehsain/coordination-metrics.git"
|
|
215
|
+
|
|
216
|
+
# Everything
|
|
217
|
+
pip install "coordination-metrics[all] @ git+https://github.com/houssameehsain/coordination-metrics.git"
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Command-Line Interface
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
# Full health report
|
|
224
|
+
coord-metrics report ./data/ --output report.html
|
|
225
|
+
|
|
226
|
+
# Individual metrics
|
|
227
|
+
coord-metrics clashes ./exports/
|
|
228
|
+
coord-metrics rfis ./rfi_register.csv
|
|
229
|
+
coord-metrics submittals ./submittal_register.csv
|
|
230
|
+
coord-metrics meetings ./meeting_minutes.csv
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## Examples
|
|
234
|
+
|
|
235
|
+
See the [`examples/`](examples/) directory:
|
|
236
|
+
|
|
237
|
+
- **`quick_start.py`** — Parse clash exports and compute trajectory in 10 lines.
|
|
238
|
+
- **`full_dashboard.py`** — Run all 5 metrics and generate an HTML report.
|
|
239
|
+
- **`navisworks_workflow.py`** — Navisworks-specific workflow with charts.
|
|
240
|
+
|
|
241
|
+
## References
|
|
242
|
+
|
|
243
|
+
- GIRI (Get It Right Initiative). *Literature Review, Revision 3*. 2019.
|
|
244
|
+
- Construction Industry Institute. *Research Summary 153-1*. Rework costs 5-15% of project value.
|
|
245
|
+
- Navigant/CMAA. *Construction Industry Survey*. 2013. ~1M RFIs across 1,362 projects.
|
|
246
|
+
- Chahrour, R. et al. *Cost-benefit analysis of BIM-enabled design clash detection and resolution*. 2020. 20% cost savings.
|
|
247
|
+
- Cavka, H.B. et al. *Developing owner information requirements for BIM-enabled project delivery*. 2015.
|
|
248
|
+
- Leite, F. et al. *Analysis of modeling effort and impact of different levels of detail in building information models*. Automation in Construction, 2011.
|
|
249
|
+
- Eastman, C. et al. *BIM Handbook*. Wiley, 2018.
|
|
250
|
+
|
|
251
|
+
## Contributing
|
|
252
|
+
|
|
253
|
+
Contributions welcome. Please open an issue first for major changes.
|
|
254
|
+
|
|
255
|
+
## License
|
|
256
|
+
|
|
257
|
+
[MIT](LICENSE) — Houssame E. Hsain, 2026.
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# coordination-metrics
|
|
2
|
+
|
|
3
|
+
**5 Metrics That Predict Design Coordination Failure Before It Hits Site**
|
|
4
|
+
|
|
5
|
+
[](https://www.python.org/downloads/)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://pypi.org/project/coordination-metrics/)
|
|
8
|
+
|
|
9
|
+
A Python toolkit that extracts leading indicators of coordination failure from standard AEC project data — Navisworks clash exports, submittal registers, RFI logs, and meeting minutes. Designed for BIM managers, design coordinators, and digital engineering leads who need to catch problems weeks before they reach site.
|
|
10
|
+
|
|
11
|
+
## Why These Metrics
|
|
12
|
+
|
|
13
|
+
Design coordination on complex buildings is where projects are won or lost:
|
|
14
|
+
|
|
15
|
+
- **70% of construction defects originate in design** (GIRI, 2019) — most are coordination failures between disciplines, not individual design errors.
|
|
16
|
+
- **Rework costs 5-15% of total project value** (CII) — and the majority traces back to information that was available but never surfaced at the right time.
|
|
17
|
+
|
|
18
|
+
The standard practice of counting open clashes tells you where you are, not where you're heading. These 5 metrics are the *derivatives* — they tell you whether coordination is improving or deteriorating, while there's still time to act.
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install git+https://github.com/houssameehsain/coordination-metrics.git
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
from coordination_metrics import build_trajectory, compute_trajectory_slope
|
|
28
|
+
|
|
29
|
+
summaries = build_trajectory(["round1.xml", "round2.xml", "round3.xml"])
|
|
30
|
+
result = compute_trajectory_slope(summaries)
|
|
31
|
+
print(f"Slope: {result['slope']:+.1f} clashes/day — {result['interpretation']}")
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## The 5 Metrics
|
|
35
|
+
|
|
36
|
+
| # | Metric | What It Measures | Healthy | Critical |
|
|
37
|
+
|---|--------|-----------------|---------|----------|
|
|
38
|
+
| 1 | **Clash Trajectory Slope** | Rate of change in total hard clashes across detection rounds | Negative slope (clashes decreasing) | Positive slope > 2/day |
|
|
39
|
+
| 2 | **Recurring Clash Rate** | Percentage of resolved clashes that reappear near the same location | < 10% | > 25% |
|
|
40
|
+
| 3 | **First-Submission Approval Rate** | Submittals approved on the first attempt, by discipline | > 75% | < 50% |
|
|
41
|
+
| 4 | **RFI Response Time P90** | 90th percentile response time — exposes the long tail | P90 < 7 days | P90 > 14 days |
|
|
42
|
+
| 5 | **Meeting Decision Rate** | Fraction of agenda items that reach a decision, correlated with attendance | > 70% | < 45% |
|
|
43
|
+
|
|
44
|
+
## Metric Maturity
|
|
45
|
+
|
|
46
|
+
| Metric | Status | Notes |
|
|
47
|
+
|--------|--------|-------|
|
|
48
|
+
| Clash Trajectory | **Stable** | Exponential decay model validated against sample data |
|
|
49
|
+
| Recurring Clashes | **Beta** | Works well with BCF/GUID data; spatial matching has known limitations in dense MEP zones |
|
|
50
|
+
| Approval Rates | **Stable** | Requires column mapping for your specific platform export |
|
|
51
|
+
| RFI Distribution | **Stable** | Most reliable metric; survival analysis handles open RFIs |
|
|
52
|
+
| Meeting Decisions | **Experimental** | Requires custom CSV data; <10% of teams produce this format today |
|
|
53
|
+
| ECV | **Beta** | Novel metric; S-curve shape is configurable but defaults may not suit all project types |
|
|
54
|
+
| Benchmarks | **Indicative** | Based on published research + author estimates; not empirical percentile distributions |
|
|
55
|
+
|
|
56
|
+
## Full Dashboard
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from coordination_metrics import CoordinationHealthDashboard
|
|
60
|
+
|
|
61
|
+
dashboard = CoordinationHealthDashboard(data_dir="./project_data/")
|
|
62
|
+
health = dashboard.run()
|
|
63
|
+
|
|
64
|
+
print(f"Overall: {health.overall_health:.0f}/100 ({health.health_level.value})")
|
|
65
|
+
dashboard.generate_html_report(health, output_path="report.html")
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Data Sources
|
|
69
|
+
|
|
70
|
+
| Source | Format | Metrics Supported |
|
|
71
|
+
|--------|--------|-------------------|
|
|
72
|
+
| **Navisworks** Clash Detective | XML export | Clash trajectory, recurring clashes |
|
|
73
|
+
| **Solibri** | BCF / CSV results | Clash-based metrics |
|
|
74
|
+
| **BIM 360 / ACC** | CSV export | Clashes, issues (as RFIs) |
|
|
75
|
+
| **Procore** | CSV export | Submittals, RFIs |
|
|
76
|
+
| **Aconex** | CSV export | Submittals, RFIs, correspondence |
|
|
77
|
+
| **Manual registers** | CSV / Excel | All 5 metrics |
|
|
78
|
+
|
|
79
|
+
## AI Integration (MCP Server)
|
|
80
|
+
|
|
81
|
+
Connect to Claude Code as an MCP server for natural-language analysis:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
claude mcp add --scope project coordination-metrics -- \
|
|
85
|
+
python -m coordination_metrics.mcp_server
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Then ask Claude:
|
|
89
|
+
|
|
90
|
+
> "Analyse the clash trajectory from the exports in `./data/` and tell me which
|
|
91
|
+
> disciplines are falling behind."
|
|
92
|
+
|
|
93
|
+
Available tools: `analyse_clash_trajectory`, `detect_recurring_clashes`, `analyse_submittal_rates`, `analyse_rfi_distribution`, `analyse_meeting_decisions`, `generate_coordination_health_report`, `compute_earned_coordination_value`, `compare_to_benchmarks`, `discover_cross_correlations_tool`.
|
|
94
|
+
|
|
95
|
+
## Earned Coordination Value (ECV)
|
|
96
|
+
|
|
97
|
+
A novel composite metric analogous to Earned Value Management (EVM), adapted for design coordination. It answers: "Are we resolving coordination issues fast enough to meet the project milestone?"
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from datetime import date
|
|
101
|
+
from coordination_metrics.ecv import ECVConfig, compute_ecv
|
|
102
|
+
|
|
103
|
+
config = ECVConfig(
|
|
104
|
+
project_start=date(2026, 1, 1),
|
|
105
|
+
coordination_deadline=date(2026, 7, 1),
|
|
106
|
+
total_expected_clashes=200,
|
|
107
|
+
total_expected_rfis=100,
|
|
108
|
+
total_expected_submittals=80,
|
|
109
|
+
total_expected_meetings=24,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
ecv = compute_ecv(
|
|
113
|
+
config=config,
|
|
114
|
+
measurement_date=date(2026, 4, 1),
|
|
115
|
+
clashes_resolved=120,
|
|
116
|
+
rfis_answered=55,
|
|
117
|
+
submittals_approved=45,
|
|
118
|
+
decisions_made=60,
|
|
119
|
+
)
|
|
120
|
+
print(f"CPI: {ecv.cpi:.2f} — {ecv.status}")
|
|
121
|
+
# CPI > 1.0 = ahead, CPI = 1.0 = on track, CPI < 1.0 = behind
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Benchmark Comparisons
|
|
125
|
+
|
|
126
|
+
Compare your project's metrics against industry benchmarks derived from published research (Navigant, GIRI, CII, Chahrour et al.):
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
from coordination_metrics.benchmarks import compare_to_benchmark
|
|
130
|
+
|
|
131
|
+
result = compare_to_benchmark("recurring_clash_rate", 12.5)
|
|
132
|
+
print(f"{result['insight']}")
|
|
133
|
+
# "Your Recurring clash rate (%) of 12.5 is at the 55th percentile."
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Supported benchmarks: `clash_reduction_rate_per_round`, `recurring_clash_rate`, `first_submission_approval_rate`, `rfi_response_p90_days`, `rfi_no_response_rate`, `meeting_decision_rate`.
|
|
137
|
+
|
|
138
|
+
## Cross-Metric Correlations
|
|
139
|
+
|
|
140
|
+
The correlation engine discovers relationships between the 5 metrics that reveal systemic coordination failures:
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
from coordination_metrics.cross_correlation import discover_cross_correlations
|
|
144
|
+
|
|
145
|
+
insights = discover_cross_correlations(
|
|
146
|
+
clash_trajectory_data={"health": "stalled"},
|
|
147
|
+
recurrence_data={"recurrence_rate_pct": 18.0},
|
|
148
|
+
approval_data={},
|
|
149
|
+
rfi_data={"no_response_pct": 25},
|
|
150
|
+
meeting_data={"avg_decision_rate_pct": 40, "critical_absence": "Mechanical"},
|
|
151
|
+
)
|
|
152
|
+
for i in insights:
|
|
153
|
+
print(f"[{'ACTION' if i.actionable else 'INFO'}] {i.insight}")
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Architecture
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
coordination_metrics/
|
|
160
|
+
core.py # Data models: ClashRoundSummary, CoordinationHealth, etc.
|
|
161
|
+
clash_trajectory.py # Metric 1: slope + exponential decay + zero-clash projection
|
|
162
|
+
recurring_clashes.py # Metric 2: 3D spatial recurrence detection
|
|
163
|
+
approval_rates.py # Metric 3: first-submission approval by discipline
|
|
164
|
+
rfi_distribution.py # Metric 4: response time P90 + bottleneck flagging
|
|
165
|
+
meeting_decisions.py # Metric 5: decision rate + attendance correlation
|
|
166
|
+
ecv.py # Earned Coordination Value (CPI for coordination)
|
|
167
|
+
benchmarks.py # Industry benchmark database and comparison
|
|
168
|
+
cross_correlation.py # Cross-metric correlation engine
|
|
169
|
+
dashboard.py # Unified health score + benchmark + insight integration
|
|
170
|
+
visualizations.py # Dark-themed matplotlib charts
|
|
171
|
+
exporters.py # HTML report, JSON, chart images
|
|
172
|
+
mcp_server.py # FastMCP server for Claude Code integration
|
|
173
|
+
cli.py # Command-line interface
|
|
174
|
+
parsers/
|
|
175
|
+
navisworks.py # Navisworks Clash Detective XML parser
|
|
176
|
+
solibri.py # Solibri BCF/results parser
|
|
177
|
+
bim360.py # BIM 360 / ACC export parser
|
|
178
|
+
csv_register.py # Generic CSV/Excel with auto-detection
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Installation
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
# Core (pandas, numpy, matplotlib)
|
|
185
|
+
pip install git+https://github.com/houssameehsain/coordination-metrics.git
|
|
186
|
+
|
|
187
|
+
# With MCP server support
|
|
188
|
+
pip install "coordination-metrics[mcp] @ git+https://github.com/houssameehsain/coordination-metrics.git"
|
|
189
|
+
|
|
190
|
+
# Everything
|
|
191
|
+
pip install "coordination-metrics[all] @ git+https://github.com/houssameehsain/coordination-metrics.git"
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Command-Line Interface
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
# Full health report
|
|
198
|
+
coord-metrics report ./data/ --output report.html
|
|
199
|
+
|
|
200
|
+
# Individual metrics
|
|
201
|
+
coord-metrics clashes ./exports/
|
|
202
|
+
coord-metrics rfis ./rfi_register.csv
|
|
203
|
+
coord-metrics submittals ./submittal_register.csv
|
|
204
|
+
coord-metrics meetings ./meeting_minutes.csv
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Examples
|
|
208
|
+
|
|
209
|
+
See the [`examples/`](examples/) directory:
|
|
210
|
+
|
|
211
|
+
- **`quick_start.py`** — Parse clash exports and compute trajectory in 10 lines.
|
|
212
|
+
- **`full_dashboard.py`** — Run all 5 metrics and generate an HTML report.
|
|
213
|
+
- **`navisworks_workflow.py`** — Navisworks-specific workflow with charts.
|
|
214
|
+
|
|
215
|
+
## References
|
|
216
|
+
|
|
217
|
+
- GIRI (Get It Right Initiative). *Literature Review, Revision 3*. 2019.
|
|
218
|
+
- Construction Industry Institute. *Research Summary 153-1*. Rework costs 5-15% of project value.
|
|
219
|
+
- Navigant/CMAA. *Construction Industry Survey*. 2013. ~1M RFIs across 1,362 projects.
|
|
220
|
+
- Chahrour, R. et al. *Cost-benefit analysis of BIM-enabled design clash detection and resolution*. 2020. 20% cost savings.
|
|
221
|
+
- Cavka, H.B. et al. *Developing owner information requirements for BIM-enabled project delivery*. 2015.
|
|
222
|
+
- Leite, F. et al. *Analysis of modeling effort and impact of different levels of detail in building information models*. Automation in Construction, 2011.
|
|
223
|
+
- Eastman, C. et al. *BIM Handbook*. Wiley, 2018.
|
|
224
|
+
|
|
225
|
+
## Contributing
|
|
226
|
+
|
|
227
|
+
Contributions welcome. Please open an issue first for major changes.
|
|
228
|
+
|
|
229
|
+
## License
|
|
230
|
+
|
|
231
|
+
[MIT](LICENSE) — Houssame E. Hsain, 2026.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""Full dashboard example — runs all 5 metrics and generates an HTML report.
|
|
2
|
+
|
|
3
|
+
Usage:
|
|
4
|
+
python examples/full_dashboard.py
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from coordination_metrics.dashboard import CoordinationHealthDashboard
|
|
10
|
+
from coordination_metrics.exporters import export_to_json, export_to_html
|
|
11
|
+
|
|
12
|
+
DATA = Path(__file__).parent / "sample_data"
|
|
13
|
+
OUTPUT = Path(__file__).parent / "output"
|
|
14
|
+
OUTPUT.mkdir(exist_ok=True)
|
|
15
|
+
|
|
16
|
+
# Create dashboard with auto-discovery
|
|
17
|
+
dashboard = CoordinationHealthDashboard(
|
|
18
|
+
data_dir=DATA,
|
|
19
|
+
clash_exports=sorted(DATA.glob("clash_round*.xml")),
|
|
20
|
+
submittal_register=DATA / "submittal_register.csv",
|
|
21
|
+
rfi_register=DATA / "rfi_register.csv",
|
|
22
|
+
meeting_register=DATA / "meeting_minutes.csv",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# Run all 5 metrics
|
|
26
|
+
health = dashboard.run()
|
|
27
|
+
summary = health.summary()
|
|
28
|
+
|
|
29
|
+
# Print results
|
|
30
|
+
print("=" * 60)
|
|
31
|
+
print("COORDINATION HEALTH DASHBOARD")
|
|
32
|
+
print("=" * 60)
|
|
33
|
+
print(f"\n Overall Health: {summary['overall_health']}/100")
|
|
34
|
+
print(f" Status: {summary['health_level'].upper()}")
|
|
35
|
+
print(f"\n Metric Scores:")
|
|
36
|
+
for metric, score in summary["metrics"].items():
|
|
37
|
+
label = metric.replace("_", " ").title()
|
|
38
|
+
bar = "#" * int(score / 5) + "-" * (20 - int(score / 5))
|
|
39
|
+
print(f" {label:.<25} [{bar}] {score}")
|
|
40
|
+
|
|
41
|
+
# Generate HTML report
|
|
42
|
+
html_path = OUTPUT / "coordination_report.html"
|
|
43
|
+
export_to_html(health, output_path=html_path)
|
|
44
|
+
print(f"\n HTML report: {html_path}")
|
|
45
|
+
|
|
46
|
+
# Generate JSON export
|
|
47
|
+
json_path = OUTPUT / "coordination_report.json"
|
|
48
|
+
export_to_json(health, output_path=json_path)
|
|
49
|
+
print(f" JSON export: {json_path}")
|
|
50
|
+
|
|
51
|
+
# Show details for any critical metrics
|
|
52
|
+
print("\n" + "-" * 60)
|
|
53
|
+
print("DETAIL: Metrics requiring attention")
|
|
54
|
+
print("-" * 60)
|
|
55
|
+
|
|
56
|
+
details = summary.get("details", {})
|
|
57
|
+
|
|
58
|
+
# Clash trajectory
|
|
59
|
+
ct = details.get("clash_trajectory", {})
|
|
60
|
+
if "slope" in ct:
|
|
61
|
+
print(f"\n Clash Trajectory: {ct.get('interpretation', '')}")
|
|
62
|
+
|
|
63
|
+
# RFI bottlenecks
|
|
64
|
+
rfi = details.get("rfi_distribution", {})
|
|
65
|
+
if "by_discipline" in rfi:
|
|
66
|
+
bottlenecks = [d for d in rfi["by_discipline"] if d.get("is_bottleneck")]
|
|
67
|
+
if bottlenecks:
|
|
68
|
+
print(f"\n RFI Bottleneck disciplines:")
|
|
69
|
+
for b in bottlenecks:
|
|
70
|
+
print(f" - {b['discipline']}: P90 = {b['p90_days']} days")
|
|
71
|
+
|
|
72
|
+
# Meeting decisions
|
|
73
|
+
mtg = details.get("meeting_decisions", {})
|
|
74
|
+
if "correlation_strength" in mtg:
|
|
75
|
+
print(f"\n Meeting attendance-decision correlation: {mtg['correlation_strength']}")
|
|
76
|
+
print(f" {mtg.get('interpretation', '')}")
|
|
77
|
+
|
|
78
|
+
print("\nDone!")
|