diff --git a/scripts/device_accuracy.py b/scripts/device_accuracy.py index 8607c8f..5b0c200 100644 --- a/scripts/device_accuracy.py +++ b/scripts/device_accuracy.py @@ -5,6 +5,8 @@ import re import xlsxwriter from datetime import datetime import math +import matplotlib.pyplot as plt +import io curdir = os.getcwd() path_delim = '/' @@ -13,45 +15,62 @@ precision_threshold = 0.009 accuracy_threshold = 0.02 denovix_reference_values = { - "Tartrazine": { - "50": 0.187191676, - "75": 0.187191676, - "100": 0.187191676, - "125": 0.187191676, - "150": 0.187191676, - "175": 0.187191676, - "200": 0.187191676, - "225": 0.187191676, - "250": 0.187191676, - "275": 0.187191676, - "300": 0.187191676, - }, - "KMnO4": { - "250": 0.187191676, - "350": 0.187191676, - "450": 0.187191676, - "550": 0.187191676, - "650": 0.187191676, - "750": 0.187191676, - "850": 0.187191676, - "950": 0.187191676, - "1050": 0.187191676, - "1150": 0.187191676, - "1250": 0.187191676, - "1350": 0.187191676, - "1450": 0.187191676, - "1550": 0.187191676, - }, -} + "Tartrazine": { + "10": 0.187191676, + "30": 0.187191676, + "50": 0.187447015, + "60": 0.187191676, + "75": 0.294739334, + "90": 0.187191676, + "100": 0.410113264, + "120": 0.187191676, + "125": 0.512526022, + "150": 0.622883833, + "175": 0.721095085, + "180": 0.187191676, + "200": 0.824065454, + "210": 0.187191676, + "225": 0.931385567, + "250": 1.002224884, + "275": 1.091996882, + "300": 1.16558307, + "350": 1.16558307, + }, + "KMnO4": { + "10": 0.187191676, + "100": 0.187191676, + "145": 0.187191676, + "175": 0.187191676, + "250": 0.077846397, + "290": 0.359288533, + "350": 0.111884606, + "435": 0.187191676, + "450": 0.138031952, + "550": 0.175111257, + "580": 0.628039375, + "650": 0.208337398, + "720": 0.187191676, + "750": 0.238773222, + "850": 0.267574903, + "950": 0.299568449, + "1050": 0.329271864, + "1150": 0.365827844, + "1160": 0.388015579, + "1250": 0.388015579, + "1350": 0.417304075, + "1450": 0.447634285, + "1550": 0.478220085, + }, + } df_reference_device = pd.DataFrame(denovix_reference_values).T df_reference_device.index.name = 'Solution' df_reference_device.columns.name = 'Wavelength' -df = pd.read_excel(curdir + path_delim + "data" + path_delim + "data_03_12_2023_11_25.xlsx", sheet_name="Sheet2") +df = pd.read_excel(curdir + path_delim + "data" + path_delim + "data_06_12_2023_12_47.xlsx", sheet_name="data") -texts_to_check = ['Tar', 'KM'] +texts_to_check = ['T', 'K'] df['solution'] = df['name'].str.extract(f"({'|'.join(texts_to_check)})", flags=re.IGNORECASE) -df['solution'] = df['solution'].replace({'Tar': 'Tartrazine', 'KM': 'KMnO4'}, regex=True) +df['solution'] = df['solution'].replace({'T': 'Tartrazine', 'K': 'KMnO4'}, regex=True) def extract_numbers(s): match = re.match(r'\d+', s) @@ -68,6 +87,9 @@ df_precision_acc['precision'] = df_precision_acc['max'] - df_precision_acc['min' df_precision_acc['precision_result'] = ['Fail' if diff > precision_threshold else 'Pass' for diff in df_precision_acc['precision']] +df_precision_acc.reset_index(inplace=True) +df_precision_acc.set_index(["deviceId", "solution", "concentration"], inplace=True) + device_precision_results = {} for index, group_df in df_precision_acc.groupby(level=[0, 1, 2]): soln = index[1] @@ -87,11 +109,11 @@ df_precision_acc = df_precision_acc.assign(accuracy='', accuracy_result='') device_accuracy_results = {} -# Calculate accuracy based on the mean column and reference values for idx, row in df_precision_acc.iterrows(): device_id = row.name[0] solution = row.name[1] - concentration = str(row.name[2]) + concentration = str(int(row.name[2])) + # print(concentration) reference_value = denovix_reference_values[solution][concentration] try: @@ -99,7 +121,6 @@ for idx, row in df_precision_acc.iterrows(): accuracy = math.fabs(row['mean'] - reference_value) df_precision_acc.at[idx, 'accuracy'] = accuracy - # Add accuracy_result column accuracy_result = 'Pass' if accuracy < accuracy_threshold else 'Fail' df_precision_acc.at[idx, 'accuracy_result'] = accuracy_result if device_id not in device_accuracy_results: @@ -108,24 +129,20 @@ for idx, row in df_precision_acc.iterrows(): if accuracy_result == 'Fail': device_accuracy_results[device_id] = 'Fail' except KeyError: - # Handle the case where the solution or concentration is not in the dictionary - df_precision_acc.at[idx, 'accuracy'] = np.nan # You can use any value to represent missing data - df_precision_acc.at[idx, 'accuracy_result'] = 'Fail' # Assume 'Fail' for missing data + df_precision_acc.at[idx, 'accuracy'] = np.nan + df_precision_acc.at[idx, 'accuracy_result'] = 'Fail' df_device_accuracy_results = pd.DataFrame(list(device_accuracy_results.items()), columns=['Device', 'Result']) device_results = {} -# Mark deviceId as "Fail" if either precision or accuracy is failing df_device_results = pd.merge(df_device_precicion_results, df_device_accuracy_results, on='Device', how='outer', suffixes=('_precision', '_accuracy')) df_device_results['Result'] = np.where((df_device_results['Result_precision'] == 'Fail') | (df_device_results['Result_accuracy'] == 'Fail'), 'Fail', 'Pass') -output_filename = f'precision_{datetime.today().strftime("%d_%m_%Y_%H_%M")}.xlsx' +output_filename = f'data/accuracy_{datetime.today().strftime("%d_%m_%Y_%H_%M")}.xlsx' writer = pd.ExcelWriter(output_filename, engine = 'xlsxwriter') df_device_results.to_excel(writer, sheet_name="device_results") -df_device_precicion_results.to_excel(writer, sheet_name="device_precision") -df_device_accuracy_results.to_excel(writer, sheet_name="device_accuracy") df_precision_acc.to_excel(writer, sheet_name="concentration") df.to_excel(writer, sheet_name="in") df_reference_device.to_excel(writer, sheet_name="reference_device") @@ -146,6 +163,61 @@ worksheet_device_results.conditional_format('E2:E{}'.format(df_device_results.sh 'value': 'Pass', 'format': green_format}) + +wks1 = workbook.add_worksheet('abs_plot') +wks1.write(0,0,'Abs Plot') + +# Write the header +wks1.write(0, 0, 'Solution') +wks1.write(0, 1, 'Slope') +wks1.write(0, 2, 'Intercept') +row = 1 + +fig, ax = plt.subplots() + +unique_solutions = df['solution'].unique() + +for solution in unique_solutions: + if pd.notna(solution): + solution_data = df[df['solution'] == solution] + + concentration_means = solution_data.groupby('concentration')['absorbance'].mean() + + # Fit a linear regression model + coefficients = np.polyfit(concentration_means.index, concentration_means.values, 1) + + # Print the coefficients + print(f'Coefficients for {solution}: Slope={coefficients[0]}, Intercept={coefficients[1]}') + + # Plot the mean absorbance + ax.plot(concentration_means.index, concentration_means.values, marker='o', linestyle='-', label=f'Mean Absorbance for {solution}') + + # Plot the linear fit + ax.plot(concentration_means.index, np.polyval(coefficients, concentration_means.index), linestyle='--', label=f'Linear Fit for {solution}') + + # Add coefficients next to the linear fit trendline + annotation_text = f'Slope: {coefficients[0]:.4f}\nIntercept: {coefficients[1]:.4f}' + ax.text(concentration_means.index[-1] + 5, np.polyval(coefficients, concentration_means.index[-1]), annotation_text, fontsize=10, verticalalignment='center') + + # Write the coefficients to the worksheet + wks1.write(row, 0, solution) + wks1.write(row, 1, coefficients[0]) + wks1.write(row, 2, coefficients[1]) + + row += 1 + +# writer.save() + +ax.set_title('Mean Absorbance for Each Solution') +ax.set_xlabel('Concentration') +ax.set_ylabel('Mean Absorbance') +ax.legend() +# plt.show() + +imgdata=io.BytesIO() +fig.savefig(imgdata, format='png') +wks1.insert_image(2,2, '', {'image_data': imgdata}) + ### debug each row # # Merge df and df_device_precicion_results on deviceId # df_merged = pd.merge(df, df_device_precicion_results, left_on='deviceId', right_on='Device', how='left')