{ "cells": [ { "cell_type": "markdown", "id": "51c6734c", "metadata": {}, "source": [ "# Reorientation and fragmentation\n", "\n", "One coherent story: under load, grains **reorient**; that reorientation **fragments** them into\n", "orientation sub-grains; and the grains that fragment the most are the **rare events**. The same\n", "two classes drive all of it -- `OrientationTracker` builds the IPF trajectories and\n", "`FragmentationAnalyzer` does the segmentation, split detection, and per-grain fragment counts.\n", "\n", "**Needs:** NEML2 v3 (orientation math) and networkit (segmentation); no external binaries. The\n", "simulation parts run on the shipped real CPFE run `mwe_data/cpfe_ff_fragmentation`; the\n", "experiment parts on the synthetic split series `mwe_data/synthetic_split_{ff,nf,ebsd}`." ] }, { "cell_type": "markdown", "id": "47c5e821", "metadata": {}, "source": [ "## 1. Simulation: grains reorient under load\n", "\n", "`OrientationTracker().simulation_grain_tracks` reads each grain's `ori_rodrigues` (neml2 MRP)\n", "block time series; `plot_ipf_orientation_tracking` draws one IPF triangle with a start dot and a\n", "reorientation arrow per grain." ] }, { "cell_type": "code", "execution_count": 1, "id": "05626330", "metadata": { "execution": { "iopub.execute_input": "2026-10-09T23:27:54.781046Z", "iopub.status.busy": "2026-10-09T23:27:54.780547Z", "iopub.status.idle": "2026-10-09T23:27:57.466888Z", "shell.execute_reply": "2026-10-09T23:27:57.464402Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/workspace/personal/repos/graintrace/.venv/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", " from .autonotebook import tqdm as notebook_tqdm\n" ] }, { "data": { "text/plain": [ "PosixPath('out/ipf_orientation_tracking.png')" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numpy as np\n", "from graintrace.simulation_postprocessing import SimulationResults, FieldFileNaming\n", "from graintrace.ipf_orientation_tracking import OrientationTracker\n", "from graintrace.fragmentation import FragmentationAnalyzer\n", "from graintrace import plot_postprocessing as pp\n", "\n", "naming = FieldFileNaming(prefix=\"out_element_centroid\", index_width=4, sep=\"_\", suffix=\".csv\")\n", "res = SimulationResults(\n", " \"../../mwe_data/cpfe_ff_fragmentation/out.csv\",\n", " \"../../mwe_data/cpfe_ff_fragmentation/mesh_out\", field_naming=naming)\n", "tracker, analyzer = OrientationTracker(), FragmentationAnalyzer()\n", "steps = sorted(res.field_files.keys())\n", "tracks = tracker.simulation_grain_tracks(res, grain_ids=list(range(1, 11)), steps=steps)\n", "pp.plot_ipf_orientation_tracking(tracks, angle_convention=\"mrp\", output_folder=\"out\")" ] }, { "cell_type": "code", "execution_count": 2, "id": "5fbfbde5", "metadata": { "execution": { "iopub.execute_input": "2026-10-09T23:27:57.471661Z", "iopub.status.busy": "2026-10-09T23:27:57.470907Z", "iopub.status.idle": "2026-10-09T23:27:57.483643Z", "shell.execute_reply": "2026-10-09T23:27:57.481813Z" } }, "outputs": [ { "data": { "image/png": "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PwD5N23atJgxY0bDmbUplJ0gDgDkUpFi+HvvvRd33nnnGf/w8PnPfz6WLVt2zp+3LgVIYcGCBbFq1apRvXfVqlXD3iIEoPiya1N27dqVaBJoD0EcAMidIsTw3t7eeOWVV2LLli3x9/7e34uNGzc2/Pptt90W3/zmN+Opp56KG264YcTPEsSBVO65556mvg+A4skGcStTKDtBHADIlbzH8IceeihuvvnmWLhwYVx33XVx2WWXxTPPPNPwniuvvDK++c1vRk9PT8yfPz9+8IMfxOc///lhP2/mzJlx4403tmN0gDOsXr061qxZM+J71qxZE6tXr27TRAC0W/ZPAAnilJ0gDgDkRt5j+L333ht33313rFu37qzvufjii+O73/1uzJ49+/TZ9OnT4zvf+U78zM/8zBnv//znPx9dXV0tmRdgNO6777548MEHh12fcumll8Z9992XYCoA2iUbxO0Qp+z80xcAkAvNiuGDJ/vjxJ6Dcbz3veg/cjzqg0NR6+yI7mk90bNgTky5cFZ0Tu4e83xf/epX4z/8h/9wzvf9y3/5L2PRokVnnE+aNCn+5//8n3HhhRfG1772tdPn//Sf/tMxzwLQbKtXr47Vq1fHQw89FHfffffp823btsWBAwcafpMPgHJxQ5yqqdXr9XrqIQCAaptoDB8aGIxDb7wTB57fFEd37IsY6X/e1GoxddHcmH3T5XH+ysXR0dV5zvnuvffeuP/++0f1r2XVqlXx7LPPjvieb33rW/HII4/EF77whfixH/uxUX0uQDucPHkyZs2aFcePHz999pd/+ZcNkRyAcvnzP//zhj/JuGLFijOejwNlIogDAElNJIbXh+pxYP2m2PuDV2Lg6Ikxf3fX1Ckx/45rY/bHL49aR23Y92RvS47G7t27z7hpA1AUX/ziF+N73/ve6de//Mu/HP/lv/yXhBMB0EqPP/543HHHHadfT58+Pfr6+tINBC1mhzgAkMxEYvipg4dj6599P3Z9Z924YnhExMDRE7HrO+ti6599P04dPDzsex544IExf+6+ffvGNQ9AHnz2s59teP3II48kmgSAdshe5Dh8+HAcPXo00TTQeoI4AJDERGL40e3vxqY//E4c3ba3KbMc3bb3g8/b/m7DeW9v74gP0DybuXPnNmUugBQ+97nPNbzetGlT7Ny5M9E0ALTacH+y0R5xykwQBwDa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", "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.display import Image\n", "\n", "# plot_ipf_orientation_tracking writes to output_folder and does not call plt.show(),\n", "# so load the PNG it just wrote.\n", "Image(\"out/ipf_orientation_tracking.png\")" ] }, { "cell_type": "markdown", "id": "d4d5ce90", "metadata": {}, "source": [ "Each dot is a grain's starting orientation, coloured by the standard IPF key; the\n", "black line is its path through the load steps and the arrowhead is where it ended.\n", "Short arrows are grains rotating barely at all, long ones are grains whose lattice is\n", "being dragged around by slip. This is the per-grain *average* — section 2 opens each\n", "grain up to see whether its elements moved together." ] }, { "cell_type": "markdown", "id": "8bfec279", "metadata": {}, "source": [ "## 2. Simulation: reorientation to fragmentation (the 1x2 figure)\n", "\n", "`FragmentationAnalyzer().grain_fragments` re-segments each grain's elements by orientation into\n", "sub-grains. For intragranular data pass a fixed low Leiden `gamma` (here `gamma=0.25`; the\n", "gamma-by-percolation sweep is only for large many-grain NF/EBSD, and `gamma=0.1` under-splits --\n", "it leaves most grains whole). Leiden alone will still chop a *smooth* intragranular gradient into\n", "several near-identical communities, so `min_subgrain_miso_deg` (here 1°) imposes a **minimum\n", "sub-grain misorientation**: after Leiden, fragments whose (symmetry-aware) mean orientations are\n", "closer than that are merged, so only genuine sub-grains -- separated by a real low-angle\n", "sub-boundary -- survive as distinct fragments. The signature figure puts the two views side by\n", "side on the **real CPFE data** and links them by two channels:\n", "\n", "- **LEFT** -- every element of each grain (`OrientationTracker().simulation_element_tracks`), so\n", " the width of each fan is that grain's intragranular reorientation *spread*. Lines are thin and\n", " headless (`line_width=0.8`, `show_arrow=False`) because the panel is crowded.\n", "- **RIGHT** -- the resulting sub-grain forks (`plot_ipf_fragmentation_tracking`): the parent\n", " trajectory (neutral gray) forks at its split point into one child per fragment, small arrowhead.\n", "\n", "The linking channels are **color** and **line style**, both keyed to a per-grain *fragment* index.\n", "Color comes from a dark, high-contrast qualitative palette (ColorBrewer Dark2) so a grain's\n", "sub-grains **contrast sharply** -- pass a per-element `arrow_color` list on the left and the\n", "per-child `child_colors` (with `parent_color` for the gray parent) on the right. The palette is\n", "reused across grains (grains are told apart by their IPF *position*, sub-grains by color), and the\n", "start dots are drawn neutral **black** (`start_color=\"black\"`). Line style (`-`, `--`, `-.`, `:`)\n", "reinforces the same fragment index in the crowded left panel. So a fork on the right and the\n", "element cloud that formed it on the left share both color and style. Both plotters take a shared\n", "`ax` (returning it instead of saving) plus `line_width`, `arrow_scale`, `show_arrow`, and\n", "`label_fontsize`. (`arrow_color=\"ipf_final\"` is also available, tinting each track by the IPF\n", "color of its endpoint, when you prefer color to encode the final orientation.)" ] }, { "cell_type": "code", "execution_count": 3, "id": "c2986ecb", "metadata": { "execution": { "iopub.execute_input": "2026-10-09T23:27:57.488198Z", "iopub.status.busy": "2026-10-09T23:27:57.487664Z", "iopub.status.idle": "2026-10-09T23:28:14.883089Z", "shell.execute_reply": "2026-10-09T23:28:14.881186Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "=== Running GraphSpatialCluster ===\n", "\n", "Data loaded.\n", "\n", "Building graph with mode: knn\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r", "Building edges from nodes: 0%| | 0/161 [00:00\n", "\t\t\t\n", "\t\t\t\n", "\t\t" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ " NetworKit Leiden threads set to 1 (machine max 1)\n", "\n", "=== Running GraphSpatialCluster ===\n", "\n", "Data loaded.\n", "\n", "Building graph with mode: knn\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r", "Building edges from nodes: 0%| | 0/61 [00:00" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "\n", "last = steps[-1]\n", "ori_cols = [\"ori_rodrigues_x\", \"ori_rodrigues_y\", \"ori_rodrigues_z\"]\n", "grains = list(range(1, 11))\n", "STYLES = [\"-\", \"--\", \"-.\", \":\"]\n", "# dark, high-contrast qualitative palette (ColorBrewer Dark2) keyed by fragment\n", "COLORS = [\"#1b9e77\", \"#d95f02\", \"#7570b3\", \"#e7298a\", \"#66a61e\", \"#a6761d\"]\n", "\n", "# min_subgrain_miso_deg=1.0: only keep a split if the sub-grains differ by >1 deg, so a\n", "# smooth intragranular gradient is not chopped into near-identical fragments (the mean used\n", "# for the merge and the fork endpoints is a symmetry-aware quaternion mean).\n", "frags_df, per_elem = analyzer.grain_fragments(\n", " res, last, tol_deg=5.0, min_subgrain_miso_deg=1.0, seg_kwargs={\"gamma\": 0.25})\n", "\n", "# per-grain fragment-label -> (style, color): sub-grains of one grain contrast sharply\n", "frag_style, frag_color = {}, {}\n", "for g in grains:\n", " labs = sorted(l for l in per_elem.values() if l.startswith(f\"{g}.\"))\n", " frag_style[g] = {lab: STYLES[i % len(STYLES)] for i, lab in enumerate(labs)}\n", " frag_color[g] = {lab: COLORS[i % len(COLORS)] for i, lab in enumerate(labs)}\n", "\n", "# LEFT: every element of each grain, colored + styled by the fragment it belongs to\n", "df0 = res.load_field_data(steps[0])\n", "blk0 = np.rint(df0[\"block_id\"].to_numpy()).astype(int)\n", "left_tracks, left_styles, left_colors = [], [], []\n", "for g in grains:\n", " eids = df0.loc[blk0 == g, \"id\"].astype(int).tolist()\n", " for eid, tr in zip(eids, tracker.simulation_element_tracks(res, element_ids=eids, steps=steps)):\n", " lab = per_elem.get(eid)\n", " left_tracks.append(tr)\n", " left_styles.append(frag_style[g].get(lab, \"-\"))\n", " left_colors.append(frag_color[g].get(lab, \"0.35\"))\n", "\n", "# RIGHT: parent (pre-last) forks into per-fragment children at the last step\n", "# (mean_orientation_mrp is symmetry-aware -- pass the analyzer's symmetry)\n", "last_df = res.load_field_data(last).set_index(\"id\")\n", "branches, child_styles, child_colors = [], [], []\n", "for g in grains:\n", " parent = np.asarray([\n", " analyzer.mean_orientation_mrp(\n", " df[np.rint(df[\"block_id\"].to_numpy()).astype(int) == g][ori_cols].to_numpy(),\n", " analyzer.symmetry)\n", " for df in (res.load_field_data(int(s)) for s in steps[:-1])])\n", " labs = sorted(frag_style[g])\n", " children = [analyzer.mean_orientation_mrp(\n", " last_df.loc[[e for e, l in per_elem.items() if l == lab], ori_cols].to_numpy(),\n", " analyzer.symmetry)[None, :] for lab in labs]\n", " branches.append((parent, children))\n", " child_styles.append([frag_style[g][lab] for lab in labs])\n", " child_colors.append([frag_color[g][lab] for lab in labs])\n", "\n", "# color = dark categorical fragment color (a grain's sub-grains contrast), black start\n", "# dots, gray parent, no legend; line style reinforces the fragment.\n", "fig, (axL, axR) = plt.subplots(1, 2, figsize=(14, 7))\n", "pp.plot_ipf_orientation_tracking(left_tracks, angle_convention=\"mrp\", arrow_color=left_colors,\n", " start_color=\"black\", line_style=left_styles, line_width=0.8, show_arrow=False,\n", " label_fontsize=18, ax=axL)\n", "pp.plot_ipf_fragmentation_tracking(branches, angle_convention=\"mrp\", child_colors=child_colors,\n", " parent_color=\"0.35\", start_color=\"black\", child_line_styles=child_styles, line_width=2.0,\n", " arrow_scale=12, show_arrow=True, label_fontsize=18, ax=axR)\n", "fig.tight_layout()\n", "fig.savefig(\"out/reorientation_vs_fragmentation.png\")" ] }, { "cell_type": "markdown", "id": "ac6cc502", "metadata": {}, "source": [ "**Reading the figure -- visualizing fragmentation.** The left panel is the *evidence* and the\n", "right panel is the *interpretation*. A grain whose elements stay in a tight bundle on the left is\n", "rotating almost rigidly (one fragment, one solid fork on the right); a grain whose elements fan\n", "out into two or more lobes is developing intragranular orientation gradients, and the segmenter\n", "turns each lobe into a distinctly colored + styled fork. Reading the two together tells you what\n", "kind of split it is: if the right panel forks but the left element clouds *overlap* in the IPF,\n", "the sub-grains are close in orientation and the split is more a **spatial gradient** than a sharp\n", "orientation bimodal (the graph segmenter uses spatial adjacency as well as orientation, so a\n", "grain's sub-grains can share orientation yet occupy different regions). The number of forks is\n", "controlled by the segmenter (`gamma` for Leiden resolution, `tol_deg` for the misorientation edge\n", "cutoff); the left fan is the ground truth you calibrate those against. The per-grain fragment\n", "table (`grain_id, n_fragments, fragment_sizes, n_elements`) quantifies the right panel, and the\n", "fragments can be viewed in 3D in ParaView: `IPFProcessor.add_element_field_to_exodus` writes a\n", "per-element `fragment_label` scalar, and `add_element_rgb_to_exodus` writes a per-element RGB\n", "(`rgb_x/y/z`, mapped to color with scalar mapping off) in the *same* dark palette as this figure.\n", "For the colors to be meaningful, annotate the Exodus of the **analyzed** mesh (a co-registered\n", "loaded run's `mesh.e`/`sim_output.e` beside the `mesh_out` you segmented) -- the shipped bare\n", "`cpfe_hex_fragmentation/mesh.e` is a different microstructure, so the example colors it by block\n", "id only as a writer demo.\n", "\n", "**Why fragmentation matters.** Intragranular fragmentation is not just descriptive: orientation\n", "gradients and nascent sub-boundaries are where geometrically necessary dislocations pile up, they\n", "are the precursors to recrystallization nuclei, and they frequently co-locate with damage\n", "initiation. Crucially, fragmentation is a *distinct* signal from stress or strain magnitude -- a\n", "grain can be only moderately stressed yet fragment heavily (favourably oriented for multi-slip),\n", "or highly stressed yet rotate rigidly. That independence is exactly what makes \"which grains\n", "fragment the most\" worth flagging as a rare event in its own right." ] }, { "cell_type": "markdown", "id": "e896dc6e", "metadata": {}, "source": [ "**From fragmentation to rare events (REI, and REI-vs-REI plots).** Because fragmentation is an\n", "independent signal, it plugs into the same rare-event machinery used for stress or the Nye tensor,\n", "at two levels:\n", "\n", "- **Grain level** -- rank grains by `n_fragments` (or fragment-size dispersion) and select the\n", " rare ones with `rare_criteria_selection_library.select_highest_scalar`, exactly the selector the\n", " REI pipeline uses for scalar fields. This is the capstone in section 4 below.\n", "- **Field level** -- `FragmentationAnalyzer().write_reorientation_field` emits a per-element\n", " `reorientation_deg` scalar (misorientation from the reference step). Feed that CSV to\n", " `IdentifyRareClusters` with the `abs_scalar_diff` metric to find spatially coherent\n", " rare-reorientation clusters standalone, or combine `reorientation_deg` with `nye_tensor_*` /\n", " stress in a multi-feature `SimilarityMetric` so the clustering weighs fragmentation *and*\n", " mechanics together.\n", "\n", "Both routes emit rare-cluster point clouds (VTK), so a **fragmentation-driven REI can be overlaid\n", "against a stress- or GND-driven REI** with `REIComparison` -- the REI-vs-REI overlap plot\n", "(IoU/Dice, per-cluster matching) that answers \"do the grains that fragment the most coincide with\n", "the grains that are most stressed?\". That comparison is the payoff of treating reorientation as a\n", "first-class REI criterion rather than a purely visual diagnostic." ] }, { "cell_type": "markdown", "id": "a6ee7f03", "metadata": {}, "source": [ "## 3. Experiment: detect grain splits across load steps (FF / NF / EBSD)\n", "\n", "`FragmentationAnalyzer().detect_splits` finds one grain becoming several between two steps\n", "(cross-step graph + connected components). FF grain tables feed it directly; NF/EBSD reach the\n", "same detector via `.segment` (graph/Leiden) + `.seg_to_grain_table`. The shipped synthetic\n", "series has mixed multiplicity (1→1, 1→2, 1→3) with a `ground_truth.json`." ] }, { "cell_type": "code", "execution_count": 4, "id": "c836f9b6", "metadata": { "execution": { "iopub.execute_input": "2026-10-09T23:28:14.888970Z", "iopub.status.busy": "2026-10-09T23:28:14.888745Z", "iopub.status.idle": "2026-10-09T23:28:14.913943Z", "shell.execute_reply": "2026-10-09T23:28:14.912223Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3 parent_a children_b n_children child_radii\n", "0 2 2;6 2 10;10\n", "1 3 3;7;8 3 10;10;10\n", "2 5 5;9 2 10;10\n" ] } ], "source": [ "import glob, json\n", "gt = json.load(open(\"../../mwe_data/synthetic_split_ff/ground_truth.json\"))\n", "ff = sorted(glob.glob(\"../../mwe_data/synthetic_split_ff/ff_step*.csv\"))\n", "s = gt[\"split_step\"]\n", "res_ff = analyzer.detect_splits(ff[s - 1], ff[s], d_tol=20.0, theta_tol_deg=15.0, angle_type=\"degrees\")\n", "print(res_ff[\"n_splits\"], res_ff[\"split_correspondences\"]) # matches gt['n_splitting_grains']" ] }, { "cell_type": "markdown", "id": "9bc21d46", "metadata": {}, "source": [ "## 4. Rare events: the grains that split the most\n", "\n", "Close the loop: rank grains by fragment count and flag the rare (most-fragmented) ones, reusing\n", "`rare_criteria_selection_library.select_highest_scalar` (the same REI selector used for\n", "nye/stress). Reorientation-from-initial (`FragmentationAnalyzer().write_reorientation_field` +\n", "the `abs_scalar_diff` metric) is the field-level analogue for full REI." ] }, { "cell_type": "code", "execution_count": 5, "id": "d3521c36", "metadata": { "execution": { "iopub.execute_input": "2026-10-09T23:28:14.917414Z", "iopub.status.busy": "2026-10-09T23:28:14.917255Z", "iopub.status.idle": "2026-10-09T23:28:14.926126Z", "shell.execute_reply": "2026-10-09T23:28:14.924800Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "most-fragmented grains: [4, 5, 6]\n" ] } ], "source": [ "from graintrace import rare_criteria_selection_library as rcs\n", "rank = frags_df.rename(columns={\"grain_id\": \"cluster_label\", \"n_elements\": \"n\"})\n", "rare = rcs.select_highest_scalar(rank, required_cols=\"n_fragments\", k=3, min_size=1)\n", "print(\"most-fragmented grains:\", list(map(int, rare)))" ] }, { "cell_type": "markdown", "id": "4f7f3177", "metadata": {}, "source": [ "See :doc:`/api/fragmentation`, :doc:`/api/ipf_orientation_tracking`, and\n", ":doc:`/api/plot_postprocessing` for the API, and\n", "`examples/demonstrate_reorientation_fragmentation.py` for the full runnable script." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" } }, "nbformat": 4, "nbformat_minor": 5 }