import pandas as pd
import numpy as np
from datetime import datetime
from maccorcyclingdata.schedules import sort_scheduler_steps
[docs]def validation_check_time_interval(validation_df, df, time_interval, i, cell_id):
"""
This function will validate the testdata to make sure data was collected regularly at the correct time interval.
Parameters
-----------
validation_df : pandas dataframe
The validation dataframe where any errors will be recorded
df : pandas dataframe
The testdata dataframe (from the import_maccor_data or import_multiple_csv_data functions)
time_interval : integer
The time interval between data point. How often data should be collected.
i : integer
An integer of the index where you want to validate
cell_id : integer
The cell id of the testdata
Returns
--------
validation_df : pandas dataframe
The validation dataframe with any errors listed
Examples
---------
>>> import maccorcyclingdata.validate as validate
>>> validation_df = validate.validation_check_time_interval(validation_df, df, 10, i, 1)
>>> validation_df
"""
if not isinstance(validation_df, pd.DataFrame):
raise TypeError('validation_df input must be a pandas dataframe')
if not len(validation_df.columns) == 5:
raise IndexError("validation dataframe must have 5 columns")
if (validation_df.columns.tolist() != ["time", "run", "cell_num", "row_number", "error"]):
raise IndexError("validation dataframe must have these columns: ['time', 'run', 'cell_num', 'row_number', 'error']")
if not isinstance(df, pd.DataFrame):
raise TypeError('df input must be a pandas dataframe')
if not len(df.columns) == 10:
raise IndexError("testdata dataframe must have 10 columns")
if (df.columns.tolist() != ['cyc', 'step', 'test_time_s', 'step_time_s', 'capacity_mah', 'current_ma', 'voltage_v', 'dpt_time', 'thermocouple_temp_c', 'ev_temp']):
raise IndexError("Pandas dataframe must have these columns: ['cyc', 'step', 'test_time_s', 'step_time_s', 'capacity_mah', 'current_ma', 'voltage_v', 'dpt_time', 'thermocouple_temp_c', 'ev_temp']")
if not isinstance(time_interval, int):
raise TypeError("time_interval must be an integer")
if not isinstance(i, int):
raise TypeError("i must be an integer")
if not isinstance(cell_id, int):
raise TypeError("cell_id must be an integer")
if df['test_time_s'][i] > (df['test_time_s'][i-1] + time_interval):
validation_df = validation_df.append({'time':datetime.now().strftime("%d/%m/%Y %H:%M:%S"), 'run': 'in progress', 'cell_num': cell_id, 'row_number': i, 'error': ('time interval anomaly - more than ' + str(time_interval) + ' seconds has passed since the last collected data')}, ignore_index=True)
return validation_df
[docs]def validation_check_temp_interval(validation_df, df, temp_interval, i, cell_id):
"""
This function will validate the testdata to make sure the temperature does not fluctuate suddenly.
Parameters
-----------
validation_df : pandas dataframe
The validation dataframe where any errors will be recorded
df : pandas dataframe
The testdata dataframe (from the import_maccor_data or import_multiple_csv_data functions)
temp_interval : integer
The maximum temperature change allowed between two data points.
i : integer
An integer of the index where you want to validate
cell_id : integer
The cell id of the testdata
Returns
--------
validation_df : pandas dataframe
The validation dataframe with any errors listed
Examples
---------
>>> import maccorcyclingdata.validate as validate
>>> validation_df = validate.validation_check_temp_interval(validation_df, df, 10, i, 1)
>>> validation_df
"""
if not isinstance(validation_df, pd.DataFrame):
raise TypeError('validation_df input must be a pandas dataframe')
if not len(validation_df.columns) == 5:
raise IndexError("validation dataframe must have 5 columns")
if (validation_df.columns.tolist() != ["time", "run", "cell_num", "row_number", "error"]):
raise IndexError("validation dataframe must have these columns: ['time', 'run', 'cell_num', 'row_number', 'error']")
if not isinstance(df, pd.DataFrame):
raise TypeError('df input must be a pandas dataframe')
if not len(df.columns) == 10:
raise IndexError("testdata dataframe must have 10 columns")
if (df.columns.tolist() != ['cyc', 'step', 'test_time_s', 'step_time_s', 'capacity_mah', 'current_ma', 'voltage_v', 'dpt_time', 'thermocouple_temp_c', 'ev_temp']):
raise IndexError("Pandas dataframe must have these columns: ['cyc', 'step', 'test_time_s', 'step_time_s', 'capacity_mah', 'current_ma', 'voltage_v', 'dpt_time', 'thermocouple_temp_c', 'ev_temp']")
if not isinstance(temp_interval, int):
raise TypeError("temp_interval must be an integer")
if not isinstance(i, int):
raise TypeError("i must be an integer")
if not isinstance(cell_id, int):
raise TypeError("cell_id must be an integer")
if (df['thermocouple_temp_c'][i] >= (df['thermocouple_temp_c'][i-1] + temp_interval)) or (df['thermocouple_temp_c'][i] <= (df['thermocouple_temp_c'][i-1] - temp_interval)):
validation_df = validation_df.append({'time':datetime.now().strftime("%d/%m/%Y %H:%M:%S"), 'run': 'in progress', 'cell_num': cell_id, 'row_number': i, 'error': 'temp interval anomaly - jump in temperature (more than ' + str(temp_interval) + ' degrees)'}, ignore_index=True)
return validation_df
[docs]def validation_check_advanced_cycle(validation_df, df, i, cell_id):
"""
This function will validate the testdata against the advance cycle steps by making sure the cycle advances
Parameters
-----------
validation_df : pandas dataframe
The validation dataframe where any errors will be recorded
df : pandas dataframe
The testdata dataframe (from the import_maccor_data or import_multiple_csv_data functions)
i : integer
An integer of the index where you want to validate
cell_id : integer
The cell id of the testdata
Returns
--------
validation_df : pandas dataframe
The validation dataframe with any errors listed
Examples
---------
>>> import maccorcyclingdata.validate as validate
>>> validation_df = validate.validation_check_advanced_cycle(validation_df, df, i, 1)
>>> validation_df
"""
if not isinstance(validation_df, pd.DataFrame):
raise TypeError('validation_df input must be a pandas dataframe')
if not len(validation_df.columns) == 5:
raise IndexError("validation dataframe must have 5 columns")
if (validation_df.columns.tolist() != ["time", "run", "cell_num", "row_number", "error"]):
raise IndexError("validation dataframe must have these columns: ['time', 'run', 'cell_num', 'row_number', 'error']")
if not isinstance(df, pd.DataFrame):
raise TypeError('df input must be a pandas dataframe')
if not len(df.columns) == 10:
raise IndexError("testdata dataframe must have 10 columns")
if (df.columns.tolist() != ['cyc', 'step', 'test_time_s', 'step_time_s', 'capacity_mah', 'current_ma', 'voltage_v', 'dpt_time', 'thermocouple_temp_c', 'ev_temp']):
raise IndexError("Pandas dataframe must have these columns: ['cyc', 'step', 'test_time_s', 'step_time_s', 'capacity_mah', 'current_ma', 'voltage_v', 'dpt_time', 'thermocouple_temp_c', 'ev_temp']")
if not isinstance(i, int):
raise TypeError("i must be an integer")
if not isinstance(cell_id, int):
raise TypeError("cell_id must be an integer")
if df['cyc'][i] != (df['cyc'][i-1] + 1):
validation_df = validation_df.append({'time':datetime.now().strftime("%d/%m/%Y %H:%M:%S"), 'run': 'in progress', 'cell_num': cell_id, 'row_number': i, 'error': 'advance cycle error - the cycle did not increase by 1 as expected'}, ignore_index=True)
return validation_df
[docs]def validation_check_charging(validation_df, df, schedule_df, i, cell_id, char_tol=2):
"""
This function will validate the testdata against the charging steps by making sure the value of either the voltage or current matches with the value specfied in the scheduler.
Parameters
-----------
validation_df : pandas dataframe
The validation dataframe where any errors will be recorded
df : pandas dataframe
The testdata dataframe (from the import_maccor_data or import_multiple_csv_data functions)
schedule_df : pandas dataframe
The dataframe of the cleaned schedule file (from import_schedules function)
i : integer
An integer of the index where you want to validate
cell_id : integer
The cell id of the testdata
char_tol : integer
Sets the tolerance between the current/discharging current values and the set value in the schedule file. Default is 2.
Returns
--------
validation_df : pandas dataframe
The validation dataframe with any errors listed
Examples
---------
>>> import maccorcyclingdata.validate as validate
>>> validation_df = validate.validation_check_charging(validation_df, df, schedule_df, i, 1)
>>> validation_df
"""
if not isinstance(validation_df, pd.DataFrame):
raise TypeError('validation_df input must be a pandas dataframe')
if not len(validation_df.columns) == 5:
raise IndexError("validation dataframe must have 5 columns")
if (validation_df.columns.tolist() != ["time", "run", "cell_num", "row_number", "error"]):
raise IndexError("validation dataframe must have these columns: ['time', 'run', 'cell_num', 'row_number', 'error']")
if not isinstance(df, pd.DataFrame):
raise TypeError('df input must be a pandas dataframe')
if not len(df.columns) == 10:
raise IndexError("testdata dataframe must have 10 columns")
if (df.columns.tolist() != ['cyc', 'step', 'test_time_s', 'step_time_s', 'capacity_mah', 'current_ma', 'voltage_v', 'dpt_time', 'thermocouple_temp_c', 'ev_temp']):
raise IndexError("Pandas dataframe must have these columns: ['cyc', 'step', 'test_time_s', 'step_time_s', 'capacity_mah', 'current_ma', 'voltage_v', 'dpt_time', 'thermocouple_temp_c', 'ev_temp']")
if not isinstance(schedule_df, pd.DataFrame):
raise TypeError('schedule_df input must be a pandas dataframe')
if not len(schedule_df.columns) == 14:
raise IndexError("Pandas dataframe must have 14 columns")
if (schedule_df.columns.tolist() != ['step', 'step_type', 'step_mode', 'step_mode_value', 'step_limit', 'step_limit_value', 'step_end_type', 'step_end_type_op', 'step_end_type_value', 'goto_step', 'report_type', 'report_type_value', 'options', 'step_note']):
raise IndexError("Pandas dataframe must have these columns: ['step', 'step_type', 'step_mode', 'step_mode_value', 'step_limit', 'step_limit_value', 'step_end_type', 'step_end_type_op', 'step_end_type_value', 'goto_step', 'report_type', 'report_type_value', 'options', 'step_note']")
if not isinstance(char_tol, int):
raise TypeError("char_tol must be an integer")
if not isinstance(i, int):
raise TypeError("i must be an integer")
if not isinstance(cell_id, int):
raise TypeError("cell_id must be an integer")
step = df['step'][i]
mode = schedule_df['step_mode'][step+1]
mode_value = schedule_df['step_mode_value'][step+1]
limit = schedule_df['step_limit'][step+1]
limit_value = schedule_df['step_limit_value'][step+1]
if mode == 'Current':
mode = 'current_ma'
mode_value = mode_value * 1000
if ((round(df[mode][i]) + char_tol) >= mode_value) and ((round(df[mode][i]) - char_tol) <= mode_value):
return validation_df
elif mode == 'Voltage':
mode = 'voltage_v'
if (round(df[mode][i], 2)) == mode_value:
return validation_df
if not pd.isna(limit):
if limit == 'Current':
limit = 'current_ma'
limit_value = limit_value * 1000
if ((round(df[limit][i]) + char_tol) >= limit_value) and ((round(df[limit][i]) - char_tol) <= limit_value):
return validation_df
elif limit == 'Voltage':
limit = 'voltage_v'
if (round(df[limit][i], 2)) == limit_value:
return validation_df
validation_df = validation_df.append({'time':datetime.now().strftime("%d/%m/%Y %H:%M:%S"), 'run': 'in progress', 'cell_num': str(cell_id), 'row_number': str(i), 'error': 'charging error - ' + str(mode) + 'or ' + str(limit) + ' is at the wrong value'}, ignore_index=True)
return validation_df
[docs]def validation_check_discharging(validation_df, df, schedule_df, i, cell_id, discharge_neg, char_tol=2):
"""
This function will validate the testdata against the discharging steps by making sure the value of either the voltage or current matches with the value specfied in the scheduler.
Parameters
-----------
validation_df : pandas dataframe
The validation dataframe where any errors will be recorded
df : pandas dataframe
The testdata dataframe (from the import_maccor_data or import_multiple_csv_data functions)
schedule_df : pandas dataframe
The dataframe of the cleaned schedule file (from the import_schedules function)
i : integer
An integer of the index where you want to validate
cell_id : integer
The cell id of the testdata
discharge_neg : boolean
Set to True if the current is exported as negative during discharge steps.
char_tol : integer
Sets the tolerance between the current/discharging current values and the set value in the schedule file. Default is 2.
Returns
--------
validation_df : pandas dataframe
The validation dataframe with any errors listed
Examples
---------
>>> import maccorcyclingdata.validate as validate
>>> validation_df = validate.validation_check_discharging(validation_df, df, schedule_df, i, 1, True)
>>> validation_df
"""
if not isinstance(validation_df, pd.DataFrame):
raise TypeError('validation_df input must be a pandas dataframe')
if not len(validation_df.columns) == 5:
raise IndexError("validation dataframe must have 5 columns")
if (validation_df.columns.tolist() != ["time", "run", "cell_num", "row_number", "error"]):
raise IndexError("validation dataframe must have these columns: ['time', 'run', 'cell_num', 'row_number', 'error']")
if not isinstance(df, pd.DataFrame):
raise TypeError('df input must be a pandas dataframe')
if not len(df.columns) == 10:
raise IndexError("testdata dataframe must have 10 columns")
if (df.columns.tolist() != ['cyc', 'step', 'test_time_s', 'step_time_s', 'capacity_mah', 'current_ma', 'voltage_v', 'dpt_time', 'thermocouple_temp_c', 'ev_temp']):
raise IndexError("Pandas dataframe must have these columns: ['cyc', 'step', 'test_time_s', 'step_time_s', 'capacity_mah', 'current_ma', 'voltage_v', 'dpt_time', 'thermocouple_temp_c', 'ev_temp']")
if not isinstance(schedule_df, pd.DataFrame):
raise TypeError('schedule_df input must be a pandas dataframe')
if not len(schedule_df.columns) == 14:
raise IndexError("Pandas dataframe must have 14 columns")
if (schedule_df.columns.tolist() != ['step', 'step_type', 'step_mode', 'step_mode_value', 'step_limit', 'step_limit_value', 'step_end_type', 'step_end_type_op', 'step_end_type_value', 'goto_step', 'report_type', 'report_type_value', 'options', 'step_note']):
raise IndexError("Pandas dataframe must have these columns: ['step', 'step_type', 'step_mode', 'step_mode_value', 'step_limit', 'step_limit_value', 'step_end_type', 'step_end_type_op', 'step_end_type_value', 'goto_step', 'report_type', 'report_type_value', 'options', 'step_note']")
if not isinstance(char_tol, int):
raise TypeError("char_tol must be an integer")
if not isinstance(i, int):
raise TypeError("i must be an integer")
if not isinstance(cell_id, int):
raise TypeError("cell_id must be an integer")
if not isinstance(discharge_neg, bool):
raise TypeError("discharge_neg must be an boolean")
step = df['step'][i]
mode = schedule_df['step_mode'][step+1]
mode_value = schedule_df['step_mode_value'][step+1]
limit = schedule_df['step_limit'][step+1]
limit_value = schedule_df['step_limit_value'][step+1]
if mode == 'Current':
mode = 'current_ma'
mode_value = mode_value * 1000
if discharge_neg:
mode_value = -(mode_value)
if ((round(df[mode][i]) + char_tol) >= mode_value) and ((round(df[mode][i]) - char_tol) <= mode_value):
return validation_df
elif mode == 'Voltage':
mode = 'voltage_v'
if (round(df[mode][i], 1)) == mode_value:
return validation_df
if not pd.isna(limit):
if limit == 'Current':
limit = 'current_ma'
limit_value = limit_value * 1000
if discharge_neg:
limit_value = -limit_value
if ((round(df[limit][i]) + char_tol) >= limit_value) and ((round(df[limit][i]) - char_tol) <= limit_value):
return validation_df
elif limit == 'Voltage':
limit = 'voltage_v'
if (round(df[limit][i], 1)) == limit_value:
return validation_df
validation_df = validation_df.append({'time':str(datetime.now().strftime("%d/%m/%Y %H:%M:%S")), 'run': 'in progress', 'cell_num': str(cell_id), 'row_number': str(i), 'error': 'discharging error - ' + str(mode) + ' or ' + str(limit) + ' is at the wrong value'}, ignore_index=True)
return validation_df
[docs]def validation_check_max_step_num(validation_df, df, max_step, i, cell_id):
"""
This function will validate the testdata against the max step by making sure no steps surpass the max.
Parameters
-----------
validation_df : pandas dataframe
The validation dataframe where any errors will be recorded
df : pandas dataframe
The testdata dataframe (from the import_maccor_data or import_multiple_csv_data functions)
max_step : integer
The last step from the schedule file
i : integer
An integer of the index where you want to validate
cell_id : integer
The cell id of the testdata
Returns
--------
validation_df : pandas dataframe
The validation dataframe with any errors listed
Examples
---------
>>> import maccorcyclingdata.validate as validate
>>> validation_df = validate.validation_check_max_step_num(validation_df, df, max_step, i, 1)
>>> validation_df
"""
if not isinstance(validation_df, pd.DataFrame):
raise TypeError('validation_df input must be a pandas dataframe')
if not len(validation_df.columns) == 5:
raise IndexError("validation dataframe must have 5 columns")
if (validation_df.columns.tolist() != ["time", "run", "cell_num", "row_number", "error"]):
raise IndexError("validation dataframe must have these columns: ['time', 'run', 'cell_num', 'row_number', 'error']")
if not isinstance(df, pd.DataFrame):
raise TypeError('df input must be a pandas dataframe')
if not len(df.columns) == 10:
raise IndexError("testdata dataframe must have 10 columns")
if (df.columns.tolist() != ['cyc', 'step', 'test_time_s', 'step_time_s', 'capacity_mah', 'current_ma', 'voltage_v', 'dpt_time', 'thermocouple_temp_c', 'ev_temp']):
raise IndexError("Pandas dataframe must have these columns: ['cyc', 'step', 'test_time_s', 'step_time_s', 'capacity_mah', 'current_ma', 'voltage_v', 'dpt_time', 'thermocouple_temp_c', 'ev_temp']")
if not isinstance(max_step, int):
raise TypeError("max_step must be an integer")
if not isinstance(i, int):
raise TypeError("i must be an integer")
if not isinstance(cell_id, int):
raise TypeError("cell_id must be an integer")
if df['step'][i] > max_step:
validation_df = validation_df.append({'time':datetime.now().strftime("%d/%m/%Y %H:%M:%S"), 'run': 'in progress', 'cell_num': cell_id, 'row_number': i, 'error': 'max step error - this step number surpasses the steps in cycler schedule'}, ignore_index=True)
return validation_df
[docs]def validation_check_max_temp(validation_df, df, max_temp, i, cell_id, temp_tol=3):
"""
This function will validate the testdata against the max temperature by making sure no steps surpass the max.
Parameters
-----------
validation_df : pandas dataframe
The validation dataframe where any errors will be recorded
df : pandas dataframe
The testdata dataframe (from the import_maccor_data or import_multiple_csv_data functions)
max_temp : integer
The threshold for the highest temperature allowed
i : integer
An integer of the index where you want to validate
cell_id : integer
The cell id of the testdata
Returns
--------
validation_df : pandas dataframe
The validation dataframe with any errors listed
Notes
------
There are 3 possibilities of error messages:
1. warning - temperature approaching the max! (current temperature + tol > max)
2. error - temperature has surpassed the max! (current temperature >= max)
3. ABORT - temperature is way too hot! (current temperature > max + tol)
Examples
---------
>>> import maccorcyclingdata.validate as validate
>>> validation_df = validate.validation_check_max_temp(validation_df, df, 30, i, 1, 3)
>>> validation_df
"""
if not isinstance(validation_df, pd.DataFrame):
raise TypeError('validation_df input must be a pandas dataframe')
if not len(validation_df.columns) == 5:
raise IndexError("validation dataframe must have 5 columns")
if (validation_df.columns.tolist() != ["time", "run", "cell_num", "row_number", "error"]):
raise IndexError("validation dataframe must have these columns: ['time', 'run', 'cell_num', 'row_number', 'error']")
if not isinstance(df, pd.DataFrame):
raise TypeError('df input must be a pandas dataframe')
if not len(df.columns) == 10:
raise IndexError("testdata dataframe must have 10 columns")
if (df.columns.tolist() != ['cyc', 'step', 'test_time_s', 'step_time_s', 'capacity_mah', 'current_ma', 'voltage_v', 'dpt_time', 'thermocouple_temp_c', 'ev_temp']):
raise IndexError("Pandas dataframe must have these columns: ['cyc', 'step', 'test_time_s', 'step_time_s', 'capacity_mah', 'current_ma', 'voltage_v', 'dpt_time', 'thermocouple_temp_c', 'ev_temp']")
if not isinstance(max_temp, int):
raise TypeError("max_temp must be an integer")
if not isinstance(temp_tol, int):
raise TypeError("temp_tol must be an integer")
if not isinstance(i, int):
raise TypeError("i must be an integer")
if not isinstance(cell_id, int):
raise TypeError("cell_id must be an integer")
if ((max_temp) <= (df['thermocouple_temp_c'][i]) <= (max_temp+temp_tol)):
validation_df = validation_df.append({'time':datetime.now().strftime("%d/%m/%Y %H:%M:%S"), 'run': 'in progress', 'cell_num': cell_id, 'row_number': i, 'error': 'max temp error - temperature has surpassed the max of ' + str(max_temp) + '!'}, ignore_index=True)
elif ((df['thermocouple_temp_c'][i]) > (max_temp+temp_tol)):
validation_df = validation_df.append({'time':datetime.now().strftime("%d/%m/%Y %H:%M:%S"), 'run': 'in progress', 'cell_num': cell_id, 'row_number': i, 'error': 'ABORT - temperature is way too hot! It has far surpassed the max of ' + str(max_temp) + '!'}, ignore_index=True)
elif ((max_temp-temp_tol) < (df['thermocouple_temp_c'][i])):
validation_df = validation_df.append({'time':datetime.now().strftime("%d/%m/%Y %H:%M:%S"), 'run': 'in progress', 'cell_num': cell_id, 'row_number': i, 'error': 'max temp warning - temperature approaching the max of ' + str(max_temp) + '!'}, ignore_index=True)
return validation_df
[docs]def validation_check_rest(validation_df, df, i, cell_id):
"""
This function will validate the testdata against the rest steps by making sure the current is at 0 when resting.
Parameters
-----------
validation_df : pandas dataframe
The validation dataframe where any errors will be recorded
df : pandas dataframe
The testdata dataframe (from the import_maccor_data or import_multiple_csv_data functions)
i : integer
An integer of the index where you want to validate
cell_id : integer
The cell id of the testdata
Returns
--------
validation_df : pandas dataframe
The validation dataframe with any errors listed
Examples
---------
>>> import maccorcyclingdata.validate as validate
>>> validation_df = validate.validation_check_rest_steps(validation_df, df, i, 1)
>>> validation_df
"""
if not isinstance(validation_df, pd.DataFrame):
raise TypeError('validation_df input must be a pandas dataframe')
if not len(validation_df.columns) == 5:
raise IndexError("validation dataframe must have 5 columns")
if (validation_df.columns.tolist() != ["time", "run", "cell_num", "row_number", "error"]):
raise IndexError("validation dataframe must have these columns: ['time', 'run', 'cell_num', 'row_number', 'error']")
if not isinstance(df, pd.DataFrame):
raise TypeError('df input must be a pandas dataframe')
if not len(df.columns) == 10:
raise IndexError("testdata dataframe must have 10 columns")
if (df.columns.tolist() != ['cyc', 'step', 'test_time_s', 'step_time_s', 'capacity_mah', 'current_ma', 'voltage_v', 'dpt_time', 'thermocouple_temp_c', 'ev_temp']):
raise IndexError("Pandas dataframe must have these columns: ['cyc', 'step', 'test_time_s', 'step_time_s', 'capacity_mah', 'current_ma', 'voltage_v', 'dpt_time', 'thermocouple_temp_c', 'ev_temp']")
if not isinstance(i, int):
raise TypeError("i must be an integer")
if not isinstance(cell_id, int):
raise TypeError("cell_id must be an integer")
if df['current_ma'][i] != 0:
validation_df = validation_df.append({'time':datetime.now().strftime("%d/%m/%Y %H:%M:%S"), 'run': 'in progress', 'cell_num': cell_id, 'row_number': i, 'error': 'rest step error - current is not at 0 during rest step'}, ignore_index=True)
return validation_df
[docs]def validate_test_data(schedule_df , df, cell_id, time_interval, temp_interval, max_temp, discharge_neg, temp_tol=3, char_tol=2):
"""
This is a wrapper function that validates the testdata against the schedule file.
The sub-modules that are validated are:
- validation_check_rest(validation_df, df, i, cell_id)
- validation_check_charging(validation_df, df, schedule_df, i, cell_id)
- validation_check_discharging(validation_df, df, schedule_df, i, cell_id, discharge_neg)
- validation_check_advanced_cycle(validation_df, df, i, cell_id)
- validation_check_max_step_num(validation_df, df, max_step, i, cell_id)
- validation_check_max_temp(validation_df, df, max_temp, i, cell_id, tol=3)
- validation_check_time_interval(validation_df, df, time_interval, i, cell_id)
- validation_check_temp_interval(validation_df, df, temp_interval, i, cell_id)
Parameters
-----------
schedule_df : pandas dataframe
The dataframe of the cleaned schedule file (from import_schedules function)
df : pandas dataframe
The testdata dataframe (from the import_maccor_data or import_multiple_csv_data functions)
cell_id : integer
The cell id of the testdata
time_interval : integer
The maximum interval of how often the cycler should be recording data
temp_interval : integer
The maximum interval of a temperature change
max_temp : integer
The threshold for the highest temperature allowed
discharge_neg : boolean
Set to True if the current was exported as negative during discharge steps.
temp_tol : integer
Sets the tolerance between warning, error, and ABORT messages. Default is 3 degrees.
char_tol : integer
Sets the tolerance between the current/discharging current values and the set value in the schedule file. Default is 2.
Returns
--------
validation_df : pandas dataframe
The validation dataframe with any errors (if any) listed
Headers of the validation_df:
1. time (the current time of when the validation occurs)
2. run (tells whether the validation function is in progress or complete)
3. cell_num (the cell number of the testdata)
4. row_number (the row number where the error occurs)
5. error (what the error is)
Notes
------
Depending on the size of your testdata and schedules, this function may take much longer to run.
For reference, the example in the jupyter notebook ran from 1:40pm-3:15pm for 901 cycles. Using timeit to time: 12min 3s ± 1min 56s per loop (mean ± std. dev. of 7 runs, 1 loop each)
There are 3 possibilities of error messages:
1. warning - temperature approaching the max! (current temperature + temp_tol > max)
2. error - temperature has surpassed the max! (current temperature >= max)
3. ABORT - temperature is way too hot! (current temperature > max + temp_tol)
Examples
---------
>>> import maccorcyclingdata.validate as validate
>>> validation_df = validate.validate_test_data(schedule_df, df, 1, 10, 30, True, 5)
>>> validation_df
"""
if not isinstance(df, pd.DataFrame):
raise TypeError('df input must be a pandas dataframe')
if not len(df.columns) == 10:
raise IndexError("testdata dataframe must have 10 columns")
if (df.columns.tolist() != ['cyc', 'step', 'test_time_s', 'step_time_s', 'capacity_mah', 'current_ma', 'voltage_v', 'dpt_time', 'thermocouple_temp_c', 'ev_temp']):
raise IndexError("Pandas dataframe must have these columns: ['cyc', 'step', 'test_time_s', 'step_time_s', 'capacity_mah', 'current_ma', 'voltage_v', 'dpt_time', 'thermocouple_temp_c', 'ev_temp']")
if not isinstance(schedule_df, pd.DataFrame):
raise TypeError('schedule_df input must be a pandas dataframe')
if not len(schedule_df.columns) == 14:
raise IndexError("Pandas dataframe must have 14 columns")
if (schedule_df.columns.tolist() != ['step', 'step_type', 'step_mode', 'step_mode_value', 'step_limit', 'step_limit_value', 'step_end_type', 'step_end_type_op', 'step_end_type_value', 'goto_step', 'report_type', 'report_type_value', 'options', 'step_note']):
raise IndexError("Pandas dataframe must have these columns: ['step', 'step_type', 'step_mode', 'step_mode_value', 'step_limit', 'step_limit_value', 'step_end_type', 'step_end_type_op', 'step_end_type_value', 'goto_step', 'report_type', 'report_type_value', 'options', 'step_note']")
if not isinstance(char_tol, int):
raise TypeError("char_tol must be an integer")
if not isinstance(time_interval, int):
raise TypeError("time_interval must be an integer")
if not isinstance(temp_interval, int):
raise TypeError("temp_interval must be an integer")
if not isinstance(max_temp, int):
raise TypeError("max_temp must be an integer")
if not isinstance(temp_tol, int):
raise TypeError("temp_tol must be an integer")
if not isinstance(cell_id, int):
raise TypeError("cell_id must be an integer")
if not isinstance(discharge_neg, bool):
raise TypeError("discharge_neg must be an boolean")
column_names = ["time", "run", "cell_num", "row_number", "error"]
validation_df = pd.DataFrame(columns = column_names)
rest_steps, charge_steps, advance_steps, discharge_steps, end_steps, max_step = sort_scheduler_steps(schedule_df)
for i in df.index:
validation_df = validation_check_max_temp(validation_df, df, max_temp, i, cell_id, temp_tol)
if i != 0:
validation_df = validation_check_time_interval(validation_df, df, time_interval, i, cell_id)
validation_df = validation_check_temp_interval(validation_df, df, temp_interval, i, cell_id)
if df['step'][i] in rest_steps:
validation_df = validation_check_rest(validation_df, df, i, cell_id)
elif df['step'][i] in charge_steps:
validation_df = validation_check_charging(validation_df, df, schedule_df, i, cell_id, char_tol)
elif df['step'][i] in discharge_steps:
validation_df = validation_check_discharging(validation_df, df, schedule_df, i, cell_id, discharge_neg, char_tol)
elif df['step'][i] in advance_steps:
validation_df = validation_check_advanced_cycle(validation_df, df, i, cell_id)
elif df['step'][i] >= max_step:
validation_df = validation_check_max_step_num(validation_df, df, int(max_step), i, cell_id)
if validation_df.empty:
validation_df = validation_df.append({'time':datetime.now().strftime("%d/%m/%Y %H:%M:%S"), 'run': 'run complete', 'cell_num': str(cell_id), 'row_number': '-', 'error': 'there are no errors'}, ignore_index=True)
return validation_df
validation_df = validation_df.append({'time': datetime.now().strftime("%d/%m/%Y %H:%M:%S"), 'run': 'run complete', 'cell_num': str(cell_id), 'row_number': '-', 'error': 'errors listed above'}, ignore_index=True)
return validation_df