Instructions

PyBEP works backwards from a full cell. Give it the OCV curve you measured on a complete battery and it finds the cathode and the anode whose own curves, used over the right portion of each, add up to what you measured.

You get back the identity of both electrodes, how much of each the cell actually uses, a graph of the reconstruction against your measurement, and the numbers behind it. There is a second tool, Format data, that only cleans and standardises files without decomposing anything.

Try it with no data

Everything needed for a complete run is already here, so you can see what PyBEP produces before preparing anything of your own.

  1. Open Run optimization.
  2. Under Battery OCV curve, choose one of the 4 bundled measurements instead of “Upload my own file”.
  3. Press Run optimization.

Nothing else needs touching: all 7 cathodes and 2 anodes are selected already, and because you uploaded nothing there are no columns to confirm, so the results appear straight away. Then swap in your own measurement and keep everything else the same.

Running an optimization

  1. Choose the battery OCV curve. This is your measurement: the full-cell curve to be decomposed. Upload it, or pick one of the bundled examples.
  2. Check the candidates. 7 reference cathodes and 2 reference anodes are built in and all selected by default, so you can usually leave this alone. Open a panel to see the list, preview any curve, or untick materials that cannot apply to your cell — fewer candidates means a faster run. Their names are the material followed by the DOI of the paper the curve came from, with / written as _; ones ending in -LICeM were measured in-house. For a material that is not listed, the second panel — Your own files — takes files of yours; those are used for that run only and are not added to the shared list.
  3. Set iterations. The search starts from random points, so each run can land somewhere slightly different. More iterations repeat it and keep the best, trading time for consistency. Start at 1 while you are finding your way, raise it for a result you intend to keep.
  4. Set the weights. These decide what “closest” means. Battery weight fits the voltage curve itself. Differential capacity weight fits its derivative instead, which is far more sensitive to the position of peaks and plateaux — the features that identify a material. The two always sum to 1, so moving one moves the other. Fit on voltage alone and a smooth curve can hide a wrong material; add derivative weight to make the peaks matter.
  5. Confirm the columns. Only for files of your own, and it happens the moment you pick one: PyBEP reads the file there and then and asks, over the form, which column is SOC and which is OCV — with the first few rows shown and its guess already selected. Answer it and the file is named under the box it came from, with a × beside it for taking it back out. Built-in curves never ask, because their layout is already known.

However the curves were chosen, Run optimization is the only button that starts a run. By the time you press it, any file of your own is already on the server with its columns settled, so nothing is asked in between.

Comparing the whole built-in set is 14 electrode pairs: a few seconds at one iteration, up to about a minute at five, depending on how busy the server is. The button turns into a charging battery while it works, and nothing else on the page moves — so the last graph is still there to read while you wait. Leave the tab open; the results come up on their own when it finishes.

Reading the results

The graph overlays your measured curve with the reconstruction, plus the cathode and anode curves that produced it. Dashed sections are the parts of each electrode curve lying outside the window actually used in the fit.

Best cathode / anode ID
Which candidates won, named by their file.
Best parameters
Where each electrode curve was cut, as (anode start, anode end, cathode start, cathode end) in points out of 1001. They say how much of each electrode the cell is using: a real cell never cycles either electrode over its full range, and these are the fitted limits. The anode may be trimmed by up to 30 % at each end, the cathode by up to 15 %.
Lowest RMSD
How far the reconstruction sits from your measurement — lower is better. At a battery weight of 1 it is a root-mean-square voltage error in volts. Any derivative weight adds a second term measured in different units, so it becomes a score rather than a voltage, and is only comparable between runs that used the same weights.

Anything unusual about your file — SOC read as a percentage, points reordered, values out of range — is reported in a note above the results rather than corrected silently. Read those notes; they are the difference between a fit and a coincidence.

A winner is always reported, even when nothing fits well. The RMSD, and your own eye on the graph, are what tell you whether the answer means anything. If the best fit is poor, the right material is probably not among the candidates.

Download the numbers as JSON, CSV or Excel. All three describe the same run. JSON keeps full precision; Excel stores about 15 significant digits, so use JSON if the last digits matter. The form stays on the left while the results appear beside it, so moving a slider and pressing Run optimization runs the same comparison again — the quick way to see how sensitive a result is to the weights.

