Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .issueflows/03-solved-issues/issue1125_original.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Issue #1125: Docstring and docs instrument neutral

Source: https://github.com/jepegit/cellpy/issues/1125

## Original issue text

Several places in the docs (and docstrings) leftovers from very long time ago when this was a script for loading .res files remain. Docs should be more instrument neutral. Go through docs and docstring. Find suspects. Decide keep/change/leave. Implement change.
167 changes: 167 additions & 0 deletions .issueflows/03-solved-issues/issue1125_plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# Issue #1125 — plan: instrument-neutral docs and docstrings

## Goal

Remove wording that still assumes cellpy is a `.res` (Arbin) loader: generic
prose that says "res-files" / "hdf5 file" when it means "raw files" / "cellpy
file", and copy-paste docstrings that name the wrong tester. Keep every
mention that is genuinely Arbin-specific.

## Constraints

- Docs live on `master` (same PR as code); preview with
`uv run --group docs zensical serve` ([docs-on-master.md](../04-designs-and-guides/docs-on-master.md)).
- Docstrings render through mkdocstrings (`docs/api/cellpy.md`,
`docs/api/cell.md`, `docs/api/instruments.md`) — wording changes there are
user-visible docs.
- Prose only. No behaviour, no header/column renames, no code changes other
than comments, docstrings and one `logging.debug` string.
- Rendered tutorials under `docs/examples/*.md` come from `examples/*.ipynb`;
out of scope here (render drift risk, separate pass as in #1023).
- `_old_docs/`, `HISTORY.md`, `DEPRECATIONS.md`, tests and `testdata/` names
are not touched.
- Loader modules named for a tester (`arbin_res.py`, `arbin_sql*.py`,
`_aux_map.py`) legitimately talk about Arbin — leave.

### Prior art

- `#1023` iterations 1–13 (docs usability review,
[docs-usability-review.md](../04-designs-and-guides/docs-usability-review.md))
— same docs tree, same conventions (short code-first pages, `my_cell.res`
as the running example filename). Coexist: this pass only neutralises
prose, it does not restructure pages.
- `.issueflows/00-tools/check_docs_relative_links.py`,
`check_rtd_latest_links.py` — run after edits (docs CI already does).
- No toolbox script for prose scanning; `rg -i '\.res\b|res[- ]file|arbin'`
is the whole inventory (done, see below).
- Graph: not needed (no code structure involved).

## Inventory and decision

Scan: `rg -n -i '\.res\b|res[- ]file|arbin' src/cellpy docs` excluding Arbin
loader modules, tests, `_old_docs`, `docs/examples`. ~200 hits; triaged into:

### Change — generic prose that means "raw file" / "cellpy file"

`src/cellpy/readers/cellreader.py`

- Module docstring: "exporting them in a common hdf5-format" → "a common
`.cellpy` format"; example `c.save("super_battery_run.h5")` → `.cellpy`;
keep the two-file merge example but drop the tester-specific suffix
(`super_battery_run_01.res` → neutral name, or state "any supported raw
file").
- `set_raw_datadir`: "directory containing .res-files" / "res-files" /
"res-directory" → raw files / raw-data directory.
- `set_cellpy_datadir`: ".hdf5-files" / "hdf5-directory" / `"MyData/HDF5"` →
cellpy files / cellpy-file directory.
- `check_file_ids`: "raw-data and cellpy hdf5", "hdf5 file and the res-files",
".res -files", "cellpy hdf5-file" (x2) → raw files / cellpy file.
- `logging.debug("contains %i res-files")` → "contains %i raw files".
- `load` (deprecated path): `raw_files (list): name of res-files` → raw files.
- `get()` docstring examples: keep the first example (explicitly
`instrument="arbin_res"`), but the later generic examples
(`cellpy_file=`, list merge, `units=`) use `.res` as if it were the only
format — keep filenames (valid, autodetected) and add one sentence that any
registered tester file works and `.res` is just the example. Comment
"read an arbin .res file" stays (that example is Arbin).
- `fetch_meta` example `cellpy.get("cell_042.res")` — keep (valid), no change
needed; revisit only if we settle on a neutral example name (open question).

`src/cellpy/readers/instruments/neware_xlsx.py`

- Class docstring "Class for loading arbin-data from MS SQL server" and
loader docstring "Loads data from arbin SQL server h5 export" → Neware xlsx
export. Copy-paste bug.

`src/cellpy/readers/instruments/biologics_mpr.py`

- `file_name (str): path to .res file.` → path to `.mpr` file. Copy-paste bug.

`src/cellpy/readers/instruments/configurations/maccor_txt_one.py`,
`maccor_txt_zero.py`

- Comments `# new Arbin SQL Server` on Maccor header aliases → `# shared
alias (also used by the Arbin SQL loaders)` or drop. Comment only.

`docs/`

- `docs/reference/summary_columns.md:3` "for a plain Arbin file with no extra
options — 58 columns" → "for a plain file (any tester) with no extra
options"; the count does not depend on the tester.
- `docs/getting_started/basic_usage.md:65` "For an Arbin file that means Ah"
→ "For an Arbin `.res` file, for example, that means Ah" (keeps the fact,
marks it as one tester).
- `docs/agents/index.md:450` "large `.res` / SQL dumps" → "large raw files
(e.g. `.res`, SQL dumps)".
- `docs/guides/units.md:41`, `:206`, `docs/fundamentals/glossary.md:84`,
`docs/reference/summary_columns.md:31` — same pattern: keep the Arbin fact,
phrase it as an example ("the tester's unit — Ah for an Arbin `.res`
file").

### Keep — genuinely Arbin / `.res` specific

- Installation / checkup / troubleshooting / CLI pages: Access driver,
mdbtools, `cellpy info --check` "arbin .res support", several data sets in
one `.res` file, `dataset_number`.
- Instrument table in `docs/index.md`, `arbin_res` loader ids in
`batch_database.md`, migration notes about Arbin loaders / aux columns,
`ArbinConfig` in configuration reference, folder-structure listing.
- `example_data.raw_file()` "a small Arbin file" — it is one.
- `cli_api.py` Arbin driver checks; `prms.py` / `config/*` legacy Arbin SQL
secrets; `data_structures.py` vendor map; `merger.py` / `hooks.py` /
`harmonize.py` / `declarations.py` comments that compare testers by name.
- `docs/fundamentals/fundamentals.md` mermaid "(.res, .txt, .csv, …)" —
already neutral.

### Leave — not worth touching

- `__main__` / `_check_*` dev code in `ocv_rlx.py`, `data_structures.py`,
`filefinder.py` that hard-codes the Arbin test fixture.
- `docs/examples/*.md` rendered notebooks (separate render pass).

## Approach

1. Apply the **Change** list above file by file (docstrings, comments, one
debug string, ~8 doc pages). Each edit keeps facts and only removes the
"everything is a .res file" framing.
2. Re-run the inventory `rg` and confirm every remaining hit falls in Keep /
Leave; paste the residual count into the status file.
3. `uv run --group docs zensical build --clean` → "No issues found";
`uv run .issueflows/00-tools/check_docs_relative_links.py`.
4. `uv run pytest -m essential` (no behaviour change expected; guards the
`logging.debug` string edit and the loader docstring edits).
5. HISTORY entry at close (docs line).

## Files to touch

- `src/cellpy/readers/cellreader.py` — module docstring, `set_raw_datadir`,
`set_cellpy_datadir`, `check_file_ids`, `load`, `get` docstrings; one
debug string.
- `src/cellpy/readers/instruments/neware_xlsx.py` — two docstrings.
- `src/cellpy/readers/instruments/biologics_mpr.py` — one arg docstring.
- `src/cellpy/readers/instruments/configurations/maccor_txt_one.py`,
`maccor_txt_zero.py` — three comments each.
- `docs/reference/summary_columns.md`, `docs/getting_started/basic_usage.md`,
`docs/guides/units.md`, `docs/fundamentals/glossary.md`,
`docs/agents/index.md` — one or two sentences each.
- `.issueflows/01-current-issues/issue1125_status.md` — new.

## Test strategy

- `uv run pytest -m essential` (merge gate; no new tests — prose only).
- `uv run --group docs zensical build --clean` must report no issues.
- `uv run .issueflows/00-tools/check_docs_relative_links.py`.
- Final `rg` inventory shows zero hits in the Change category.

## Open questions

1. **Example filename convention.** ~40 doc snippets use `my_cell.res`
(often with `instrument="arbin_res"`). Options: (a) keep — valid, one
consistent running example, Arbin is still the most common tester for
this user base; (b) rotate a few generic snippets (no `instrument=`) to
another suffix (`my_cell.txt` + `instrument="maccor_txt"`) to show
variety. Recommendation: **(a)** plus the single "any registered tester
file works" sentence in `get()` and `basic_usage.md`. Say if you want (b).
2. **`hdf5` → `.cellpy` wording** in the same `cellreader.py` docstrings is
not strictly "instrument" but is the same era of leftover and sits on
the same lines. Recommendation: include. Say if you want it left out.
44 changes: 44 additions & 0 deletions .issueflows/03-solved-issues/issue1125_status.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Issue #1125 — status

- [x] Done

Branch: `cursor/1125-instrument-neutral-docs-0881` (cloud run; in-place branch).
Plan accepted 2026-10-01 with defaults: keep `my_cell.res` as the running
example filename; include `hdf5` → `.cellpy` wording on the same docstring lines.

## What's done

- Inventory (`rg -i '\.res\b|res[- ]file|arbin'` over `src/cellpy` + `docs`)
triaged into Change / Keep / Leave (see plan file).
- `src/cellpy/readers/cellreader.py`: module docstring (`.cellpy` format, any
registered loader, `.cellpy` save example), `set_raw_datadir`,
`set_cellpy_datadir` (example now calls the right method), `check_file_ids`,
`load` arg doc, `logging.debug("contains %i raw files")`.
- `neware_xlsx.py`: class/loader docstrings no longer claim "arbin-data from
MS SQL server"; `biologics_mpr.py`: `file_name` is a `.mpr` path.
- `maccor_txt_one.py` / `maccor_txt_zero.py`: `# new Arbin SQL Server`
comments → `# alias shared with the Arbin SQL loaders`.
- Docs: `reference/summary_columns.md` (58 columns for any tester; Arbin Ah
as an example), `getting_started/basic_usage.md` (`.res` is just the
running example; `print_instruments()`), `guides/units.md`,
`fundamentals/glossary.md`, `agents/index.md`.
- `HISTORY.md` bullet under Unreleased.
- `get()` docstring left as is: its examples already show Arbin, Maccor txt,
custom csv and `.cellpy`.

## Verification

- `uv run --group docs zensical build --clean` → `No issues found`.
- `uv run .issueflows/00-tools/check_docs_relative_links.py` → all resolve.
- `MPLBACKEND=Agg uv run pytest -m essential` → 981 passed, 74 skipped,
2 failed in `tests/test_filefinder.py::test_find_by_project_*`. Those two
fail identically on a stashed `origin/master` in this VM (returns `[]`) while
master CI is green — environment-specific, not from this change.
- Residual `rg` hits in the touched files are all Keep (Arbin stats-frame
comment, "read an arbin .res file" example, Biologic's real intermediate
hdf5 dump) or commented-out legacy `logging.debug` lines.

## Remaining work

- None for this issue. `docs/examples/*.md` (rendered notebooks) were out of
scope; a later render pass can sweep them if wanted.
7 changes: 7 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

## [Unreleased]

* Docs and docstrings made instrument neutral: generic prose in
`cellreader` no longer calls raw files "res-files" or cellpy files
"hdf5 files"; copy-paste docstrings in the Neware xlsx and Biologic mpr
loaders name the right tester; unit/summary pages phrase the Arbin Ah
example as one tester among many. Genuinely Arbin-specific text
(drivers, `arbin_res`, `dataset_number`) is unchanged. (#1125)

* File pointers from external metadata sources (Epic M / M4). `MetaRecord`
gains `files: tuple[FileRef, ...]` (`kind`, `uri`, `order`, `size`,
`mtime`, `checksum`, `loader`); `cellpy.get(source=, key=, kind=, project=)`
Expand Down
2 changes: 1 addition & 1 deletion docs/agents/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ Other measured knobs for a slow first batch load:

- **Hard-coded column names** — use `c.schema.raw.potential` (etc.), not
remembered 1.x header strings.
- **Blocking the UI thread** — `get` on large `.res` / SQL dumps can take
- **Blocking the UI thread** — `get` on large raw files (`.res`, SQL dumps, …) can take
seconds; load off the main thread.
- **Missing mass / instrument** — wrong capacities or wrong loader; surface
these as required inputs in the GUI.
Expand Down
2 changes: 1 addition & 1 deletion docs/fundamentals/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ script.
| specific capacity / gravimetric | `…_gravimetric` | Per active mass. Needs a real `mass=` (default is 1.0 mg). |
| areal capacity | `…_areal` | Per electrode area. Needs `area=` (cm²). Stored as `c.data.active_electrode_area`. |
| absolute / not normalised | `…_absolute` | In *your* units (`c.cellpy_units`), not divided by mass or area. |
| the bare name (`charge_capacity`) | tester units | `c.data.raw_units` — often Ah on Arbin. Off by 1000 vs mAh if you assume the wrong set. |
| the bare name (`charge_capacity`) | tester units | `c.data.raw_units` — depends on the tester (Ah for Arbin `.res`, for example). Off by 1000 vs mAh if you assume the wrong set. |
| coulombic efficiency | `coulombic_efficiency` | Per cycle, on the summary. Upside-down? Check `cycle_mode`. |
| C-rate | `c_rate` (steps); `charge_c_rate` / `discharge_c_rate` (summary) | Meaningless until you set `nominal_capacity=` (`c.data.nom_cap`). |
| nominal / rated / nameplate capacity | `nominal_capacity=` / `c.data.nom_cap` | Used for C-rates and equivalent full cycles, not for scaling the capacity columns. |
Expand Down
6 changes: 4 additions & 2 deletions docs/getting_started/basic_usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ c = example_data.raw_file() # bundled dat
```

`cellpy.get` reads the file, builds the step table and makes the per-cycle
summary. `cellpy.print_instruments()` lists the `instrument=` names.
summary. The `.res` files on this page are just the running example: any
registered tester format works the same way, and
`cellpy.print_instruments()` lists the `instrument=` names.

## Set the cell up

Expand Down Expand Up @@ -62,7 +64,7 @@ c.data.summary[c.schema.summary.coulombic_efficiency]

!!! warning
The bare `charge_capacity` column is in the **tester's** units, not yours.
For an Arbin file that means Ah, a factor of 1000 off from mAh.
For an Arbin `.res` file, for example, that means Ah — a factor of 1000 off from mAh.

## Curves for one cycle

Expand Down
6 changes: 3 additions & 3 deletions docs/guides/units.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ want to work in.
| `c.cellpy_units` | the units cellpy converts to when it builds the summary | your configuration, or `units=` |

```python
print(c.data.raw_units.charge) # e.g. "Ah" — what the Arbin file contained
print(c.data.raw_units.charge) # e.g. "Ah" — what the tester file contained
print(c.cellpy_units.charge) # "mAh" — what the summary is in
```

Expand Down Expand Up @@ -203,8 +203,8 @@ distinguished by a postfix:

!!! warning "The bare column name is in the tester's units"
Only the three postfixed columns get the raw → cellpy unit conversion; the
base column is left as the summary engine produced it. For an Arbin `.res`
file (Ah) with the default cellpy unit (mAh), `charge_capacity` and
base column is left as the summary engine produced it. For a tester that
records Ah (an Arbin `.res` file, say) with the default cellpy unit (mAh), `charge_capacity` and
`charge_capacity_absolute` are a factor of 1000 apart:

```python
Expand Down
8 changes: 4 additions & 4 deletions docs/reference/summary_columns.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Summary columns explained

`c.data.summary` has one row per cycle and — for a plain Arbin file with no
extra options — **58 columns**. This page says what each one means, how it is
`c.data.summary` has one row per cycle and — for a plain load from any tester
with no extra options — **58 columns**. This page says what each one means, how it is
computed, and which units it is in.

```python
Expand All @@ -28,8 +28,8 @@ The three postfixed columns are the base column multiplied by a conversion
factor that includes the raw → cellpy unit change. The **base column does
not** get that conversion.

For an Arbin `.res` file, which records charge in Ah, with the default cellpy
unit of mAh:
For example, with an Arbin `.res` file, which records charge in Ah, and the
default cellpy unit of mAh:

```python
c.data.summary["charge_capacity"] # 0.00163 <- Ah, the tester's unit
Expand Down
Loading
Loading