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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions docs/source/version.7_0.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
**yadg** version next
`````````````````````

..
.. image:: https://img.shields.io/static/v1?label=yadg&message=v6.2&color=blue&logo=github
:target: https://github.com/PeterKraus/yadg/tree/6.2
.. image:: https://img.shields.io/static/v1?label=yadg&message=v6.2&color=blue&logo=pypi
:target: https://pypi.org/project/yadg/6.2/
.. image:: https://img.shields.io/static/v1?label=release%20date&message=2025-08-20&color=red&logo=pypi


Developed in the `ConCat Lab <https://tu.berlin/en/concat>`_ at Technische Universität Berlin (Berlin, DE).

New features in ``yadg-next`` are:

- Support for Battery Capacity Determination (BCD) technique in :mod:`yadg.extractors.eclab.mpr` and :mod:`yadg.extractors.eclab.mpt`. Note that the ``Set I/C`` parameters in BCD are renamed to ``Set I/C 1`` and ``Set I/C 2`` in both :mod:`~yadg.extractors.eclab.mpr` and :mod:`~yadg.extractors.eclab.mpt` files. Thank you to `Joachim Laviolette <https://github.com/JL-CEA>`_ for providing test files.

Breaking changes in ``yadg-next`` are:

Bug fixes in ``yadg-next`` include:

- The parameter ``Set I/C`` in :mod:`yadg.extractors.eclab.mpr` files should be ``C / N`` when set to 1, not ``C``.

2 changes: 2 additions & 0 deletions docs/source/version.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
**yadg** version history
------------------------

.. include:: version.7_0.rst

.. include:: version.6_2.rst

.. include:: version.6_1.rst
Expand Down
17 changes: 12 additions & 5 deletions src/yadg/extractors/eclab/mpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@
flag_columns,
data_columns,
conflict_columns,
technique_dependent_ids,
log_dtypes,
extdev_dtypes,
)
Expand Down Expand Up @@ -279,10 +280,12 @@ def process_settings(data: bytes, minver: str) -> tuple[dict, list]:
params = {k: [d[k] for d in params] for k in params[0]}
else:
params = {}
return settings, params
return technique, settings, params


def parse_columns(column_ids: list[int]) -> tuple[list, list, list, dict]:
def parse_columns(
column_ids: list[int], technique: str
) -> tuple[list, list, list, dict]:
"""Puts together column info from a list of data column IDs.

Note
Expand Down Expand Up @@ -319,6 +322,8 @@ def parse_columns(column_ids: list[int]) -> tuple[list, list, list, dict]:
units.append(None)
elif idd in data_columns and idd not in conflict_columns:
dtype, name, unit = data_columns[idd]
if idd in technique_dependent_ids:
name = technique_dependent_ids[idd].get(technique, name)
if name in names:
logger.error(
"Column ID %d (%d) is a duplicate of '%s' with unit '%s'. "
Expand Down Expand Up @@ -383,6 +388,7 @@ def process_data(
Eranges: list[float],
Iranges: list[float],
controls: list[str],
technique: str,
):
"""Processes the contents of data modules.

