ionworksdata 0.4.0__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 (30) hide show
  1. ionworksdata-0.4.0/.gitignore +30 -0
  2. ionworksdata-0.4.0/LICENSE.md +21 -0
  3. ionworksdata-0.4.0/PKG-INFO +191 -0
  4. ionworksdata-0.4.0/README.md +146 -0
  5. ionworksdata-0.4.0/ionworksdata/__init__.py +11 -0
  6. ionworksdata-0.4.0/ionworksdata/_version.py +34 -0
  7. ionworksdata-0.4.0/ionworksdata/cycle_metrics.py +290 -0
  8. ionworksdata-0.4.0/ionworksdata/load.py +1350 -0
  9. ionworksdata-0.4.0/ionworksdata/logger.py +66 -0
  10. ionworksdata-0.4.0/ionworksdata/piecewise_linear_timeseries.py +678 -0
  11. ionworksdata-0.4.0/ionworksdata/read/__init__.py +15 -0
  12. ionworksdata-0.4.0/ionworksdata/read/_utils.py +82 -0
  13. ionworksdata-0.4.0/ionworksdata/read/biologic.py +263 -0
  14. ionworksdata-0.4.0/ionworksdata/read/csv.py +248 -0
  15. ionworksdata-0.4.0/ionworksdata/read/detect.py +224 -0
  16. ionworksdata-0.4.0/ionworksdata/read/maccor.py +687 -0
  17. ionworksdata-0.4.0/ionworksdata/read/neware.py +368 -0
  18. ionworksdata-0.4.0/ionworksdata/read/novonix.py +222 -0
  19. ionworksdata-0.4.0/ionworksdata/read/read.py +734 -0
  20. ionworksdata-0.4.0/ionworksdata/read/repower.py +374 -0
  21. ionworksdata-0.4.0/ionworksdata/settings.py +204 -0
  22. ionworksdata-0.4.0/ionworksdata/steps/__init__.py +57 -0
  23. ionworksdata-0.4.0/ionworksdata/steps/_core.py +622 -0
  24. ionworksdata-0.4.0/ionworksdata/steps/_cycling.py +137 -0
  25. ionworksdata-0.4.0/ionworksdata/steps/_eis.py +60 -0
  26. ionworksdata-0.4.0/ionworksdata/steps/_pulse.py +218 -0
  27. ionworksdata-0.4.0/ionworksdata/steps/_validate.py +77 -0
  28. ionworksdata-0.4.0/ionworksdata/transform.py +970 -0
  29. ionworksdata-0.4.0/ionworksdata/util.py +96 -0
  30. ionworksdata-0.4.0/pyproject.toml +43 -0
