cellpycore 0.1.1__tar.gz → 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. cellpycore-0.1.2/.issueflows/03-solved-issues/issue44_status.md +23 -0
  2. cellpycore-0.1.2/.issueflows/03-solved-issues/issue45_original.md +17 -0
  3. cellpycore-0.1.2/.issueflows/03-solved-issues/issue45_plan.md +130 -0
  4. cellpycore-0.1.2/.issueflows/03-solved-issues/issue45_status.md +56 -0
  5. cellpycore-0.1.2/.issueflows/03-solved-issues/issue54_original.md +45 -0
  6. cellpycore-0.1.2/.issueflows/03-solved-issues/issue54_plan.md +53 -0
  7. cellpycore-0.1.2/.issueflows/03-solved-issues/issue54_status.md +19 -0
  8. cellpycore-0.1.2/.issueflows/03-solved-issues/issue55_original.md +47 -0
  9. cellpycore-0.1.2/.issueflows/03-solved-issues/issue55_plan.md +95 -0
  10. cellpycore-0.1.2/.issueflows/03-solved-issues/issue55_status.md +34 -0
  11. cellpycore-0.1.2/.issueflows/03-solved-issues/issue56_original.md +64 -0
  12. cellpycore-0.1.2/.issueflows/03-solved-issues/issue56_plan.md +48 -0
  13. cellpycore-0.1.2/.issueflows/03-solved-issues/issue56_status.md +26 -0
  14. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/04-designs-and-guides/cellpy-core-integration-roadmap.md +2 -1
  15. cellpycore-0.1.2/.issueflows/04-designs-and-guides/release-procedure.md +60 -0
  16. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/04-designs-and-guides/selector-dead-code-deferral.md +18 -0
  17. cellpycore-0.1.2/HISTORY.md +48 -0
  18. {cellpycore-0.1.1 → cellpycore-0.1.2}/PKG-INFO +16 -2
  19. {cellpycore-0.1.1 → cellpycore-0.1.2}/README.md +15 -1
  20. {cellpycore-0.1.1 → cellpycore-0.1.2}/graphify-out/.graphify_labels.json +16 -3
  21. cellpycore-0.1.2/graphify-out/GRAPH_REPORT.md +329 -0
  22. cellpycore-0.1.2/graphify-out/graph.html +305 -0
  23. {cellpycore-0.1.1 → cellpycore-0.1.2}/graphify-out/graph.json +7655 -4996
  24. {cellpycore-0.1.1 → cellpycore-0.1.2}/graphify-out/manifest.json +27 -23
  25. {cellpycore-0.1.1 → cellpycore-0.1.2}/pyproject.toml +1 -1
  26. {cellpycore-0.1.1 → cellpycore-0.1.2}/src/cellpycore/cell_core.py +124 -5
  27. {cellpycore-0.1.1 → cellpycore-0.1.2}/src/cellpycore/selectors.py +2 -180
  28. {cellpycore-0.1.1 → cellpycore-0.1.2}/src/cellpycore/summarizers.py +76 -0
  29. {cellpycore-0.1.1 → cellpycore-0.1.2}/uv.lock +1 -1
  30. cellpycore-0.1.1/.issueflows/02-partly-solved-issues/issue44_status.md +0 -16
  31. cellpycore-0.1.1/HISTORY.md +0 -23
  32. cellpycore-0.1.1/graphify-out/GRAPH_REPORT.md +0 -291
  33. cellpycore-0.1.1/graphify-out/graph.html +0 -305
  34. {cellpycore-0.1.1 → cellpycore-0.1.2}/.aliases +0 -0
  35. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/rules/cellpy-core-migration.mdc +0 -0
  36. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/rules/graphify.mdc +0 -0
  37. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/rules/issueflow-rules.mdc +0 -0
  38. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/rules/kiss.mdc +0 -0
  39. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/rules/this-project.mdc +0 -0
  40. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/skills/caveman/SKILL.md +0 -0
  41. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/skills/grill-me/SKILL.md +0 -0
  42. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/skills/iflow/SKILL.md +0 -0
  43. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/skills/iflow-cleanup/SKILL.md +0 -0
  44. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/skills/iflow-close/SKILL.md +0 -0
  45. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/skills/iflow-comments/SKILL.md +0 -0
  46. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/skills/iflow-fix/SKILL.md +0 -0
  47. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/skills/iflow-graphify/SKILL.md +0 -0
  48. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/skills/iflow-history-update/SKILL.md +0 -0
  49. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/skills/iflow-init/SKILL.md +0 -0
  50. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/skills/iflow-pause/SKILL.md +0 -0
  51. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/skills/iflow-pick/SKILL.md +0 -0
  52. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/skills/iflow-plan/SKILL.md +0 -0
  53. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/skills/iflow-start/SKILL.md +0 -0
  54. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/skills/iflow-status/SKILL.md +0 -0
  55. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/skills/iflow-version-bump/SKILL.md +0 -0
  56. {cellpycore-0.1.1 → cellpycore-0.1.2}/.cursor/skills/iflow-yolo/SKILL.md +0 -0
  57. {cellpycore-0.1.1 → cellpycore-0.1.2}/.gitignore +0 -0
  58. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/00-tools/.gitkeep +0 -0
  59. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/00-tools/README.md +0 -0
  60. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/01-current-issues/.gitkeep +0 -0
  61. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/02-partly-solved-issues/.gitkeep +0 -0
  62. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/.gitkeep +0 -0
  63. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue10_original.md +0 -0
  64. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue10_plan.md +0 -0
  65. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue10_status.md +0 -0
  66. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue12_original.md +0 -0
  67. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue12_plan.md +0 -0
  68. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue12_status.md +0 -0
  69. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue13_original.md +0 -0
  70. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue13_plan.md +0 -0
  71. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue13_status.md +0 -0
  72. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue21_original.md +0 -0
  73. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue21_plan.md +0 -0
  74. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue21_status.md +0 -0
  75. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue22_original.md +0 -0
  76. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue22_plan.md +0 -0
  77. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue22_status.md +0 -0
  78. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue23_original.md +0 -0
  79. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue23_plan.md +0 -0
  80. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue23_status.md +0 -0
  81. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue24_original.md +0 -0
  82. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue24_status.md +0 -0
  83. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue29_original.md +0 -0
  84. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue29_plan.md +0 -0
  85. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue29_status.md +0 -0
  86. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue30_original.md +0 -0
  87. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue30_plan.md +0 -0
  88. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue30_status.md +0 -0
  89. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue32_original.md +0 -0
  90. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue32_plan.md +0 -0
  91. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue32_status.md +0 -0
  92. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue34_original.md +0 -0
  93. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue34_plan.md +0 -0
  94. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue36_original.md +0 -0
  95. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue36_status.md +0 -0
  96. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue39_original.md +0 -0
  97. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue39_plan.md +0 -0
  98. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue39_status.md +0 -0
  99. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue40_original.md +0 -0
  100. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue40_plan.md +0 -0
  101. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue40_status.md +0 -0
  102. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue41_original.md +0 -0
  103. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue41_plan.md +0 -0
  104. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue41_status.md +0 -0
  105. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue42_original.md +0 -0
  106. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue42_plan.md +0 -0
  107. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue42_status.md +0 -0
  108. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue43_original.md +0 -0
  109. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue43_plan.md +0 -0
  110. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue43_status.md +0 -0
  111. {cellpycore-0.1.1/.issueflows/02-partly-solved-issues → cellpycore-0.1.2/.issueflows/03-solved-issues}/issue44_original.md +0 -0
  112. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue50_original.md +0 -0
  113. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue50_plan.md +0 -0
  114. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/03-solved-issues/issue50_status.md +0 -0
  115. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/04-designs-and-guides/.gitkeep +0 -0
  116. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/04-designs-and-guides/cellpy-core-integration-into-cellpy.md +0 -0
  117. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/04-designs-and-guides/cellpy-core-migration.md +0 -0
  118. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/04-designs-and-guides/code-review-2026-07.md +0 -0
  119. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/04-designs-and-guides/column-headers-review.md +0 -0
  120. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/04-designs-and-guides/metadata-scaffolding.md +0 -0
  121. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/04-designs-and-guides/step-table-polars-migration.md +0 -0
  122. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/04-designs-and-guides/summary-extractors.md +0 -0
  123. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/04-designs-and-guides/test-data-and-fixtures.md +0 -0
  124. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/04-designs-and-guides/test-metadata-and-merging.md +0 -0
  125. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/04-designs-and-guides/this-project.md +0 -0
  126. {cellpycore-0.1.1 → cellpycore-0.1.2}/.issueflows/config.toml +0 -0
  127. {cellpycore-0.1.1 → cellpycore-0.1.2}/.python-version +0 -0
  128. {cellpycore-0.1.1 → cellpycore-0.1.2}/.vscode/settings.json +0 -0
  129. {cellpycore-0.1.1 → cellpycore-0.1.2}/AGENTS.md +0 -0
  130. {cellpycore-0.1.1 → cellpycore-0.1.2}/LICENSE +0 -0
  131. {cellpycore-0.1.1 → cellpycore-0.1.2}/cellpy-core.code-workspace +0 -0
  132. {cellpycore-0.1.1 → cellpycore-0.1.2}/graphify-out/.graphify_root +0 -0
  133. {cellpycore-0.1.1 → cellpycore-0.1.2}/scratch.db +0 -0
  134. {cellpycore-0.1.1 → cellpycore-0.1.2}/src/cellpycore/__init__.py +0 -0
  135. {cellpycore-0.1.1 → cellpycore-0.1.2}/src/cellpycore/_helpers.py +0 -0
  136. {cellpycore-0.1.1 → cellpycore-0.1.2}/src/cellpycore/config.py +0 -0
  137. {cellpycore-0.1.1 → cellpycore-0.1.2}/src/cellpycore/extractors.py +0 -0
  138. {cellpycore-0.1.1 → cellpycore-0.1.2}/src/cellpycore/header_mapping.py +0 -0
  139. {cellpycore-0.1.1 → cellpycore-0.1.2}/src/cellpycore/legacy.py +0 -0
  140. {cellpycore-0.1.1 → cellpycore-0.1.2}/src/cellpycore/metadata/__init__.py +0 -0
  141. {cellpycore-0.1.1 → cellpycore-0.1.2}/src/cellpycore/metadata/io.py +0 -0
  142. {cellpycore-0.1.1 → cellpycore-0.1.2}/src/cellpycore/metadata/models.py +0 -0
  143. {cellpycore-0.1.1 → cellpycore-0.1.2}/src/cellpycore/settings_base.py +0 -0
  144. {cellpycore-0.1.1 → cellpycore-0.1.2}/src/cellpycore/timestamps.py +0 -0
  145. {cellpycore-0.1.1 → cellpycore-0.1.2}/src/cellpycore/units.py +0 -0