Expand Down Expand Up @@ -411,7 +417,7 @@ def process_data(
column_ids = np.frombuffer(data, offset=0x005, dtype="<u2", count=n_columns)
logger.debug("Found %d columns with IDs: %s", n_columns, column_ids)
# Length of each datapoint depends on number and IDs of columns.
namelist, dtypelist, unitlist, flaglist = parse_columns(column_ids)
namelist, dtypelist, unitlist, flaglist = parse_columns(column_ids, technique)
units = {k: v for k, v in zip(namelist, unitlist) if v is not None}
data_dtype = np.dtype(list(zip(namelist, dtypelist)))
# Depending on module version, datapoints start at different offsets.
Expand Down Expand Up @@ -554,6 +560,7 @@ def process_modules(contents: bytes) -> tuple[dict, list, list, dict, dict]:
"""
modules = contents.split(b"MODULE")[1:]
settings = log = loop = ext = None
technique = None
for module in modules:
for mhd in module_header_dtypes:
try:
Expand Down Expand Up @@ -584,7 +591,7 @@ def process_modules(contents: bytes) -> tuple[dict, list, list, dict, dict]:
logger.debug("Read '%s' with version '%s' ('%s')", name, version, minver)
module_data = module[mhd.itemsize :]
if name == "VMP Set":
settings, params = process_settings(module_data, minver)
technique, settings, params = process_settings(module_data, minver)

E_range_max = params.get("E range max (V)", [float("inf")])
E_range_min = params.get("E range min (V)", [float("-inf")])
Expand All @@ -597,7 +604,7 @@ def process_modules(contents: bytes) -> tuple[dict, list, list, dict, dict]:
else:
ctrls = [None] * len(Iranges)
elif name == "VMP data":
ds = process_data(module_data, version, Eranges, Iranges, ctrls)
ds = process_data(module_data, version, Eranges, Iranges, ctrls, technique)
elif name == "VMP LOG":
log = process_log(module_data)
elif name == "VMP loop":
Expand Down
6 changes: 6 additions & 0 deletions src/yadg/extractors/eclab/mpr_columns.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@
},
}

technique_dependent_ids = {
6: {
"BCD": "Ecell",
}
}

# Relates the offset in log data to the corresponding dtype and name.
# NOTE: The safety limits are maybe at 0x200?
# NOTE: The log also seems to contain the settings again. These are left
Expand Down
9 changes: 7 additions & 2 deletions src/yadg/extractors/eclab/mpt.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,15 @@ def process_params(technique: str, lines: list[str], locale: str) -> dict[str, A
name = f"{prev} {items[0]}"
else:
name = items[0]
if name not in params:
if technique == "Battery Capacity Determination" and name == "Set I/C":
if "Set I/C 1" in params:
params["Set I/C 2"] = vals
else:
params["Set I/C 1"] = vals
elif name not in params:
params[name] = vals
else:
raise RuntimeError(f"Trying to assing same parameter {items[0]!r} twice.")
raise RuntimeError(f"Trying to assign same parameter {items[0]!r} twice.")
prev = name
return params

Expand Down
67 changes: 61 additions & 6 deletions src/yadg/extractors/eclab/techniques.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- MP - Modular Potentio
- CoV - Constant Voltage
- CoC - Constant Current
- BCD - Battery Capacity Determination

The module also implements resolution determination for parameters of techniques,
in :func:`get_resolution`.
Expand Down Expand Up @@ -1318,6 +1319,52 @@
)
]

# ~~~~~~~~~~~~~ Battery Capacity Determination ~~~~~~~~~~~~~
_bcd_params_dtypes = [
(
np.dtype(
[
("Set I/C 1", "|u1"),
("Is1", "<f4"),
("unit Is1", "|u1"),
("N1", "<f4"),
("I1 sign", "|u1"),
("t1 (h:m:s)", "<f4"),
("EM1 (V)", "<f4"),
("EM1 vs.", "|u1"),
("EM2 (V)", "<f4"),
("EM2 vs.", "|u1"),
("dE1 (mV)", "<f4"),
("dt1 (s)", "<f4"),
("Hold NONE/EM1/EM2", "|u1"),
("tM (h:m:s)", "<f4"),
("Set I limit", "|u1"),
("Im", "<f4"),
("unit Im", "|u1"),
("Nl", "<f4"),
("I Range", "|u1"),
("Bandwidth", "|u1"),
("E range min (V)", "<f4"),
("E range max (V)", "<f4"),
("tR (h:m:s)", "<f4"),
("dER/dt (mV/h)", "<f4"),
("dER (mV)", "<f4"),
("dtR (s)", "<f4"),
("Charge/Discharge", "|u1"),
("Set I/C 2", "|u1"),
("Is2", "<f4"),
("unit Is2", "|u1"),
("N2", "<f4"),
("I2 sign", "|u1"),
("t2 (h:m:s)", "<f4"),
("Return Ei", "|u1"),
("use C", "|u1"),
]
),
{"10.40"},
)
]


# Maps the technique byte to its corresponding dtype.
technique_params_dtypes = {
Expand All @@ -1338,6 +1385,7 @@
0x76: ("coC", _coc_params_dtypes),
0x77: ("GCPL", _gcpl_params_dtypes),
0x7F: ("MB", _mb_params_dtypes),
0x88: ("BCD", _bcd_params_dtypes),
}

unit_map = {
Expand Down Expand Up @@ -1371,6 +1419,12 @@
("Ref", 4),
)

ic_map = (
("I", 0),
("C / N", 1),
("C x N", 2),
)

param_map = {
"I Range": (
("10 mA", 1, 1e-2),
Expand Down Expand Up @@ -1582,6 +1636,8 @@
"unit Imax": unit_map["I"],
"unit Imin": unit_map["I"],
"unit Is": unit_map["I"],
"unit Is1": unit_map["I"],
"unit Is2": unit_map["I"],
"unit Is vs.": unit_map["vs."],
"E (V) vs.": vs_map,
"E1 (V) vs.": vs_map,
Expand All @@ -1590,12 +1646,11 @@
"Ei (V) vs.": vs_map,
"EL (V) vs.": vs_map,
"Es (V) vs.": vs_map,
"Set I/C": (
("I", 0),
("C", 1),
("C x N", 2),
("C / N", 3),
),
"EM1 vs.": vs_map,
"EM2 vs.": vs_map,
"Set I/C": ic_map,
"Set I/C 1": ic_map,
"Set I/C 2": ic_map,
"Apply I/C": (
("I", 0),
("C", 1),
Expand Down
1 change: 1 addition & 0 deletions tests/test_x_eclab.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def compare_params(left, right):
@pytest.mark.parametrize(
"froot, locale",
[
("bcd.issue_241", "en_US"),
("ca", "en_US"),
("ca.issue_134", "en_US"),
("ca.issue_149", "de_DE"),
Expand Down
Binary file added tests/test_x_eclab/bcd.issue_241.mpr
Binary file not shown.
Binary file added tests/test_x_eclab/bcd.issue_241.mpr.pkl
Binary file not shown.
Loading
Loading