# -*- coding: utf-8 -*- # SPDX-FileCopyrightText: 2013-2020 Christopher Kerr # # SPDX-License-Identifier: GPL-3.0-or-later import os.path import re from datetime import date, datetime import numpy as np from numpy.testing import assert_array_almost_equal, assert_array_equal, assert_allclose import pytest from galvani import BioLogic, MPTfile, MPRfile from galvani.BioLogic import MPTfileCSV # not exported def test_open_MPT(testdata_dir): mpt1, comments = MPTfile(os.path.join(testdata_dir, "bio_logic1.mpt")) assert comments == [] assert mpt1.dtype.names == ( "mode", "ox/red", "error", "control changes", "Ns changes", "counter inc.", "time/s", "control/V/mA", "Ewe/V", "dQ/mA.h", "P/W", "I/mA", "(Q-Qo)/mA.h", "x", ) def test_open_MPT_fails_for_bad_file(testdata_dir): with pytest.raises(ValueError, match="Bad first line"): MPTfile(os.path.join(testdata_dir, "bio_logic1.mpr")) def test_open_MPT_csv(testdata_dir): mpt1, comments = MPTfileCSV(os.path.join(testdata_dir, "bio_logic1.mpt")) assert comments == [] assert mpt1.fieldnames == [ "mode", "ox/red", "error", "control changes", "Ns changes", "counter inc.", "time/s", "control/V/mA", "Ewe/V", "dq/mA.h", "P/W", "/mA", "(Q-Qo)/mA.h", "x", ] def test_open_MPT_csv_fails_for_bad_file(testdata_dir): with pytest.raises((ValueError, UnicodeDecodeError)): MPTfileCSV(os.path.join(testdata_dir, "bio_logic1.mpr")) def test_colID_map_uniqueness(): """Check some uniqueness properties of the VMPdata_colID_xyz maps.""" field_colIDs = set(BioLogic.VMPdata_colID_dtype_map.keys()) flag_colIDs = set(BioLogic.VMPdata_colID_flag_map.keys()) field_names = [v[0] for v in BioLogic.VMPdata_colID_dtype_map.values()] flag_names = [v[0] for v in BioLogic.VMPdata_colID_flag_map.values()] assert not field_colIDs.intersection(flag_colIDs) # 'I/mA' and 'dQ/mA.h' are duplicated # assert len(set(field_names)) == len(field_names) assert len(set(flag_names)) == len(flag_names) assert not set(field_names).intersection(flag_names) @pytest.mark.parametrize( "colIDs, expected", [ ([1, 2, 3], [("flags", "u1")]), ([4, 6], [("time/s", "/V": assert_allclose( mpr.data[fieldname], mpt["Ewe/V"].astype(mpr.data[fieldname].dtype), ) elif fieldname == "/mA": assert_allclose( mpr.data[fieldname], mpt["I/mA"].astype(mpr.data[fieldname].dtype), ) elif fieldname == "dq/mA.h": assert_allclose( mpr.data[fieldname], mpt["dQ/mA.h"].astype(mpr.data[fieldname].dtype), ) else: assert_allclose( mpr.data[fieldname], mpt[fieldname].astype(mpr.data[fieldname].dtype), ) def assert_field_exact(fieldname): if fieldname in mpr.dtype.fields: assert_array_equal(mpr.data[fieldname], mpt[fieldname]) for key in mpr.flags_dict.keys(): assert_array_equal(mpr.get_flag(key), mpt[key]) for d in mpr.dtype.descr[1:]: assert_field_matches(d[0]) try: assert timestamp_from_comments(comments) == mpr.timestamp.replace(microsecond=0) except AttributeError: pass @pytest.mark.parametrize( "basename", [ "bio_logic1", "bio_logic2", # No bio_logic3.mpt file "bio_logic4", # bio_logic5 and bio_logic6 are special cases "CV_C01", "121_CA_455nm_6V_30min_C01", "020-formation_CB5", ], ) def test_MPR_matches_MPT(testdata_dir, basename): """Check the MPR parser against the MPT parser. Load a binary .mpr file and a text .mpt file which should contain exactly the same data. Check that the loaded data actually match. """ binpath = os.path.join(testdata_dir, basename + ".mpr") txtpath = os.path.join(testdata_dir, basename + ".mpt") mpr = MPRfile(binpath) mpt, comments = MPTfile(txtpath, encoding="latin1") assert_MPR_matches_MPT(mpr, mpt, comments) def test_MPR5_matches_MPT5(testdata_dir): mpr = MPRfile(os.path.join(testdata_dir, "bio_logic5.mpr")) mpt, comments = MPTfile( ( re.sub(b"\tXXX\t", b"\t0\t", line) for line in open(os.path.join(testdata_dir, "bio_logic5.mpt"), mode="rb") ) ) assert_MPR_matches_MPT(mpr, mpt, comments) def test_MPR6_matches_MPT6(testdata_dir): mpr = MPRfile(os.path.join(testdata_dir, "bio_logic6.mpr")) mpt, comments = MPTfile(os.path.join(testdata_dir, "bio_logic6.mpt")) mpr.data = mpr.data[:958] # .mpt file is incomplete assert_MPR_matches_MPT(mpr, mpt, comments) @pytest.mark.parametrize( "basename_v1150", ["v1150_CA", "v1150_CP", "v1150_GCPL", "v1150_GEIS", "v1150_MB", "v1150_OCV", "v1150_PEIS"], ) def test_MPR_matches_MPT_v1150(testdata_dir, basename_v1150): """Check the MPR parser against the MPT parser. Load a binary .mpr file and a text .mpt file which should contain exactly the same data. Check that the loaded data actually match. """ binpath = os.path.join(testdata_dir, "v1150", basename_v1150 + ".mpr") txtpath = os.path.join(testdata_dir, "v1150", basename_v1150 + ".mpt") mpr = MPRfile(binpath) mpt, comments = MPTfile(txtpath, encoding="latin1") assert_MPR_matches_MPT_v2(mpr, mpt, comments) def test_loop_from_file(testdata_dir): """Check if the loop_index is correctly extracted from the _LOOP.txt file """ mpr = MPRfile(os.path.join(testdata_dir, "running", "running_OCV.mpr")) assert mpr.loop_index is not None, "No loop_index found" assert len(mpr.loop_index) == 4, "loop_index is not the right size" assert_array_equal(mpr.loop_index, [0, 4, 8, 11], "loop_index values are wrong") def test_timestamp_from_file(testdata_dir): """Check if the loop_index is correctly extracted from the _LOOP.txt file """ mpr = MPRfile(os.path.join(testdata_dir, "running", "running_OCV.mpr")) assert hasattr(mpr, "timestamp"), "No timestamp found" assert mpr.timestamp.timestamp() == pytest.approx(1707299985.908), "timestamp value is wrong"