diff --git a/spo2evaluation/evaluation/blant_altman.py b/spo2evaluation/evaluation/blant_altman.py index fe3144f..949aba1 100644 --- a/spo2evaluation/evaluation/blant_altman.py +++ b/spo2evaluation/evaluation/blant_altman.py @@ -130,7 +130,8 @@ def BlandAltmanPlot(Xdata, Ydata, fig_num=None): if fig_num != None: - plt.figure(fig_num) + + plt.figure() ##Set axis limits, this will account for the maximum average difference and the upper and lower ##limits of agreement, and all data points. @@ -151,12 +152,14 @@ def BlandAltmanPlot(Xdata, Ydata, fig_num=None): ms="8", lw="2", ) - # Add the mean, upper and lower levels of agreement to the Bland-Altman plot. + # Add the mean, upper and lower levels of agrespo2evaluation/evaluation/blant_altman.pyement to the Bland-Altman plot. plt.axhline(y=mean_difference, lw="2", color="k", ls="dashed") plt.axhline(y=upper_limit, lw="2", color="k", ls="dashed") plt.axhline(y=lower_limit, lw="2", color="k", ls="dashed") # Horizontal axis label - plt.xlabel("Average difference", fontsize="16") + plt.xlabel("Original SPO2 value", fontsize="16") # Vertical axis label plt.ylabel("Difference", fontsize="16") + plt.xlim(min(Average), max(Average)) + plt.show() return (mean_difference, std_difference, upper_limit, lower_limit) diff --git a/spo2evaluation/modelling/lamonaca_and_nemcova/lamonaca_2015.py b/spo2evaluation/modelling/lamonaca_and_nemcova/lamonaca_2015.py index 098e113..b03358b 100644 --- a/spo2evaluation/modelling/lamonaca_and_nemcova/lamonaca_2015.py +++ b/spo2evaluation/modelling/lamonaca_and_nemcova/lamonaca_2015.py @@ -8,7 +8,7 @@ import numpy as np import math -import utils +from . import utils class Camera_specs(object): diff --git a/spo2evaluation/modelling/lamonaca_and_nemcova/nemcova_2020.py b/spo2evaluation/modelling/lamonaca_and_nemcova/nemcova_2020.py index 7fc7cc5..2193cc2 100644 --- a/spo2evaluation/modelling/lamonaca_and_nemcova/nemcova_2020.py +++ b/spo2evaluation/modelling/lamonaca_and_nemcova/nemcova_2020.py @@ -3,7 +3,7 @@ import numpy as np import math -import utils +from . import utils import matplotlib.pyplot as plt diff --git a/spo2evaluation/modelling/wang_2017/wang_2017.py b/spo2evaluation/modelling/wang_2017/wang_2017.py index 79af9bd..bc39cfa 100644 --- a/spo2evaluation/modelling/wang_2017/wang_2017.py +++ b/spo2evaluation/modelling/wang_2017/wang_2017.py @@ -3,7 +3,7 @@ import numpy as np import math -import utils +from . import utils import matplotlib.pyplot as plt import scipy diff --git a/spo2evaluation/preprocessing/data_loader_pandas.py b/spo2evaluation/preprocessing/data_loader_pandas.py index 607d0cd..7b5686f 100644 --- a/spo2evaluation/preprocessing/data_loader_pandas.py +++ b/spo2evaluation/preprocessing/data_loader_pandas.py @@ -155,7 +155,7 @@ def __init__(self, data_path): self.meta = pd.DataFrame([data_sample_label_id, meta], ["sample_id", "fps"]).T - self.number_of_videos = self.sample_data['sample_id'].max() + self.number_of_videos = len(self.meta.index) # self.data = self.data.T print(self.sample_data) @@ -222,7 +222,7 @@ def load_pickle(self): self.ground_truths_sample = pd.read_pickle(self.path_gt) self.meta = pd.read_pickle(self.path_meta) # print("yo\n", self.sample_data.loc[self.sample_data['sample_id'] == 1]) - self.number_of_videos = self.sample_data['sample_id'].max() + self.number_of_videos = len(self.meta.index) print("Loaded", self.number_of_videos) def is_pickled(self) -> bool: diff --git a/src/evaluation/Spo2_evaluation.py b/src/evaluation/Spo2_evaluation.py index cf1c6d7..07be5ba 100644 --- a/src/evaluation/Spo2_evaluation.py +++ b/src/evaluation/Spo2_evaluation.py @@ -7,6 +7,8 @@ sys.path.append('../..') from spo2evaluation.evaluation import blant_altman from argparse import ArgumentParser +import pandas as pd +import matplotlib.pyplot as plt def main(): @@ -21,18 +23,21 @@ def main(): args = parser.parse_args() print("Launching the evaluatio for", args.data_file) + results_df = pd.read_csv(args.data_file) + + # Extract Camera data - Data_camera = [] + Data_camera = results_df['spo2_pred'] # Extract GT data - Data_gt = [] + Data_gt = results_df['spo2_gt'] # Do statistical estimation least_square_slope_1, least_square_y_intercept_1, R_and_P_1 = blant_altman.Correlation( Data_camera, Data_gt ) mean_difference_1, std_difference_1, upper_limit_1, lower_limit_1 = blant_altman.BlandAltmanPlot( - Data_camera, Data_gt + Data_camera, Data_gt, fig_num=1 ) diff --git a/src/fit_healthwatcher.py b/src/fit_healthwatcher.py new file mode 100644 index 0000000..395ed8a --- /dev/null +++ b/src/fit_healthwatcher.py @@ -0,0 +1,54 @@ +import numpy as np +from sklearn.linear_model import LinearRegression +import pandas as pd +import os + +DATA_DIR = '../data/0430/community' + +gts = pd.read_pickle(os.path.join(DATA_DIR, 'ground_truths_sample')) +meta = pd.read_pickle(os.path.join(DATA_DIR, 'meta')) +df = pd.read_pickle(os.path.join(DATA_DIR, 'sample_data')) + +df[['mean_red', 'std_red', 'mean_green', 'std_green', 'mean_blue', 'std_blue']] = df[['mean_red', 'std_red', 'mean_green', 'std_green', 'mean_blue', 'std_blue']].apply(pd.to_numeric) + +df = df.groupby(['sample_id']).mean() + +y = gts['SpO2'].to_numpy().reshape(-1,1) + +mean_red = df['mean_red'].to_numpy() +std_red = df['std_red'].to_numpy() +mean_blue = df['mean_blue'].to_numpy() +std_blue = df['std_blue'].to_numpy() +mean_green = df['mean_green'].to_numpy() +std_green = df['std_green'].to_numpy() + +X = np.array([mean_red, std_red, mean_blue, std_blue, mean_green]).T # <-- 'new' method, linear regression on all features +# X = (std_red / mean_red) / (std_blue / mean_blue).reshape(-1,1) <-- healthwatcher's method, aggregates all into 1 + +split=int(len(X)*0.75) + +X_train=X[:split] +X_test=X[split:] + +y_train=y[:split] +y_test=y[split:] + +reg = LinearRegression().fit(X_train, y_train) +print(reg.score(X, y)) +print(reg.coef_) +print(reg.intercept_) + +y_pred = reg.predict(X_test) + +import matplotlib.pyplot as plt + +plt.scatter(x=y_pred, y=y_test) +plt.xlabel('predictions') +plt.ylabel('ground truth values') +plt.show() +import time + +pd.DataFrame(data={'spo2_gt': y_test.reshape(1,-1)[0], 'spo2_pred': y_pred.reshape(1,-1)[0]}).to_csv(f'../results/hw-fit-{int(time.time())}') + + + diff --git a/src/healthwatcher.py b/src/healthwatcher.py index 0edd6c8..8bbc59c 100644 --- a/src/healthwatcher.py +++ b/src/healthwatcher.py @@ -5,6 +5,8 @@ import spo2evaluation from spo2evaluation.modelling.healthwatcher import healthwatcher from spo2evaluation.preprocessing import data_loader_pandas +import pandas as pd +import time if __name__ == "__main__": @@ -35,6 +37,12 @@ print("Picling the data") dataset.pickle_data() + predictions = {'id': [], + 'spo2_gt': [], + 'spo2_pred': [], + } + + for i in range(dataset.number_of_videos): sample, gt, meta = dataset.get_video(i) @@ -48,4 +56,16 @@ spo2 = healthwatcher.health_watcher(blue, blue_std, red, red_std, fps, smooth=False) - print(spo2) + + print(gt['path']) + survey_id = gt['path'].iloc[0].split('/')[-1].split('=')[-1] + + + predictions['id'].append(survey_id) + predictions['spo2_gt'].append(gt['SpO2'].iloc[0]) + predictions['spo2_pred'].append(spo2) + + results_df = pd.DataFrame(predictions) + + results_df.to_csv(f'../results/healthwatcher_{int(time.time())}.csv') + diff --git a/src/wang.py b/src/wang.py index 8b5772b..857a952 100644 --- a/src/wang.py +++ b/src/wang.py @@ -1,5 +1,7 @@ import cv2 -from spo2evaluation.modelling import wang_2017 +import sys +sys.path.append('..') # expected to be run from inside src/ +from spo2evaluation.modelling.wang_2017 import wang_2017 def main():