Skip to content

Commit 24873bd

Browse files
committed
Update readers for compatibility with bitrode data
1 parent cbb6b46 commit 24873bd

1 file changed

Lines changed: 33 additions & 21 deletions

File tree

src/ampworks/_core/_read.py

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from __future__ import annotations
22

3+
import csv
4+
35
from warnings import warn
46
from typing import Sequence, TYPE_CHECKING
57

@@ -25,7 +27,7 @@ def format_alias(names: Sequence[str], units: Sequence[str]) -> list[str]:
2527
return aliases
2628

2729

28-
t_names = ['t', 'time', 'testtime']
30+
t_names = ['t', 'time', 'testtime', 'totaltime']
2931
t_units = ['s', 'sec', 'seconds', 'min', 'minutes', 'h', 'hrs', 'hours']
3032

3133
i_names = ['i', 'amperage', 'current']
@@ -34,10 +36,10 @@ def format_alias(names: Sequence[str], units: Sequence[str]) -> list[str]:
3436
v_names = ['voltage', 'potential', 'ecell']
3537
v_units = ['v', 'volts']
3638

37-
q_names = ['capacity']
39+
q_names = ['capacity', 'amphours']
3840
q_units = ['ah', 'ahr', 'amphr', 'mah', 'mahr', 'mamphr']
3941

40-
e_names = ['energy']
42+
e_names = ['energy', 'watthours']
4143
e_units = ['wh', 'whr', 'watthr']
4244

4345
HEADER_ALIASES = {
@@ -47,20 +49,20 @@ def format_alias(names: Sequence[str], units: Sequence[str]) -> list[str]:
4749

4850
'Cycle': ['cycle', 'cyc', 'cycleindex', 'cyclenumber', 'cyclec', 'cyclep'],
4951
'Step': ['step', 'ns', 'stepindex'],
50-
'State': ['state', 'md'],
52+
'State': ['state', 'md', 'mode'],
5153

5254
'Ah': format_alias(q_names, q_units),
5355
'Wh': format_alias(e_names, e_units),
5456

55-
'DateTime': ['datetime', 'dpttime'],
57+
'DateTime': ['datetime', 'dpttime', 'realtime'],
5658
}
5759

5860
REQUIRED_HEADERS = ['Seconds', 'Amps', 'Volts']
5961

6062

6163
# Remove unnecessary characters from header strings
6264
def strip_chars(string: str) -> str:
63-
transmap = str.maketrans('(/', '..', ' _-#<>)')
65+
transmap = str.maketrans('(/,', '...', ' _-#<>)')
6466
return string.lower().translate(transmap)
6567

6668

@@ -124,6 +126,9 @@ def standardize_headers(data: pd.DataFrame) -> Dataset:
124126

125127
# Guarantee sign 'Amps' sign convention (+ charge, - discharge)
126128
if 'State' in df.columns:
129+
rename_bitrode = {'REST': 'R', 'DCHG': 'D', 'CHRG': 'C'}
130+
df['State'] = df['State'].replace(rename_bitrode)
131+
127132
df['Amps'] = df['Amps'].astype(float)
128133
df['State'] = df['State'].astype(str)
129134

@@ -152,13 +157,14 @@ def standardize_headers(data: pd.DataFrame) -> Dataset:
152157
# Convert types
153158
if std_header in df.columns:
154159
if std_header in ['State', 'DateTime']:
155-
df[std_header] = df[std_header].astype(str)
160+
df[std_header] = df[std_header].astype('string')
156161
elif std_header in ['Cycle', 'Step']:
157-
df[std_header] = df[std_header].astype(int)
162+
df[std_header] = df[std_header].astype('Int64')
158163
else:
159164
df[std_header] = df[std_header].replace('#', '', regex=True)
160165
df[std_header] = df[std_header].replace(',', '', regex=True)
161-
df[std_header] = df[std_header].astype(float)
166+
167+
df[std_header] = pd.to_numeric(df[std_header], errors='coerce')
162168
else:
163169
missing.append(std_header)
164170

@@ -172,16 +178,19 @@ def read_table(filepath: PathLike) -> Dataset:
172178
"""Read tab-delimited file."""
173179
from ampworks import Dataset
174180

175-
with open(filepath, encoding='utf-8') as datafile:
181+
options = {'separator': '\t', 'skip_rows': 0, 'ignore_errors': True}
182+
with open(filepath, encoding='latin1') as datafile:
183+
reader = csv.reader(datafile, delimiter='\t')
176184

177-
skiprows, found_header = 0, False
178-
for idx, line in enumerate(datafile):
179-
if header_matches(line.rstrip('\n').split('\t'), REQUIRED_HEADERS):
180-
skiprows, found_header = idx, True
185+
found_header = False
186+
for idx, line in enumerate(reader):
187+
if header_matches(line, REQUIRED_HEADERS):
188+
options['skip_rows'] = idx
189+
found_header = True
181190
break
182191

183192
if found_header:
184-
df = pl.read_csv(filepath, separator='\t', skip_rows=skiprows)
193+
df = pl.read_csv(filepath, **options)
185194
return standardize_headers(df.to_pandas())
186195

187196
return Dataset()
@@ -286,16 +295,19 @@ def read_csv(filepath: PathLike) -> Dataset:
286295
"""Read csv file."""
287296
from ampworks import Dataset
288297

289-
with open(filepath, encoding='utf-8') as datafile:
298+
options = {'separator': ',', 'skip_rows': 0, 'ignore_errors': True}
299+
with open(filepath, encoding='latin1') as datafile:
300+
reader = csv.reader(datafile, delimiter=',')
290301

291-
skiprows, found_header = 0, False
292-
for idx, line in enumerate(datafile):
293-
if header_matches(line.rstrip('\n').split(','), REQUIRED_HEADERS):
294-
skiprows, found_header = idx, True
302+
found_header = False
303+
for idx, line in enumerate(reader):
304+
if header_matches(line, REQUIRED_HEADERS):
305+
options['skip_rows'] = idx
306+
found_header = True
295307
break
296308

297309
if found_header:
298-
df = pl.read_csv(filepath, separator=',', skip_rows=skiprows)
310+
df = pl.read_csv(filepath, **options)
299311
return standardize_headers(df.to_pandas())
300312

301313
return Dataset()

0 commit comments

Comments
 (0)