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#

  1. Validate and summarize a tiny unified event table from two bracket-review sessions.

  2. Fit and compare Markov-chain traces, build a condition metric table, and run a permutation-style pair comparison on mass-oriented scores.

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