@@ -0,0 +1,23 @@
1
+ # Issue #44 status — Release: tag cellpy-core (and decide PyPI publish)
2
+
3
+ - [x] Done
4
+
5
+ ## What has been done
6
+
7
+ - User added `.github/workflows/release.yml`: on GitHub release publish → ruff + pytest → `uv build` → PyPI publish (trusted publishing via `pypi` environment, `id-token: write`).
8
+ - User added a release alias (commit `06831f0`) to trigger releases, modeled on jepegit/issue-flow.
9
+ - Release `v0.1.0` was published 2026-07-02, but its CI test job failed on ruff F401 — PyPI publish never ran. Fix landed via PR #53.
10
+ - **2026-07-02 (evening): release verified end-to-end.** `v0.1.1` tagged, `release.yml` ran green, and `cellpycore 0.1.1` is live on PyPI. The release/tagging convention works.
11
+ - Note: tag `v0.1.1` points at `63066bf`, which **pre-dates** the #45 selector removal (merged to `main` as `2da165e` after the tag). cellpy `master` is compatible with both (it no longer passes `selector=` and works against 0.1.1 and `main`). The next release will include the removal.
12
+
13
+ ## Remaining work
14
+
15
+ - ~~Document the release procedure~~ — done 2026-07-02:
16
+ `.issueflows/04-designs-and-guides/release-procedure.md` (alias, workflow,
17
+ happy path, failure mode, per-release re-pin checklist).
18
+ - ~~Execute the cellpy-side re-pin~~ — done 2026-07-02: cellpy PR
19
+ [jepegit/cellpy#400](https://github.com/jepegit/cellpy/pull/400)
20
+ (branch `core44-pin-cellpycore-release`): `cellpycore>=0.1.1` from PyPI,
21
+ editable `[tool.uv.sources]` override kept, `allow-direct-references`
22
+ removed, `uv.lock` refreshed, seam tests green.
23
+ - ~~Merge PR #400~~ — merged 2026-07-02 17:21Z. **Issue fully resolved.**
@@ -0,0 +1,17 @@
1
+ # Issue #45: Cleanup (blocked): remove create_selector/summary_selector_exluder once cellpy migrates off them
2
+
3
+ Source: https://github.com/cellpy/cellpy-core/issues/45
4
+
5
+ ## Original issue text
6
+
7
+ Tracking issue for the deferred dead-code removal documented in `.issueflows/04-designs-and-guides/selector-dead-code-deferral.md`.
8
+
9
+ ## Status: blocked (do not remove yet)
10
+
11
+ `selectors.create_selector` is **still imported by the external cellpy repo** (`cellpy/readers/cellreader.py` via `core_selectors.create_selector(...)`, and `cellpy/tests/test_slim.py`). `selectors.summary_selector_exluder` is the pandas engine it wraps, so it must live as long as `create_selector` does. cellpy pins `cellpycore @ ...@main`, so removing now breaks cellpy at its next pin resolution.
12
+
13
+ ## Removal trigger (future work)
14
+
15
+ Remove **both** functions only after cellpy stops importing `core_selectors.create_selector` (i.e. cellpy moves its summary selection onto the native `make_summary` path or its own helper). Then this is a small dead-code deletion in `src/cellpycore/selectors.py`.
16
+
17
+ (The sibling pair `generate_absolute_summary_columns` / `end_voltage_to_summary` was already removed in issue #24.)
@@ -0,0 +1,130 @@
1
+ # Issue #45 plan: remove `create_selector` / `summary_selector_exluder` (two-repo cleanup)
2
+
3
+ ## Goal
4
+
5
+ Migrate cellpy off `core_selectors.create_selector`, then delete both
6
+ `create_selector` and `summary_selector_exluder` from cellpy-core
7
+ (`src/cellpycore/selectors.py`), plus the dead `selector` parameter on
8
+ `make_core_summary`.
9
+
10
+ ## Key finding (unblocks the issue)
11
+
12
+ Both `make_core_summary` implementations in `src/cellpycore/cell_core.py`
13
+ (native, line ~159; legacy bridge, line ~563) accept `selector` but **never use
14
+ it** — the polars engine selects cycle-end rows via `final_data_points`
15
+ internally. So the selector cellpy builds in `_make_summary`
16
+ (`cellpy/readers/cellreader.py:5794-5805`) and passes at line 5917 is already a
17
+ no-op, as are cellpy's public `selector` / `selector_type` / `exclude_types` /
18
+ `exclude_steps` kwargs on `make_summary`. Migration is therefore a pure
19
+ dead-code removal on the cellpy side too — no behavior replacement needed.
20
+
21
+ ## Constraints
22
+
23
+ - **Merge order:** cellpy pins `cellpycore @ git+…@main`
24
+ (`cellpy/pyproject.toml:61`). The cellpy PR (stop importing) must merge
25
+ **before** the cellpy-core PR (delete functions), or cellpy breaks at its
26
+ next pin resolution.
27
+ - **Branch, don't fork** (per `cellpy-core-migration.md`): cellpy work goes on
28
+ a dedicated branch of the existing cellpy repo, e.g.
29
+ `core45-drop-create-selector`. cellpy-core work stays on the existing
30
+ branch `45-cleanup-blocked-remove-create_selectorsummary_selector_exluder-once-cellpy-migrates-off-them`.
31
+ - **Local dev wiring:** cellpy already has the editable
32
+ `[tool.uv.sources] cellpycore = { path = "../cellpy-core", editable = true }`
33
+ override, so both branches can be tested together locally.
34
+ - **User decisions (2026-07-02):** keep cellpy's `selector*` / `exclude*`
35
+ kwargs but emit `DeprecationWarning` when supplied; also remove the dead
36
+ `selector` parameter from both `make_core_summary` signatures in core.
37
+
38
+ ### Prior art
39
+
40
+ - `selector-dead-code-deferral.md` (04-designs-and-guides) — the deferral
41
+ decision this issue executes; update it when done.
42
+ - `code-review-2026-07.md` — notes #45 covers only these two functions;
43
+ `get_step_numbers` / `get_cycle_numbers` / `get_rates` stay.
44
+ - Issue #24 removed the sibling pair `generate_absolute_summary_columns` /
45
+ `end_voltage_to_summary`; `tests/test_schema.py::test_no_module_header_globals`
46
+ shows the "assert name gone" test pattern to mirror.
47
+ - Toolbox (`.issueflows/00-tools/`) and graph checked: no relevant helper.
48
+
49
+ ## Approach
50
+
51
+ ### Phase 1 — cellpy (branch `core45-drop-create-selector`)
52
+
53
+ 1. Create the branch from cellpy's default branch.
54
+ 2. `cellpy/readers/cellreader.py`:
55
+ - Remove `from cellpycore import selectors as core_selectors` (line 73).
56
+ - In `_make_summary`: delete the selector-building block (lines 5794-5805)
57
+ and stop passing `selector=selector` to `self.core.make_core_summary`
58
+ (line 5917).
59
+ - Emit `DeprecationWarning` when `selector`, `selector_type`,
60
+ `exclude_types`, or `exclude_steps` is supplied (non-None) to
61
+ `make_summary` — they have been no-ops since the core seam.
62
+ 3. `tests/test_slim.py`: drop the `core_selectors` import; update
63
+ `test_direct_core_make_core_summary` to call
64
+ `make_core_summary(data, find_ir=True, find_end_voltage=True)` without a
65
+ selector.
66
+ 4. Run cellpy tests (conda `cellpy_dev_313`): at least `pytest tests/test_slim.py`
67
+ plus summary-related tests (`-k summary`).
68
+
69
+ ### Phase 2 — cellpy-core (existing branch for #45)
70
+
71
+ 1. `src/cellpycore/selectors.py`: delete `create_selector` and
72
+ `summary_selector_exluder`; remove now-unused imports/constants
73
+ (`functools`, `FIRST`/`LAST`/`DELTA` if unused elsewhere — verify).
74
+ 2. `src/cellpycore/cell_core.py`: remove the unused `selector` parameter from
75
+ both `make_core_summary` signatures + docstrings.
76
+ 3. `tests/test_schema.py`: extend the dead-code assertions with
77
+ `create_selector` / `summary_selector_exluder` gone from `selectors`
78
+ (mirror `test_no_module_header_globals`).
79
+ 4. Docs: update `selector-dead-code-deferral.md` (resolved, date, link #45)
80
+ and flip #45 in `cellpy-core-integration-roadmap.md` from blocked to done.
81
+ 5. Run `uv run pytest`; rerun cellpy's `test_slim.py` against the edited core
82
+ via the editable path source.
83
+
84
+ ### Merge sequencing
85
+
86
+ cellpy PR merges first → then cellpy-core PR. Local editable wiring keeps both
87
+ testable during development.
88
+
89
+ ## Files to touch
90
+
91
+ - `cellpy/cellpy/readers/cellreader.py` — remove import + selector block, add
92
+ deprecation warnings.
93
+ - `cellpy/tests/test_slim.py` — drop selector usage.
94
+ - `cellpy-core/src/cellpycore/selectors.py` — delete the two functions.
95
+ - `cellpy-core/src/cellpycore/cell_core.py` — drop dead `selector` param (2 sites).
96
+ - `cellpy-core/tests/test_schema.py` — add removed-name assertions.
97
+ - `cellpy-core/.issueflows/04-designs-and-guides/selector-dead-code-deferral.md`,
98
+ `cellpy-core-integration-roadmap.md` — status updates.
99
+
100
+ ## Test strategy
101
+
102
+ - cellpy-core: `uv run pytest` (top dir) — includes `tests/test_golden.py`
103
+ (golden parquet fixtures: 103 steps / 18 cycles / cycle-1 `data_point` 1457),
104
+ which is the core-side parity oracle.
105
+ - cellpy: activate conda `cellpy_dev_313`, run `pytest tests/test_slim.py` and
106
+ `pytest -k summary`.
107
+
108
+ ### End-to-end verification (both branches together, before either PR)
109
+
110
+ With the cellpy branch checked out and the editable
111
+ `[tool.uv.sources]` path resolving `cellpycore` to the edited
112
+ `../cellpy-core` working copy (branch for #45):
113
+
114
+ 1. Full seam pipeline via `tests/test_slim.py` — covers raw load
115
+ (`arbin_res` `from_raw`) → `make_step_table` → `make_summary` →
116
+ golden value (`summary.loc[1, data_point] == 1457`) → `save(.h5)`
117
+ roundtrip, now without any selector import.
118
+ 2. Full cellpy test suite: `pytest` (conda `cellpy_dev_313`) — catches any
119
+ other path that indirectly relied on the removed functions or the
120
+ `selector` kwarg plumbing.
121
+ 3. Deprecation check: call `make_summary(selector_type="non-cv")` (e.g. in a
122
+ test with `pytest.warns(DeprecationWarning)`) to verify the warning fires
123
+ and the summary still builds.
124
+ 4. Sanity import check against edited core:
125
+ `uv run python -c "import cellpycore.selectors as s; assert not hasattr(s, 'create_selector')"`.
126
+
127
+ ## Open questions
128
+
129
+ - None — kwargs handling, core-param removal, and cellpy branching resolved by
130
+ user 2026-07-02.
@@ -0,0 +1,56 @@
1
+ # Issue #45 status: remove `create_selector` / `summary_selector_exluder`
2
+
3
+ - [x] Done
4
+
5
+ ## What was done (2026-07-02)
6
+
7
+ ### cellpy (branch `core45-drop-create-selector`, off `master`)
8
+
9
+ - `cellpy/readers/cellreader.py`:
10
+ - Removed `from cellpycore import selectors as core_selectors`.
11
+ - `make_summary`: kept the `selector` / `selector_type` / `exclude_types` /
12
+ `exclude_steps` kwargs but they now emit a `DeprecationWarning` when
13
+ supplied (they have been no-ops since the core seam); docstring updated.
14
+ - `_make_summary`: dropped the four dead kwargs, the `create_selector`
15
+ block, and the `selector=` forwarding to `make_core_summary`.
16
+ - `tests/test_slim.py`: removed `core_selectors` usage in
17
+ `test_direct_core_make_core_summary`; added
18
+ `test_make_summary_selector_kwargs_deprecated` (asserts warning + summary
19
+ still builds).
20
+
21
+ ### cellpy-core (branch `45-cleanup-blocked-...`)
22
+
23
+ - `src/cellpycore/selectors.py`: deleted `create_selector` and
24
+ `summary_selector_exluder`, plus now-unused imports (`functools`,
25
+ `Callable`, `Iterable`, `List`, `StepCols`, `RawCols`) and the
26
+ `FIRST`/`LAST`/`DELTA` constants.
27
+ - `src/cellpycore/cell_core.py`: removed the never-used `selector` parameter
28
+ from both `make_core_summary` signatures (native + legacy bridge).
29
+ - `tests/test_schema.py`: added `test_no_legacy_selector_functions`.
30
+ - Docs: `selector-dead-code-deferral.md` marked resolved;
31
+ `cellpy-core-integration-roadmap.md` #45 row flipped to done.
32
+
33
+ ## Test results
34
+
35
+ - cellpy-core: `uv run pytest` — **95 passed** (includes golden fixtures).
36
+ - cellpy (conda `cellpy_dev_313`, editable core via `[tool.uv.sources]`):
37
+ - `tests/test_slim.py` — 6 passed (incl. new deprecation test).
38
+ - `pytest -k summary` — 79 passed, 1 skipped, 1 xfailed.
39
+ - Full suite (excluding `test_ica.py`, `test_ocv_relax.py`,
40
+ `test_plotutils_summary_plot.py`) — **428 passed, 17 skipped, 11 xfailed**.
41
+
42
+ ### Pre-existing environment crash (not caused by this change)
43
+
44
+ `test_ica.py`, `test_ocv_relax.py`, and `test_plotutils_summary_plot.py`
45
+ abort the interpreter with `Windows fatal exception: code 0xc06d007f` inside
46
+ scipy/numpy LAPACK (`lstsq` / `inv`). A standalone
47
+ `python -c "from scipy.signal import savgol_filter; ..."` (no cellpy imports)
48
+ crashes the same way in `cellpy_dev_313`, so this is a broken scipy/BLAS DLL
49
+ situation in that conda env on this machine, unrelated to the selector
50
+ removal. Should be fixed separately (e.g. reinstall scipy/numpy in the env).
51
+
52
+ ## Remaining work
53
+
54
+ - Commit + push both branches, open PRs.
55
+ - **Merge order:** cellpy PR first (cellpy pins `cellpycore @ git+…@main`),
56
+ then the cellpy-core PR.
@@ -0,0 +1,45 @@
1
+ # Issue #54: Native exclude-types summary support (replace removed create_selector exclusion feature)
2
+
3
+ Source: https://github.com/cellpy/cellpy-core/issues/54
4
+
5
+ ## Original issue text
6
+
7
+ ## Context
8
+
9
+ Issue #45 removed the legacy pandas selector pair (`create_selector` / `summary_selector_exluder`). The default row selection (one cycle-end datapoint per cycle) was already native in `summarizers.make_summary`, so nothing was lost there.
10
+
11
+ But the old selector had a second, distinct capability that was never ported to the polars engine (and has been silently a no-op since the core seam landed): **exclude-types summaries** (`selector_type="non-cv" / "non-rest" / "non-ocv" / "only-cv"`). Because capacities are cycle-cumulative, this is not row selection — it subtracts the excluded steps' deltas (`last - first` per step, summed per cycle) from the cycle-end values, producing a summary "as if" those steps never happened.
12
+
13
+ cellpy's `make_summary(selector_type=...)` kwargs currently emit a `DeprecationWarning` and do nothing.
14
+
15
+ ## Proposed design (concrete first, KISS)
16
+
17
+ Add an option to the native engine:
18
+
19
+ ```python
20
+ summarizers.make_summary(data, schema, exclude_step_types=["cv_"], ...)
21
+ ```
22
+
23
+ Implementation sketch:
24
+
25
+ 1. Filter the step table by excluded `step_type` prefix(es).
26
+ 2. Compute per-step deltas from the existing `*_first` / `*_last` stat columns (charge, discharge, current, voltage).
27
+ 3. Group by cycle (and `test_id` when present), sum.
28
+ 4. Subtract the per-cycle correction from the selected cycle-end summary rows.
29
+
30
+ No new protocol/abstraction yet. If a second variant appears (custom exclusion logic, different correction policy), promote it to a pluggable `SummaryAdjuster` mirroring `extractors.SummaryExtractor` — giving the clean vocabulary: *selectors* pick rows, *extractors* derive columns, *adjusters* correct values.
31
+
32
+ ## Testing
33
+
34
+ - Parity test against the removed pandas implementation (resurrect `summary_selector_exluder` from git history as a test oracle on a fixture with CV steps).
35
+ - Guard: `exclude_step_types=None` must stay byte-identical to the current summary (golden fixtures).
36
+
37
+ ## Follow-up on the cellpy side
38
+
39
+ Once this lands, cellpy can wire `selector_type` / `exclude_types` / `exclude_steps` to the new argument instead of warning, or keep the deprecation and expose the new API directly.
40
+
41
+ ## Links
42
+
43
+ - #45 (dead-code removal that surfaced this)
44
+ - #13 (polars summary rewrite that deliberately skipped the exclusion machinery)
45
+ - `.issueflows/04-designs-and-guides/selector-dead-code-deferral.md`
@@ -0,0 +1,53 @@
1
+ # Plan — Issue #54: Native exclude-types summary support
2
+
3
+ ## Goal
4
+
5
+ Add native exclude-types summary support to the polars engine: `summarizers.make_summary(..., exclude_step_types=["cv_"])` subtracts the excluded steps' per-cycle deltas from the cycle-end summary values, replacing the capability lost when `create_selector` / `summary_selector_exluder` were removed (issue #45).
6
+
7
+ ## Constraints
8
+
9
+ - KISS: concrete kwarg first, no `SummaryAdjuster` protocol yet (issue explicitly defers it until a second variant appears).
10
+ - `exclude_step_types=None` (default) must be **byte-identical** to today's summary — no join, no extra columns, golden fixtures untouched.
11
+ - Engine stays schema-injected, polars-native, thread-safe; no module-level state.
12
+ - cellpy-side wiring (`selector_type` → this kwarg) is a follow-up in the cellpy repo, out of scope here (per migration guide: core PR first).
13
+ - Google-style docstrings.
14
+
15
+ ### Prior art
16
+
17
+ - **Oracle:** removed pandas `summary_selector_exluder` recovered from `git show 2da165e^:src/cellpycore/selectors.py`. Math: filter steps whose `step_type` starts with any excluded prefix; per step compute `last - first` for current, voltage, charge, discharge; group by cycle, sum; left-merge onto selected cycle-end raw rows, `fillna(0.0)`, subtract.
18
+ - **Deviations to document:** (1) old code also corrected current and voltage on the raw rows — the native summary's base subset carries only capacities (end potentials come from step-table joins), so the native correction targets `charge_capacity` / `discharge_capacity` only; (2) old `exclude_steps` matched step *numbers* against the step **type** column (`steps[t_st_txt].isin(exclude_steps)`) — a latent bug; we do not port `exclude_steps` at all; (3) old `create_selector` mapped `"non-rest"` → prefix `"rest_"` which never matched label `"rest"` — mapping strings stay in cellpy's follow-up, core takes explicit prefixes.
19
+ - **Siblings/conventions to mirror:** `_group_keys` / `use_tid` composite-key handling and `join ... how="left"` + `fill_null` pattern already used by `_add_end_potentials`, `c_rates_to_summary`, `ir_to_summary` in [summarizers.py](../../src/cellpycore/summarizers.py). Step table provides `charge_capacity_first/_last`, `discharge_capacity_first/_last` stat columns (native names). Do **not** reuse `_delta_expr` (it is percent-based); the correction needs plain `last - first`.
20
+ - Toolbox `.issueflows/00-tools/`: empty — nothing to reuse.
21
+ - Graph: Community 50 (`make_summary`, `_group_keys`, `_add_end_potentials`) and 53 (step table) confirm the touch points; no surprises.
22
+
23
+ ## Approach
24
+
25
+ 1. **`summarizers.make_summary`** gains `exclude_step_types: Optional[Sequence[str]] = None`.
26
+ - When `None`: current code path, untouched.
27
+ - Else, right after the base `summary = selected.select(...)` and **before** the CE / coulombic-difference / loss / cumulated `with_columns` (so every derived column reflects corrected capacities, mirroring the oracle which corrected raw rows before summary derivation):
28
+ - Filter steps: `pl.any_horizontal(pl.col(shdr.step_type).str.starts_with(p) for p in exclude_step_types)`.
29
+ - Aggregate per `(test_id?, cycle)` (via `_group_keys`): `(charge_capacity_last - charge_capacity_first).sum()` and same for discharge, into temp `__excl_charge` / `__excl_discharge` columns.
30
+ - Left-join onto summary (same `use_tid` join-key logic as `_add_end_potentials`), `fill_null(0.0)` (oracle's `replace_nan=True`), subtract from `chdr.charge_capacity` / `chdr.discharge_capacity`, drop temp columns.
31
+ 2. **`CellpyCellCore.make_core_summary`** in [cell_core.py](../../src/cellpycore/cell_core.py) gains the same kwarg and passes it through (native entry point). Legacy bridge `OldCellpyCellCore` untouched for now — see open questions.
32
+ 3. Docstrings updated; short note added to `.issueflows/04-designs-and-guides/selector-dead-code-deferral.md` marking #54 resolved once merged (done at close, not plan).
33
+
34
+ ## Files to touch
35
+
36
+ - `src/cellpycore/summarizers.py` — new kwarg + correction block in `make_summary` (~30 lines).
37
+ - `src/cellpycore/cell_core.py` — pass-through kwarg on `CellpyCellCore.make_core_summary`.
38
+ - `tests/test_schema.py` (or new `tests/test_exclude_types.py` if cleaner) — new tests, see below.
39
+
40
+ ## Test strategy
41
+
42
+ Command: `uv run pytest` (project venv).
43
+
44
+ - **Parity vs oracle:** synthetic native-named raw with CV steps (extend the `_build_cumulative_raw`-style builders; golden Arbin fixture has *no* CV steps, so it can't drive parity). Inline a small pandas oracle in the test file — the resurrected `summary_selector_exluder` math ported to native column names, capacities only — and assert the native `exclude_step_types=["cv_"]` summary capacities match.
45
+ - **Guard:** `exclude_step_types=None` output equals current summary frame exactly (and existing golden tests `test_golden.py` stay green).
46
+ - **Edge:** cycle without any excluded step gets zero correction (fill_null path); merged two-test frame keeps corrections isolated per `test_id` (reuse `_build_merged_raw` pattern).
47
+ - **`only-cv` analogue:** `exclude_step_types=["charge", "discharge"]` excludes the plain `charge` / `discharge` steps but keeps `cv_charge` / `cv_discharge` (neither starts with those prefixes) — a test locks this `startswith` semantics, matching the oracle.
48
+
49
+ ## Open questions
50
+
51
+ 1. **Legacy bridge:** should `OldCellpyCellCore.make_core_summary` also accept/forward `exclude_step_types` now (making cellpy's follow-up wiring trivial), or stay untouched until the cellpy-side issue? Recommendation: add the pass-through now — it is ~3 lines and the bridge is the path cellpy actually calls.
52
+ 2. **Correction scope:** confirm capacities-only is acceptable (old code also adjusted the raw current/voltage of the selected row; those adjusted values fed nothing that survives in the native summary). Recommendation: capacities only, documented.
53
+ 3. Branch: create `54-exclude-types-summary` off up-to-date `main` at `/iflow-start`.
@@ -0,0 +1,19 @@
1
+ # Issue #54 status — Native exclude-types summary support
2
+
3
+ - [x] Done
4
+
5
+ ## What's done
6
+
7
+ - 2026-07-02: plan accepted (`issue54_plan.md`); branch `54-exclude-types-summary` created off up-to-date `main`.
8
+ - 2026-07-02: implemented per plan:
9
+ - `summarizers.make_summary` gained `exclude_step_types: Optional[Sequence[str]] = None`; new helper `_subtract_excluded_step_deltas` subtracts excluded steps' per-cycle `last - first` capacity deltas (prefix match on `step_type`, `_group_keys`-aware, `fill_null(0.0)`) from the cycle-end capacities **before** CE / loss / cumulated columns are derived.
10
+ - Pass-through kwarg on `CellpyCellCore.make_core_summary` and `OldCellpyCellCore.make_core_summary` (legacy bridge, per accepted open question 1).
11
+ - Capacities-only correction (accepted open question 2); documented in the helper docstring.
12
+ - New `tests/test_exclude_types.py` (7 tests): parity vs inline pandas oracle (resurrected `summary_selector_exluder` math), derived-column correctness, `None`/`[]` guard, unmatched-prefix zero correction, cycle-without-excluded-step, `startswith` ("only-cv") semantics lock, merged two-test isolation.
13
+ - Full suite green: 107 passed (golden fixtures untouched → `None` path byte-identical).
14
+
15
+ ## Remaining work
16
+
17
+ - None in this repo. Cellpy-side follow-up (wire `selector_type` / `exclude_types`
18
+ to the new kwarg instead of the bare `DeprecationWarning`) is a separate issue in
19
+ jepegit/cellpy. `selector-dead-code-deferral.md` note updated at close.
@@ -0,0 +1,47 @@
1
+ # Issue #55: Add validating front door for raw frames (Data.from_raw_frame)
2
+
3
+ Source: https://github.com/cellpy/cellpy-core/issues/55
4
+
5
+ ## Original issue text
6
+
7
+ ## Context
8
+
9
+ The slim-consumer story (a user who builds a polars DataFrame in the native `config.RawCols` schema themselves and wants step/cycle summaries straight from cellpy-core, without cellpy) currently has no validating entry point:
10
+
11
+ ```python
12
+ core = CellpyCellCore(initialize=True)
13
+ core.data.raw = df # accepts anything
14
+ ```
15
+
16
+ A wrong column name or dtype only fails deep inside a polars expression in `summarizers`, with an error message that does not point back at the actual problem (the input frame not matching the schema).
17
+
18
+ ## Proposal
19
+
20
+ Add a small validating constructor on `Data` (in `src/cellpycore/cell_core.py`):
21
+
22
+ ```python
23
+ data = Data.from_raw_frame(df, validate=True)
24
+ ```
25
+
26
+ Behavior:
27
+
28
+ - Wraps the frame in a fresh `Data` (with the usual `MockMetaTestDependent`, so the graceful-degradation metadata guarantee is untouched).
29
+ - When `validate=True` (default), checks the frame against `config.RawCols`:
30
+ - required columns present (clear error listing missing ones);
31
+ - dtype sanity for the load-bearing columns, in particular `epoch_time_utc` must be int64 (ns, UTC — the STEP-11 contract) and datapoint/cycle/step numbers integer;
32
+ - optional columns (`test_id`, `internal_resistance`, …) allowed absent.
33
+ - Fails fast with a single actionable error message instead of a deep polars stack trace.
34
+
35
+ Keep it KISS: one classmethod + one module-level validation helper, no schema-validation framework.
36
+
37
+ ## Tests
38
+
39
+ - Happy path: valid native frame round-trips through `make_step_table` + `make_summary` identically to plain `data.raw = df`.
40
+ - Missing column → error naming the missing column(s).
41
+ - Wrong dtype on `epoch_time_utc` → error mentioning the int64-ns contract.
42
+ - `validate=False` skips checks entirely.
43
+
44
+ ## Links
45
+
46
+ - Raised while discussing the future slim-consumer / cellpy v2 interaction pattern (roadmap doc `cellpy-core-integration-roadmap.md`).
47
+ - Related: #42 (reset-granularity normalization is the other half of "arbitrary external raw frames").
@@ -0,0 +1,95 @@
1
+ # Plan — Issue #55: Add validating front door for raw frames (`Data.from_raw_frame`)
2
+
3
+ ## Goal
4
+
5
+ Give slim consumers a validating entry point for native-schema polars raw frames:
6
+ `Data.from_raw_frame(df, validate=True)` fails fast with one actionable error
7
+ instead of a deep polars stack trace inside `summarizers`.
8
+
9
+ ## Constraints
10
+
11
+ - KISS (per issue): one classmethod + one module-level validation helper in
12
+ `src/cellpycore/cell_core.py`. No schema-validation framework, no new deps.
13
+ - Graceful-degradation metadata guarantee untouched: `Data()` already attaches
14
+ `MockMetaTestDependent`; `from_raw_frame` reuses the plain constructor.
15
+ - `validate=False` must skip all checks entirely (zero cost).
16
+ - Google-style docstrings.
17
+
18
+ ### Prior art
19
+
20
+ - `tests/test_harmonized_fixture.py::_rawcols_names()` — derives the full
21
+ `RawCols` name set via `vars(RawCols)`; the helper mirrors the idea but only
22
+ needs the explicit required subset (coexist, no migration).
23
+ - `summarizers._ensure_test_id` — engine already auto-adds `test_id`; validator
24
+ must therefore treat `test_id` as optional.
25
+ - `summarizers.make_step_table` signal resolution (lines ~360-375) — engine
26
+ skips absent `internal_resistance` / `ref_potential` / `step_time`; validator
27
+ treats these as optional too.
28
+ - `_helpers.create_raw_data()` + `mock_data_with_raw` fixture — valid native
29
+ frame for tests (reuse, no new fixture needed).
30
+ - Toolbox (`.issueflows/00-tools/`) empty; graph report checked — nothing else relevant.
31
+
32
+ ## Approach
33
+
34
+ 1. **Module-level helper** `validate_raw_frame(raw, raw_cols=None)` in
35
+ `cell_core.py` (public, so cellpy v2 can call it directly later):
36
+ - `raw_cols` defaults to `config.RawCols()`.
37
+ - Type check: must be a `polars.DataFrame` (the slim-consumer story is
38
+ polars-native) — clear `TypeError` otherwise.
39
+ - **Required columns** (the engine's load-bearing set):
40
+ `datapoint_num`, `cycle_num`, `step_num`, `epoch_time_utc`, `test_time`,
41
+ `current`, `potential`, `cumulative_charge_capacity`,
42
+ `cumulative_discharge_capacity`. Missing ones → single `ValueError`
43
+ listing all of them.
44
+ - **Dtype sanity** (collected, reported together with missing-column errors
45
+ in one message):
46
+ - `epoch_time_utc` must be exactly `pl.Int64` — error text mentions the
47
+ int64 nanoseconds-since-epoch UTC (STEP-11) contract.
48
+ - `datapoint_num`, `cycle_num`, `step_num` must be integer dtypes.
49
+ - `test_time`, `current`, `potential`, `cumulative_*_capacity` must be
50
+ numeric.
51
+ - **Optional columns** (`test_id`, `internal_resistance`, `ref_potential`,
52
+ `step_time`, `mask`, `source_*`, aux columns, …): allowed absent, not
53
+ dtype-checked (KISS).
54
+ 2. **Classmethod** on `Data`:
55
+
56
+ ```python
57
+ @classmethod
58
+ def from_raw_frame(cls, raw, validate=True, raw_cols=None) -> "Data":
59
+ if validate:
60
+ validate_raw_frame(raw, raw_cols)
61
+ data = cls()
62
+ data.raw = raw
63
+ return data
64
+ ```
65
+
66
+ 3. Run `graphify update .` after the code change (project rule).
67
+
68
+ ## Files to touch
69
+
70
+ - [src/cellpycore/cell_core.py](c:\scripting\cellpy-core\src\cellpycore\cell_core.py)
71
+ — add `validate_raw_frame()` helper + `Data.from_raw_frame()` classmethod
72
+ (imports `polars` lazily inside the helper, matching module style).
73
+ - [tests/test_creation.py](c:\scripting\cellpy-core\tests\test_creation.py)
74
+ — add the new tests (creation-themed file already exists; no new test module).
75
+
76
+ ## Test strategy
77
+
78
+ Command: `uv run pytest` (project default).
79
+
80
+ New tests in `tests/test_creation.py`:
81
+
82
+ - **Happy path / round-trip**: `Data.from_raw_frame(create_raw_data())` runs
83
+ through `CellpyCellCore.make_core_step_table` + `make_core_summary` and the
84
+ resulting steps/summary frames equal those from plain `data.raw = df`.
85
+ - **Missing columns**: drop e.g. `cycle_num` + `current` → `ValueError` naming
86
+ both.
87
+ - **Wrong dtype**: cast `epoch_time_utc` to `pl.Float64` → error mentioning
88
+ int64-ns contract.
89
+ - **`validate=False`**: same broken frame passes without error.
90
+ - **Not a polars frame**: pandas frame → `TypeError`.
91
+
92
+ ## Open questions
93
+
94
+ - None — polars-only input is assumed (the issue's slim-consumer story);
95
+ pandas users go through the legacy bridge instead.
@@ -0,0 +1,34 @@
1
+ # Issue #55 status — validating front door for raw frames
2
+
3
+ Branch: `55-from-raw-frame`
4
+
5
+ ## Done
6
+
7
+ - 2026-07-02: Added `validate_raw_frame()` module-level helper and
8
+ `Data.from_raw_frame(raw, validate=True, raw_cols=None)` classmethod in
9
+ `src/cellpycore/cell_core.py` (per confirmed `issue55_plan.md`):
10
+ - `TypeError` on non-polars input (pandas users -> legacy bridge).
11
+ - Single `ValueError` collecting all problems: missing required columns
12
+ (`datapoint_num`, `cycle_num`, `step_num`, `epoch_time_utc`, `test_time`,
13
+ `current`, `potential`, `cumulative_charge_capacity`,
14
+ `cumulative_discharge_capacity`), `epoch_time_utc` must be Int64
15
+ (STEP-11 int64-ns UTC contract named in the message), datapoint/cycle/step
16
+ integer, rest numeric.
17
+ - Optional columns (`test_id`, `internal_resistance`, `ref_potential`,
18
+ `step_time`, `source_*`, `aux_*`, …) allowed absent, not dtype-checked.
19
+ - `validate=False` skips all checks; fresh `Data()` keeps the
20
+ `MockMetaTestDependent` graceful-degradation guarantee.
21
+ - 5 new tests in `tests/test_creation.py`: round-trip parity vs plain
22
+ `data.raw = df` through `make_core_step_table` + `make_core_summary`,
23
+ missing columns all named, wrong epoch dtype mentions int64-ns,
24
+ `validate=False` skip, pandas `TypeError`.
25
+ - Test suite green: `uv run pytest` -> 100 passed.
26
+ - `graphify update .` run after the code change.
27
+
28
+ ## Remaining
29
+
30
+ - Nothing (ready for `/iflow-close`).
31
+
32
+ ## Status
33
+
34
+ - [x] Done
@@ -0,0 +1,64 @@
1
+ # Issue #56: Document standalone use of cellpy-core (slim-consumer guide)
2
+
3
+ Source: https://github.com/cellpy/cellpy-core/issues/56
4
+
5
+ ## Original issue text
6
+
7
+ ## Context
8
+
9
+ cellpy-core is designed to be usable on its own: anyone who can produce a polars DataFrame in the native `config.RawCols` schema should be able to get step tables and per-cycle summaries without pulling in full cellpy. That story currently lives only in design docs and code docstrings — there is no user-facing documentation for it.
10
+
11
+ ## Proposal
12
+
13
+ Add a "Using cellpy-core standalone" guide to `docs/` covering:
14
+
15
+ ### 1. The recommended entry point
16
+
17
+ Native `CellpyCellCore` (not the `OldCellpyCellCore` legacy bridge, which exists only to serve legacy cellpy headers):
18
+
19
+ ```python
20
+ from cellpycore.cell_core import CellpyCellCore, Data
21
+
22
+ core = CellpyCellCore(initialize=True)
23
+ core.data.raw = my_polars_frame # native config.RawCols schema
24
+ core.cycle_mode = "anode" # only for half-cells; default "standard"
25
+
26
+ data = core.make_core_step_table(
27
+ core.data,
28
+ nom_cap=my_nom_cap_abs, # absolute Ah, for the per-step C-rate
29
+ raw_limits=my_instrument_limits, # optional; DEFAULT_RAW_LIMITS otherwise
30
+ )
31
+ data = core.make_core_summary(
32
+ data,
33
+ current_conversion_factor=1.0, # raw-current -> output-current, by value
34
+ )
35
+ # optional: specific / normalized columns
36
+ data = core.add_scaled_summary_columns(
37
+ data,
38
+ nom_cap_abs=my_nom_cap_abs,
39
+ normalization_cycles=None,
40
+ specific_converters={"gravimetric": f_g, "areal": f_a, "absolute": f_abs},
41
+ )
42
+
43
+ steps, summary = data.steps, data.summary # polars frames (StepCols / CycleCols)
44
+ ```
45
+
46
+ Also mention the class-free alternative (`summarizers.make_step_table(data)` + `summarizers.make_summary(data)` with the default schema) and when the class is worth it (cycle-mode -> TestMode handling, IR/C-rate orchestration).
47
+
48
+ ### 2. The contract the caller must honor
49
+
50
+ - **Order matters:** step table before summary (`make_summary` reads `data.steps`).
51
+ - **No metadata required:** `Data()` ships `MockMetaTestDependent`; only `cycle_mode` changes the math (CE direction).
52
+ - **Units by value:** core never sees unit objects — the caller precomputes floats (`nom_cap`, `current_conversion_factor`, `specific_converters`); pint fallback only via the optional `units` extra.
53
+ - **Raw shape assumptions:** `epoch_time_utc` is int64 ns UTC; capacities are cycle-cumulative per direction (point at `normalize_capacity_granularity` for step-/test-cumulative inputs); `test_id` optional, defaults to 0.
54
+ - **Legacy cruft absent by design:** native summary is the clean `CycleCols` subset + C-rate/IR; cumulated CE / shifted / RIC columns exist only on the legacy bridge.
55
+
56
+ ### 3. Housekeeping
57
+
58
+ - Link the guide from the README.
59
+ - Once #55 (`Data.from_raw_frame`) lands, switch the example to use it.
60
+
61
+ ## Links
62
+
63
+ - Raised together with #55 while discussing the future slim-consumer / cellpy v2 interaction pattern.
64
+ - Background: `.issueflows/04-designs-and-guides/cellpy-core-integration-roadmap.md`, `cellpy-core-migration.md` §4 (metadata/units boundaries).
@@ -0,0 +1,48 @@
1
+ # Issue #56 — plan
2
+
3
+ ## Goal
4
+
5
+ Add a user-facing "Using cellpy-core standalone" guide to `docs/` so slim consumers
6
+ (anyone with a polars frame in the native `config.RawCols` schema) can get step
7
+ tables and per-cycle summaries without full cellpy. Link it from the README.
8
+
9
+ ## Approach
10
+
11
+ - New `docs/standalone-use.md` covering:
12
+ - Recommended entry point: native `CellpyCellCore` + `Data.from_raw_frame`
13
+ (#55 landed, so the example uses the validating front door, not bare
14
+ `core.data.raw = ...`).
15
+ - Full pipeline example: `make_core_step_table` (nom_cap, raw_limits) →
16
+ `make_core_summary` (current_conversion_factor, exclude_step_types) →
17
+ optional `add_scaled_summary_columns` (specific_converters).
18
+ - Class-free alternative: `summarizers.make_step_table` + `summarizers.make_summary`
19
+ with the default schema, and when the class is worth it (cycle_mode → TestMode,
20
+ IR/C-rate orchestration).
21
+ - Caller contract: step table before summary; no metadata required; units by
22
+ value (pint only via the optional `units` extra); raw-shape assumptions
23
+ (`epoch_time_utc` int64 ns UTC, cycle-cumulative capacities →
24
+ `normalize_capacity_granularity` for step-/test-cumulative inputs, `test_id`
25
+ optional); legacy cruft only on the `OldCellpyCellCore` bridge.
26
+ - Links to `docs/data_format_specifications/harmonized_raw.md` and
27
+ `docs/data-object-definition.md`.
28
+ - README: add a short Documentation section linking the guide (and install note —
29
+ package is on PyPI as `cellpycore` since v0.1.1, README still says GitHub-only;
30
+ fix that line while touching it).
31
+
32
+ ## Files to touch
33
+
34
+ - `docs/standalone-use.md` (new)
35
+ - `README.md` (link + install line)
36
+ - `.issueflows/01-current-issues/issue56_*.md` (tracking)
37
+ - `HISTORY.md`, `pyproject.toml` (at close: patch bump + promote)
38
+
39
+ ## Test strategy
40
+
41
+ Docs-only change — no engine code touched. Re-run `uv run pytest` (107 tests) to
42
+ confirm the suite stays green; verify the example snippets against the real
43
+ signatures in `cell_core.py` / `summarizers.py` (done while writing).
44
+
45
+ ## Design docs consulted
46
+
47
+ `cellpy-core-integration-roadmap.md`, `cellpy-core-migration.md` §4,
48
+ `release-procedure.md` (for the close/release steps).