How the voltage curves of four ageing batteries become rows that keep only their shape,
and what PCA, UMAP, a held-out-battery test and ΔQ(V) show about how that shape changes with age.
Data source. CALCE CS2 lithium-ion cycling data with a derived per-cycle state-of-health series. Detailed dataset provenance and usage conditions are on the Dataset page.
Notebook lineage
Source / context
PC5251 final project, National University of Singapore, 2024.
Notebook
Report.ipynb · 2024-05-03
Our changes
Our changes — 3 deviations from the notebook
Added persistence and linear-trend baselines, recursive forecasts on the held-out battery, remaining-life scoring with a sustained threshold, and training with three seeds.
Added the raw voltage and current views and the curve-shape analyses (PCA, UMAP, leave-one-battery-out and ΔQ(V)) from the earlier explorer page.
Made the spike filter backward-looking (causal) and used the window and learning rate that the notebook’s code runs (30 and 0.01).
What the data files contain
Each value stated in the source record is set beside a count made directly from the CALCE files. The four batteries’ archives hold 106 exported workbooks; after removing the duplicate final exports, the analysis uses 104 workbooks (test sessions) and 1,119,328 samples logged every 30 seconds, roughly 280,000 per battery.
Property
Stated value
Measured in the files
Check
CALCE CS2 batteries · PC5251 final project (2024) · 2010-08-16 to 2011-02-03 · four batteries · within-cycle voltage/current samples and 128 standardised shape coordinates.
Battery-by-battery inventory
battery
recorded samples
record date span
sessions used
logged cycles
rows in X
cycles checked against Statistics sheet
median relative difference
over 1%
CS2_35
260,931
2010-08-16 → 2011-02-03
24
886
774
559
2.504e-9
0
CS2_36
269,656
2010-08-16 → 2011-02-02
26
976
760
595
2.982e-8
0
CS2_37
290,998
2010-08-16 → 2011-02-02
27
1,043
845
643
0.000e+0
0
CS2_38
297,743
2010-08-16 → 2011-02-03
27
1,032
866
626
4.198e-7
0
What the raw files required
The CALCE exports are not a ready-made table of cycles. These findings shaped how the cycles were rebuilt and screened.
The files are test sessions, not a table of cycles
Files must be ordered by the timestamps inside them; cycle numbers restart in every file, and capacity columns keep adding up within a file.
104 files · 3,937 logged cycles
So the analysis rebuilds one continuous cycle count and measures each charge and discharge from its own start and end.
Two files are duplicate exports
Two batteries’ final sessions were exported twice under different dates: the files differ byte for byte, but the measurements in them are identical.
2 duplicate exports · 50 cycles each
Duplicates are removed by comparing the measurements, before any analysis.
Every removed cycle has a named reason
Missing halves, off-protocol cycles, truncated cycles and cycles with too few samples are counted separately.
16 half missing · 4 off protocol · 120 truncated · 552 too few samples
The final matrix keeps 3,245 of 3,937 logged cycles.
Recomputed capacities match the cycler’s own records
Where the cycler’s Statistics sheet records a capacity for a cycle, the capacity recomputed from the samples agrees with it.
2,423 checked cycles · largest median relative difference 4.198e-7
The relative difference stays within 10⁻⁶.
From raw exports to a table of curve shapes
A design matrix is the table a model learns from: one row per example, one column per input value. Here each row is one charge–discharge cycle, and each column is the voltage at one fixed point in that cycle, after the curve’s level and spread have been removed.
Size of the table (design matrix) given to PCA
—
Each row is one screened charge–discharge cycle; each column is one fixed point in the charge or the discharge, measured as a fraction of that half’s duration.
4batteries
1,119,328raw samples
692cycles excluded
How a row is built
Order the files by the timestamps inside them, rebuild one continuous cycle count, and remove duplicate exports.
Find the charge where the current is above 0.02 A and the discharge where it stays below -0.5 A, using the current rather than the logged step number.
Resample the charge and the discharge separately to 64 points each, so the switch from charge to discharge always falls at column 64.
Standardise each row (subtract its mean voltage, divide by its spread) so only the shape remains. The removed level and spread, the durations, the capacity and the coulombic efficiency are kept as labels beside X.
Fig 1 · One full cycle, as the cycler logged it
CS2_35, cycle 30 · SOH 0.98 · 30 s sampling
Voltage (upper) and current (lower) on one time axis
How one cycle runs. The cycler charges at a constant 0.55 A until the voltage reaches 4.2 V (constant current, CC), then holds the voltage while the current falls to 0.05 A (constant voltage, CV). After a rest, it discharges at 1.1 A until the voltage drops to 2.7 V. The upper chart is the battery’s voltage; the lower chart is the current the cycler applies.
What the export files do. File names carry the export date, not the date of the data; cycle counters restart in every file; capacity adds up within a file; and each duplicate final export would add 50 cycles that were already counted.
Fig 2 · How the discharge curve changes with age
Discharge voltage over time, V(t): seven cycles across life
The same cycles against charge delivered, V(Q)
cycle 18cycle 161cycle 301cycle 439cycle 581cycle 724cycle 869 · not in X
SOH over life; dots mark the seven cycles above
The curve shrinks and sags. Later discharges are shorter, and the sloping middle sits lower. In V(Q) the curves separate first at low voltage, the region that ΔQ(V) measures later on this page. In “SOH over life”, ticks mark the start of each test session; SOH dips and partly recovers around them, so it falls steadily only on average. Dashed late curves are complete but have fewer than 64 samples, so they are left out of X.
The selected raw curves as a table
Fig 3 · Cycles removed by each screening rule, per battery
Counts are cycles; each removed cycle fails one of four rules.
battery
files
logged
half missing
off protocol
truncated
too few samples
rows in X
kept
CS2_35
24
886
4
0
28
80
774
87.4%
CS2_36
26
976
3
0
29
184
760
77.9%
CS2_37
27
1,043
5
2
29
162
845
81.0%
CS2_38
27
1,032
4
2
34
126
866
83.9%
total
104
3,937
16
4
120
552
3,245
82.4%
The rules, in order. “Half missing”: a file boundary cut the cycle, so only the charge or only the discharge is present. “Off protocol”: the cycle does not follow the test schedule; the batteries arrived already formed, so this check replaces a rule about initial conditioning cycles, and it removes only 4 cycles. “Truncated”: the discharge does not reach 2.75 V or lower, or the constant-voltage hold does not taper to 0.07 A or lower. “Too few samples”: a half has fewer than 64 logged samples, so filling 64 points would mean inventing data. This last rule is why the matrix stops near SOH 0.52: late discharges are short enough to fall below 64 samples.
Fig 4 · From one logged cycle to one row: split, resample, standardise
1 · Find the two halvesUse the current, not the logged step number.
2 · Rescale timeGive each half its own 64-point time axis.
3 · Standardise the rowRemove the average level and spread so only the shape remains.
4 · Keep what was removedStore the mean, spread, durations, capacity and CE as labels.
Real time: halves of unequal length
Resampled voltage: the switch fixed at column 64
Standardised row: shape only
The same recipe at every age. CS2_35 cycle 40 has SOH 0.97, charge duration 2.31 h and discharge duration 0.96 h. After resampling, each half has exactly 64 columns. Standardising removes the mean 3.840 V and the spread 0.249 V; the capacity 1.070 Ah and CE 1.009 are kept as labels.
Why two separate time axes? Giving the charge and the discharge their own time axes lines up, in every row, the corner where constant current switches to constant voltage and the knee near the end of the discharge, so PCA does not have to spend components on differences in duration. Every kept half has at least 64 samples, so resampling only ever reduces the number of points. During the constant-voltage hold, samples can be minutes apart, but the voltage is held at 4.200 V, so interpolating voltage across those gaps is justified.
Fig 5 · The design matrix
Click the heatmap or use either slider; every linked view and table follows.
The whole matrix
Rows are stacked battery by battery, each in order of cycle. Colour shows the standardised voltage of each entry. The vertical line is the switch from charge to discharge, at the same column in every row.
X[i,:]X[:,j]x_ij
x[425,83] = -0.40 z = 3.720 V
X[i,:]one cycle
Across one row
Shown in volts, by undoing the standardisation with this row’s stored mean and spread.
X[425,:] → CS2_35, cycle 438; reconstructed with v_mean 3.831 V and v_std 0.278 V.
X[:,j]one normalized instant
Down one column
Every battery across cycle number; the selected battery is emphasised.
X[:,83] → 30% through normalized discharge time across 3,245 rows.
Labels sit beside X, not inside it. Capacity, CE, durations, mean voltage and voltage spread appear in the linked tables below; PCA never receives them.
The matrix as tables: click a row or column, or use the keyboard, to select it
i
battery
cycle
SOH
q_dis
j
half
position
z
V
Labels stored beside the selected row
Rows and columns answer different questions. A row is everything PCA knows about one cycle. A column shows how the voltage at one point of the cycle changes across life. The selected mid-discharge column already shows a pattern with age; PCA finds the weighted combination of all 128 columns that varies most.
Transformation: the shape rows given to the model
Every retained cycle is represented by 128 standardised voltage values: 64 for the charge and 64 for the discharge. Cycle number, capacity, duration and battery identity are kept out of the model.
Modelling: letting PCA find the main patterns in the shapes
PCA (principal component analysis) receives only the shape rows. It finds the combinations of columns along which the rows differ most, called principal components; a row’s position along one of them is its score. Cycle number and capacity are kept aside and used only afterwards, to check what the components mean. UMAP, a nonlinear method, gives a second view of the same rows.
Fig 6 · PCA on all four batteries together: the first component carries 86.4% of the shape variance
Can the four batteries be analysed together? Only if PC1 does not simply tell one battery from another. Here η²(battery), the share of PC1’s variation explained by which battery a cycle came from, is 0.018, so battery identity explains little of PC1. In an earlier analysis of lithium-metal batteries with different chemistries and test schedules, PC1 fitted on all of them instead separated the chemistries (η² = 0.99), and two truncated cycles changed the rank correlation from -0.95 to -0.56; this is why truncated cycles are screened out here.
Variance explained
PC1 and PC2 loadings
Every cycle on PC1–PC2
early cyclelate cycle
What PC1 measures. A loading is the weight a component gives each column. PC1 weights the charge half and the discharge half with opposite signs, so it measures the gap between them: as resistance rises with age, charging voltage rides higher and discharge voltage sags lower. The same contrast appeared in both chemistries of the earlier lithium-metal analysis and appears here in a third, LCO. In “Every cycle on PC1–PC2”, cycles move from early to late along PC1, with the four batteries overlapping; PC2 carries 3.4% of the variance, mostly ripples within a test session.
Numbers behind the PCA: components, scores, loadings and rank correlations
PCA scores as a table
row
battery
cycle
SOH
PC1
PC2
Fig 7 · A separate PCA on each battery finds the same first component
PC1 loadings from four separate PCAs
CS2_35CS2_36CS2_37CS2_38dashed line = switch from charge to discharge
battery (own PCA)
PC1 variance
ρ(PC1, cycle)
ρ(PC1, capacity)
CS2_35
88.3%
0.911
-0.953
CS2_36
87.9%
0.943
-0.960
CS2_37
88.8%
0.937
-0.960
CS2_38
83.2%
0.637 *
-0.670
* Same loading; this battery also has a reversible episode unrelated to ageing (see Fig 9).
Four separate fits, one loading. Cosine similarity measures how closely two loading curves point the same way (1 = identical); the lowest value between any two batteries is 0.997. CS2_38 finds the same PC1 but orders its cycles by age less cleanly, because its polarisation rises and then recovers during one episode.
Numbers behind the per-battery PCAs
Fig 8 · UMAP: a second, nonlinear view
Islands ordered by age, with the batteries mixed. Each point is one cycle. Every island contains cycles from all four batteries, unlike the earlier lithium-metal UMAP, where the chemistries separated. The islands follow test sessions and the partial recovery after each rest. Parameters are n_neighbors = 15, min_dist = 0.1, seed = 42.
UMAP coordinates as a table
row
battery
cycle
UMAP-1
UMAP-2
Evaluation: bringing back cycle number and capacity
The main test fits PCA on three batteries and applies it to the fourth, which the fit never saw. The resulting scores are then compared with cycle number and with capacity, neither of which was part of X. Use “Evaluation view” to switch between this test and the ΔQ(V) features.
Fig 9 · Leave one battery out: fit PCA on three, project the fourth
CS2_38 projected from the other threeρ with cycle 0.644ρ with capacity -0.677
held-out battery
PC1 variance (fit on the other three)
ρ(PC1, cycle)
ρ(PC1, capacity)
|ρ| with its own PC1
CS2_35
85.88%
0.910
-0.953
1.000
CS2_36
86.43%
0.943
-0.960
1.000
CS2_37
85.71%
0.937
-0.960
1.000
CS2_38
87.82%
0.644
-0.677
1.000
Why hold out whole batteries? Neighbouring cycles of one battery are nearly identical. If rows were split at random, every test row would have a near-twin among the training rows. Holding out a whole battery avoids that.
Each point is one cycle of the held-out battery: its PC1 score against its cycle number. Ticks on the horizontal axis mark the start of each test session. CS2_38 has a reversible episode. During cycles 60–150, its discharge voltage sits about 40 mV lower and its charge voltage about 30 mV higher, then relaxes back, while capacity keeps falling at its usual rate. PC1 follows this voltage change, so ρ with cycle drops to 0.64, against 0.91–0.94 for the other batteries. The projection still works; PC1 tracks polarisation rather than age itself.
Fig 10 · PC1 against capacity, which PCA never saw
Shape tracks capacity. Capacity was computed from the current and never entered X, and standardising each row also removed the voltage level. Even so, the rank correlation ρ between PC1 and capacity (−1 means a perfectly opposite ordering) is -0.95, -0.96, -0.96 for the first three batteries. CS2_38 reaches only -0.68, because its temporary polarisation episode moves PC1 while capacity stays on trend. PC1 measures the gap between charge and discharge voltage, which ageing usually, but not always, widens steadily.
PC1 and capacity as a table
row
battery
cycle
capacity
PC1
ΔQ(V) curves across life
One log-variance value per cycle
Early ΔQ(V) variance against lifetime, four batteries
What this analysis establishes
The main results, most important first.
One curve-shape direction dominates all four batteries and carries over between them
PCA receives no cycle numbers or capacity, yet its first component orders most of each battery’s life and reappears when PCA is fitted to each battery separately.
Components fitted on three batteries reproduce the fourth battery’s own PC1 almost exactly. Holding out whole batteries keeps nearly identical neighbouring cycles out of the test.
agreement with each battery’s own PC1 = 1.000 · 1.000 · 1.000 · 1.000
PC1 tracks capacity, which PCA never saw
Capacity is computed from the current and never enters X. Three batteries show a strong inverse rank correlation; CS2_38’s is weaker.
CS2_38’s reversible episode changes the curve shape while capacity keeps fading. That PC1 follows the voltage gap here, not capacity, supports reading it as polarisation.
ΔQ(V) grows at low voltage and tracks remaining life within each battery
The difference curves grow most at low voltage, and within each battery their log variance tracks remaining life; the comparison across batteries has four points.
CS2_38 ρ = -0.809 · n = 4
The analysis covers life down to about SOH 0.52
Late cycles with fewer than 64 samples in a half are left out rather than filled in, so the last part of life is not in X.
matrix rows = 3,245 · coverage floor ≈ SOH 0.52
Glossary and scientific background
Each term is defined as it is used on this page.
Battery and protocol
Battery
One of the four CALCE CS2 test batteries, CS2_35 to CS2_38. Each is a single 1.1 Ah prismatic cell, so “battery” and “cell” mean the same thing here.
LCO
Lithium cobalt oxide, the chemistry of these batteries. Its discharge voltage slopes continuously rather than staying on a long flat plateau.
LFP
Lithium iron phosphate, the flatter-voltage chemistry used in the comparison studies discussed on this page.
CC charge
Constant-current charging at the protocol’s fixed current until the upper voltage limit is reached.
CV hold
Constant-voltage charging at the upper voltage limit while current tapers to the cutoff.
C-rate
Current relative to rated capacity; here the discharge current equals one nominal capacity per hour.
Capacity
The charge delivered in one discharge, obtained by adding up the current over time. Here it is kept as a label, not used as an input.
SOH
State of health: the capacity delivered in one discharge divided by the rated capacity, 1.1 Ah. (The Battery SOH demo divides by a fixed 4,100 A·s, about 1.14 Ah, instead.)
CE
Coulombic efficiency: discharged charge relative to charged charge for one cycle; stored as a label.
EOL80
End of life at 80%: the first cycle from which SOH stays at or below 0.80 for 5 consecutive cycles.
Session
One exported workbook covering a stretch of testing. Cycle counters restart in each one.
Polarisation
The charge branch riding higher and the discharge branch lower under load, producing a voltage gap associated with resistance.
Rest recovery
Partial relaxation of voltage and capacity after idle time, visible as session-aligned sawteeth rather than true rejuvenation.
Cyclable-lithium inventory
Lithium still available to shuttle during cycling. Its loss shortens the delivered-capacity span.
Internal resistance
Opposition inside the battery that raises charging voltage and lowers discharging voltage under current.
Rows and transformations
Cycle curve
The complete recorded round trip of charge, hold, rest and discharge for one cycle.
Half-cycle
The behavior-located charge or discharge portion treated separately during time normalization.
Normalized time
Position from start to end of one half-cycle, independent of its real duration.
Resampling
Interpolation onto the shared normalized-time columns. Retained rows are downsampled, never upsampled.
Seam
The fixed boundary between the charge and discharge column blocks in every row.
Z-score
For each row, subtract its own mean and divide by its own standard deviation, removing level and scale.
Design matrix X
The sample-by-feature array given to PCA: one retained cycle per row and one normalized-time voltage-shape value per column.
Feature
A value inside X that the model is allowed to use.
Label
Context stored beside X, such as cycle, capacity, duration and battery identity, revealed only for evaluation.
Truncated cycle
A record that contains apparent phases but does not reach the protocol’s termination span.
Too-few-samples rule
Removes a cycle if either half has fewer than 64 logged samples, too few to fill the 64 columns without inventing points.
Representation and evaluation
PCA
Principal component analysis, fitted here only to X to find orthogonal directions of greatest shape covariance.
Principal component
A weighted direction through the shape columns. PC1 is the leading direction.
Loading
A column’s weight in a principal component; its sign pattern shows what curve contrast the component measures.
Score
A row’s coordinate after projection onto a component.
Explained variance
The share of total shape variance carried by one principal component.
η²
The share of a component’s variance explained by which battery a cycle came from; used here to check whether PCA on all four batteries mostly separates them.
Spearman ρ
Rank correlation used to ask whether scores order cycles or capacity without assuming a straight-line relation.
Cosine similarity
Agreement between loading directions after their arbitrary sign is aligned.
Leave one battery out
Fit on every row from three batteries and project every row from the fourth.
UMAP
A nonlinear method that places rows with similar shapes near each other in two dimensions; used here as a second view alongside PCA.
ΔQ(V)
The delivered-capacity curve at a later cycle minus an early reference curve on a shared voltage grid.
Log variance
The base-ten logarithm of variance across one ΔQ(V) curve, reducing it to one scalar per cycle.
Remaining life
Cycles from the current cycle to the sustained EOL80 crossing in the within-battery ΔQ(V) check.