Results stay on the page. Going to Format Data or to these instructions and coming back leaves them where they were, and so does the back button. Refreshing the page, or clicking the PyBEP mark in the corner, starts over: the form returns to its defaults and the panel to its starting state, ready for the next run. Nothing is thrown away — a link on the empty panel brings the last run back.

Download before you start another run. Each new run replaces the previous one, and the earlier result cannot be retrieved afterwards.

Files of your own stay on the server between runs. The box they came from looks empty afterwards — no browser will refill a file box — but the file is named underneath it, and the next run uses it without your picking it again. Starting over clears them along with everything else.

Preparing your own files

Every curve, whatever it describes, is just two columns of numbers: state of charge and voltage. Files may be .txt, .csv or .xlsx, up to 32 MB.

Every curve is finally resampled onto a common grid of 1001 points, which is what makes different sources comparable.

If a file is rejected, the message says why. The one problem PyBEP will not work around is text sitting between rows of numbers — an error line logged mid-measurement, say — because at that point there is no way to tell a stray label from corrupted data. Delete the offending line and try again.

Naming is free-form, but the built-in curves follow the project convention, and matching it keeps a collection readable: Material-DOI for a half cell (NMC811-10.1016_j.xcrp.2020.100253), CathodevsAnode_OCV-DOI for a full cell, and -LICeM in place of the DOI for in-house measurements. Write / in a DOI as _.

Formatting data

Format data runs the same cleaning on your files without optimizing anything: each becomes a plain two-column, 1001-point file. Use it to standardise a set of measurements, or to see exactly what PyBEP made of an awkward file.

Files in one batch must all be the same kind of curve, since the type decides which orientation is expected — rising voltage for cathodes and full cells, falling for anodes. You confirm the SOC and voltage columns for each file first, the same way as before an optimization, so a file with an unusual layout is never converted on a guess.

Each converted file can be downloaded on its own, or the whole batch as one zip.

Download them before you refresh. Refreshing starts over, the same as clicking the PyBEP mark in the corner, and that clears the list of converted files along with the rest of the page.

Submitting a curve

Submit a curve adds a cathode, anode or full-cell curve to this site for everybody to use. It is kept on the server for good, not only for your session.

  1. Choose the files and say what they are. Up to 12 at a time, all of the same kind, in the same formats the rest of the site takes.
  2. Say who you are. Your name and your organization are required and are shown beside the curve, so it is credited and can be asked about. The DOI is optional — leave it out for an unpublished measurement of your own — but it is what lets somebody check the curve against its source later.
  3. Confirm the columns, exactly as when formatting. Nothing is stored until you do.

Submitted curves are not verified. They appear on the run page in a panel of their own, headed “Submitted — not verified”, and are never ticked unless you tick them. Anyone can add one and nobody has checked it, so look at the curve before trusting an answer that used it — a result naming a curve with (submitted) after it was fitted against one of these.

A curve joins the built-in set only by hand, once somebody at LICeM has read the paper it came from and is satisfied it is right. Until then it stays where it is, marked as it is.

Everything sent in is public: the file can be downloaded, and the name, the organization and the DOI are on the page. Send only data you are free to share, and no more about yourself than the name you want credited.

Limits and privacy

The optimization compares every cathode against every anode, so the work grows as cathodes × anodes × iterations. To keep the site responsive:

Uploaded files live only in your own session. They are deleted when you start another run, and are never added to the built-in list that other people see.

How to cite

PyBEP and the method behind it are described in our paper in Batteries. If PyBEP helps with your work, please cite it:

Pišek, J.; Katrašnik, T.; Zelič, K. PyBEP: An Open-Source Tool for Electrode Potential Determination from Battery OCV Measurements. Batteries 2025, 11, 295. https://doi.org/10.3390/batteries11080295

As BibTeX:

@article{pisek2025pybep,
  title   = {PyBEP: An Open-Source Tool for Electrode Potential Determination from Battery OCV Measurements},
  author  = {Pišek, Jon and Katrašnik, Tomaž and Zelič, Klemen},
  journal = {Batteries},
  year    = {2025},
  volume  = {11},
  number  = {8},
  pages   = {295},
  doi     = {10.3390/batteries11080295}
}