Mechanical Design Review Analysis#
Source: examples/mechanical_design_review_analysis.py
Introduction#
Analyze a compact mechanical design review centered on a lightweight mounting bracket redesign. The example keeps the workflow small while surfacing the sequence, statistics, embedding, and reporting helpers that are useful in engineering design studies.
Technical Implementation#
Validate and summarize a tiny unified event table from two bracket-review sessions.
Fit and compare Markov-chain traces, build a condition metric table, and run a permutation-style pair comparison on mass-oriented scores.
Embed the review notes with a deterministic custom embedder and render quick transition visualizations for the session traces.
1from __future__ import annotations
2
3import matplotlib.pyplot as plt
4import numpy as np
5
6import design_research_analysis as dran
7
8
9def _review_rows() -> list[dict[str, object]]:
10 """Return one tiny bracket-design review table."""
11 return [
12 {
13 "timestamp": "2026-02-01T09:00:00Z",
14 "session_id": "bracket-baseline",
15 "actor_id": "analyst-a",
16 "event_type": "propose",
17 "text": "baseline bracket keeps the rib layout but stays heavy near the mounting boss",
18 },
19 {
20 "timestamp": "2026-02-01T09:02:00Z",
21 "session_id": "bracket-baseline",
22 "actor_id": "analyst-b",
23 "event_type": "evaluate",
24 "text": "stress stays acceptable yet the mounting boss still drives unnecessary mass",
25 },
26 {
27 "timestamp": "2026-02-01T09:04:00Z",
28 "session_id": "bracket-baseline",
29 "actor_id": "analyst-a",
30 "event_type": "refine",
31 "text": "reduce web thickness and taper the fillet to remove aluminum from the boss",
32 },
33 {
34 "timestamp": "2026-02-01T09:06:00Z",
35 "session_id": "bracket-lightweight",
36 "actor_id": "analyst-a",
37 "event_type": "propose",
38 "text": "lightweight concept adds a diagonal rib and shortens the unsupported flange",
39 },
40 {
41 "timestamp": "2026-02-01T09:08:00Z",
42 "session_id": "bracket-lightweight",
43 "actor_id": "analyst-b",
44 "event_type": "evaluate",
45 "text": (
46 "the diagonal rib improves stiffness and should reduce peak "
47 "deflection at the bolt hole"
48 ),
49 },
50 {
51 "timestamp": "2026-02-01T09:10:00Z",
52 "session_id": "bracket-lightweight",
53 "actor_id": "analyst-a",
54 "event_type": "refine",
55 "text": (
56 "final concept trims flange mass while preserving load path "
57 "continuity into the base plate"
58 ),
59 },
60 ]
61
62
63def _custom_embedder(texts: list[str]) -> np.ndarray:
64 """Return one deterministic embedding matrix for example text."""
65 vectors = []
66 for index, text in enumerate(texts, start=1):
67 token_count = len(text.split())
68 vectors.append([float(index), float(token_count), float(len(set(text.split())))])
69 return np.asarray(vectors, dtype=float)
70
71
72def _follow_on_analysis_toolkit() -> dict[str, object]:
73 """Return advanced follow-on tools relevant to design-review studies."""
74 return {
75 "comparison_result_type": dran.ComparisonResult,
76 "decode_result_type": dran.DecodeResult,
77 "discrete_hmm_result_type": dran.DiscreteHMMResult,
78 "gaussian_hmm_result_type": dran.GaussianHMMResult,
79 "markov_result_type": dran.MarkovChainResult,
80 "table_report_type": dran.UnifiedTableValidationReport,
81 "dataset_module": dran.dataset,
82 "embedding_maps_module": dran.embedding_maps,
83 "embedding_result_type": dran.EmbeddingResult,
84 "language_module": dran.language,
85 "runtime_module": dran.runtime,
86 "sequence_module": dran.sequence,
87 "stats_module": dran.stats,
88 "visualization_module": dran.visualization,
89 "decode_hmm": dran.decode_hmm,
90 "embed_records": dran.embed_records,
91 "fit_discrete_hmm_from_table": dran.fit_discrete_hmm_from_table,
92 "fit_mixed_effects": dran.fit_mixed_effects,
93 "fit_text_gaussian_hmm_from_table": dran.fit_text_gaussian_hmm_from_table,
94 "fit_topic_model": dran.fit_topic_model,
95 "is_google_colab": dran.is_google_colab,
96 "is_notebook": dran.is_notebook,
97 "plot_state_graph": dran.plot_state_graph,
98 "plot_transition_matrix": dran.plot_transition_matrix,
99 "rank_tests_one_stop": dran.rank_tests_one_stop,
100 }
101
102
103def main() -> None:
104 """Run a lightweight mechanical design-review analysis workflow."""
105 rows = _review_rows()
106 report = dran.validate_unified_table(rows)
107 if not report.is_valid:
108 raise RuntimeError(f"Invalid unified table: {report.errors}")
109
110 markov = dran.fit_markov_chain_from_table(rows, order=1, smoothing=1.0)
111 alternate = dran.fit_markov_chain_from_table(list(reversed(rows)), order=1, smoothing=1.0)
112 comparison = markov - alternate
113 print("Validation:", report.is_valid, "warnings", len(report.warnings))
114 print("States:", ", ".join(str(state) for state in markov.states))
115 print("Comparison object:", isinstance(comparison, dran.ComparisonResult))
116
117 condition_rows = [
118 {"condition_id": "baseline", "condition": "baseline"},
119 {"condition_id": "lightweight", "condition": "lightweight"},
120 ]
121 run_rows = [
122 {"run_id": "run-1", "condition_id": "baseline"},
123 {"run_id": "run-2", "condition_id": "baseline"},
124 {"run_id": "run-3", "condition_id": "lightweight"},
125 {"run_id": "run-4", "condition_id": "lightweight"},
126 ]
127 evaluation_rows = [
128 {
129 "run_id": "run-1",
130 "metric_name": "mass_score",
131 "metric_value": 0.68,
132 "aggregation_level": "run",
133 },
134 {
135 "run_id": "run-2",
136 "metric_name": "mass_score",
137 "metric_value": 0.71,
138 "aggregation_level": "run",
139 },
140 {
141 "run_id": "run-3",
142 "metric_name": "mass_score",
143 "metric_value": 0.81,
144 "aggregation_level": "run",
145 },
146 {
147 "run_id": "run-4",
148 "metric_name": "mass_score",
149 "metric_value": 0.84,
150 "aggregation_level": "run",
151 },
152 ]
153 condition_metric_table = dran.build_condition_metric_table(
154 run_rows,
155 metric="mass_score",
156 evaluations=evaluation_rows,
157 conditions=condition_rows,
158 )
159 pair_report = dran.compare_condition_pairs(condition_metric_table, metric_name="mass_score")
160 print(pair_report.render_brief().splitlines()[1])
161
162 rank_result = dran.rank_tests_one_stop([0.68, 0.71], [0.81, 0.84], kind="mannwhitney")
163 print("Rank test:", rank_result["test"], f"p={rank_result['p_value']:.4f}")
164
165 embedding_result = dran.embed_records(
166 rows,
167 record_id_mapper=lambda row: f"{row['session_id']}-{row['event_type']}",
168 embedder=_custom_embedder,
169 )
170 print("Embedding shape:", embedding_result.embeddings.shape)
171 print("Embedding result object:", isinstance(embedding_result, dran.EmbeddingResult))
172
173 topic_summary = dran.fit_topic_model(
174 [str(row["text"]) for row in rows], n_topics=2, top_k_terms=3
175 )
176 print("Topic model topics:", topic_summary["n_topics"])
177
178 transition_figure, _ = dran.plot_transition_matrix(
179 markov, title="Bracket Review Transition Matrix"
180 )
181 state_graph_figure, _ = dran.plot_state_graph(
182 markov,
183 title="Bracket Review State Graph",
184 threshold=0.0,
185 )
186 plt.close(transition_figure)
187 plt.close(state_graph_figure)
188
189 toolkit = _follow_on_analysis_toolkit()
190 print(
191 "Toolkit modules:",
192 ", ".join(
193 module.__name__.split(".")[-1]
194 for module in (
195 toolkit["dataset_module"],
196 toolkit["embedding_maps_module"],
197 toolkit["language_module"],
198 toolkit["runtime_module"],
199 toolkit["sequence_module"],
200 toolkit["stats_module"],
201 toolkit["visualization_module"],
202 )
203 ),
204 )
205 print("Follow-on tools tracked:", len(toolkit))
206
207
208if __name__ == "__main__":
209 main()
Expected Results#
Run Command
PYTHONPATH=src python examples/mechanical_design_review_analysis.py
The script prints validation status, state labels, one significance summary, and an embedding shape for the bracket-design review sessions.