Matlab Extract Battery Features
MathWorksOfficialCreated by MathWorks
- Skill
- Tool integration
- Science and research
- BSD-2-Clause
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a structured interface for the MATLAB Predictive Maintenance Toolbox to extract diagnostic features from battery test data. It supports multi-cycle cycling tests, HPPC/pulse tests, EIS impedance sweeps, and in-field operational segments. The skill automates the segmentation and feature extraction process, outputting a structured feature table ready for downstream analysis like SOH or RUL estimation. It is designed to handle various data shapes and provides clear reporting on column mappings and data quality, ensuring consistent and reproducible feature engineering.
What it does
- Segments raw battery cycling data into charge, discharge, and rest phases.
- Extracts capacity, energy, and cycle-level statistics from cycling tests.
- Computes internal resistance and polarization features from pulse/HPPC tests.
- Analyzes impedance spectroscopy (EIS) data to extract resistance and arc features.
- Generates differential curves (IC/DV/DT) for aging mechanism analysis.
- Processes single-segment in-field data for operational condition monitoring.
When to use it
- When you need to extract features from raw voltage, current, and temperature traces.
- For analyzing battery degradation, SOH, or RUL using extracted feature tables.
- When performing cell screening or comparing performance across multiple battery cells.
- For extracting physical aging indicators like IC peak shifts or impedance growth.
- When you have raw data from bench cyclers, BMS logs, or drive/charge events.
Advantages
- Uses performance-optimized, native MATLAB functions for reliable feature extraction.
- Automates complex segmentation and peak detection tasks.
- Provides a standardized workflow for diverse battery test types.
- Ensures consistent data handling through explicit mapping and validation steps.
- Reduces manual coding effort for common electrochemical analysis tasks.
Usage examples
- “Extract features from my battery cycling data to help with SOH modeling.”
- The agent identifies the cycling data structure, maps the voltage/current/time columns, runs the parser and extractor, and presents a feature table with cycle-level metrics.
- “What is the charge-transfer resistance from this EIS file?”
- The agent processes the frequency, Zreal, and Zimag data using the EIS feature extraction function and reports the extracted resistance values.
- “Calculate the internal resistance from these HPPC pulse tests.”
- The agent identifies the pulse segments, applies the pulse feature extraction function, and returns a table containing resistance features for each pulse.
- “Can you extract features from this partial discharge segment logged by my BMS?”
- The agent uses the measurement features function to compute statistical and cumulative features from the single discharge segment.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/matlab/matlab-extract-battery-features/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip matlab-extract-battery-features.zip -d .agents/skills
Documentation by MathWorks
Battery Feature Extraction
Router for MATLAB's Predictive Maintenance Toolbox battery feature extraction functions. Detailed workflows live in references/*.md — load only the file that matches the inspected data type.
When to Use
Trigger on the domain questions asked about battery voltage / current / temperature measurements — from bench cycler / HPPC / EIS tests or from in-field / in-use operational data logged by a BMS or captured during a drive or charge event. The skill produces the feature table that feeds each question's downstream analysis. Concretely:
Degradation, SOH, RUL, capacity/energy fade. "How much has this cell degraded over 1000 cycles?" · "Track SOH." · "Estimate remaining useful life." · "Which cell is fading fastest?"
Aging mechanism from differential curves. "How are the dQ/dV peaks shifting?" · "Loss of lithium inventory vs. active-material loss?" · "Plot IC curves at cycles 1, 250, 500, 1000." · "What's the DV signature of aging?"
Internal resistance from HPPC / pulse tests. "What's R0 at 50% SOC?" · "How has DCR grown?" · "Get polarization resistance and recovery rate per pulse."
EIS / impedance analysis. "Fit the Nyquist plot." · "What's the charge-transfer resistance?" · "How has R0 grown from EIS?" · "Extract arc widths and Warburg tail."
Segmentation of cycling data. "Split this into charge / discharge / rest." · "Separate CC and CV portions of each cycle." · "Give me only the discharge segments." (With or without downstream feature extraction.)
In-field / operational condition monitoring. Features from a single measured segment that has no multi-cycle test structure — a partial charge or discharge logged by a BMS, one CC segment, or a drive/charge event. "Extract features from this field charge segment." · "Summarize this discharge from the vehicle log." · "What condition-monitoring features can I get from this partial charge?" (Served by
batteryMeasurementFeatures, which works stats-only when no cycle/time structure is present.)Fast-charging stress / plating indicators. "Is CV duration growing?" · "Any thermal signature of plating (DT)?" · "Recovery slowdown at high SOC?"
Cell screening / cell-to-cell comparison. "Compare these 10 cells." · "Rank by fade rate." · "Which cells are outliers?"
Feature engineering for ML. "Give me a feature table for SOH modeling." · "Which features best correlate with capacity fade?"
Batch processing of multiple test files through any of the above.
When NOT to Use
First-look / data classification / orientation questions on battery data: "What kind of test is this?" · "Describe this data." · "Tell me about this file." · "Analyze cycling.csv and tell me what it contains." These are inspection; the skill fires later when the user asks one of the analyses above.
Role-framing without a specific analysis in the current turn. A system prompt setting a "battery reliability agent" persona, a filename containing "battery" / "cycling" / "SOH", or a bare "analyze this" verb is not enough — the current user turn must name one of the specific analyses.
Data import or vendor-format conversion (Arbin
.res, Neware.nda, Maccor, BioLogic → MATLAB table).Plotting raw voltage / current / temperature vs time or capacity without first segmenting or computing an IC/DV/DT curve — that's a plain plotting task.
Cleaning, resampling, interpolating, or filtering time-series that does not feed into segmentation, differential curves, or feature extraction.
SOH / RUL model training or prediction — or any ML training — on an already-extracted feature table. This skill is the upstream feature step; modeling and prediction are downstream.
Battery simulation, equivalent-circuit modeling, or Simulink battery plant models.
Non-electrochemical data (fuel cells, supercapacitors, generic sensor streams).
This skill covers the 7 PMT battery feature extraction functions. These functions work natively with MATLAB tables and vectors, handle segmentation and peak detection internally, and are performance-optimized. Prefer these PMT functions over manual feature computation (e.g., hand-coded cumtrapz loops, manual peak finding). Override only if the user explicitly requests otherwise.
API Overview
The Predictive Maintenance Toolbox provides 7 public functions for battery feature extraction, organized by the kind of measurement they consume:
Battery Data
│
┌────────────────┬─────────────┴────────┬────────────────────┐
│ │ │ │
Multi-cycle Single measured Pulse tests EIS tests
cycling test segment (HPPC / GITT) (impedance)
│ (bench or in-field) │ │
▼ │ ▼ ▼
batteryTest- │ batteryPulseFeatures batteryEISFeatures
DataParser │ │ │
+ │ ▼ ▼
batteryTest- │ Pulse feature EIS feature
FeatureExtractor │ table table
│ │
▼ ├── batteryMeasurementFeatures → Measurement feature table
Full-pipeline │
feature table ├── batteryDifferentialCurves → IC / DV / DT curves
│
└── batteryDifferentialCurveFeatures → Curve peak feature tableThe single measured segment branch is the in-field / operational path: its functions take raw V / I / T / t from one charge or discharge segment and need no multi-cycle test structure, so they serve BMS-logged or drive/charge-event data as well as a segment pulled from a bench test.
| Function | Input | Output | Use When | Available From |
|---|---|---|---|---|
batteryTestDataParser | Raw cycling table | Parser object (segmented data) | Multi-cycle data needing segmentation | R2024b |
batteryTestFeatureExtractor | Options | Extractor object | Full pipeline: parser → all cycling features | R2024b |
batteryMeasurementFeatures | V, I, T, t vectors | Statistical + cumulative feature table | Any single-phase segment (partial or full charge/discharge) | R2026a |
batteryDifferentialCurves | V, I, T, t vectors | dQ/dV, dV/dQ, dT/dV tables | Constant-current segment only (CC charge or CC discharge) | R2026a |
batteryDifferentialCurveFeatures | Curve + x-axis | Peak feature table | Extracting features from differential curves | R2026a |
batteryPulseFeatures | V, I, t (or table) | Pulse feature table + pulse data | HPPC/pulse test resistance features | R2026b |
batteryEISFeatures | Zr, Zi, F vectors | EIS feature table | Impedance spectroscopy analysis | R2026b |
Load the Right Reference Before Proceeding
Step 1 — inspect the data shape. Load the file directly from the exact path the user gave, resolved against the current working folder. Do not recursively search temp, home, or system directories to locate it — a recursive dir(..., '**', ...) over such a tree can stall for over a minute. Then read the file and answer two questions:
Granularity. Is each row a per-sample raw record (many rows per cycle: voltage / current sampled at 1 Hz or faster), or is each row a per-cycle / per-cell summary (one row per cycle per cell, with columns like
Capacity,SOH,CV_hold_duration)?Multi-cell. Is there a
CellID/Cell/SerialNumbercolumn identifying multiple cells in the same file?
Step 2 — route by shape:
| Data shape inspected | Route |
|---|---|
| Raw per-sample multi-cycle cycling table with cycle and step index columns (one cell, or multi-cell — see note below) | references/cycling-pipeline.md |
| Raw per-sample cycling table with step index but no cycle index — either multiple cycles the parser can synthesize a cycle index for, or a single full charge-discharge cycle (see reference for the multi- vs single-cycle rule) | references/cycling-pipeline.md |
| Raw per-sample single-phase cycling segment (partial charge, one discharge, CC segment) with no cycle index and no full charge-discharge boundary | references/individual-cycling-functions.md |
| Raw short current pulses separated by rest periods (HPPC / GITT) | references/pulse-features.md |
Raw impedance sweep with Frequency, Zreal, Zimag | references/eis-features.md |
Already-aggregated per-cell / per-cycle summary — one row per (cell, cycle) with pre-computed Capacity, SOH, CV_hold_duration, RPT_capacity, temperature summaries, etc. (no per-sample V/I/t traces) | No reference loads. See § Data Is Already Aggregated below. |
Additionally, when tuning Tolerance, WindowSize, IC/DV/DT smoothing, or diagnosing "not CC data" errors | Also load references/parameter-tuning.md |
Multi-battery-cell data. When the data covers more than one battery cell, see the loaded reference's § Preprocessing: Data Layout for detection and combine/iterate rules, and § Postprocessing: Feature Table Organization for the featuresPerCell{k} output convention.
Data Is Already Aggregated — Skill Does Not Apply
If each row is already a per-cycle or per-cell summary (e.g., a CSV with columns CellID, Cycle, Capacity_Ah, SOH, CV_hold_s, Temp_max_C), the PMT battery* functions covered by this skill have nothing to add — they compute those very features from raw traces, and you already have them. Tell the user this, then handle the cell-ranking / degradation-comparison task with plain table operations:
Rank cells by fade rate: fit a slope of
CapacityvsCycleperCellID, sort ascending.Compare mechanisms by trending
CV_hold_s, temperature statistics, or resistance summaries per cell.Visualize with
tiledlayout: capacity-vs-cycle families, SOH trajectories, CV-hold growth.
This is standard MATLAB table wrangling — no PMT function is required. If a downstream skill fits better (e.g. matlab-analyze-data for the ranking workflow), route there instead of loading a reference from this skill.
Application × data shape. When the user names an application (SOH, RUL, Fast Charging, Cell Screening) that could be served by multiple data types, still route by inspected shape first — application alone doesn't pick a workflow. Then read the matching reference's "Feature Selection for Common Applications" section for the recipe.
Workflow Skeleton
Every reference in this skill follows the same phase template. Load the matching reference for the phase-by-phase details; the skeleton is:
| # | Phase | What it does |
|---|---|---|
| 1 | Identify inputs | Map data columns to the function's parameters. Workflow-specific vocabulary table lives at the top of each reference. General rules (vocabulary-first, datetime > numeric, unit conversion) below. |
| 2 | Data layout | Detect single-file vs multi-file, single-cell vs multi-cell, single-sweep vs multi-sweep; combine or split accordingly. |
| 3 | Call functions | Issue the primary computation call(s). |
| 4 | Verify results | Cross-check outputs against independent evidence. Cycling uses verifySegmentation + checkCyclingProtocol; individual-cycling uses verifySingleSegment. Pulse and EIS skip this phase — no verifier helper exists. |
| 5 | Tune parameters | Only if Phase 4 flagged an issue (or the caller reports symptoms of a wrong setting). Sweep tuning parameters and re-call. |
| 6 | Postprocess / organize | Attach tag columns (CellID, ExperimentIndex), keep per-cell tables in a cell array, etc. |
| 7 | Report + next steps | Present the feature table with the key-decisions summary and the Next Steps offer (§ Stop After Extraction rule below). |
Reference-to-phase map:
| Reference | Phases | Verify helper | Tuning reference |
|---|---|---|---|
cycling-pipeline.md (+ cycling/*.md on demand) | 1-7 | verifySegmentation or verifyAgainstSchedule, + checkCyclingProtocol | cycling/tolerance-tuning.md or cycling/schedule-verification.md; parameter-tuning.md (IC/DV/DT smoothing) |
individual-cycling-functions.md | 1-7 | verifySingleSegment | parameter-tuning.md (IC/DV/DT smoothing, NoiseTolerance) |
pulse-features.md | 1-3, 5-7 (no Verify) | — | inline (ValidPulseDurationRange, MinCurrentChange) |
eis-features.md | 1-3, 5-7 (no Verify) | — | inline (NumArcs, multi-sweep splitting) |
Interaction Rules
Cross-cutting rules that apply to every workflow — do not skip regardless of which reference you loaded.
Interaction Model: Stop or Proceed
Do not stop and ask before every extraction. Most decisions have a deterministic rule — apply it, extract, and report what you did so the user can correct it. Only stop when a decision is genuinely ambiguous and guessing it wrong would fail silently (plausible-but-wrong features). The rule applies to every workflow — cycling pipeline, individual cycling functions, pulse, and EIS.
STOP and ask the user first — but only when one of these is true:
General (all workflows):
Two or more candidate columns of the same type for one variable (e.g. two numeric elapsed-time columns, two current-like columns) — no rule can choose between them.
Raw unnamed numeric matrix — column roles must be inferred, not read from names.
A required variable cannot be mapped — a needed column is missing or its role is unclear.
Cycling pipeline only:
checkCyclingProtocolfinds neither phase consistent — no phase can be recommended.Anomalous cycles detected — never silently exclude them.
Otherwise PROCEED, then REPORT. Apply the deterministic rules — datetime/duration beats numeric time; set DT=true iff temperature is present; set CC=true whenever IC/DV/DT is requested; for cycling, use checkCyclingProtocol's RecommendedPhase — write and run the extraction, then present in a single after-extraction turn:
the column mappings used (noting any alternatives considered and why the chosen one won),
any workflow-specific decisions — cycling:
CyclingPhaseand its consistency reason; pulse: pulse-detection thresholds if adjusted; EIS: frequency range or sweep selected if the file had multiple,any data-quality findings (time-gap indices, invalid-point count, negative Zreal, missing rests, etc.) as a report line — not a gate,
any goal-vs-data tension, if present (see the loaded reference — e.g. cycling-pipeline.md Phase 4),
the resulting feature table, followed by the "what next?" offer.
Close the report with an explicit undo invitation, e.g. "If any mapping or the phase choice looks wrong, tell me and I'll re-run." This preserves the safety net without a blocking question.
Stop After Extraction — Offer Next Steps
Once the feature table is extracted and displayed, stop and present available next steps to the user. Do not autonomously proceed to visualization, feature ranking, or script saving. The stopping turn must have three parts:
Feature-table summary — M features across N rows / cycles / pulses / sweeps.
Key decisions + undo invitation — the autonomous choices you made, each stated so the user can override it, because these were decisions the user never explicitly approved:
Column mappings used (with any alternatives considered) and any unit conversion applied.
The workflow-specific settings the loaded reference tells you to report (cycling: CyclingPhase + consistency reason + feature categories; pulse: pulse-detection settings; EIS: frequency range / sweep selection; individual cycling: segment identified). The full workflow-specific template lives in each reference's § Report to the user after extraction.
Undo invitation, pointed at those choices — e.g. "I chose the time column, CyclingPhase, and feature categories automatically — tell me and I'll re-run with different ones." Do not use a generic "if anything looks wrong, let me know."
When Phase 4 flagged a concern, this is required and must name the finding — e.g.
verifySegmentationreturnedTuningRecommended,checkCyclingProtocolreported anomalous cycles, or pulse/EIS detection returned empty/failed. State the flag and the concrete re-run it implies ("3 cycles segmented inconsistently — I can re-run with a tighter Tolerance, or exclude them").
Next-steps offer — the four standing options:
Visualize: plots appropriate to the workflow (see the loaded reference's Phase 7 Visualize hints; cycling loads
references/cycling/postprocess.md)Rank features: identify most discriminative features for your analysis goal
Export: save the feature table to a .mat or .csv file
Refine: adjust feature categories, phase, or smoothing parameters
Only execute a next step when the user explicitly requests it. This applies even if the original prompt contains phrasing like "show me" or "plot" — extract first, present the table with the key decisions, then offer to visualize.
Column Mapping: General Rules
Workflow-specific column vocabularies live in the loaded reference's Phase 1 (Identify inputs). The rules below apply regardless of which vocabulary you're consulting.
Vocabulary first — try common vendor names before declaring a column missing. The 4 mainstream cyclers (Arbin, Neware, Maccor, BioLogic) and typical EIS/potentiostat exports each use different conventions. Match case-insensitively; strip units suffixes (_V, _A, /mA, /V, /Hz, /Ohm); a match on any name in the reference's Phase 1 vocabulary is sufficient — no need to stop-and-ask.
Unit conversion when the column name carries units. If the current column is I/mA (milliamps), convert to Amps before passing to the function (data.I_A = data.("I/mA") / 1000); same for mV → V. Report the conversion in the after-extraction summary.
Prefer datetime/duration over numeric elapsed time. If one candidate is
datetime/durationtype and another is numeric seconds, the datetime column wins — this is a rule, not a judgment call. Apply it and report it rather than asking. Note the alternative you considered in the after-extraction report (e.g., "I found bothTest_Time(numeric) andDateTime(datetime type) — usedDateTimeas it is a proper datetime column").Stop only when the rule can't decide. If two candidates share the same type (e.g. two numeric elapsed-time columns) so no rule can pick, ask. Likewise if a required variable has no clear column.
Report the mappings after extracting — with any workflow-specific decisions, data-quality findings, and an undo invitation. See § Stop After Extraction above and the loaded reference's Phase 7 for the workflow-specific template.
Unnamed Data (Matrices Without Column Names)
When data is a raw numeric matrix (no column names), infer column roles from value characteristics, then confirm with the user before proceeding:
EIS data: Frequency spans orders of magnitude (all positive), Zreal is non-negative with narrow range, Zimag can be negative with similar magnitude to Zreal
Pulse data: Current has distinct pulse/rest pattern, voltage shows step responses, time is monotonically increasing
Otherwise: If the data does not clearly match EIS or pulse patterns, ask the user what type of data it is rather than guessing
Present the inferred mapping and ask the user to confirm. Example:
Your data is a 641×3 matrix with no column names. Based on value ranges:
Column 1: spans 0.05 to 10000 (likely Frequency)
Column 2: all positive, range 13–22 (likely Zreal)
Column 3: range -14 to 6, mixed sign (likely Zimag)
Does this mapping look correct?
Cross-Function Pitfalls
Only two pitfalls are truly cross-cutting. Workflow-specific pitfalls (time format, phase mixing, DT requirements, feature-count overfitting, CC data requirements, EIS sign conventions, pulse-detection thresholds, etc.) live in the loaded reference's own § Pitfalls section — consult it before extracting.
Manual loops when a PMT function exists. If the user asks for capacity fade, IC peaks, pulse R0, EIS Rct, etc., use the PMT function — do not hand-code
cumtrapz,findpeaks, or manual segmentation loops.Wrong units. Current in Amps (not mA), voltage in Volts. Convert unit-suffixed columns before passing them to any PMT function.
Copyright 2026 The MathWorks, Inc.
Files
- ATTRIBUTION.mdAdded by AutoGineer1.1 KiB
- LICENSELicence file added by AutoGineer1.4 KiB
- SKILL.md21.6 KiB
- manifest.yaml469 B
- references/cycling-pipeline.md21.1 KiB
- references/cycling/feature-selection.md2.6 KiB
- references/cycling/multi-cell.md5.1 KiB
- references/cycling/postprocess.md2.4 KiB
- references/cycling/schedule-verification.md4.2 KiB
- references/cycling/tolerance-tuning.md2.4 KiB
- references/eis-features.md10.8 KiB
- references/individual-cycling-functions.md10.1 KiB
- references/parameter-tuning.md14.2 KiB
- references/pulse-features.md12.6 KiB
- scripts/checkCyclingProtocol.m9.2 KiB
- scripts/sweepScheduleAndReport.m3.7 KiB
- scripts/verifyAgainstSchedule.m8.5 KiB
- scripts/verifySegmentation.m6.3 KiB
- scripts/verifySingleSegment.m3.0 KiB
references/cycling-pipeline.md
Cycling Pipeline: batteryTestDataParser + batteryTestFeatureExtractor
Load this reference when the data is a multi-cycle cycling table with cycle and step index columns.
Interaction model: follow SKILL.md § Interaction Model: Stop or Proceed — apply deterministic rules, run the pipeline, then report mappings, CyclingPhase, and any data-quality findings in a single after-extraction turn. Do not gate on pre-extraction confirmations. The only STOP conditions specific to this workflow are (a) checkCyclingProtocol finds neither phase consistent, and (b) anomalous cycles detected (never silently exclude).
Follows the 7-phase workflow skeleton from SKILL.md. This file is the golden path for one battery cell in one file with no tester schedule. Load the files under references/cycling/ only when their condition applies:
| Load | When |
|---|---|
references/cycling/multi-cell.md | More than one file for a battery cell, or more than one battery cell (Phase 2 Layouts 2-3, Phase 6-7 per-battery-cell loop and report) |
references/cycling/schedule-verification.md | The user provides the tester schedule (Phase 4a Route B and its Phase 5 sweep) |
references/cycling/tolerance-tuning.md | verifySegmentation returns TuningRecommended == true (Phase 5 Route A) |
references/cycling/postprocess.md | The user picks Visualize or Rank features after extraction |
references/cycling/feature-selection.md | Choosing features for SOH / RUL / fast charging / cell screening, or interpreting a ranked list |
For tuning Tolerance, WindowSize, NumInterpolatedPoints, or diagnosing bad IC/DV/DT curves, also load references/parameter-tuning.md.
Phase 1 — Identify Inputs
batteryTestDataParser takes a table plus NV-pair column mappings. Identify each of the following columns before constructing the parser:
| NV-pair | Common column names |
|---|---|
CurrentVariable | Current, Current_A, I, I/mA, I/A, I_load, I_cell |
VoltageVariable | Voltage, Voltage_V, V, V_cell, V_load, Ecell/V, Ewe/V, Ewe |
TimeVariable | DateTime, Timestamp, Time, Test_Time, Step_Time, time/s, elapsed_time, t |
CycleIndexVariable | Cycle, Cycle_Index, CycleIndex, cycleIndex, Cycle_Number |
StepIndexVariable | Step, Step_Index, Step_Number, StepIndex, Ns, State |
TemperatureVariable (optional) | Temperature, Temperature_C, Temp, T, T_cell, T_ambient, AuxT |
Time must be datetime or duration (see § Pitfalls). Temperature is optional — omit or set TemperatureVariable="" when absent.
Multi-cell files additionally carry a CellID / Cell / SerialNumber column — kept as a separate tag, not passed to the parser (see references/cycling/multi-cell.md).
Required columns present? Handle missing ones before Phase 2
CurrentVariable, VoltageVariable, and TimeVariable are always required — if any is missing, this is a STOP (see SKILL.md § Interaction Model rule 3). For the others:
| Missing column | Do this |
|---|---|
CycleIndexVariable | Decide multi- vs single-cycle before synthesizing: <br>• Multi-cycle — step index resets (any(diff(step) < 0)) or current-sign flips multiple times: synthesize cumsum(diff([0; step]) < 0) or cumsum(diff([0; sign(current)]) ~= 0)/2. <br>• Single full cycle — step index present, no step resets, but the trace contains a full charge and discharge (current sign flips at least once, then never again): the whole record is one cycle. Synthesize CycleIndex = ones(height(tbl),1) and proceed — the parser still uses StepIndex for CC/CV/Rest segmentation and returns one row of cycle-level features. <br>• Neither (single partial segment, no full cycle boundary) — reroute to references/individual-cycling-functions.md. <br>Report which case was detected in the Phase 7 summary. |
StepIndexVariable | The cycling pipeline needs step index for CC/CV/Rest classification; the parser cannot synthesize it. Reroute to references/individual-cycling-functions.md (which segments a single phase by current/voltage behavior). |
TemperatureVariable | Set TemperatureVariable="" (or omit); set DT=false in the extractor. Statistics on temperature will not be extracted. Report this in the Phase 7 summary so the user knows thermal features were skipped. |
| Only a partial charge or discharge segment (no cycle boundaries at all) | Not a multi-cycle record — reroute to references/individual-cycling-functions.md (batteryMeasurementFeatures for statistics; batteryDifferentialCurves on the CC subset for IC/DV). |
| Voltage or current entirely (should not happen with a battery cycler) | STOP — this is not battery cycling data. |
Phase 2 — Data Layout
Cycling data usually arrives from the cycler as one file per test session (a session may contain many cycles). Detect the layout first. For cycling the rule is combine before parsing.
Layout 1 — One battery cell, one file
No preprocessing. Pass directly to batteryTestDataParser in Phase 3.
Layouts 2 and 3 — Multiple files, or multiple battery cells
Load references/cycling/multi-cell.md. It covers concatenating multiple files for one battery cell (cycle-index offset) and combining multiple battery cells under a CellID tag, plus the per-battery-cell extraction loop and report.
Report the detected layout in the Phase 7 summary so the user knows how the output is organized.
Phase 3 — Call the Functions (parse + segment)
Create batteryTestDataParser with the column mappings from Phase 1, then segment:
parser = batteryTestDataParser(tbl, ...
CurrentVariable="Current_A", ...
VoltageVariable="Voltage_V", ...
TimeVariable="Time", ...
CycleIndexVariable="Cycle", ...
StepIndexVariable="Step", ...
TemperatureVariable="Temperature_C", ...
ExcludedCycles=[], ...
Tolerance=5e-5, ...
NumInterpolatedPoints=1000, ...
WindowSize=10);
segmented = segmentData(parser);segmentData introduces three columns: CyclingModes (CC/CV/Rest), CyclingPhases (Charge/Discharge/Rest), and IsValid (logical). Data points that cannot be definitively classified are marked IsValid=false and excluded from analysis.
Column mappings are chosen by the router's deterministic rules (see SKILL.md § Column Mapping: General Rules) — datetime/duration beats numeric time, etc. Do not ask the user to confirm mappings before running the parser; report them in the Phase 7 summary.
The feature-extractor half of the pipeline (batteryTestFeatureExtractor + extract) runs in Phase 6 — after segmentation is verified and CyclingPhase is chosen.
Phase 4 — Verify Results
Three verification concerns run here. The first two are hard gates (route to Phase 5 tuning or STOP on failure); the third is a silent data-quality report line surfaced in Phase 7.
4a. Verify Segmentation
segmentData uses Tolerance (dV/dt threshold, default 5e-5 V/s) to decide CC vs CV. The default fails on low-sample-rate data (dt > 5 s) and on chemistries with flat plateaus, silently mislabeling CC segments as CV — which then propagates to wrong feature counts and missing IC/DV curves. Verify before extracting.
Two verification routes — pick by whether the user provided a tester schedule. Do not chain them; a schedule is authoritative when present.
| User input | Route | Helper |
|---|---|---|
| No schedule (default) | Raw-signal RSD signature vs CyclingModes | verifySegmentation(parser) |
| Schedule provided (per-step Type: CC / CV / Rest / CCCV) | Strict per-step assertions + CCCV interior check | verifyAgainstSchedule(parser, schedule) + sweepScheduleAndReport(...) for Tolerance sweep with data-collection exclusion |
Set the MATLAB current folder to the skill's scripts/ directory (MCP project_path) — both helpers live there.
Route A — No schedule provided
report = verifySegmentation(parser);report fields:
| Field | Type | Meaning |
|---|---|---|
RawSignatureTable | table | Per (Cycle, Step): RSD_Current, MedianCurrent_A, Expected mode (CC / Rest / Undefined) from the raw signal. |
SegmentationTable | table | Per (Cycle, Step): CC_Pct, CV_Pct, Rest_Pct from segmentData. |
MismatchGroups | table | The (Cycle, Step) rows where expected disagrees with observed, plus a Reason string. |
MismatchCount | integer | height(MismatchGroups). |
MismatchFraction | double | MismatchCount / (total groups). |
TuningRecommended | logical | true when MismatchFraction > MinMismatchFraction (default 2%). Sporadic single-cycle outliers below the threshold do not trip tuning — they are typically per-cycle data artifacts, not a systematic Tolerance mis-set. |
DiagnosticDt | double | Median inter-sample dt in seconds. Use as a starting hint for the Tolerance sweep. |
Agent action:
TuningRecommended == false→ proceed to 4b. IfMismatchCount > 0(sporadic outliers below the fraction threshold), surface the mismatched(Cycle, Step)rows as a one-line finding in the Phase 7 report so the user can decide toExcludedCyclesthem; do not force a Tolerance sweep.TuningRecommended == true→ go to Phase 5 and loadreferences/cycling/tolerance-tuning.mdfor the log-scale Tolerance sweep.
Route B — Schedule provided
Load references/cycling/schedule-verification.md and follow its Phase 4a (schedule struct, verifyAgainstSchedule) and, if any cycle fails, its Phase 5 sweep. Then return here for 4b.
4b. Protocol Consistency & CyclingPhase Selection
Run checkCyclingProtocol to assess whether the cycling protocol is consistent across cycles. Set the MATLAB current folder to the skill's scripts/ directory (pass its absolute path as the MCP tool's project_path) — do not call addpath. The script lives at scripts/checkCyclingProtocol.m alongside the verifier helpers.
result = checkCyclingProtocol(parser);result is a struct with these fields (agent should not need to read the script source):
| Field | Type | Meaning |
|---|---|---|
RecommendedPhase | string: "Charge" | "Discharge" | "Both" | The CyclingPhase to pass to the extractor. "Both" when both phases are consistent. |
ChargeConsistent | logical | true if charge-step protocol is repeatable across the majority cycles. |
DischargeConsistent | logical | true if discharge-step protocol is repeatable across the majority cycles. |
AnomalousCycles | numeric vector | Cycle indices whose step sequence does not match the dominant protocol. STOP trigger — never silently exclude. |
MajorityCycles | numeric vector | Cycle indices matching the dominant protocol; used to compute consistency flags. |
NumCycles | integer | Total cycles in the parsed data. |
StepTable | table | Per-step statistics (C-rate, voltage limits, duration) for the majority cycles — the reference protocol. |
The same parser object is reused for extraction in Phase 6 (with ExcludedCycles added if a STOP fires on anomalous cycles and the user confirms exclusion).
Agent should:
Pick CyclingPhase from
result.RecommendedPhaseand justify the choice by citing the repeating C-rate and voltage limits from the reference protocol table. The choice is purely about protocol consistency — do not justify it with the user's analysis goal (SOH, RUL, etc.).Surface goal-vs-data tension in the report, but do not let it change the phase choice. If the consistent phase is not the one conventionally associated with the user's stated goal (SOH and lithium-inventory loss → charge-side IC / dQ-dV; discharge only when the user explicitly asks about delivered-capacity fade), say so in the Phase 7 report. For an SOH goal, choosing
Dischargeis always a tension to report — even though discharge capacity also trends with SOH:You asked about <goal>, which conventionally leans on <charge/discharge>-side features. In your data, the <charge/discharge> protocol varies across cycles, so those features would not trend on a fixed baseline. Only the <other> protocol is consistent, so I extracted from there. Here's what the consistent phase can still tell you about <goal>: <what it can / can't deliver>.
This is a report line, not a phase-selection input.
STOP condition — anomalous cycles. If
result.AnomalousCyclesis non-empty, do not silently exclude them. Present the list and ask before proceeding:The protocol check found N anomalous cycles (X.X%) with non-standard step sequences: [list or first 10]. These cycles likely have data-collection issues (missing steps). Exclude them (
ExcludedCycles=[...]) and re-run?Only add
ExcludedCyclesafter the user confirms. This is one of two places in the cycling workflow where it legitimately blocks (the other is STOP condition 4).STOP condition — no consistent phase. If neither
ChargeConsistentnorDischargeConsistentis true, present the reference protocol table (C-rates, voltage limits, consistency flags) and ask which phase to extract from. Do not default silently.
4c. Data-Quality Signals (silent — surface in Phase 7)
Compute these two signals silently — they are reporting inputs, not gates. Include the numbers in the Phase 7 after-extraction report; do not pause the workflow.
Time anomalies. Battery cyclers sometimes have unexpectedly long gaps between data points (e.g., computer auto-restarts during multi-day tests). Detect and count them:
timeCol = segmented.(parser.TimeVariable);
if isdatetime(timeCol) || isduration(timeCol)
timeDiffSec = seconds(diff(timeCol));
else
timeDiffSec = diff(timeCol);
end
longInterval = 3600; % threshold in seconds (1 hour)
longIdx = find(timeDiffSec > longInterval) + 1;Include the count (and the first few indices) as a one-line report finding in the Phase 7 summary. If a long gap coincides with an anomalous cycle from 4b, that is a STOP condition (see 4b, anomalous-cycles rule).
Invalid data points. The parser automatically flags ambiguous points as IsValid=false. Compute the fraction:
nInvalid = sum(~segmented.IsValid);
invalidPct = 100 * nInvalid / height(segmented);Include nInvalid / total / percent in the Phase 7 report. A small fraction (<1%) is normal (mode transitions). If a large fraction is invalid, mention that the column mappings or Tolerance may need adjustment (references/parameter-tuning.md) — mention as a suggestion, not a gate.
Phase 5 — Tune Parameters (on Phase 4 failure)
Runs only when Phase 4a fails. Load the file for the route you are on:
Route A (
TuningRecommended == true) →references/cycling/tolerance-tuning.md— log-scale Tolerance sweep and its STOP condition.Route B (a cycle fails the schedule) →
references/cycling/schedule-verification.md§ Phase 5 — sweep with data-collection exclusion.Noisy or flattened IC/DV/DT curves →
references/parameter-tuning.md§ Differential Curve Parameters.
Skip Phase 5 entirely when the user has already fixed Tolerance in an earlier turn and the current call is a re-run.
Phase 6 — Postprocess / Organize Results
With segmentation verified (Phase 4) and Tolerance tuned if needed (Phase 5), call the extractor to produce the feature table. The code below is for one battery cell; for multiple battery cells, loop per battery cell as shown in references/cycling/multi-cell.md § Phase 6.
Feature extraction — single battery cell
extractor = batteryTestFeatureExtractor( ...
CyclingPhase="Charge", ... % 'Charge', 'Discharge', or 'Both' (from Phase 4b)
Statistics=true, ... % Voltage/current/temp statistics
CycleCumulative=true, ... % Capacity, energy, duration
CC=true, ... % Constant-current segment features
CV=true, ... % Constant-voltage segment features
CCCV=true, ... % CC+CV combined features
IC=true, ... % Incremental capacity curve features
DV=false, ... % Differential voltage curve features
DT=false); % Differential temperature curve features
featureTable = extract(extractor, parser);One row per cycle; the cycle-index column is the main x-axis for trending.
Feature Categories (165+ features total)
| Category | Property | Features | Tracks |
|---|---|---|---|
| Statistics | Statistics=true | max, min, mean, std, skewness, kurtosis of V, I, T | General degradation trends |
| CycleCumulative | CycleCumulative=true | Capacity (Ah), energy (Wh), duration, start voltage | Capacity fade, energy efficiency |
| CC | CC=true | CC duration, median current, slope, energy, skewness, kurtosis | CC phase degradation |
| CV | CV=true | CV duration, median voltage, slope, energy, skewness, kurtosis | CV phase degradation |
| CCCV | CCCV=true | Energy ratio (CC/CV), energy difference | Phase balance shift |
| IC | IC=true | Peak value, width, location, prominence, area, slopes | Electrode degradation mechanisms |
| DV | DV=true | Peak features from dV/dQ curve | Electrode capacity balance |
| DT | DT=true | Peak features from dT/dV curve | Thermal degradation signatures |
Dependency: IC, DV, and DT require CC=true. These differential curve features are computed from CC segments identified by the parser. If CC=false, no CC segments are identified and IC/DV/DT will silently produce no features. Always set CC=true when enabling IC, DV, or DT.
CCCV requires both CC=true and CV=true. The extractor handles this automatically.
Phase 7 — Report + Next Steps
Present a single after-extraction report containing everything the user needs to spot-check the run:
Single battery cell
Feature extraction complete — M features across N cycles.
Key decisions:
Column mappings:
CurrentVariable→ "…" (any alternative considered)
VoltageVariable→ "…"
TimeVariable→ "…"
CycleIndexVariable→ "…",StepIndexVariable→ "…"
TemperatureVariable→ "…"CyclingPhase → "Charge" — consistent C-rate <X> and voltage limits <a-b V> across all cycles.
Feature categories: [list enabled categories];
DT= <true/false> (temperature <present/absent>).Tolerance = <value> {default | tuned from Phase 5 sweep}.
Data quality: <k> long time gaps (> 1 h); <n>/<total> invalid points (<pct>%). <optional: note if suggests Tolerance retune>
If any mapping or the phase choice looks wrong, tell me and I'll re-run.
For multiple battery cells, use the report in references/cycling/multi-cell.md § Phase 7 instead.
Then stop and offer the four standing next steps (Visualize / Rank features / Export / Refine) exactly as defined in SKILL.md § Stop After Extraction — Visualize and Rank load references/cycling/postprocess.md. Only execute a next step when the user explicitly requests it.
Visualization & Feature Ranking (next-step options)
When the user picks Visualize or Rank features, load references/cycling/postprocess.md — it has the plot-type table (segmented data, IC/DV/DT overlays, feature trends) and the correlation-ranking recipe. Do not run either before the feature table is extracted and reported.
Complete Workflow Example
Deterministic-rule path: parse+segment (Phase 3) → verifySegmentation, sweeping Tolerance via the Phase 5 loop if TuningRecommended (Phase 4a) → silent data-quality signals (Phase 4c: longIdx, nInvalid) → checkCyclingProtocol for RecommendedPhase (Phase 4b) → extract with the chosen phase + categories (Phase 6) → single after-extraction report (Phase 7). No pre-extraction gate; STOP only on anomalous cycles, no consistent phase, or a Tolerance sweep exhausted on substantive steps (1-3-sample artifact steps are benign — see references/cycling/tolerance-tuning.md). The per-phase code blocks above are the canonical copies — follow them in order.
Pitfalls
Mixing charge and discharge data. Both parser and extractor require CyclingPhase to be set correctly. Features extracted from mixed phases are not meaningful for degradation trending.
Time format. Time must be
datetimeorduration, NOT numeric seconds. Convert:t = seconds(numericTime)ort = datetime(numericTime, 'ConvertFrom', 'posixtime').Missing temperature for DT curves. Set
DT=trueonly when temperature data is present; setDT=falsewhen it is not.Extracting all features blindly. 165+ features with <50 cycles = overfitting risk. Use
references/cycling/feature-selection.mdto pick physically meaningful subsets.Capacity/energy depend on unit correctness. Capacity is computed internally as Ah via
cumtrapz(I, t)/3600— soImust be in Amps andtin seconds/duration. Passing mA or mV silently produces wrong-scaledCapacity/Energy/CycleCumulativefeatures without erroring; convert unit-suffixed columns before constructing the parser.
Copyright 2026 The MathWorks, Inc.
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- MathWorks
- Publisher
- MathWorks (Official)
- Source
- matlab/matlab-agentic-toolkit · skills-catalog/control-systems/matlab-extract-battery-features · commit 2a7f215
- Licence
- BSD 2-Clause License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE.md)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by MathWorks or MathWorks.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download matlab-extract-battery-features.zip