cellpycore 0.2.2__tar.gz → 0.2.4__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.
- cellpycore-0.2.4/.issueflows/01-current-issues/issue138_original.md +85 -0
- cellpycore-0.2.4/.issueflows/01-current-issues/issue138_plan.md +18 -0
- cellpycore-0.2.4/.issueflows/01-current-issues/issue138_status.md +26 -0
- cellpycore-0.2.4/.issueflows/03-solved-issues/issue139_original.md +61 -0
- cellpycore-0.2.4/.issueflows/03-solved-issues/issue139_plan.md +119 -0
- cellpycore-0.2.4/.issueflows/03-solved-issues/issue139_status.md +18 -0
- cellpycore-0.2.4/.issueflows/04-designs-and-guides/legacy-raw-energy-mapping.md +24 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/HISTORY.md +25 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/PKG-INFO +1 -1
- {cellpycore-0.2.2 → cellpycore-0.2.4}/graphify-out/.graphify_labels.json +0 -4
- {cellpycore-0.2.2 → cellpycore-0.2.4}/graphify-out/GRAPH_REPORT.md +132 -133
- {cellpycore-0.2.2 → cellpycore-0.2.4}/graphify-out/graph.html +4 -4
- {cellpycore-0.2.2 → cellpycore-0.2.4}/graphify-out/graph.json +1238 -1048
- {cellpycore-0.2.2 → cellpycore-0.2.4}/graphify-out/manifest.json +13 -13
- {cellpycore-0.2.2 → cellpycore-0.2.4}/pyproject.toml +1 -1
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/cell_core.py +6 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/config.py +4 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/legacy/headers.py +2 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/legacy/mapping.py +9 -6
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/summarizers.py +168 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/units/__init__.py +2 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/units/converters.py +30 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/uv.lock +1 -1
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.aliases +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/rules/cellpy-core-migration.mdc +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/rules/graphify.mdc +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/rules/issueflow-rules.mdc +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/rules/kiss.mdc +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/rules/this-project.mdc +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/caveman/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/grill-me/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/iflow/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/iflow-archive/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/iflow-cleanup/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/iflow-close/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/iflow-comments/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/iflow-cycle/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/iflow-epic/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/iflow-fix/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/iflow-graphify/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/iflow-history-update/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/iflow-init/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/iflow-pause/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/iflow-pick/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/iflow-plan/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/iflow-start/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/iflow-status/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/iflow-version-bump/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.cursor/skills/iflow-yolo/SKILL.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.gitattributes +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.gitignore +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/00-tools/.gitkeep +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/00-tools/README.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/01-current-issues/.gitkeep +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/02-partly-solved-issues/.gitkeep +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/02-partly-solved-issues/issue100_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/02-partly-solved-issues/issue100_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/02-partly-solved-issues/issue100_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/.gitkeep +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue10_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue10_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue10_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue110_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue110_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue110_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue112_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue112_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue112_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue114_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue114_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue114_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue115_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue115_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue115_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue116_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue116_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue116_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue117_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue117_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue117_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue118_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue118_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue118_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue121_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue121_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue121_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue12_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue12_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue12_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue136_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue136_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue136_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue13_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue13_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue13_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue21_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue21_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue21_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue22_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue22_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue22_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue23_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue23_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue23_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue24_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue24_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue29_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue29_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue29_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue30_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue30_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue30_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue32_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue32_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue32_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue34_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue34_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue36_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue36_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue39_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue39_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue39_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue40_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue40_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue40_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue41_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue41_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue41_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue42_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue42_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue42_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue43_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue43_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue43_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue44_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue44_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue45_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue45_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue45_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue50_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue50_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue50_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue54_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue54_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue54_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue55_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue55_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue55_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue56_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue56_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue56_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue62_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue62_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue62_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue64_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue64_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue64_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue66_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue66_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue66_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue67_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue67_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue67_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue68_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue68_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue68_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue69_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue69_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue69_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue70_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue70_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue70_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue72_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue72_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue77_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue77_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue77_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue82_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue82_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue84_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue84_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue84_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue86_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue86_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue86_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue91_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue91_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue91_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue95_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue95_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue95_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue96_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue96_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue96_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue97_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue97_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue97_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue98_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue98_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue98_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue99_original.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue99_plan.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/03-solved-issues/issue99_status.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/.gitkeep +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/bdf-io-placement.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/cellpy-core-integration-into-cellpy.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/cellpy-core-integration-roadmap.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/cellpy-core-migration.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/code-review-2026-07.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/column-headers-review.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/legacy-bridge-test-id.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/metadata-scaffolding.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/nom-cap-naming.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/rawcols-dtype-map.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/release-procedure.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/selector-dead-code-deferral.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/step-c-rate-split.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/step-table-polars-migration.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/summary-extractors.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/test-data-and-fixtures.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/test-metadata-and-merging.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/this-project.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/04-designs-and-guides/zensical-docs.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/05-epics/.gitkeep +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.issueflows/config.toml +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.pre-commit-config.yaml +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.python-version +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.readthedocs.yaml +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/.vscode/settings.json +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/AGENTS.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/LICENSE +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/README.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/ROADMAP.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/SCRATCHPAD.md +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/graphify-out/.graphify_root +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/__init__.py +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/curves.py +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/exceptions.py +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/extractors.py +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/legacy/__init__.py +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/legacy/limits.py +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/legacy/meta.py +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/legacy/meta_mapping.py +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/legacy/mock_core.py +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/legacy/selectors.py +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/merge.py +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/metadata/__init__.py +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/metadata/io.py +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/metadata/models.py +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/py.typed +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/settings_base.py +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/testing/__init__.py +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/testing/mock_data.py +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/timestamps.py +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/src/cellpycore/units/spec.py +0 -0
- {cellpycore-0.2.2 → cellpycore-0.2.4}/zensical.toml +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Issue #138: Add a built-in utility for calculating Equivalent Full Cycles (EFC) from time-series data.
|
|
2
|
+
|
|
3
|
+
Author: jepegit
|
|
4
|
+
URL: https://github.com/cellpy/cellpy-core/issues/138
|
|
5
|
+
|
|
6
|
+
Cellpy currently provides cycle-based summaries and performance metrics for cycling experiments. However, many battery datasets particularly operational, field, and BMS datasets do not contain well-defined charge/discharge cycles. Instead, they consist of continuous time-series measurements of voltage, current, temperature, and time.
|
|
7
|
+
|
|
8
|
+
For these datasets, researchers and engineers often use Equivalent Full Cycles (EFC) as a throughput-based ageing metric. Currently, users must calculate EFC outside of cellpy and maintain custom implementations, leading to duplicated effort and inconsistent definitions across projects.
|
|
9
|
+
|
|
10
|
+
As battery research increasingly incorporates operational and real-world datasets, the lack of a built-in EFC calculation makes it more difficult to compare ageing across datasets and integrate operational data into existing cellpy workflows.
|
|
11
|
+
|
|
12
|
+
## Proposed Solution
|
|
13
|
+
|
|
14
|
+
Add a built-in utility for calculating **Equivalent Full Cycles (EFC)** from time-series data.
|
|
15
|
+
|
|
16
|
+
Example usage:
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
cell.calculate_efc(nominal_capacity=300.0)
|
|
20
|
+
````
|
|
21
|
+
|
|
22
|
+
or
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
cell.make_summary(add_efc=True)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The implementation could:
|
|
29
|
+
|
|
30
|
+
* Calculate cumulative charge throughput from current and time:
|
|
31
|
+
|
|
32
|
+
$$
|
|
33
|
+
Q_{throughput} = \sum |I| \Delta t
|
|
34
|
+
$$
|
|
35
|
+
|
|
36
|
+
* Compute EFC as:
|
|
37
|
+
|
|
38
|
+
$$
|
|
39
|
+
EFC = \frac{Q_{throughput}}{2Q_{nom}}
|
|
40
|
+
$$
|
|
41
|
+
|
|
42
|
+
where $$Q_{nom}$$ is the nominal capacity.
|
|
43
|
+
|
|
44
|
+
* Optionally add:
|
|
45
|
+
* Instantaneous cumulative EFC to the raw dataframe.
|
|
46
|
+
* EFC columns to the summary dataframe.
|
|
47
|
+
* Energy-throughput-based equivalents (optional future extension).
|
|
48
|
+
* Support for SoC-based EFC calculations when SoC data is available.
|
|
49
|
+
|
|
50
|
+
Suggested outputs:
|
|
51
|
+
|
|
52
|
+
* `cumulative_ah_throughput`
|
|
53
|
+
* `cumulative_energy_throughput`
|
|
54
|
+
* `equivalent_full_cycles`
|
|
55
|
+
|
|
56
|
+
This would provide a standardized and reproducible EFC implementation directly within the cellpy ecosystem.
|
|
57
|
+
|
|
58
|
+
***
|
|
59
|
+
|
|
60
|
+
**Describe alternatives you've considered**
|
|
61
|
+
|
|
62
|
+
Current alternatives include:
|
|
63
|
+
|
|
64
|
+
* Implementing custom EFC calculations in downstream analysis scripts.
|
|
65
|
+
* Adding project-specific preprocessing steps prior to importing data into cellpy.
|
|
66
|
+
|
|
67
|
+
While these approaches work, they lead to code duplication and make it harder to compare results across projects and users. A native cellpy implementation would provide a common reference method and improve reproducibility.
|
|
68
|
+
|
|
69
|
+
***
|
|
70
|
+
|
|
71
|
+
**Additional context**
|
|
72
|
+
|
|
73
|
+
This feature would be particularly useful for:
|
|
74
|
+
|
|
75
|
+
* Operational battery datasets.
|
|
76
|
+
* BMS and field-monitoring data.
|
|
77
|
+
* Fleet and stationary storage applications.
|
|
78
|
+
* Machine learning pipelines where degradation progress is tracked using throughput-based metrics.
|
|
79
|
+
* Continuous time-series datasets that do not contain explicit cycle boundaries.
|
|
80
|
+
|
|
81
|
+
As cellpy expands beyond traditional cycling experiments and is increasingly used for large-scale battery data analysis, a standardized EFC utility would help bridge the gap between laboratory cycling data and real-world operational datasets.
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
```
|
|
85
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Issue #138 — Plan: Equivalent Full Cycles (EFC) utility
|
|
2
|
+
|
|
3
|
+
Confirmed approach (user-approved 2026-07-18):
|
|
4
|
+
|
|
5
|
+
- **Both surfaces**: raw-level current integration + summary-level per-cycle columns.
|
|
6
|
+
- **Summary basis**: existing `test_cumulated_charge_capacity + test_cumulated_discharge_capacity` (unit-consistent with nom_cap, no conversion factor).
|
|
7
|
+
- **Skipped**: energy throughput, SoC-based EFC (issue marks optional/future); `make_summary(add_efc=True)` wiring (standalone functions match `equivalent_cycles_to_summary` precedent); legacy-bridge columns (native-only feature).
|
|
8
|
+
|
|
9
|
+
## Changes
|
|
10
|
+
|
|
11
|
+
1. `summarizers.py`: two free functions next to `equivalent_cycles_to_summary`:
|
|
12
|
+
- `throughput_to_raw(data, schema=None, nom_cap_abs=1.0, conversion_factor=1.0, *, nom_cap=None)` — adds `test_cumulated_capacity_throughput` (= cum_sum(|current|·Δt·factor), windowed over test_id when present, negative Δt clipped to 0) and `equivalent_full_cycles` (= throughput / (2·nom_cap_abs)) to `data.raw`. `conversion_factor` converts current·time units to the capacity unit (e.g. A·s→mAh = 1000/3600), caller-supplied per codebase convention.
|
|
13
|
+
- `efc_to_summary(data, schema=None, nom_cap_abs=1.0, normalization_cycles=None, step_txt=None, *, nom_cap=None)` — same two columns on the summary, throughput = cumulated charge + discharge capacity; supports `normalization_cycles` like its sibling.
|
|
14
|
+
2. `config.py` `CycleCols`: the two new column-name fields (raw function reuses the same names via `schema.cycle`).
|
|
15
|
+
3. `docs/specifications/cycle-table.md`: two new spec rows (conformance-locked).
|
|
16
|
+
4. `legacy/mapping.py`: names added to `NATIVE_ONLY_CYCLE` (no legacy counterpart).
|
|
17
|
+
5. `tests/test_config_columns.py`: names added to `CYCLE_EXPECTED`.
|
|
18
|
+
6. `tests/test_efc.py` (new): raw integration vs hand-computed Σ|I|Δt, rest-rows-add-nothing, monotonicity, conversion factor, pandas round-trip, summary identity vs cumulated capacities.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Issue #138 — Status
|
|
2
|
+
|
|
3
|
+
- [x] Done
|
|
4
|
+
|
|
5
|
+
## 2026-07-18
|
|
6
|
+
|
|
7
|
+
- Implemented `throughput_to_raw` and `efc_to_summary` in `src/cellpycore/summarizers.py`.
|
|
8
|
+
- Registered `test_cumulated_capacity_throughput` and `equivalent_full_cycles` on `CycleCols` (`config.py`), in `docs/specifications/cycle-table.md`, in `tests/test_config_columns.py`, and as `NATIVE_ONLY_CYCLE` in `legacy/mapping.py`.
|
|
9
|
+
- Added `tests/test_efc.py` (4 tests). Full suite: 265 passed.
|
|
10
|
+
- End-to-end sanity run on mock data with A·s→mAh factor verified by hand (≈194 mAh throughput → EFC ≈ 0.324 at nom_cap 300 mAh).
|
|
11
|
+
|
|
12
|
+
## 2026-07-23 (revision after review)
|
|
13
|
+
|
|
14
|
+
- **Integration fixed**: right-Riemann `|I_i|·dt` → trapezoidal `mean(|I|)·dt` in `throughput_to_raw`. The old rule charged a whole preceding rest to the first sample of a pulse — wrong for the irregularly sampled field/BMS data this targets.
|
|
15
|
+
- **Silent failures now logged**: missing current values and negative time deltas are counted and emitted as `logger.warning` instead of passing as zero.
|
|
16
|
+
- **Legacy names **: `equivalent_full_cycles` and `cumulated_capacity_throughput` added to legacy `HeadersSummary` + `CYCLE_PAIRS` + `LEGACY_ATTR_TO_SCHEMA`; removed from `NATIVE_ONLY_CYCLE`. EFC now reaches default-schema cellpy users, not only `native_schema=True`.
|
|
17
|
+
- **Wired into `add_scaled_summary_columns`** (native + legacy bridge), unconditionally — no `add_efc` flag (`nom_cap_abs` is already resolved there, next to `equivalent_cycles_to_summary`).
|
|
18
|
+
- **Units helper**: `calculate_throughput_conversion_factor(current_unit, time_unit)` in `units/converters.py` so cellpy computes the A·s→charge factor the pint way (mirrors `calculate_current_conversion_factor`), instead of hand-derived `1000/3600` at call sites.
|
|
19
|
+
- **Docs**: raw derived-columns table in `harmonized-raw.md`; `cycle-table.md` notes `EFC = normalized_cycle_index·(1+CE)/2`.
|
|
20
|
+
- **Tests**: analytic case (1 A × 3600 s → EFC 0.5), trapezoidal-vs-right-Riemann, bad-input warnings, native + legacy-bridge wiring, units factor. The old `_expected_raw_throughput` helper mirrored the implementation and could not fail; kept but now backed by the analytic + bridge cases. Full suite: **271 passed**.
|
|
21
|
+
|
|
22
|
+
## Remaining
|
|
23
|
+
|
|
24
|
+
- **Blocking cellpy PR**: bump `cellpycore==0.2.4` pin in cellpy `pyproject.toml`, add `helpers.add_efc` wrapper (mirrors `add_normalized_cycle_index`) for the `cell.calculate_efc(...)` API from the issue. Plot label (`plotutils.py:823`) stays as-is, `equivalent_full_cycles` gets no axis-label entry (falls back to column name).
|
|
25
|
+
- Version bump to **0.3.0** on close (new spec columns = schema change).
|
|
26
|
+
- Deferred (per approved plan): energy throughput, SoC-based EFC.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Issue #139: legacy mapping: no entries for the energy columns (charge_energy_txt -> cumulative_charge_energy)
|
|
2
|
+
|
|
3
|
+
Source: https://github.com/cellpy/cellpy-core/issues/139
|
|
4
|
+
|
|
5
|
+
## Original issue text
|
|
6
|
+
|
|
7
|
+
## Summary
|
|
8
|
+
|
|
9
|
+
`cellpycore.legacy.mapping.LEGACY_ATTR_TO_SCHEMA["raw"]` has no entries for the
|
|
10
|
+
energy columns, although both sides exist:
|
|
11
|
+
|
|
12
|
+
- native schema defines `cumulative_charge_energy` and
|
|
13
|
+
`cumulative_discharge_energy`;
|
|
14
|
+
- cellpy's loader configurations declare `charge_energy_txt` and
|
|
15
|
+
`discharge_energy_txt`, and vendor files carry the data (Maccor `Watt-hr`,
|
|
16
|
+
Neware energy columns, …).
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
>>> from cellpycore.legacy import mapping
|
|
20
|
+
>>> {k: v for k, v in mapping.LEGACY_ATTR_TO_SCHEMA["raw"].items() if "energy" in k}
|
|
21
|
+
{}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Why it matters now
|
|
25
|
+
|
|
26
|
+
Found while porting loaders to the `harmonize()` framework
|
|
27
|
+
(jepegit/cellpy#559 → #560). Consequences today:
|
|
28
|
+
|
|
29
|
+
1. On the native runtime, `to_native()` passes the unmapped columns through
|
|
30
|
+
under their **legacy** names, so a native frame carries `charge_energy`
|
|
31
|
+
while the schema says the column should be `cumulative_charge_energy`.
|
|
32
|
+
Asking `c.schema.raw` for energy finds nothing.
|
|
33
|
+
2. `harmonize()` drops undeclared columns by design, so a ported loader would
|
|
34
|
+
silently lose energy data unless it declares a passthrough — which is the
|
|
35
|
+
wrong long-term answer for a column the schema already has a name for.
|
|
36
|
+
|
|
37
|
+
## Ask
|
|
38
|
+
|
|
39
|
+
Add the mapping entries:
|
|
40
|
+
|
|
41
|
+
| legacy attribute | native column |
|
|
42
|
+
|---|---|
|
|
43
|
+
| `charge_energy_txt` | `cumulative_charge_energy` |
|
|
44
|
+
| `discharge_energy_txt` | `cumulative_discharge_energy` |
|
|
45
|
+
|
|
46
|
+
Please confirm the reset-granularity convention for the energy columns matches
|
|
47
|
+
the capacity one (cycle-cumulative per direction, per the harmonized-raw spec's
|
|
48
|
+
*Capacity convention*) — the cellpy side will normalise them the same way.
|
|
49
|
+
|
|
50
|
+
## Also unmapped (for a decision, not necessarily this issue)
|
|
51
|
+
|
|
52
|
+
These native raw columns have no legacy attribute mapped to them. Several are
|
|
53
|
+
correctly framework-owned or native-only, but `datetime_txt → epoch_time_utc`
|
|
54
|
+
looks like a genuine omission of the same kind:
|
|
55
|
+
|
|
56
|
+
`epoch_time_utc`, `step_type`, `step_mode`, `step_type_detail`, `cycle_type`,
|
|
57
|
+
`ref_potential`, `step_charge_power`, `step_discharge_power`, `aux_*`,
|
|
58
|
+
`source_*`, `mask`, `test_id`.
|
|
59
|
+
|
|
60
|
+
Cross-repo order per the cellpy 2 release plan §3: core PR → core release →
|
|
61
|
+
cellpy re-pin → cellpy consumes.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Plan — issue #139 (legacy raw energy mapping)
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Bridge legacy raw energy columns through the authoritative header map so
|
|
6
|
+
`charge_energy` / `discharge_energy` rename to
|
|
7
|
+
`cumulative_charge_energy` / `cumulative_discharge_energy` (same pattern as
|
|
8
|
+
capacity), enabling `to_native()` / `harmonize()` consumers to find them under
|
|
9
|
+
the native schema names.
|
|
10
|
+
|
|
11
|
+
## Constraints
|
|
12
|
+
|
|
13
|
+
- Keep change to `mapping.py` + its existing totality / spot-check tests.
|
|
14
|
+
No loader work, no engine changes, no cycle/step energy columns.
|
|
15
|
+
- Totality discipline (#116): every legacy attr / column value is either mapped
|
|
16
|
+
or in an exception set — never both, never neither.
|
|
17
|
+
- Value-level pairs (`RAW_PAIRS`) drive DataFrame renames; attribute table
|
|
18
|
+
(`LEGACY_ATTR_TO_SCHEMA`) must stay in sync (`test_legacy_attr_matches_value_mapping`).
|
|
19
|
+
- Out of scope (issue itself): `datetime_txt → epoch_time_utc` and the other
|
|
20
|
+
unmapped native-only list — track separately if wanted.
|
|
21
|
+
- Cross-repo: core PR → core release → cellpy re-pin → cellpy consumes
|
|
22
|
+
(cellpy #560). This issue is the core PR only.
|
|
23
|
+
- Spec already states the reset convention (see Approach); record that as the
|
|
24
|
+
answer to the issue's ask — do not invent a new convention here.
|
|
25
|
+
|
|
26
|
+
### Prior art
|
|
27
|
+
|
|
28
|
+
- `RAW_PAIRS` / `LEGACY_ATTR_TO_SCHEMA["raw"]` / exception sets —
|
|
29
|
+
[`src/cellpycore/legacy/mapping.py`](src/cellpycore/legacy/mapping.py).
|
|
30
|
+
Mirror capacity entries (`charge_capacity_txt` →
|
|
31
|
+
`cumulative_charge_capacity`).
|
|
32
|
+
- Totality + spot-check tests —
|
|
33
|
+
[`tests/test_header_mapping.py`](tests/test_header_mapping.py)
|
|
34
|
+
(`test_raw_*_totality`, `test_known_translations`,
|
|
35
|
+
`test_legacy_attr_*`).
|
|
36
|
+
- Spec Capacity convention —
|
|
37
|
+
[`docs/specifications/harmonized-raw.md`](docs/specifications/harmonized-raw.md)
|
|
38
|
+
(§ Capacity convention): energy columns share cycle-cumulative / per-direction
|
|
39
|
+
semantics with capacity.
|
|
40
|
+
- Issue #42 (solved): engine reset-granularity normalizer already covers
|
|
41
|
+
`cumulative_*_energy` when source granularity differs.
|
|
42
|
+
- Fixture helper already assumes the rename —
|
|
43
|
+
[`dev/make_harmonized_raw.py`](dev/make_harmonized_raw.py)
|
|
44
|
+
(`charge_energy` → `cumulative_charge_energy`).
|
|
45
|
+
- Issue #116 (solved): attribute-table + `LEGACY_ATTR_UNMAPPED` discipline.
|
|
46
|
+
- Toolbox: none relevant.
|
|
47
|
+
- Graph: community 87 (`mapping.py`) / 82 (legacy headers) — no extra modules.
|
|
48
|
+
|
|
49
|
+
**Note vs architecture-plan D3:** `cellpy2-native-headers-migration-plan.md`
|
|
50
|
+
still lists raw energy as passthrough ("not synthesized — different reset
|
|
51
|
+
semantics"). That is **stale relative to the harmonized-raw Capacity
|
|
52
|
+
convention + #42**. Mapping is a rename of already-supplied columns, not
|
|
53
|
+
synthesis. After Accept, add a one-line correction in
|
|
54
|
+
`.issueflows/04-designs-and-guides/` (or a comment in the plan status) so
|
|
55
|
+
future agents do not re-block the bridge; updating the architecture-plan
|
|
56
|
+
doc can be a tiny follow-up outside this PR if desired.
|
|
57
|
+
|
|
58
|
+
## Approach
|
|
59
|
+
|
|
60
|
+
1. **Confirm convention (recorded decision):** energy matches capacity —
|
|
61
|
+
cumulative per cycle, per direction, reset at cycle boundary
|
|
62
|
+
(`harmonized-raw.md` Capacity convention). Cellpy loaders normalize the
|
|
63
|
+
same way; if a source is step-cumulative, #42's normalizer is the path,
|
|
64
|
+
not leaving the columns unmapped.
|
|
65
|
+
|
|
66
|
+
2. **Value map** — add to `RAW_PAIRS` (next to the capacity pairs):
|
|
67
|
+
```python
|
|
68
|
+
("cumulative_charge_energy", "charge_energy"),
|
|
69
|
+
("cumulative_discharge_energy", "discharge_energy"),
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
3. **Exception sets** — remove from the raw exceptions so totality stays
|
|
73
|
+
exact:
|
|
74
|
+
- `LEGACY_ONLY_RAW`: drop `"charge_energy"`, `"discharge_energy"`
|
|
75
|
+
- `NATIVE_ONLY_RAW`: drop `"cumulative_charge_energy"`,
|
|
76
|
+
`"cumulative_discharge_energy"`
|
|
77
|
+
|
|
78
|
+
4. **Attribute map** — add to `LEGACY_ATTR_TO_SCHEMA["raw"]`:
|
|
79
|
+
```python
|
|
80
|
+
"charge_energy_txt": "cumulative_charge_energy",
|
|
81
|
+
"discharge_energy_txt": "cumulative_discharge_energy",
|
|
82
|
+
```
|
|
83
|
+
and remove those attrs from `LEGACY_ATTR_UNMAPPED["raw"]`.
|
|
84
|
+
|
|
85
|
+
5. **Do not touch** step/cycle maps (`NATIVE_ONLY_STEP` still has
|
|
86
|
+
`charge_energy` / `discharge_energy` as *step-table* base signals — different
|
|
87
|
+
columns).
|
|
88
|
+
|
|
89
|
+
6. **Behavior:** `legacy_to_native_raw()` / bridge renames will translate
|
|
90
|
+
energy instead of leaving it as a passthrough extra. That is the intended
|
|
91
|
+
fix for native-schema lookup and `harmonize()`.
|
|
92
|
+
|
|
93
|
+
## Files to touch
|
|
94
|
+
|
|
95
|
+
| Path | Change |
|
|
96
|
+
|------|--------|
|
|
97
|
+
| `src/cellpycore/legacy/mapping.py` | `RAW_PAIRS` + attr table + raw exception sets |
|
|
98
|
+
| `tests/test_header_mapping.py` | Extend `test_known_translations` expected dict with the two energy renames |
|
|
99
|
+
| `.issueflows/04-designs-and-guides/` (short note) | Optional: "raw energy bridged like capacity (#139)" so D3 staleness is local |
|
|
100
|
+
|
|
101
|
+
## Test strategy
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
uv run pytest tests/test_header_mapping.py
|
|
105
|
+
uv run ruff check && uv run ruff format --check
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Existing totality / attr-sync tests should go green once exceptions and pairs
|
|
109
|
+
move together. No new fixture goldens expected (energy was not in
|
|
110
|
+
`RAW_PAIRS` before; bridge goldens that omit energy columns stay unaffected).
|
|
111
|
+
|
|
112
|
+
## Open questions
|
|
113
|
+
|
|
114
|
+
1. **Energy reset convention = capacity?** **Recommended: yes** (spec + #42
|
|
115
|
+
already say so). Accepting this plan accepts that answer for the GitHub
|
|
116
|
+
issue ask.
|
|
117
|
+
2. **Update architecture-plan D3 in this PR?** **Recommended: no** — keep
|
|
118
|
+
core PR small; optional local design-guide note only. Say if you want the
|
|
119
|
+
architecture-plan edit bundled.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Issue #139 status
|
|
2
|
+
|
|
3
|
+
- [x] Done
|
|
4
|
+
|
|
5
|
+
## What's done
|
|
6
|
+
|
|
7
|
+
- Plan accepted (energy reset = capacity convention).
|
|
8
|
+
- `RAW_PAIRS` + `LEGACY_ATTR_TO_SCHEMA["raw"]` energy entries added.
|
|
9
|
+
- Dropped energy from `LEGACY_ONLY_RAW` / `NATIVE_ONLY_RAW` /
|
|
10
|
+
`LEGACY_ATTR_UNMAPPED["raw"]`.
|
|
11
|
+
- `test_known_translations` updated.
|
|
12
|
+
- Design note: `.issueflows/04-designs-and-guides/legacy-raw-energy-mapping.md`.
|
|
13
|
+
- `uv run pytest` — 261 passed; ruff clean.
|
|
14
|
+
- Version bump `0.2.2` → `0.2.3`; `HISTORY.md` promoted.
|
|
15
|
+
|
|
16
|
+
## Remaining work
|
|
17
|
+
|
|
18
|
+
- None (ship via PR).
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Legacy raw energy mapping (#139)
|
|
2
|
+
|
|
3
|
+
**Context.** Raw `charge_energy` / `discharge_energy` used to sit in
|
|
4
|
+
`LEGACY_ONLY_RAW` (passthrough). Architecture-plan D3 still says that and
|
|
5
|
+
claims different reset semantics vs native cumulative energy.
|
|
6
|
+
|
|
7
|
+
**Decision.** Bridge them like capacity via `RAW_PAIRS` /
|
|
8
|
+
`LEGACY_ATTR_TO_SCHEMA["raw"]`:
|
|
9
|
+
|
|
10
|
+
| legacy value | native |
|
|
11
|
+
|---|---|
|
|
12
|
+
| `charge_energy` | `cumulative_charge_energy` |
|
|
13
|
+
| `discharge_energy` | `cumulative_discharge_energy` |
|
|
14
|
+
|
|
15
|
+
Reset convention matches capacity: cycle-cumulative, per direction
|
|
16
|
+
(`docs/specifications/harmonized-raw.md` Capacity convention). Wrong source
|
|
17
|
+
granularity → issue #42 normalizer, not leaving columns unmapped.
|
|
18
|
+
|
|
19
|
+
**Alternatives.** Keep passthrough (rejected — breaks `to_native()` /
|
|
20
|
+
`harmonize()` schema lookup). Synthesize energy from other signals (rejected —
|
|
21
|
+
rename only).
|
|
22
|
+
|
|
23
|
+
**Refs.** #139; cellpy #560; supersedes architecture-plan D3 for these two
|
|
24
|
+
columns only.
|
|
@@ -4,6 +4,31 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.2.4] - 2026-07-23
|
|
8
|
+
|
|
9
|
+
- Add Equivalent Full Cycles (EFC) utilities (#138). `summarizers.throughput_to_raw`
|
|
10
|
+
integrates `|current|` over test time (trapezoidal, windowed per `test_id`) to add
|
|
11
|
+
`test_cumulated_capacity_throughput` and `equivalent_full_cycles` to the raw frame —
|
|
12
|
+
for continuous / BMS / field data without cycle boundaries. `summarizers.efc_to_summary`
|
|
13
|
+
adds the same two columns to the per-cycle summary from the cumulated charge+discharge
|
|
14
|
+
capacities. Both use `EFC = throughput / (2 x nominal capacity)`. Missing current values
|
|
15
|
+
and negative time deltas contribute zero and are logged as warnings.
|
|
16
|
+
- EFC is emitted unconditionally by `add_scaled_summary_columns` (native + legacy bridge),
|
|
17
|
+
so it reaches default-schema cellpy users; the legacy bridge renames the summary columns
|
|
18
|
+
to `cumulated_capacity_throughput` / `equivalent_full_cycles`.
|
|
19
|
+
- New spec columns in `docs/specifications/cycle-table.md` (with the
|
|
20
|
+
`EFC = normalized_cycle_index x (1 + CE) / 2` relationship noted) and the raw
|
|
21
|
+
derived-columns table in `harmonized-raw.md`.
|
|
22
|
+
- `units.calculate_throughput_conversion_factor(current_unit, time_unit)` computes the
|
|
23
|
+
current·time → charge factor (e.g. A·s → mAh) the pint way, mirroring
|
|
24
|
+
`calculate_current_conversion_factor`.
|
|
25
|
+
## [0.2.3] - 2026-07-19
|
|
26
|
+
|
|
27
|
+
- Bridge legacy raw ``charge_energy`` / ``discharge_energy`` to
|
|
28
|
+
``cumulative_charge_energy`` / ``cumulative_discharge_energy`` via
|
|
29
|
+
``RAW_PAIRS`` and ``LEGACY_ATTR_TO_SCHEMA``, matching the capacity
|
|
30
|
+
cycle-cumulative convention. (#139)
|
|
31
|
+
|
|
7
32
|
## [0.2.2] - 2026-07-17
|
|
8
33
|
|
|
9
34
|
- Legacy bridge carries ``test_id`` through step and summary frames (identity
|
|
@@ -322,7 +322,6 @@
|
|
|
322
322
|
"320": "Community 320",
|
|
323
323
|
"321": "Community 321",
|
|
324
324
|
"322": "Community 322",
|
|
325
|
-
"323": "Community 323",
|
|
326
325
|
"324": "Community 324",
|
|
327
326
|
"325": "Community 325",
|
|
328
327
|
"326": "Community 326",
|
|
@@ -351,14 +350,11 @@
|
|
|
351
350
|
"349": "Community 349",
|
|
352
351
|
"350": "Community 350",
|
|
353
352
|
"351": "Community 351",
|
|
354
|
-
"352": "Community 352",
|
|
355
353
|
"353": "Community 353",
|
|
356
354
|
"354": "Community 354",
|
|
357
|
-
"355": "Community 355",
|
|
358
355
|
"356": "Community 356",
|
|
359
356
|
"357": "Community 357",
|
|
360
357
|
"358": "Community 358",
|
|
361
|
-
"359": "Community 359",
|
|
362
358
|
"360": "Community 360",
|
|
363
359
|
"361": "Community 361",
|
|
364
360
|
"362": "Community 362",
|