@@ -0,0 +1,30 @@
1
+ private
2
+ .idea
3
+ *.egg-info
4
+ __pycache__
5
+ .vscode
6
+ .DS_Store
7
+ .venv
8
+ build
9
+ _version.py
10
+ _build
11
+ .coverage
12
+
13
+ # Working directories for testing and development
14
+ workspace
15
+ configs
16
+ output
17
+
18
+ # Large test data files
19
+ tests/test_data/repower2.csv
20
+
21
+ # Figures
22
+ *.png
23
+ *.pdf
24
+ *.jpg
25
+ *.eps
26
+ figures/
27
+
28
+ # Local development/testing scripts
29
+ .local/
30
+ .mypy_cache/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ionworks Technologies Inc
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,191 @@
1
+ Metadata-Version: 2.4
2
+ Name: ionworksdata
3
+ Version: 0.4.0
4
+ Summary: Data processing for Ionworks software.
5
+ License: MIT License
6
+
7
+ Copyright (c) 2026 Ionworks Technologies Inc
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in all
17
+ copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ SOFTWARE.
26
+ License-File: LICENSE.md
27
+ Requires-Python: >=3.10
28
+ Requires-Dist: fastexcel
29
+ Requires-Dist: ionworks-api>=0.1.0
30
+ Requires-Dist: iwutil>=0.3.10
31
+ Requires-Dist: matplotlib
32
+ Requires-Dist: numpy
33
+ Requires-Dist: pandas<3.0.0
34
+ Requires-Dist: polars-lts-cpu>=0.20.0
35
+ Requires-Dist: pybamm
36
+ Requires-Dist: scipy
37
+ Provides-Extra: dev
38
+ Requires-Dist: myst-nb; extra == 'dev'
39
+ Requires-Dist: openpyxl; extra == 'dev'
40
+ Requires-Dist: pydata-sphinx-theme; extra == 'dev'
41
+ Requires-Dist: pytest; extra == 'dev'
42
+ Requires-Dist: pytest-cov; extra == 'dev'
43
+ Requires-Dist: sphinx-design; extra == 'dev'
44
+ Description-Content-Type: text/markdown
45
+
46
+ # Ionworks data
47
+
48
+ Package to extract, transform, and validate battery data for use in Ionworks software.
49
+
50
+ ## Package overview
51
+
52
+ `ionworksdata` is organized into the following modules:
53
+
54
+ - Read: read raw data from files
55
+ - Transform: transform time series data into Ionworks-compatible format
56
+ - Label: label steps for easy processing or visualization
57
+
58
+ ## Data format
59
+
60
+ The data is processed to be compatible with the Ionworks software. Documentation for the data format can be found in the [Knowledge base](https://www.notion.so/ionworks/Ionworks-Data-Data-management-tools-1ce7637d96ae801da6a1eb0e81669cac?pvs=4).
61
+
62
+ # Data processing
63
+
64
+ ## Processing time series data
65
+
66
+ Time series data can be extracted from a cycler file using the `read.time_series` function, which takes the filename and optionally the reader name (e.g. `csv`, `biologic_mpt`, `maccor`, `neware`, `repower`). If the reader is not specified, it will be automatically detected from the file. The function returns a Polars DataFrame.
67
+
68
+ ```python
69
+ # With explicit reader
70
+ data = iwdata.read.time_series("path/to/file.mpt", "biologic_mpt")
71
+
72
+ # With auto-detection (reader is optional)
73
+ data = iwdata.read.time_series("path/to/file.mpt")
74
+ ```
75
+
76
+ The function automatically performs several processing steps and adds columns to the output:
77
+
78
+ ### Data Processing Steps
79
+
80
+ 1. **Reader-specific processing** (varies by reader):
81
+
82
+ - Column renaming to standardized names (e.g., "Voltage" → "Voltage [V]")
83
+ - Numeric coercion (removing thousands separators, converting strings to numbers)
84
+ - Dropping message/error rows (for some readers)
85
+ - Parsing timestamp columns and computing time if needed
86
+ - Converting time units (e.g., hours to seconds)
87
+ - Fixing unsigned current (if current is always positive, negate during charge)
88
+ - Validating and fixing decreasing times (if `time_offset_fix` option is set)
89
+
90
+ 2. **Standard data processing** (applied to all readers):
91
+
92
+ - Removing rows with null values in current or voltage columns
93
+ - Converting numeric columns to float64
94
+ - Resetting time to start at zero
95
+ - Offsetting duplicate timestamps by a small amount (1e-6 seconds) to preserve all data points
96
+ - Setting discharge current to be positive (charge current remains negative)
97
+
98
+ 3. **Post-processing**:
99
+ - Adding `Step count`: Cumulative step count (always present)
100
+ - Adding `Discharge capacity [A.h]`: Discharge capacity in ampere-hours (always present)
101
+ - Adding `Charge capacity [A.h]`: Charge capacity in ampere-hours (always present)
102
+ - Adding `Discharge energy [W.h]`: Discharge energy in watt-hours (always present)
103
+ - Adding `Charge energy [W.h]`: Charge energy in watt-hours (always present)
104
+
105
+ ### Output Columns
106
+
107
+ The output always includes:
108
+
109
+ - `Time [s]`: Time in seconds
110
+ - `Current [A]`: Current in amperes
111
+ - `Voltage [V]`: Voltage in volts
112
+ - `Step count`: Cumulative step count
113
+ - `Discharge capacity [A.h]`: Discharge capacity in ampere-hours
114
+ - `Charge capacity [A.h]`: Charge capacity in ampere-hours
115
+ - `Discharge energy [W.h]`: Discharge energy in watt-hours
116
+ - `Charge energy [W.h]`: Charge energy in watt-hours
117
+
118
+ Optional columns (if present in source data):
119
+
120
+ - `Step from cycler`: Step number from cycler file
121
+ - `Cycle from cycler`: Cycle number from cycler file
122
+ - `Temperature [degC]`: Temperature in degrees Celsius
123
+ - `Frequency [Hz]`: Frequency in hertz
124
+
125
+ For information on the expected and returned columns, see the reader documentation. Additional columns can be added by passing a dictionary to the `extra_column_mappings` argument.
126
+
127
+ ```python
128
+ data = iwdata.read.time_series(
129
+ "path/to/file.mpt", "biologic_mpt", extra_column_mappings={"My new column": "Old column name"}
130
+ )
131
+ ```
132
+
133
+ ## Processing step data
134
+
135
+ Given a processed time series data, the step summary data can be extracted as follows:
136
+
137
+ ```python
138
+ steps = iwdata.label.Steps.get_step_types_for(data)
139
+ ```
140
+
141
+ This function identifies distinct steps within battery cycling data by detecting changes in the "Step count" column (which must be present in the input data). For each identified step, it extracts and calculates relevant metrics (voltage, current, capacity, energy, etc.) and determines the step type.
142
+
143
+ The output always includes:
144
+
145
+ - `Cycle count`: Cumulative cycle count (defaults to 0 if no cycle information is available)
146
+ - `Cycle from cycler`: Cycle number from cycler file (only if provided in the input data)
147
+ - `Discharge capacity [A.h]`: Discharge capacity for the step
148
+ - `Charge capacity [A.h]`: Charge capacity for the step
149
+ - `Discharge energy [W.h]`: Discharge energy for the step
150
+ - `Charge energy [W.h]`: Charge energy for the step
151
+ - `Step from cycler`: Step number from cycler file (only if provided in the input data)
152
+
153
+ **Note:** The `step_column` and `cycle_column` parameters have been removed. The function now always uses "Step count" for step identification and "Cycle from cycler" (if available) for cycle tracking.
154
+
155
+ Alternatively, the time series and step data can be extracted together using the `read.time_series_and_steps` function.
156
+
157
+ ```python
158
+ # With explicit reader
159
+ data, steps = iwdata.read.time_series_and_steps("path/to/file.mpt", "biologic_mpt")
160
+
161
+ # With auto-detection (reader is optional)
162
+ data, steps = iwdata.read.time_series_and_steps("path/to/file.mpt")
163
+ ```
164
+
165
+ ## Labeling steps
166
+
167
+ Steps can be labeled using the classes in the `label` module. For example, the following code labels the steps as cycling and pulse (charge and discharge).
168
+
169
+ ```python
170
+ options = {"cell_metadata": {"Nominal cell capacity [A.h]": 5}}
171
+ steps = iwdata.label.Cycling.steps(steps, options=options)
172
+ for direction in ["charge", "discharge"]:
173
+ options["current direction"] = direction
174
+ steps = iwdata.label.Pulse.steps(steps, options=options)
175
+ ```
176
+
177
+ ## Measurement details
178
+
179
+ The function `ionworksdata.read.measurement_details` can be used to return a `measurement_details` dictionary, which has keys "measurement", "time_series", and "steps". You need to first create the measurement dictionary (which contains details about the test, such as its name), and then pass it to the function along with the reader name and filename, and any additional arguments. The function will return the updated measurement details dictionary, which includes information extracted from the file, such as the start time, and the cycler name. This function also automatically labels the steps with some sensible defaults (custom labels can be added by passing a list of dictionaries to the `labels` argument).
180
+
181
+ ```python3
182
+ measurement_details = iwdata.read.measurement_details(
183
+ "path/to/file.mpt",
184
+ measurement,
185
+ "biologic_mpt",
186
+ options={"cell_metadata": {"Nominal cell capacity [A.h]": 5}},
187
+ )
188
+ measurement = measurement_details["measurement"]
189
+ time_series = measurement_details["time_series"]
190
+ steps = measurement_details["steps"]
191
+ ```
@@ -0,0 +1,146 @@
1
+ # Ionworks data
2
+
3
+ Package to extract, transform, and validate battery data for use in Ionworks software.
4
+
5
+ ## Package overview
6
+
7
+ `ionworksdata` is organized into the following modules:
8
+
9
+ - Read: read raw data from files
10
+ - Transform: transform time series data into Ionworks-compatible format
11
+ - Label: label steps for easy processing or visualization
12
+
13
+ ## Data format
14
+
15
+ The data is processed to be compatible with the Ionworks software. Documentation for the data format can be found in the [Knowledge base](https://www.notion.so/ionworks/Ionworks-Data-Data-management-tools-1ce7637d96ae801da6a1eb0e81669cac?pvs=4).
16
+
17
+ # Data processing
18
+
19
+ ## Processing time series data
20
+
21
+ Time series data can be extracted from a cycler file using the `read.time_series` function, which takes the filename and optionally the reader name (e.g. `csv`, `biologic_mpt`, `maccor`, `neware`, `repower`). If the reader is not specified, it will be automatically detected from the file. The function returns a Polars DataFrame.
22
+
23
+ ```python
24
+ # With explicit reader
25
+ data = iwdata.read.time_series("path/to/file.mpt", "biologic_mpt")
26
+
27
+ # With auto-detection (reader is optional)
28
+ data = iwdata.read.time_series("path/to/file.mpt")
29
+ ```
30
+
31
+ The function automatically performs several processing steps and adds columns to the output:
32
+
33
+ ### Data Processing Steps
34
+
35
+ 1. **Reader-specific processing** (varies by reader):
36
+
37
+ - Column renaming to standardized names (e.g., "Voltage" → "Voltage [V]")
38
+ - Numeric coercion (removing thousands separators, converting strings to numbers)
39
+ - Dropping message/error rows (for some readers)
40
+ - Parsing timestamp columns and computing time if needed
41
+ - Converting time units (e.g., hours to seconds)
42
+ - Fixing unsigned current (if current is always positive, negate during charge)
43
+ - Validating and fixing decreasing times (if `time_offset_fix` option is set)
44
+
45
+ 2. **Standard data processing** (applied to all readers):
46
+
47
+ - Removing rows with null values in current or voltage columns
48
+ - Converting numeric columns to float64
49
+ - Resetting time to start at zero
50
+ - Offsetting duplicate timestamps by a small amount (1e-6 seconds) to preserve all data points
51
+ - Setting discharge current to be positive (charge current remains negative)
52
+
53
+ 3. **Post-processing**:
54
+ - Adding `Step count`: Cumulative step count (always present)
55
+ - Adding `Discharge capacity [A.h]`: Discharge capacity in ampere-hours (always present)
56
+ - Adding `Charge capacity [A.h]`: Charge capacity in ampere-hours (always present)
57
+ - Adding `Discharge energy [W.h]`: Discharge energy in watt-hours (always present)
58
+ - Adding `Charge energy [W.h]`: Charge energy in watt-hours (always present)
59
+
60
+ ### Output Columns
61
+
62
+ The output always includes:
63
+
64
+ - `Time [s]`: Time in seconds
65
+ - `Current [A]`: Current in amperes
66
+ - `Voltage [V]`: Voltage in volts
67
+ - `Step count`: Cumulative step count
68
+ - `Discharge capacity [A.h]`: Discharge capacity in ampere-hours
69
+ - `Charge capacity [A.h]`: Charge capacity in ampere-hours
70
+ - `Discharge energy [W.h]`: Discharge energy in watt-hours
71
+ - `Charge energy [W.h]`: Charge energy in watt-hours
72
+
73
+ Optional columns (if present in source data):
74
+
75
+ - `Step from cycler`: Step number from cycler file
76
+ - `Cycle from cycler`: Cycle number from cycler file
77
+ - `Temperature [degC]`: Temperature in degrees Celsius
78
+ - `Frequency [Hz]`: Frequency in hertz
79
+
80
+ For information on the expected and returned columns, see the reader documentation. Additional columns can be added by passing a dictionary to the `extra_column_mappings` argument.
81
+
82
+ ```python
83
+ data = iwdata.read.time_series(
84
+ "path/to/file.mpt", "biologic_mpt", extra_column_mappings={"My new column": "Old column name"}
85
+ )
86
+ ```
87
+
88
+ ## Processing step data
89
+
90
+ Given a processed time series data, the step summary data can be extracted as follows:
91
+
92
+ ```python
93
+ steps = iwdata.label.Steps.get_step_types_for(data)
94
+ ```
95
+
96
+ This function identifies distinct steps within battery cycling data by detecting changes in the "Step count" column (which must be present in the input data). For each identified step, it extracts and calculates relevant metrics (voltage, current, capacity, energy, etc.) and determines the step type.
97
+
98
+ The output always includes:
99
+
100
+ - `Cycle count`: Cumulative cycle count (defaults to 0 if no cycle information is available)
101
+ - `Cycle from cycler`: Cycle number from cycler file (only if provided in the input data)
102
+ - `Discharge capacity [A.h]`: Discharge capacity for the step
103
+ - `Charge capacity [A.h]`: Charge capacity for the step
104
+ - `Discharge energy [W.h]`: Discharge energy for the step
105
+ - `Charge energy [W.h]`: Charge energy for the step
106
+ - `Step from cycler`: Step number from cycler file (only if provided in the input data)
107
+
108
+ **Note:** The `step_column` and `cycle_column` parameters have been removed. The function now always uses "Step count" for step identification and "Cycle from cycler" (if available) for cycle tracking.
109
+
110
+ Alternatively, the time series and step data can be extracted together using the `read.time_series_and_steps` function.
111
+
112
+ ```python
113
+ # With explicit reader
114
+ data, steps = iwdata.read.time_series_and_steps("path/to/file.mpt", "biologic_mpt")
115
+
116
+ # With auto-detection (reader is optional)
117
+ data, steps = iwdata.read.time_series_and_steps("path/to/file.mpt")
118
+ ```
119
+
120
+ ## Labeling steps
121
+
122
+ Steps can be labeled using the classes in the `label` module. For example, the following code labels the steps as cycling and pulse (charge and discharge).
123
+
124
+ ```python
125
+ options = {"cell_metadata": {"Nominal cell capacity [A.h]": 5}}
126
+ steps = iwdata.label.Cycling.steps(steps, options=options)
127
+ for direction in ["charge", "discharge"]:
128
+ options["current direction"] = direction
129
+ steps = iwdata.label.Pulse.steps(steps, options=options)
130
+ ```
131
+
132
+ ## Measurement details
133
+
134
+ The function `ionworksdata.read.measurement_details` can be used to return a `measurement_details` dictionary, which has keys "measurement", "time_series", and "steps". You need to first create the measurement dictionary (which contains details about the test, such as its name), and then pass it to the function along with the reader name and filename, and any additional arguments. The function will return the updated measurement details dictionary, which includes information extracted from the file, such as the start time, and the cycler name. This function also automatically labels the steps with some sensible defaults (custom labels can be added by passing a list of dictionaries to the `labels` argument).
135
+
136
+ ```python3
137
+ measurement_details = iwdata.read.measurement_details(
138
+ "path/to/file.mpt",
139
+ measurement,
140
+ "biologic_mpt",
141
+ options={"cell_metadata": {"Nominal cell capacity [A.h]": 5}},
142
+ )
143
+ measurement = measurement_details["measurement"]
144
+ time_series = measurement_details["time_series"]
145
+ steps = measurement_details["steps"]
146
+ ```
@@ -0,0 +1,11 @@
1
+ from . import steps, transform, util, read, cycle_metrics
2
+ from .load import DataLoader, OCPDataLoader
3
+ from .piecewise_linear_timeseries import PiecewiseLinearTimeseries
4
+ from .logger import logger, set_logging_level, get_new_logger
5
+ from .settings import get_settings, update_settings, reset_settings
6
+
7
+ try:
8
+ from ionworksdata._version import __version__
9
+ except ModuleNotFoundError:
10
+ # Fallback for when the library is a submodule
11
+ __version__ = "0.0.0"
@@ -0,0 +1,34 @@
1
+ # file generated by setuptools-scm
2
+ # don't change, don't track in version control
3
+
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
12
+
13
+ TYPE_CHECKING = False
14
+ if TYPE_CHECKING:
15
+ from typing import Tuple
16
+ from typing import Union
17
+
18
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
20
+ else:
21
+ VERSION_TUPLE = object
22
+ COMMIT_ID = object
23
+
24
+ version: str
25
+ __version__: str
26
+ __version_tuple__: VERSION_TUPLE
27
+ version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
30
+
31
+ __version__ = version = '0.4.0'
32
+ __version_tuple__ = version_tuple = (0, 4, 0)
33
+
34
+ __commit_id__ = commit_id = None