def imp_one_cycle(testdf, cd, cyc_loop, battery, datatype, windowlength, polyorder, lenmax): """imports and fits a single charge discharge cycle of a battery file_val = directory containing current cycle cd = either 'c' for charge or 'd' for discharge cyc_loop = cycle number battery = battery name output: a dictionary of descriptors for a single battery""" # make sure this is an Excel spreadsheet by checking the file extension # assert file_val.split('.')[-1] == ('xlsx' or 'xls') # reads excel file into pandas # testdf = pd.read_excel(file_val) # extracts charge and discharge from the dataset (cycle_ind_col, data_point_col, volt_col, curr_col, dis_cap_col, char_cap_col, charge_or_discharge) = ccf.col_variables(datatype) charge, discharge = ccf.sep_char_dis(testdf, datatype) # determines if the charge, discharge indicator was inputted correctly # assigns daframe for fitting accordingly if cd == 'c': df_run = charge elif cd == 'd': df_run = discharge else: raise TypeError( "Cycle type must be either 'c' for charge or 'd' for discharge." ) print('Generating descriptors for cycle number: ' + str(cyc_loop) + cd) # determines if a cycle should be passed into the descriptor # fitting function if (len(charge[volt_col].index) >= 10) and (len( discharge[volt_col].index) >= 10): # generates a dictionary of descriptors c = fitters.descriptor_func(df_run, cd, cyc_loop, battery, windowlength, polyorder, datatype, lenmax) # df_run[volt_col], df_run['Smoothed_dQ/dV'] #c is the dictionary of descriptors here # eliminates cycle number and notifies user of cycle removal else: notice = 'Cycle ' + str(cyc_loop) + ' in battery ' + battery + \ ' had fewer than 10 datapoints and was removed from the dataset.' print(notice) c = 'throw' # print('here is the c parameter in the imp_one_cycle: ') # print(c) return c
def imp_one_cycle(file_val, cd, cyc_loop, battery): """imports and fits a single charge discharge cycle of a battery file_val = directory containing current cycle cd = either 'c' for charge or 'd' for discharge cyc_loop = cycle number battery = battery name output: a dictionary of descriptors for a single battery""" # make sure this is an Excel spreadsheet by checking the file extension assert file_val.split('.')[-1] == ('xlsx' or 'xls') # reads excel file into pandas testdf = pd.read_excel(file_val) # extracts charge and discharge from the dataset charge, discharge = ccf.sep_char_dis(testdf) # determines if the charge, discharge indicator was inputted correctly # assigns daframe for fitting accordingly if cd == 'c': df_run = charge elif cd == 'd': df_run = discharge else: raise TypeError( "Cycle type must be either 'c' for charge or 'd' for discharge.") # determines if a cycle should be passed into the descriptor # fitting function if (len(charge['Voltage(V)'].index) >= 10) and (len(discharge['Voltage(V)'].index) >= 10): # generates a dictionary of descriptors c = fitters.descriptor_func( df_run['Voltage(V)'], df_run['Smoothed_dQ/dV'], cd, cyc_loop, battery) # eliminates cycle number and notifies user of cycle removal else: notice = 'Cycle ' + str(cyc_loop) + ' in battery ' + battery + \ ' had fewer than 10 datapoints and was removed from the dataset.' print(notice) c = 'throw' return c
def update_figure2(selected_step, contents, filename, date, selected_row_indices): data = parse_contents(contents, filename, date) (charge, discharge) = ccf.sep_char_dis(data) filtered_data = discharge[discharge['Cycle_Index'] == selected_step] for i in filtered_data['Cycle_Index'].unique(): dff = filtered_data[filtered_data['Cycle_Index'] == i] fig = plotly.tools.make_subplots( rows=2, cols=1, subplot_titles=('Smoothed dQ/dV Discharge Cycle', 'Cleaned dQ/dV Discharge Cycle'), shared_xaxes=True) marker = {'color': ['#0074D9'] * len(dff)} for i in (selected_row_indices or []): marker['color'][i] = '#FF851B' fig.append_trace( { 'x': dff['Voltage(V)'], 'y': dff['Smoothed_dQ/dV'], 'type': 'scatter', 'marker': marker, 'name': 'Smoothed Data' }, 1, 1) fig.append_trace( { 'x': dff['Voltage(V)'], 'y': dff['dQ/dV'], 'type': 'scatter', 'marker': marker, 'name': 'Raw Data' }, 2, 1) fig['layout']['showlegend'] = False fig['layout']['height'] = 800 fig['layout']['margin'] = {'l': 40, 'r': 10, 't': 60, 'b': 200} fig['layout']['yaxis2'] return fig
def update_slider_value(contents, filename, date): data = parse_contents(contents, filename, date) charge, discharge = ccf.sep_char_dis(data) return charge['Cycle_Index'].max()
def update_table2(contents, filename, date): data = parse_contents(contents, filename, date) charge, discharge = ccf.sep_char_dis(data) return discharge.to_dict('records')
import dash_table_experiments as dt import pandas as pd import io import json import plotly import base64 ########################################## #Load Data ########################################## #eventually add everything in folder and create a dropdown that loads that data into data #for now just use some data we have data = pd.read_excel('data/Clean_Whole_Sets/CS2_33_12_16_10CleanSet.xlsx') charge, discharge = ccf.sep_char_dis(data) #df_dqdv = ccf.calc_dv_dqdv('data/CS2_33/CS2_33_10_04_10.xlsx') #df_dqdv = ccf.calc_dv_dqdv(data) #charge, discharge = ccf.sep_char_dis(data) ########################################## #App Layout ########################################## app = dash.Dash() #initialize dash Introduction = dcc.Markdown(''' # ChaChi ## Interface for visualizing battery cycle data #'''), #Add some Markdown
def get_model_dfs_for_jupyter(df_clean, datatype, cyc, lenmax, peak_thresh): # this function is analagous to the get_model_dfs function in the app.py file (cycle_ind_col, data_point_col, volt_col, curr_col, dis_cap_col, char_cap_col, charge_or_discharge) = ccf.col_variables(datatype) clean_charge, clean_discharge = ccf.sep_char_dis( df_clean[df_clean[cycle_ind_col] == cyc], datatype) windowlength = 75 polyorder = 3 # speed this up by moving the initial peak finder out of this, and just have those two things passed to it i_charge, volts_i_ch, peak_heights_c = descriptors.fitters.peak_finder( clean_charge, 'c', windowlength, polyorder, datatype, lenmax, peak_thresh) V_series_c = clean_charge[volt_col] dQdV_series_c = clean_charge['Smoothed_dQ/dV'] par_c, mod_c, indices_c = descriptors.fitters.model_gen( V_series_c, dQdV_series_c, 'c', i_charge, cyc, peak_thresh) model_c = descriptors.fitters.model_eval(V_series_c, dQdV_series_c, 'c', par_c, mod_c) if model_c is not None: mod_y_c = mod_c.eval(params=model_c.params, x=V_series_c) myseries_c = pd.Series(mod_y_c) myseries_c = myseries_c.rename('Model') model_c_vals = model_c.values new_df_mody_c = pd.concat([ myseries_c, V_series_c, dQdV_series_c, clean_charge[cycle_ind_col] ], axis=1) else: mod_y_c = None new_df_mody_c = None model_c_vals = None # now the discharge: i_discharge, volts_i_dc, peak_heights_d = descriptors.fitters.peak_finder( clean_discharge, 'd', windowlength, polyorder, datatype, lenmax, peak_thresh) V_series_d = clean_discharge[volt_col] dQdV_series_d = clean_discharge['Smoothed_dQ/dV'] par_d, mod_d, indices_d = descriptors.fitters.model_gen( V_series_d, dQdV_series_d, 'd', i_discharge, cyc, peak_thresh) model_d = descriptors.fitters.model_eval(V_series_d, dQdV_series_d, 'd', par_d, mod_d) if model_d is not None: mod_y_d = mod_d.eval(params=model_d.params, x=V_series_d) myseries_d = pd.Series(mod_y_d) myseries_d = myseries_d.rename('Model') new_df_mody_d = pd.concat([ -myseries_d, V_series_d, dQdV_series_d, clean_discharge[cycle_ind_col] ], axis=1) model_d_vals = model_d.values else: mod_y_d = None new_df_mody_d = None model_d_vals = None # save the model parameters in the database with the data if new_df_mody_c is not None or new_df_mody_d is not None: new_df_mody = pd.concat([new_df_mody_c, new_df_mody_d], axis=0) else: new_df_mody = None # combine the charge and discharge # update model_c_vals and model_d_vals with peak heights return new_df_mody, model_c_vals, model_d_vals, peak_heights_c, peak_heights_d