[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6QH52ACPCBV4W8GTM3KA5NM":3,"skill-same:01M6QH52ACPCBV4W8GTM3KA5NM":106},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":26,"publishedAt":46,"linkOnly":47,"markdownContent":48,"markdownBody":49,"frontMatter":50,"refName":59,"commitSha":60,"skillDirectory":61,"forksCount":14,"repositoryHtmlUrl":62,"repositoryHomepageUrl":63,"ownerHtmlUrl":64,"ownerBlogUrl":65,"ownerDescription":66,"updatedAt":67,"install":68,"resources":81},"01M6QH52ACPCBV4W8GTM3KA5NM","openpiv",null,"Performs Particle Image Velocimetry (PIV) analysis with OpenPIV. Use when extracting velocity fields from PIV image pairs, analyzing fluid dynamics or flow visualization experiments, cross-correlating interrogation windows, validating and replacing spurious PIV vectors, or computing vorticity, strain rate, and turbulence statistics from measured velocity fields.","Tashima-Tarsh\u002FDisha6.6","Tashima-Tarsh","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F269906498?v=4","01M6PBH98X03XERH0HFT4PFB1P","NITISH KUMAR","01M6PBH9DA0M6KM3Z12P848F0K",0,"BSD-3-Clause","https:\u002F\u002Fgithub.com\u002FTashima-Tarsh\u002FDisha6.6\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fkd-openpiv\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000013","分析与可视化","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000016","图像与多媒体",[5,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45],"numpy","rate","strain","turbulence","scientific","dynamics","as","fluid dynamics","scipy","image","uv","use","edit","write","read","team","windows","experiments","python","2026-11-10 10:12:30",false,"---\nname: openpiv\ndescription: Performs Particle Image Velocimetry (PIV) analysis with OpenPIV. Use when extracting velocity fields from PIV image pairs, analyzing fluid dynamics or flow visualization experiments, cross-correlating interrogation windows, validating and replacing spurious PIV vectors, or computing vorticity, strain rate, and turbulence statistics from measured velocity fields.\nlicense: BSD-3-Clause\ncompatibility: Requires Python 3.10+ with openpiv installed (uv pip install openpiv). numpy, scipy, scikit-image, and matplotlib arrive as dependencies. No network access needed after install.\nallowed-tools: Read Write Edit Bash\nmetadata:\n  version: \"1.3\"\n  skill-author: OpenPIV Team\n  tested-against: \"openpiv 0.26.1\"\n  last-reviewed: \"2026-10-01\"\ncategory: \"scientific-computing\"\n---\n\n# OpenPIV\n\n## Overview\n\nOpenPIV (Open Particle Image Velocimetry) analyzes fluid flow from PIV image pairs. It covers\npreprocessing, cross-correlation, vector validation, outlier replacement, smoothing, and scaling to\nphysical units.\n\nTargets **openpiv 0.26.1**. Synthetic checks ran on Python 3.13, NumPy 2.5.3, SciPy 1.18.1,\nscikit-image 0.26.0, and Matplotlib 3.11.2. Rust was not installed; use `backend=\"scipy\"` for the\ntested path. See [review evidence](references\u002Fadvanced_algorithms.md#review-sources-and-verification).\n\n## When to use\n\nUse this skill when working with experimental PIV or flow-visualization image pairs: measuring 2D\nvelocity fields, tuning interrogation-window parameters, validating vectors, or deriving vorticity,\nstrain rate, and turbulence statistics. For *simulating* flow rather than measuring it, use a CFD\nskill instead.\n\n## Quick Start\n\nInstall OpenPIV:\n\n```bash\nuv pip install openpiv\n\n# Pin it when the analysis needs to be reproducible -- this is the version every\n# snippet below was checked against.\nuv pip install \"openpiv==0.26.1\"\n```\n\nRun PIV analysis on an image pair:\n\n```python\nimport numpy as np\nfrom openpiv import tools, pyprocess, validation, filters, scaling\n\nframe_a = tools.imread(\"image_a.bmp\")\nframe_b = tools.imread(\"image_b.bmp\")\n\n# Always returns (u, v, s2n); s2n is all NaN if sig2noise_method=None.\nu, v, s2n = pyprocess.extended_search_area_piv(\n    frame_a.astype(np.float32),\n    frame_b.astype(np.float32),\n    window_size=32,\n    overlap=12,\n    dt=0.02,\n    search_area_size=38,\n    correlation_method=\"linear\",   # circular also supports extended search\n    normalized_correlation=True,\n    backend=\"scipy\",\n    sig2noise_method=\"peak2peak\",\n)\n\nx, y = pyprocess.get_coordinates(\n    image_size=frame_a.shape,\n    search_area_size=38,\n    overlap=12,\n    center_on_field=False,         # matches sliding-window positions\n)\n\n# flags is a boolean array: True marks a spurious vector.\nflags = validation.sig2noise_val(s2n, threshold=1.05) | ~np.isfinite(s2n)\nflags |= ~np.isfinite(u) | ~np.isfinite(v)\nu, v = filters.replace_outliers(u, v, flags, method=\"localmean\", max_iter=3, kernel_size=2)\n\n# Scale, then convert to right-handed image-boundary coordinates.\nx, y, u, v = scaling.uniform(x, y, u, v, scaling_factor=96.52)\ny, v = frame_a.shape[0] \u002F 96.52 - y, -v\n\ntools.save(\"vectors.txt\", x, y, u, v, flags)\n```\n\nOr use the bundled CLI, which also checks inputs and preserves masks and processing parameters:\n\n```bash\npython skills\u002Fopenpiv\u002Fscripts\u002Frunner.py \\\n    --image frame_a.bmp --image frame_b.bmp --output_dir results --verbose\n```\n\n## Core Concepts\n\n### PIV Fundamentals\n\nParticle Image Velocimetry is an optical method for measuring fluid velocity by tracking illuminated\ntracer particles between two images.\n\n**Process flow:**\n\n1. Capture an image pair (`frame_a`, `frame_b`) separated by a known time `dt`.\n2. Divide the images into interrogation windows.\n3. Cross-correlate matching windows to find peak displacement.\n4. Validate vectors (signal-to-noise, global range, local median).\n5. Replace spurious vectors with interpolated values.\n6. Scale pixel displacements to physical units.\n\n### Interrogation Window Parameters\n\n**`window_size`** — correlation window in pixels (typically 16–128). Larger windows give better\ncorrelation but coarser spatial resolution.\n\n**`overlap`** — pixels shared between adjacent windows (typically 50–75% of `window_size`). Higher\noverlap raises vector density and cost, but adjacent vectors become correlated rather than\nindependent.\n\n**`search_area_size`** — the window searched in the second frame. Must be ≥ `window_size`; a few\npixels larger accommodates larger displacements. Both `\"circular\"` and `\"linear\"` support extended\nsearch. The CLI chooses zero-padded `\"linear\"` with `normalized_correlation=True` for it; this\ndoes not recover arbitrary displacement or eliminate spurious peaks. Grid stride is\n`search_area_size - overlap`, so overlap must be smaller than the search area.\n\nRules of thumb: keep the largest displacement under about a quarter of `window_size`, and aim for\n5–10 particles per window.\n\n### Signal-to-Noise Ratio\n\n`s2n` measures how distinct the correlation peak is. `sig2noise_method` controls how it is computed —\n`\"peak2mean\"` (the function default) or `\"peak2peak\"`. **The two are on different scales**, so a\nthreshold tuned for one is meaningless for the other. Typical `peak2peak` thresholds are 1.05–1.3.\n\n```python\nflags = validation.sig2noise_val(s2n, threshold=1.05)\n# flags is bool: True == spurious. `~flags` selects the good vectors.\n```\n\n## Common Operations\n\n### Dynamic Masking\n\nMasking lives in `openpiv.preprocess` and returns `(image, mask)`. Use floating-point copies\nto avoid unsigned subtraction artifacts. Inspect masks on both frames before analysis.\n\n```python\nfrom openpiv import preprocess\n\n# Intensity masking uses Otsu; the threshold argument is for edges.\nframe_a_masked, mask_a = preprocess.dynamic_masking(\n    frame_a.astype(np.float64), method=\"intensity\", filter_size=7, threshold=0.005\n)\nframe_b_masked, mask_b = preprocess.dynamic_masking(\n    frame_b.astype(np.float64), method=\"intensity\", filter_size=7, threshold=0.005\n)\n```\n\nPreserve the union `mask_a | mask_b` as excluded physical regions. The CLI samples it at\ninterrogation centers, saves it, and keeps those velocities NaN after replacement. Windows\nstraddling an object can still be biased: inspect\u002Fdilate masks for the experiment. In 0.26.1\n`method=\"edges\"` indexes with uint8 instead of bool, potentially corrupting the image or failing.\nThe CLI refuses it; use intensity masking or a verified boolean mask in a custom workflow.\n\n### Multi-Pass Processing\n\nMulti-pass (window deformation) lives in `openpiv.windef`, driven by a `PIVSettings` dataclass.\n`pyprocess` has no multi-pass entry point.\n\n```python\nimport numpy as np\nfrom openpiv import scaling, windef\n\nsettings = windef.PIVSettings(\n    windowsizes=(64, 32, 16), overlap=(32, 16, 8), num_iterations=3,\n    backend=\"scipy\", sig2noise_method=\"peak2peak\", sig2noise_threshold=1.05,\n)\n\nx, y, u, v, flags = windef.simple_multipass(\n    frame_a.astype(np.float32), frame_b.astype(np.float32), settings\n)\n\n# Output is in PIXELS PER FRAME -- convert yourself. scaling.uniform only divides\n# by scaling_factor, so apply dt separately.\ndt = 0.02\nx, y, u, v = scaling.uniform(x, y, u, v, scaling_factor=96.52)\nu, v = u \u002F dt, v \u002F dt\n```\n\n`simple_multipass` validates, replaces outliers, fills remaining NaNs with zeros, and transforms\ncoordinates. Keep its flags: repaired\u002Fzero-filled output is not an independent measurement.\nAlways pass settings: its no-settings path has two window sizes but three iterations in 0.26.1.\n\n**Units trap:** `simple_multipass` and its alias `multigrid_windef` ignore `settings.dt` and\n`settings.scaling_factor`; convert their arrays as above. Batch `windef.piv(settings)` applies\nboth before saving — do not scale its files again. The simple wrapper does not honor all batch\npreprocessing\u002Foutput switches.\n\nFor control over individual passes, `windef.first_pass` and `windef.multipass_img_deform` are the\nlower-level building blocks.\n\n## Validation and Post-Processing\n\n### Validation Methods\n\nEvery validator returns a boolean array where **True marks a spurious vector**. Also reject\nnonfinite `u`, `v`, and `s2n`: `sig2noise_val` alone does not flag NaN.\n\n```python\n# Signal-to-noise\nflags = validation.sig2noise_val(s2n, threshold=1.05)\n\n# Global range -- takes (min, max) TUPLES, positionally or as u_thresholds\u002Fv_thresholds.\nflags = validation.global_val(u, v, (-300, 300), (-300, 300))\n\n# Local median -- u_threshold and v_threshold are REQUIRED; size is the neighbourhood half-width.\nflags = validation.local_median_val(u, v, u_threshold=30.0, v_threshold=30.0, size=1)\n\n# Combine with boolean OR (not np.maximum -- these are bool arrays).\nflags = (\n    validation.sig2noise_val(s2n, threshold=1.05)\n    | validation.global_val(u, v, (-300, 300), (-300, 300))\n    | validation.local_median_val(u, v, u_threshold=30.0, v_threshold=30.0)\n)\n```\n\n**Set these thresholds in the units of `u` and `v`, not in pixels per frame.**\n`extended_search_area_piv` divides by `dt`, so with `dt=0.02` a 3 px\u002Fframe displacement arrives as\n150 px\u002Fs. The thresholds above suit that case; the `(-30, 30)` figure that PIV literature and\n`PIVSettings.min_max_u_disp` use is a px\u002Fframe limit, and applying it to px\u002Fs output rejects the\nentire field. Correlate with `dt=1` to validate displacements before conversion, or adjust\nthresholds to the actual velocity units (including both time and calibration factors).\n\n### Outlier Replacement\n\n```python\nu, v = filters.replace_outliers(\n    u, v, flags, method=\"localmean\", max_iter=3, tol=1e-3, kernel_size=2\n)\n```\n\n`method` accepts `\"localmean\"`, `\"disk\"`, or `\"distance\"`; an invalid name raises `ValueError`\nwhen filling missing cells. Use `kernel_size>=2` for `\"distance\"`: size 1 truncates all neighbor\nweights to zero in 0.26.1 and leaves holes. Replacement *fills* the flagged\npositions with interpolated values — if you then overwrite them with NaN, the replacement was\nwasted. Choose one or the other:\n\n```python\n# Keep flagged vectors out of the analysis entirely, instead of interpolating them.\nu = np.where(flags, np.nan, u)\nv = np.where(flags, np.nan, v)\n```\n\n### Smoothing\n\nSmoothing is `openpiv.smoothn.smoothn`; there is no `openpiv.smooth` module. It returns a tuple\nwhose first element is the smoothed field. NaN\u002FInf are missing observations; supply a copy because\nit can modify input. Zero-filling holes first incorrectly treats them as measured zeros.\n\n```python\nfrom openpiv.smoothn import smoothn\n\nu_smooth, *_ = smoothn(np.asarray(u, dtype=float).copy(), s=0.5)  # larger == smoother\nv_smooth, *_ = smoothn(np.asarray(v, dtype=float).copy(), s=0.5)\nu_smooth = np.asarray(u_smooth)\n```\n\n## Visualization\n\n### Vector Field Plotting\n\n`display_vector_field` reads a saved vectors file and calls `plt.show()` internally, so select a\nnon-interactive backend for batch runs.\n\n```python\nimport matplotlib\nmatplotlib.use(\"Agg\")\nimport matplotlib.pyplot as plt\nfrom openpiv import tools\n\nfig, ax = plt.subplots(figsize=(8, 8))\ntools.display_vector_field(\n    \"vectors.txt\",\n    ax=ax,\n    scaling_factor=96.52,   # same factor used in scaling.uniform, to map back onto the image\n    scale=50,\n    width=0.0035,\n    on_img=False,\n)\nimage = tools.imread(\"frame_a.bmp\")\nheight, width = image.shape\nax.imshow(image, cmap=\"gray\", origin=\"upper\", zorder=-1,\n          extent=(0, width \u002F 96.52, 0, height \u002F 96.52))\nfig.savefig(\"vector_field.png\", dpi=150, bbox_inches=\"tight\")\nplt.close(fig)\n```\n\nSet image extents explicitly: the helper's `on_img=True` infers them from the last vector and\ncan stretch overlays when windows leave unused margins. The CLI plots with the actual image bounds.\n\n### Custom Visualization\n\n```python\nimport numpy as np\nimport matplotlib.pyplot as plt\n\nfig, axes = plt.subplots(1, 3, figsize=(15, 5))\n\nmag = np.sqrt(u**2 + v**2)\nfor ax, field, title, cmap in [\n    (axes[0], mag, \"Velocity Magnitude\", \"viridis\"),\n    (axes[1], u, \"U Velocity\", \"RdBu_r\"),\n    (axes[2], v, \"V Velocity\", \"RdBu_r\"),\n]:\n    im = ax.imshow(field, cmap=cmap)\n    ax.set_title(title)\n    plt.colorbar(im, ax=ax)\n\nfig.tight_layout()\nfig.savefig(\"velocity_components.png\")\nplt.close(fig)\n```\n\n## Analysis Functions\n\n`scripts\u002Fanalyze.py` bundles these against a `params.npz` written by `runner.py`. It infers the\nphysical grid spacing from the saved coordinates, so the derivatives come out per unit length:\n\n```python\nimport sys\nsys.path.insert(0, \"skills\u002Fopenpiv\u002Fscripts\")\nfrom analyze import PIVAnalyzer\n\npiv = PIVAnalyzer(\"results\u002Fparams.npz\")\nvorticity = piv.compute_vorticity()          # dv\u002Fdx - du\u002Fdy\nexx, eyy, exy = piv.compute_strain()\nstats = piv.compute_statistics()             # excludes flagged and masked vectors\npiv.plot_vector_field(save_path=\"quiver.png\")\n```\n\nThe standalone forms, if you would rather compute them inline:\n\n### Vorticity\n\n```python\ndef compute_vorticity(u, v, dx=1.0, dy=None):\n    \"\"\"Out-of-plane vorticity dv\u002Fdx - du\u002Fdy. Pass the physical grid spacing, not 1.0.\"\"\"\n    dy = dx if dy is None else dy\n    return np.gradient(v, dx, axis=1) - np.gradient(u, dy, axis=0)\n```\n\nFor the single-pass extended-search grid, spacing is\n`(search_area_size - overlap) \u002F scaling_factor` in physical units; it reduces to\n`(window_size - overlap) \u002F scaling_factor` only when the two window sizes match.\nPrefer differences of the saved `x` and `y` coordinates, especially after multipass\nprocessing. Leaving `dx=1.0` yields vorticity per grid cell, not per unit length.\nSee [OpenPIV coordinate generation](https:\u002F\u002Fopenpiv.readthedocs.io\u002Fen\u002Fstable\u002Fsrc\u002Ftutorial1.html).\n\n**Sign convention:** the CLI writes `y = image_height \u002F scaling_factor - y` and negates `v`,\nkeeping rows in image order. Saved `y` decreases down the array. The standalone forms need\nsigned `dy` (negative here), or use `PIVAnalyzer`, which reads orientation. Positive `dy` changes\nthe y-derivative contribution and can even cancel real rotation.\n\n### Strain Rate\n\n```python\ndef compute_strain(u, v, dx=1.0, dy=None):\n    \"\"\"Return (exx, eyy, exy) of the 2D strain-rate tensor.\"\"\"\n    dy = dx if dy is None else dy\n    du_dx = np.gradient(u, dx, axis=1)\n    du_dy = np.gradient(u, dy, axis=0)\n    dv_dx = np.gradient(v, dx, axis=1)\n    dv_dy = np.gradient(v, dy, axis=0)\n    return du_dx, dv_dy, 0.5 * (du_dy + dv_dx)\n```\n\n### Turbulence Statistics\n\n```python\ndef compute_statistics(u, v):\n    \"\"\"Single-frame spatial statistics. NOT Reynolds decomposition.\"\"\"\n    u_prime = u - np.nanmean(u)\n    v_prime = v - np.nanmean(v)\n    rms_u, rms_v = np.nanstd(u_prime), np.nanstd(v_prime)\n    return {\n        \"u_mean\": np.nanmean(u),\n        \"v_mean\": np.nanmean(v),\n        \"rms_u\": rms_u,\n        \"rms_v\": rms_v,\n        \"tke\": 0.5 * (rms_u**2 + rms_v**2),\n    }\n```\n\n**Caveat:** subtracting the *spatial* mean of one frame measures spatial variance, which equals\nturbulent intensity only under justified homogeneity\u002Fergodicity assumptions. Reynolds decomposition\nneeds an ensemble: subtract its mean field from each realization. The legacy `tke` key is only\ntwo-component spatial variance energy, not full turbulent kinetic energy. The analyzer excludes\nflagged vectors by default; `compute_statistics(include_interpolated=True)` includes repaired ones.\n\n## CLI Usage\n\n```bash\n# Basic run\npython skills\u002Fopenpiv\u002Fscripts\u002Frunner.py \\\n    --image img1.bmp --image img2.bmp --output_dir results --verbose\n\n# Tuned parameters with dynamic masking\npython skills\u002Fopenpiv\u002Fscripts\u002Frunner.py \\\n    --image frame_a.bmp \\\n    --image frame_b.bmp \\\n    --output_dir results \\\n    --window_size 32 \\\n    --overlap 12 \\\n    --search_area 38 \\\n    --dt 0.02 \\\n    --scaling 96.52 \\\n    --threshold 1.05 \\\n    --mask dynamic \\\n    --mask_method intensity \\\n    --verbose\n```\n\n### CLI Options\n\n| Option | Default | Description |\n|--------|---------|-------------|\n| `--image` | required | Image file; specify exactly twice for the pair |\n| `--output_dir` | `results` | Output directory (created if absent) |\n| `--window_size` | 32 | Interrogation window size (px) |\n| `--overlap` | 12 | Search-grid overlap (px), nonnegative and less than search area |\n| `--search_area` | 38 | Search area size (px), must be ≥ `--window_size` |\n| `--dt` | 0.02 | Time between frames (s) |\n| `--scaling` | 96.52 | Scaling factor, pixels per physical unit (e.g. px\u002Fmm) |\n| `--threshold` | 1.05 | `peak2peak` signal-to-noise threshold |\n| `--mask` | `none` | `none` or `dynamic` (`openpiv.preprocess.dynamic_masking`) |\n| `--mask_method` | `intensity` | Only intensity is usable in 0.26.1; edges is refused |\n| `--backend` | `scipy` | `scipy`, `auto`, or `rust`; Rust requires its extension |\n| `--drop_invalid` | off | NaN out flagged vectors instead of keeping interpolated values |\n| `--verbose` | off | Print progress messages |\n\nVerify an install end to end against OpenPIV's own bundled image pair:\n\n```bash\npython skills\u002Fopenpiv\u002Fscripts\u002Frun_example.py --output_dir \u002Ftmp\u002Fopenpiv-demo\n```\n\n## Output Files\n\n- **vectors.txt** — tab-delimited, `%.4e` formatted, with a `# x y u v flags mask` comment header\n- **params.npz** — `x`, `y`, `u`, `v`, `flags`, `mask`, `s2n`, timing\u002Fcalibration\u002Fwindow parameters,\n  requested backend, and OpenPIV version. Coordinates use physical units; velocity uses units\u002Fs.\n- **vector_field.png** — vector field drawn over the first frame\n\n```text\n# x\ty\tu\tv\tflags\tmask\n2.1757e-01\t3.5226e+00\t-6.2220e-02\t-2.7081e+00\t0.0000e+00\t0.0000e+00\n4.8695e-01\t3.5226e+00\t-3.1587e-01\t-2.9800e+00\t0.0000e+00\t0.0000e+00\n```\n\n`flags` is float, `0` for valid and `1` for flagged. `mask=1` marks an excluded object region,\nindependently of flags. Preserve both with the measured field.\n\n## Best Practices\n\n### Parameter Selection\n\n1. **Window size** — 32×32 suits most cases. 64\u002F128 for better correlation at coarser resolution;\n   16\u002F24 for finer resolution at the cost of noise.\n2. **Overlap** — 50–75% of window size.\n3. **Threshold** — raise it to reject more vectors; always re-tune after switching\n   `sig2noise_method`.\n4. **Scaling factor** — calibrate against a known reference such as a calibration grid, and keep the\n   units straight (`96.52` in OpenPIV's `test1` tutorial data is px\u002Fmm).\n\n### Image Quality\n\n- Particles visible and evenly distributed, 5–10 per interrogation window\n- No saturated or overexposed regions\n- Minimal background noise; consider background subtraction across a run\n\n### Processing Tips\n\n1. Start from the defaults, then tune against the vector field you get.\n2. Inspect the `s2n` distribution — a low median means poor correlation, not a bad threshold.\n3. Visualize early; obvious problems (uniform vectors, edge artifacts) show up immediately.\n4. Use multi-pass (`windef`) for flows with large velocity gradients or displacements.\n5. Mask reflections and solid boundaries rather than letting them generate vectors.\n\n## Resources\n\n### references\u002F\n\n- `advanced_algorithms.md` — correlation and subpixel methods, multi-pass window deformation,\n  `PIVSettings` fields, 3D and phase-separation modules\n\nLoad the reference when detailed algorithm or settings information is needed.\n","# OpenPIV\n\n## Overview\n\nOpenPIV (Open Particle Image Velocimetry) analyzes fluid flow from PIV image pairs. It covers\npreprocessing, cross-correlation, vector validation, outlier replacement, smoothing, and scaling to\nphysical units.\n\nTargets **openpiv 0.26.1**. Synthetic checks ran on Python 3.13, NumPy 2.5.3, SciPy 1.18.1,\nscikit-image 0.26.0, and Matplotlib 3.11.2. Rust was not installed; use `backend=\"scipy\"` for the\ntested path. See [review evidence](references\u002Fadvanced_algorithms.md#review-sources-and-verification).\n\n## When to use\n\nUse this skill when working with experimental PIV or flow-visualization image pairs: measuring 2D\nvelocity fields, tuning interrogation-window parameters, validating vectors, or deriving vorticity,\nstrain rate, and turbulence statistics. For *simulating* flow rather than measuring it, use a CFD\nskill instead.\n\n## Quick Start\n\nInstall OpenPIV:\n\n```bash\nuv pip install openpiv\n\n# Pin it when the analysis needs to be reproducible -- this is the version every\n# snippet below was checked against.\nuv pip install \"openpiv==0.26.1\"\n```\n\nRun PIV analysis on an image pair:\n\n```python\nimport numpy as np\nfrom openpiv import tools, pyprocess, validation, filters, scaling\n\nframe_a = tools.imread(\"image_a.bmp\")\nframe_b = tools.imread(\"image_b.bmp\")\n\n# Always returns (u, v, s2n); s2n is all NaN if sig2noise_method=None.\nu, v, s2n = pyprocess.extended_search_area_piv(\n    frame_a.astype(np.float32),\n    frame_b.astype(np.float32),\n    window_size=32,\n    overlap=12,\n    dt=0.02,\n    search_area_size=38,\n    correlation_method=\"linear\",   # circular also supports extended search\n    normalized_correlation=True,\n    backend=\"scipy\",\n    sig2noise_method=\"peak2peak\",\n)\n\nx, y = pyprocess.get_coordinates(\n    image_size=frame_a.shape,\n    search_area_size=38,\n    overlap=12,\n    center_on_field=False,         # matches sliding-window positions\n)\n\n# flags is a boolean array: True marks a spurious vector.\nflags = validation.sig2noise_val(s2n, threshold=1.05) | ~np.isfinite(s2n)\nflags |= ~np.isfinite(u) | ~np.isfinite(v)\nu, v = filters.replace_outliers(u, v, flags, method=\"localmean\", max_iter=3, kernel_size=2)\n\n# Scale, then convert to right-handed image-boundary coordinates.\nx, y, u, v = scaling.uniform(x, y, u, v, scaling_factor=96.52)\ny, v = frame_a.shape[0] \u002F 96.52 - y, -v\n\ntools.save(\"vectors.txt\", x, y, u, v, flags)\n```\n\nOr use the bundled CLI, which also checks inputs and preserves masks and processing parameters:\n\n```bash\npython skills\u002Fopenpiv\u002Fscripts\u002Frunner.py \\\n    --image frame_a.bmp --image frame_b.bmp --output_dir results --verbose\n```\n\n## Core Concepts\n\n### PIV Fundamentals\n\nParticle Image Velocimetry is an optical method for measuring fluid velocity by tracking illuminated\ntracer particles between two images.\n\n**Process flow:**\n\n1. Capture an image pair (`frame_a`, `frame_b`) separated by a known time `dt`.\n2. Divide the images into interrogation windows.\n3. Cross-correlate matching windows to find peak displacement.\n4. Validate vectors (signal-to-noise, global range, local median).\n5. Replace spurious vectors with interpolated values.\n6. Scale pixel displacements to physical units.\n\n### Interrogation Window Parameters\n\n**`window_size`** — correlation window in pixels (typically 16–128). Larger windows give better\ncorrelation but coarser spatial resolution.\n\n**`overlap`** — pixels shared between adjacent windows (typically 50–75% of `window_size`). Higher\noverlap raises vector density and cost, but adjacent vectors become correlated rather than\nindependent.\n\n**`search_area_size`** — the window searched in the second frame. Must be ≥ `window_size`; a few\npixels larger accommodates larger displacements. Both `\"circular\"` and `\"linear\"` support extended\nsearch. The CLI chooses zero-padded `\"linear\"` with `normalized_correlation=True` for it; this\ndoes not recover arbitrary displacement or eliminate spurious peaks. Grid stride is\n`search_area_size - overlap`, so overlap must be smaller than the search area.\n\nRules of thumb: keep the largest displacement under about a quarter of `window_size`, and aim for\n5–10 particles per window.\n\n### Signal-to-Noise Ratio\n\n`s2n` measures how distinct the correlation peak is. `sig2noise_method` controls how it is computed —\n`\"peak2mean\"` (the function default) or `\"peak2peak\"`. **The two are on different scales**, so a\nthreshold tuned for one is meaningless for the other. Typical `peak2peak` thresholds are 1.05–1.3.\n\n```python\nflags = validation.sig2noise_val(s2n, threshold=1.05)\n# flags is bool: True == spurious. `~flags` selects the good vectors.\n```\n\n## Common Operations\n\n### Dynamic Masking\n\nMasking lives in `openpiv.preprocess` and returns `(image, mask)`. Use floating-point copies\nto avoid unsigned subtraction artifacts. Inspect masks on both frames before analysis.\n\n```python\nfrom openpiv import preprocess\n\n# Intensity masking uses Otsu; the threshold argument is for edges.\nframe_a_masked, mask_a = preprocess.dynamic_masking(\n    frame_a.astype(np.float64), method=\"intensity\", filter_size=7, threshold=0.005\n)\nframe_b_masked, mask_b = preprocess.dynamic_masking(\n    frame_b.astype(np.float64), method=\"intensity\", filter_size=7, threshold=0.005\n)\n```\n\nPreserve the union `mask_a | mask_b` as excluded physical regions. The CLI samples it at\ninterrogation centers, saves it, and keeps those velocities NaN after replacement. Windows\nstraddling an object can still be biased: inspect\u002Fdilate masks for the experiment. In 0.26.1\n`method=\"edges\"` indexes with uint8 instead of bool, potentially corrupting the image or failing.\nThe CLI refuses it; use intensity masking or a verified boolean mask in a custom workflow.\n\n### Multi-Pass Processing\n\nMulti-pass (window deformation) lives in `openpiv.windef`, driven by a `PIVSettings` dataclass.\n`pyprocess` has no multi-pass entry point.\n\n```python\nimport numpy as np\nfrom openpiv import scaling, windef\n\nsettings = windef.PIVSettings(\n    windowsizes=(64, 32, 16), overlap=(32, 16, 8), num_iterations=3,\n    backend=\"scipy\", sig2noise_method=\"peak2peak\", sig2noise_threshold=1.05,\n)\n\nx, y, u, v, flags = windef.simple_multipass(\n    frame_a.astype(np.float32), frame_b.astype(np.float32), settings\n)\n\n# Output is in PIXELS PER FRAME -- convert yourself. scaling.uniform only divides\n# by scaling_factor, so apply dt separately.\ndt = 0.02\nx, y, u, v = scaling.uniform(x, y, u, v, scaling_factor=96.52)\nu, v = u \u002F dt, v \u002F dt\n```\n\n`simple_multipass` validates, replaces outliers, fills remaining NaNs with zeros, and transforms\ncoordinates. Keep its flags: repaired\u002Fzero-filled output is not an independent measurement.\nAlways pass settings: its no-settings path has two window sizes but three iterations in 0.26.1.\n\n**Units trap:** `simple_multipass` and its alias `multigrid_windef` ignore `settings.dt` and\n`settings.scaling_factor`; convert their arrays as above. Batch `windef.piv(settings)` applies\nboth before saving — do not scale its files again. The simple wrapper does not honor all batch\npreprocessing\u002Foutput switches.\n\nFor control over individual passes, `windef.first_pass` and `windef.multipass_img_deform` are the\nlower-level building blocks.\n\n## Validation and Post-Processing\n\n### Validation Methods\n\nEvery validator returns a boolean array where **True marks a spurious vector**. Also reject\nnonfinite `u`, `v`, and `s2n`: `sig2noise_val` alone does not flag NaN.\n\n```python\n# Signal-to-noise\nflags = validation.sig2noise_val(s2n, threshold=1.05)\n\n# Global range -- takes (min, max) TUPLES, positionally or as u_thresholds\u002Fv_thresholds.\nflags = validation.global_val(u, v, (-300, 300), (-300, 300))\n\n# Local median -- u_threshold and v_threshold are REQUIRED; size is the neighbourhood half-width.\nflags = validation.local_median_val(u, v, u_threshold=30.0, v_threshold=30.0, size=1)\n\n# Combine with boolean OR (not np.maximum -- these are bool arrays).\nflags = (\n    validation.sig2noise_val(s2n, threshold=1.05)\n    | validation.global_val(u, v, (-300, 300), (-300, 300))\n    | validation.local_median_val(u, v, u_threshold=30.0, v_threshold=30.0)\n)\n```\n\n**Set these thresholds in the units of `u` and `v`, not in pixels per frame.**\n`extended_search_area_piv` divides by `dt`, so with `dt=0.02` a 3 px\u002Fframe displacement arrives as\n150 px\u002Fs. The thresholds above suit that case; the `(-30, 30)` figure that PIV literature and\n`PIVSettings.min_max_u_disp` use is a px\u002Fframe limit, and applying it to px\u002Fs output rejects the\nentire field. Correlate with `dt=1` to validate displacements before conversion, or adjust\nthresholds to the actual velocity units (including both time and calibration factors).\n\n### Outlier Replacement\n\n```python\nu, v = filters.replace_outliers(\n    u, v, flags, method=\"localmean\", max_iter=3, tol=1e-3, kernel_size=2\n)\n```\n\n`method` accepts `\"localmean\"`, `\"disk\"`, or `\"distance\"`; an invalid name raises `ValueError`\nwhen filling missing cells. Use `kernel_size>=2` for `\"distance\"`: size 1 truncates all neighbor\nweights to zero in 0.26.1 and leaves holes. Replacement *fills* the flagged\npositions with interpolated values — if you then overwrite them with NaN, the replacement was\nwasted. Choose one or the other:\n\n```python\n# Keep flagged vectors out of the analysis entirely, instead of interpolating them.\nu = np.where(flags, np.nan, u)\nv = np.where(flags, np.nan, v)\n```\n\n### Smoothing\n\nSmoothing is `openpiv.smoothn.smoothn`; there is no `openpiv.smooth` module. It returns a tuple\nwhose first element is the smoothed field. NaN\u002FInf are missing observations; supply a copy because\nit can modify input. Zero-filling holes first incorrectly treats them as measured zeros.\n\n```python\nfrom openpiv.smoothn import smoothn\n\nu_smooth, *_ = smoothn(np.asarray(u, dtype=float).copy(), s=0.5)  # larger == smoother\nv_smooth, *_ = smoothn(np.asarray(v, dtype=float).copy(), s=0.5)\nu_smooth = np.asarray(u_smooth)\n```\n\n## Visualization\n\n### Vector Field Plotting\n\n`display_vector_field` reads a saved vectors file and calls `plt.show()` internally, so select a\nnon-interactive backend for batch runs.\n\n```python\nimport matplotlib\nmatplotlib.use(\"Agg\")\nimport matplotlib.pyplot as plt\nfrom openpiv import tools\n\nfig, ax = plt.subplots(figsize=(8, 8))\ntools.display_vector_field(\n    \"vectors.txt\",\n    ax=ax,\n    scaling_factor=96.52,   # same factor used in scaling.uniform, to map back onto the image\n    scale=50,\n    width=0.0035,\n    on_img=False,\n)\nimage = tools.imread(\"frame_a.bmp\")\nheight, width = image.shape\nax.imshow(image, cmap=\"gray\", origin=\"upper\", zorder=-1,\n          extent=(0, width \u002F 96.52, 0, height \u002F 96.52))\nfig.savefig(\"vector_field.png\", dpi=150, bbox_inches=\"tight\")\nplt.close(fig)\n```\n\nSet image extents explicitly: the helper's `on_img=True` infers them from the last vector and\ncan stretch overlays when windows leave unused margins. The CLI plots with the actual image bounds.\n\n### Custom Visualization\n\n```python\nimport numpy as np\nimport matplotlib.pyplot as plt\n\nfig, axes = plt.subplots(1, 3, figsize=(15, 5))\n\nmag = np.sqrt(u**2 + v**2)\nfor ax, field, title, cmap in [\n    (axes[0], mag, \"Velocity Magnitude\", \"viridis\"),\n    (axes[1], u, \"U Velocity\", \"RdBu_r\"),\n    (axes[2], v, \"V Velocity\", \"RdBu_r\"),\n]:\n    im = ax.imshow(field, cmap=cmap)\n    ax.set_title(title)\n    plt.colorbar(im, ax=ax)\n\nfig.tight_layout()\nfig.savefig(\"velocity_components.png\")\nplt.close(fig)\n```\n\n## Analysis Functions\n\n`scripts\u002Fanalyze.py` bundles these against a `params.npz` written by `runner.py`. It infers the\nphysical grid spacing from the saved coordinates, so the derivatives come out per unit length:\n\n```python\nimport sys\nsys.path.insert(0, \"skills\u002Fopenpiv\u002Fscripts\")\nfrom analyze import PIVAnalyzer\n\npiv = PIVAnalyzer(\"results\u002Fparams.npz\")\nvorticity = piv.compute_vorticity()          # dv\u002Fdx - du\u002Fdy\nexx, eyy, exy = piv.compute_strain()\nstats = piv.compute_statistics()             # excludes flagged and masked vectors\npiv.plot_vector_field(save_path=\"quiver.png\")\n```\n\nThe standalone forms, if you would rather compute them inline:\n\n### Vorticity\n\n```python\ndef compute_vorticity(u, v, dx=1.0, dy=None):\n    \"\"\"Out-of-plane vorticity dv\u002Fdx - du\u002Fdy. Pass the physical grid spacing, not 1.0.\"\"\"\n    dy = dx if dy is None else dy\n    return np.gradient(v, dx, axis=1) - np.gradient(u, dy, axis=0)\n```\n\nFor the single-pass extended-search grid, spacing is\n`(search_area_size - overlap) \u002F scaling_factor` in physical units; it reduces to\n`(window_size - overlap) \u002F scaling_factor` only when the two window sizes match.\nPrefer differences of the saved `x` and `y` coordinates, especially after multipass\nprocessing. Leaving `dx=1.0` yields vorticity per grid cell, not per unit length.\nSee [OpenPIV coordinate generation](https:\u002F\u002Fopenpiv.readthedocs.io\u002Fen\u002Fstable\u002Fsrc\u002Ftutorial1.html).\n\n**Sign convention:** the CLI writes `y = image_height \u002F scaling_factor - y` and negates `v`,\nkeeping rows in image order. Saved `y` decreases down the array. The standalone forms need\nsigned `dy` (negative here), or use `PIVAnalyzer`, which reads orientation. Positive `dy` changes\nthe y-derivative contribution and can even cancel real rotation.\n\n### Strain Rate\n\n```python\ndef compute_strain(u, v, dx=1.0, dy=None):\n    \"\"\"Return (exx, eyy, exy) of the 2D strain-rate tensor.\"\"\"\n    dy = dx if dy is None else dy\n    du_dx = np.gradient(u, dx, axis=1)\n    du_dy = np.gradient(u, dy, axis=0)\n    dv_dx = np.gradient(v, dx, axis=1)\n    dv_dy = np.gradient(v, dy, axis=0)\n    return du_dx, dv_dy, 0.5 * (du_dy + dv_dx)\n```\n\n### Turbulence Statistics\n\n```python\ndef compute_statistics(u, v):\n    \"\"\"Single-frame spatial statistics. NOT Reynolds decomposition.\"\"\"\n    u_prime = u - np.nanmean(u)\n    v_prime = v - np.nanmean(v)\n    rms_u, rms_v = np.nanstd(u_prime), np.nanstd(v_prime)\n    return {\n        \"u_mean\": np.nanmean(u),\n        \"v_mean\": np.nanmean(v),\n        \"rms_u\": rms_u,\n        \"rms_v\": rms_v,\n        \"tke\": 0.5 * (rms_u**2 + rms_v**2),\n    }\n```\n\n**Caveat:** subtracting the *spatial* mean of one frame measures spatial variance, which equals\nturbulent intensity only under justified homogeneity\u002Fergodicity assumptions. Reynolds decomposition\nneeds an ensemble: subtract its mean field from each realization. The legacy `tke` key is only\ntwo-component spatial variance energy, not full turbulent kinetic energy. The analyzer excludes\nflagged vectors by default; `compute_statistics(include_interpolated=True)` includes repaired ones.\n\n## CLI Usage\n\n```bash\n# Basic run\npython skills\u002Fopenpiv\u002Fscripts\u002Frunner.py \\\n    --image img1.bmp --image img2.bmp --output_dir results --verbose\n\n# Tuned parameters with dynamic masking\npython skills\u002Fopenpiv\u002Fscripts\u002Frunner.py \\\n    --image frame_a.bmp \\\n    --image frame_b.bmp \\\n    --output_dir results \\\n    --window_size 32 \\\n    --overlap 12 \\\n    --search_area 38 \\\n    --dt 0.02 \\\n    --scaling 96.52 \\\n    --threshold 1.05 \\\n    --mask dynamic \\\n    --mask_method intensity \\\n    --verbose\n```\n\n### CLI Options\n\n| Option | Default | Description |\n|--------|---------|-------------|\n| `--image` | required | Image file; specify exactly twice for the pair |\n| `--output_dir` | `results` | Output directory (created if absent) |\n| `--window_size` | 32 | Interrogation window size (px) |\n| `--overlap` | 12 | Search-grid overlap (px), nonnegative and less than search area |\n| `--search_area` | 38 | Search area size (px), must be ≥ `--window_size` |\n| `--dt` | 0.02 | Time between frames (s) |\n| `--scaling` | 96.52 | Scaling factor, pixels per physical unit (e.g. px\u002Fmm) |\n| `--threshold` | 1.05 | `peak2peak` signal-to-noise threshold |\n| `--mask` | `none` | `none` or `dynamic` (`openpiv.preprocess.dynamic_masking`) |\n| `--mask_method` | `intensity` | Only intensity is usable in 0.26.1; edges is refused |\n| `--backend` | `scipy` | `scipy`, `auto`, or `rust`; Rust requires its extension |\n| `--drop_invalid` | off | NaN out flagged vectors instead of keeping interpolated values |\n| `--verbose` | off | Print progress messages |\n\nVerify an install end to end against OpenPIV's own bundled image pair:\n\n```bash\npython skills\u002Fopenpiv\u002Fscripts\u002Frun_example.py --output_dir \u002Ftmp\u002Fopenpiv-demo\n```\n\n## Output Files\n\n- **vectors.txt** — tab-delimited, `%.4e` formatted, with a `# x y u v flags mask` comment header\n- **params.npz** — `x`, `y`, `u`, `v`, `flags`, `mask`, `s2n`, timing\u002Fcalibration\u002Fwindow parameters,\n  requested backend, and OpenPIV version. Coordinates use physical units; velocity uses units\u002Fs.\n- **vector_field.png** — vector field drawn over the first frame\n\n```text\n# x\ty\tu\tv\tflags\tmask\n2.1757e-01\t3.5226e+00\t-6.2220e-02\t-2.7081e+00\t0.0000e+00\t0.0000e+00\n4.8695e-01\t3.5226e+00\t-3.1587e-01\t-2.9800e+00\t0.0000e+00\t0.0000e+00\n```\n\n`flags` is float, `0` for valid and `1` for flagged. `mask=1` marks an excluded object region,\nindependently of flags. Preserve both with the measured field.\n\n## Best Practices\n\n### Parameter Selection\n\n1. **Window size** — 32×32 suits most cases. 64\u002F128 for better correlation at coarser resolution;\n   16\u002F24 for finer resolution at the cost of noise.\n2. **Overlap** — 50–75% of window size.\n3. **Threshold** — raise it to reject more vectors; always re-tune after switching\n   `sig2noise_method`.\n4. **Scaling factor** — calibrate against a known reference such as a calibration grid, and keep the\n   units straight (`96.52` in OpenPIV's `test1` tutorial data is px\u002Fmm).\n\n### Image Quality\n\n- Particles visible and evenly distributed, 5–10 per interrogation window\n- No saturated or overexposed regions\n- Minimal background noise; consider background subtraction across a run\n\n### Processing Tips\n\n1. Start from the defaults, then tune against the vector field you get.\n2. Inspect the `s2n` distribution — a low median means poor correlation, not a bad threshold.\n3. Visualize early; obvious problems (uniform vectors, edge artifacts) show up immediately.\n4. Use multi-pass (`windef`) for flows with large velocity gradients or displacements.\n5. Mask reflections and solid boundaries rather than letting them generate vectors.\n\n## Resources\n\n### references\u002F\n\n- `advanced_algorithms.md` — correlation and subpixel methods, multi-pass window deformation,\n  `PIVSettings` fields, 3D and phase-separation modules\n\nLoad the reference when detailed algorithm or settings information is needed.\n",{"name":5,"license":15,"category":51,"metadata":52,"description":7,"allowed-tools":57,"compatibility":58},"scientific-computing",{"version":53,"skill-author":54,"last-reviewed":55,"tested-against":56},"1.3","OpenPIV Team","2026-10-01","openpiv 0.26.1","Read Write Edit Bash","Requires Python 3.10+ with openpiv installed (uv pip install openpiv). numpy, scipy, scikit-image, and matplotlib arrive as dependencies. No network access needed after install.","main","0da4485785ee599388900be50db1635489d53056",".agents\u002Fskills\u002Fkd-openpiv","https:\u002F\u002Fgithub.com\u002FTashima-Tarsh\u002FDisha6.6","https:\u002F\u002Fdisha6.6.thenitishkr.in\u002F","https:\u002F\u002Fgithub.com\u002FTashima-Tarsh","www.thenitishkr","thenitishkr | AI • Cyber-security • Research\r\n","2026-11-08 03:33:25",{"source":8,"skillName":5,"commands":69,"prompt":79,"zipAvailable":80},[70,73,76],{"tool":71,"command":72},"npx","npx skills add Tashima-Tarsh\u002FDisha6.6 --skill openpiv",{"tool":74,"command":75},"bunx","bunx skills add Tashima-Tarsh\u002FDisha6.6 --skill openpiv",{"tool":77,"command":78},"pnpm","pnpm dlx skills add Tashima-Tarsh\u002FDisha6.6 --skill openpiv","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FTashima-Tarsh\u002FDisha6.6\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fkd-openpiv\u002FSKILL.md",true,[82,88,94,98,102],{"path":83,"resourceType":84,"resourceTypeDesc":85,"sizeBytes":86,"sourceHtmlUrl":87},"references\u002Fadvanced_algorithms.md","REFERENCE","参考文档",15191,"https:\u002F\u002Fgithub.com\u002FTashima-Tarsh\u002FDisha6.6\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fkd-openpiv\u002Freferences\u002Fadvanced_algorithms.md",{"path":89,"resourceType":90,"resourceTypeDesc":91,"sizeBytes":92,"sourceHtmlUrl":93},"scripts\u002F__init__.py","SCRIPT","脚本",29,"https:\u002F\u002Fgithub.com\u002FTashima-Tarsh\u002FDisha6.6\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fkd-openpiv\u002Fscripts\u002F__init__.py",{"path":95,"resourceType":90,"resourceTypeDesc":91,"sizeBytes":96,"sourceHtmlUrl":97},"scripts\u002Fanalyze.py",6268,"https:\u002F\u002Fgithub.com\u002FTashima-Tarsh\u002FDisha6.6\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fkd-openpiv\u002Fscripts\u002Fanalyze.py",{"path":99,"resourceType":90,"resourceTypeDesc":91,"sizeBytes":100,"sourceHtmlUrl":101},"scripts\u002Frun_example.py",2875,"https:\u002F\u002Fgithub.com\u002FTashima-Tarsh\u002FDisha6.6\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fkd-openpiv\u002Fscripts\u002Frun_example.py",{"path":103,"resourceType":90,"resourceTypeDesc":91,"sizeBytes":104,"sourceHtmlUrl":105},"scripts\u002Frunner.py",10306,"https:\u002F\u002Fgithub.com\u002FTashima-Tarsh\u002FDisha6.6\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fkd-openpiv\u002Fscripts\u002Frunner.py",[107,136,159,186,211,235],{"skillNo":108,"name":109,"nameZh":6,"description":110,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":111,"licenseFileUrl":6,"sourceHtmlUrl":112,"categories":113,"keywords":115,"publishedAt":46},"01M6QRD07D4TGNDK6VJ4EHF8BV","youtube-full","Use when the user needs YouTube transcripts, video search, channel browsing, playlist extraction, or content monitoring. Trigger phrases: 'get the transcript for', 'search YouTube for', 'what are the latest videos on', 'list this playlist', 'monitor this channel', or any request involving a YouTube URL, video ID, or @handle. Do NOT use for downloading video or audio files, YouTube engagement data (likes, comments), or private\u002Fage-restricted videos.","MIT","https:\u002F\u002Fgithub.com\u002FTashima-Tarsh\u002FDisha6.6\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fyoutube-full\u002FSKILL.md",[114],{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135],"youtube full","youtube","full","transcript","search","monitoring","data","Video","Audio","list","files","do","get","age","trigger","URL","for","browsing","request","youtube transcripts",{"skillNo":137,"name":138,"nameZh":6,"description":139,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":111,"licenseFileUrl":6,"sourceHtmlUrl":140,"categories":141,"keywords":142,"publishedAt":46},"01M6QRCJ3112VYPA97YG7KGMC2","x-twitter-growth","X\u002FTwitter growth engine for building audience, crafting viral content, and analyzing engagement. Use when the user wants to grow on X\u002FTwitter, write tweets or threads, analyze their X profile, research competitors on X, plan a posting strategy, or optimize engagement. Complements social-content (generic multi-platform) with X-specific depth: algorithm mechanics, thread engineering, reply strategy, profile optimization, and competitive intelligence via web search.","https:\u002F\u002Fgithub.com\u002FTashima-Tarsh\u002FDisha6.6\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fx-twitter-growth\u002FSKILL.md",[],[143,144,145,146,120,147,148,149,150,151,152,153,40,154,38,155,156,157,158,132],"twitter","x twitter growth","growth","research","content","engineering","plan","web search","competitors","analyze","engine","strategy","platform","grow","posting","competitive",{"skillNo":160,"name":161,"nameZh":6,"description":162,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":111,"licenseFileUrl":6,"sourceHtmlUrl":163,"categories":164,"keywords":168,"publishedAt":46},"01M6QRBN3EHQNJY42RERP7A149","write-a-skill","Create new agent skills with proper structure, progressive disclosure, and bundled resources. Use when user wants to create, write, build, or author a new skill.","https:\u002F\u002Fgithub.com\u002FTashima-Tarsh\u002FDisha6.6\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fwrite-a-skill\u002FSKILL.md",[165],{"categoryNo":166,"categoryName":167,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[169,40,170,171,172,173,174,175,38,176,177,59,178,179,180,181,182,183,184,185],"write a skill","github","create","https","productivity","matt pocock","direct","example","build","new skill","structure","new agent","resources","with","tree","progressive disclosure","author",{"skillNo":187,"name":188,"nameZh":6,"description":189,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":111,"licenseFileUrl":6,"sourceHtmlUrl":190,"categories":191,"keywords":192,"publishedAt":46},"01M6QRB6G8P33PNGAF9Y69EJ9T","wrap-up","Close out a launched Claude Managed Agent — recap every primitive the founder now owns, regenerate the single-file overview page, and suggest the next 1-2 upgrades. Use when the user says \"wrap up\", \"close this out\", \"what do I own now\", \"give me the summary\", \"recap the agent\", or when the orchestrator routes phase=wrap-up. primitives_inventory.py tables everything owned (agent, environment, session, memory, outcome, deployment); overview_page.py regenerates a self-contained .\u002Fmy-agent\u002Fagent-overview.html; upgrade_suggester.py ranks the next moves from recorded deferrals plus standing hardening steps. Companion to run-without-you; the last stop before phase=done.","https:\u002F\u002Fgithub.com\u002FTashima-Tarsh\u002FDisha6.6\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fwrap-up\u002FSKILL.md",[],[193,194,195,196,197,198,199,200,201,38,202,127,203,204,205,206,207,208,209,210],"wrap up","up","wrap","gemini","deployment","run","file","hardening","closeout","stop","upgrade","founder","close","companion","you","tables","directions","phase",{"skillNo":212,"name":213,"nameZh":6,"description":214,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":111,"licenseFileUrl":6,"sourceHtmlUrl":215,"categories":216,"keywords":218,"publishedAt":46},"01M6QRA5AYC1RBFZ39GTWGS3N8","workflow-builder","Design and write deterministic multi-agent workflow scripts (.js files in .claude\u002Fworkflows\u002F) for Claude Code's Workflow tool. Use when a user wants to build, create, author, scaffold, or run a custom Claude Code workflow, orchestrate sub-agents (fan-out, pipeline, loop, judge-panel), or automate a repeatable multi-step task across fresh-context agents.","https:\u002F\u002Fgithub.com\u002FTashima-Tarsh\u002FDisha6.6\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fworkflow-builder\u002FSKILL.md",[217],{"categoryNo":166,"categoryName":167,"taxonomyType":21,"taxonomyTypeDesc":22},[219,220,221,222,223,171,198,224,225,226,227,228,40,229,126,230,231,232,233,234],"workflow","workflow builder","builder","design","workflows","code","orchestrate","pipeline","loop","multi-agent","context","across","fresh","scripts","judge","claude code workflow",{"skillNo":236,"name":237,"nameZh":6,"description":238,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":111,"licenseFileUrl":6,"sourceHtmlUrl":239,"categories":240,"keywords":241,"publishedAt":46},"01M6QR7QMCZESKQA0ERW1E657M","weekly-review","Use when someone wants to run a weekly review, close open loops, audit stalled projects and commitments, get their system back to trusted, restart a lapsed review habit, or says \"\u002Fcs:weekly-review\". Walks David Allen's three-phase loop — GET CLEAR, GET CURRENT, GET CREATIVE — with deterministic scripts that inventory open loops, gate the checklist with named gaps, and score commitment health 0-100.","https:\u002F\u002Fgithub.com\u002FTashima-Tarsh\u002FDisha6.6\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fweekly-review\u002FSKILL.md",[],[242,243,244,245,246,247,248,249,42,227,250,251,252,253,254,255,128,256,257,210],"review","weekly review","weekly","deterministic scripts","reflect","feeds","inventory","open","projects","project-management","scanner","conversation","back","project","sprint","cadence"]