159 lines
6.6 KiB
Python
159 lines
6.6 KiB
Python
|
|
import pandas as pd
|
||
|
|
import numpy as np
|
||
|
|
import os
|
||
|
|
import re
|
||
|
|
import xlsxwriter
|
||
|
|
from datetime import datetime
|
||
|
|
import math
|
||
|
|
|
||
|
|
curdir = os.getcwd()
|
||
|
|
path_delim = '/'
|
||
|
|
|
||
|
|
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,
|
||
|
|
},
|
||
|
|
}
|
||
|
|
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")
|
||
|
|
|
||
|
|
texts_to_check = ['Tar', 'KM']
|
||
|
|
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)
|
||
|
|
|
||
|
|
def extract_numbers(s):
|
||
|
|
match = re.match(r'\d+', s)
|
||
|
|
if match:
|
||
|
|
return int(match.group())
|
||
|
|
else:
|
||
|
|
return None
|
||
|
|
|
||
|
|
df["concentration"] = df['name'].apply(extract_numbers)
|
||
|
|
df['absorbance'] = df.apply(lambda row: row['led2Average'] if row['solution'] == 'Tartrazine' else row['led1Average'], axis=1)
|
||
|
|
|
||
|
|
df_precision_acc = df[["deviceId", "solution", "concentration", "led1Average", "led2Average", "absorbance"]].groupby(["deviceId", "solution", "concentration"]).describe()["absorbance"][["count", "min", "max", "mean"]]
|
||
|
|
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']]
|
||
|
|
|
||
|
|
device_precision_results = {}
|
||
|
|
for index, group_df in df_precision_acc.groupby(level=[0, 1, 2]):
|
||
|
|
soln = index[1]
|
||
|
|
concen = index[2]
|
||
|
|
result_values = group_df['precision_result'].values
|
||
|
|
|
||
|
|
if index[0] not in device_precision_results:
|
||
|
|
device_precision_results[index[0]] = "Pass"
|
||
|
|
else:
|
||
|
|
result = 'Fail' if 'Fail' in result_values else 'Pass'
|
||
|
|
if result == 'Fail':
|
||
|
|
device_precision_results[index[0]] = 'Fail'
|
||
|
|
|
||
|
|
df_device_precicion_results = pd.DataFrame(list(device_precision_results.items()), columns=['Device', 'Result'])
|
||
|
|
|
||
|
|
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])
|
||
|
|
reference_value = denovix_reference_values[solution][concentration]
|
||
|
|
|
||
|
|
try:
|
||
|
|
reference_value = denovix_reference_values[solution][concentration]
|
||
|
|
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:
|
||
|
|
device_accuracy_results[device_id] = accuracy_result
|
||
|
|
else:
|
||
|
|
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_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'
|
||
|
|
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")
|
||
|
|
|
||
|
|
workbook = writer.book
|
||
|
|
worksheet_device_results = writer.sheets['device_results']
|
||
|
|
|
||
|
|
red_format = workbook.add_format({'bg_color': '#FFC7CE', 'font_color': '#9C0006'})
|
||
|
|
green_format = workbook.add_format({'bg_color': '#C6EFCE', 'font_color': '#006100'})
|
||
|
|
|
||
|
|
worksheet_device_results.conditional_format('E2:E{}'.format(df_device_results.shape[0] + 1), {'type': 'text',
|
||
|
|
'criteria': 'containing',
|
||
|
|
'value': 'Fail',
|
||
|
|
'format': red_format})
|
||
|
|
|
||
|
|
worksheet_device_results.conditional_format('E2:E{}'.format(df_device_results.shape[0] + 1), {'type': 'text',
|
||
|
|
'criteria': 'containing',
|
||
|
|
'value': 'Pass',
|
||
|
|
'format': green_format})
|
||
|
|
|
||
|
|
### 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')
|
||
|
|
|
||
|
|
# # Drop the duplicate "Device" column
|
||
|
|
# df_merged.drop(columns=['Device'], inplace=True)
|
||
|
|
|
||
|
|
# # Save the merged DataFrame to the Excel file
|
||
|
|
# df_merged.to_excel(writer, sheet_name="merged_results")
|
||
|
|
|
||
|
|
writer.close()
|