From 0bb6a8ce9d3f6fa7db5661f5ca1cb075dc7f1a30 Mon Sep 17 00:00:00 2001 From: DIANE <abderrahim.diane@cefe.cnrs.fr> Date: Mon, 9 Sep 2024 15:38:43 +0200 Subject: [PATCH] zipfile --- src/Modules.py | 14 +- src/Packages.py | 23 +- src/app.py | 2 + src/images/img-sky.jpg | Bin 0 -> 142617 bytes src/messange.png | Bin 0 -> 16670 bytes src/mod.py | 2 +- src/pages/1-samples_selection.py | 355 ++++++++++---------- src/pages/2-model_creation.py | 258 +++++++------- src/pages/3-prediction.py | 553 +++++++++++++++++-------------- src/pages/4-inputs.py | 1 + src/report/report.py | 5 +- src/style/header.py | 19 +- src/utils/DATA_HANDLING.py | 36 +- src/utils/DxReader.py | 6 +- src/utils/Evaluation_Metrics.py | 4 +- src/utils/HDBSCAN_Clustering.py | 8 +- src/utils/Hash.py | 2 +- src/utils/KMEANS_.py | 12 +- src/utils/KennardStone.py | 6 +- src/utils/LWPLSR_.py | 7 +- src/utils/Miscellaneous.py | 113 ++++++- src/utils/NMF_.py | 4 +- src/utils/PCA_.py | 8 +- src/utils/PLSR_.py | 6 +- src/utils/PLSR_Preprocess.py | 6 +- src/utils/RegModels.py | 10 +- src/utils/SK_PLSR_.py | 6 +- src/utils/UMAP_.py | 2 +- src/utils/VarSel.py | 10 +- src/utils/__init__.py | 4 +- 30 files changed, 817 insertions(+), 665 deletions(-) create mode 100644 src/images/img-sky.jpg create mode 100644 src/messange.png diff --git a/src/Modules.py b/src/Modules.py index 6d97307..d4518bd 100644 --- a/src/Modules.py +++ b/src/Modules.py @@ -1,13 +1,13 @@ from Packages import * -from Class_Mod import Plsr, LinearPCA, Umap, find_col_index, PinardPlsr, Nmf, AP -from Class_Mod import LWPLSR, list_files, metrics, TpeIpls, reg_plot, resid_plot, Sk_Kmeans, DxRead, Hdbscan, read_dx, PlsProcess -from Class_Mod.DATA_HANDLING import * -from Class_Mod.Miscellaneous import prediction, download_results, plot_spectra, local_css, desc_stats, hash_data -from Class_Mod.Hash import create_hash, check_hash -from Report import report +from utils import Plsr, LinearPCA, Umap, find_col_index, PinardPlsr, Nmf, AP +from utils import LWPLSR, list_files, metrics, TpeIpls, reg_plot, resid_plot, Sk_Kmeans, DxRead, Hdbscan, read_dx, PlsProcess +from utils.DATA_HANDLING import * +from utils.Miscellaneous import prediction, download_results, plot_spectra, local_css, desc_stats, hash_data,data_split, pred_hist +from utils.Hash import create_hash, check_hash +from report import report css_file = Path("style/") pages_folder = Path("pages/") from style.header import add_header, add_sidebar from config.config import pdflatex_path local_css(css_file / "style.css") -from Class_Mod import KS, RDM +from utils import KS, RDM diff --git a/src/Packages.py b/src/Packages.py index f2f58a2..3923d3c 100644 --- a/src/Packages.py +++ b/src/Packages.py @@ -1,6 +1,5 @@ ## Data loading, handling, and preprocessing import os -import json import glob import sys from pathlib import Path @@ -8,23 +7,23 @@ import csv import re import jcamp import random -import datetime +from datetime import datetime import numpy as np -import shutil -import pandas as pd +from shutil import rmtree, move, make_archive +from pandas import DataFrame, read_csv, concat, Series, json_normalize from itertools import combinations -import zipfile -import hashlib +from hashlib import md5 from matplotlib import colors from matplotlib.colors import Normalize -from abc import ABC,abstractmethod +from abc import ABC, abstractmethod from typing import Optional, List from sklearn.preprocessing import StandardScaler, MinMaxScaler, LabelEncoder -import time from scipy.stats import skew, kurtosis from scipy.signal import savgol_filter, find_peaks_cwt, detrend import scipy as sc -import kennard_stone as ks +from kennard_stone import train_test_split as ks_train_test_split +from kennard_stone import KFold as ks_KFold + ### Exploratory data analysis-Dimensionality reduction from umap.umap_ import UMAP from sklearn.decomposition import PCA, NMF @@ -58,7 +57,7 @@ import plotly.graph_objects as go import plotly.io as pio import matplotlib.pyplot as plt, mpld3 import seaborn as sns -import matplotlib +# import matplotlib ### Important Metrics from sklearn.metrics import pairwise_distances_argmin_min, adjusted_rand_score, adjusted_mutual_info_score @@ -66,7 +65,7 @@ from sklearn.metrics import pairwise_distances_argmin_min, adjusted_rand_score, ## Web app construction import streamlit as st from st_pages import Page, Section, show_pages, add_page_title, hide_pages -from tempfile import NamedTemporaryFile +from tempfile import NamedTemporaryFile, TemporaryDirectory # help on streamlit input https://docs.streamlit.io/library/api-reference/widgets #Library for connecting to SQL DB @@ -76,7 +75,7 @@ import pyodbc import json # save models -import joblib +from joblib import dump, load, hash # import pickle as pkl from hyperopt import fmin, hp, tpe, Trials, space_eval, STATUS_OK, anneal diff --git a/src/app.py b/src/app.py index 46b5ee0..4eb6f9c 100644 --- a/src/app.py +++ b/src/app.py @@ -4,6 +4,8 @@ st.set_page_config(page_title="NIRS Utils", page_icon=":goat:", layout="wide",) from mod import * # from utils.DATA_HANDLING import * from PIL import Image +import base64 +background_img(change=None) add_header() # add_sidebar(pages_folder) diff --git a/src/images/img-sky.jpg b/src/images/img-sky.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dd6c8febdb245c403c17c1bba5ec72d596f05731 GIT binary patch literal 142617 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	i=E^y@qTg=b5 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 Tt#9A}AH6|X!+^%0{QsK(S6TST literal 0 HcmV?d00001 diff --git a/src/messange.png b/src/messange.png new file mode 100644 index 0000000000000000000000000000000000000000..fde8399fd157796d5f7d268a7f21d09a992fb8cf GIT binary patch literal 16670 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 F2>|y!Vaxyk literal 0 HcmV?d00001 diff --git a/src/mod.py b/src/mod.py index 2b7f622..ca6a0fc 100644 --- a/src/mod.py +++ b/src/mod.py @@ -12,7 +12,7 @@ from Packages import * # from utils import read_dx, DxRead, Plsr, LinearPCA, Umap, find_col_index, PinardPlsr, Nmf, AP # from utils import LWPLSR, list_files, metrics, TpeIpls, reg_plot, resid_plot, Sk_Kmeans, DxRead, Hdbscan, read_dx, PlsProcess, PinardPlsr, Plsr from utils.DATA_HANDLING import * -from utils.Miscellaneous import prediction, download_results, plot_spectra, local_css, desc_stats, hash_data +from utils.Miscellaneous import prediction, download_results, plot_spectra, local_css, desc_stats, hash_data, hist,data_split, pred_hist,background_img from utils.Hash import create_hash, check_hash from report import report css_file = Path("style/") diff --git a/src/pages/1-samples_selection.py b/src/pages/1-samples_selection.py index e4baa2a..ae13923 100644 --- a/src/pages/1-samples_selection.py +++ b/src/pages/1-samples_selection.py @@ -1,18 +1,13 @@ from Packages import * st.set_page_config(page_title="NIRS Utils", page_icon=":goat:", layout="wide") -from utils import read_dx, DxRead, LinearPCA, Umap, find_col_index, Nmf, Sk_Kmeans, AP, KS, RDM +from utils import read_dx, DxRead, LinearPCA, Umap, find_col_index, Nmf, Sk_Kmeans, AP,Hdbscan, KS, RDM from mod import * # HTML pour le bandeau "CEFE - CNRS" add_header() add_sidebar(pages_folder) local_css(css_file / "style_model.css")#load specific model page css - - - - - - +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ hash_ = '' def p_hash(add): @@ -22,17 +17,19 @@ def p_hash(add): # #################################### Methods ############################################## # empty temp figures +report_path = Path("report") +report_path_rel = Path("./report") +# st.write(os.listdir(report_path)) + def delete_files(keep): supp = [] # Walk through the directory - for root, dirs, files in os.walk('report/', topdown=False): + for root, dirs, files in os.walk(report_path, topdown=False): for file in files: if file != 'logo_cefe.png' and not any(file.endswith(ext) for ext in keep): os.remove(os.path.join(root, file)) - -dirpath = Path('report/out/model') -if dirpath.exists() and dirpath.is_dir(): - shutil.rmtree(dirpath) +if Path('report/out/model').exists() and Path('report/out/model').is_dir(): + rmtree(Path('report/out/model')) # algorithms available on our app dim_red_methods=['PCA','UMAP', 'NMF'] # List of dimensionality reduction algos @@ -69,21 +66,21 @@ delete_files(keep = ['.py', '.pyc','.bib']) # ####################################### page preamble ####################################### st.title("Calibration Subset Selection") # page title st.markdown("Create a predictive model, then use it for predicting your target variable (chemical data) from NIRS spectra") -col2, col1 = st.columns([3, 1]) -col2.image("./images/sample selection.png", use_column_width=True) # graphical abstract +c1, c2 = st.columns([3, 1]) +c1.image("./images/sample selection.png", use_column_width=True) # graphical abstract ################################### I - Data Loading and Visualization ######################################## files_format = ['csv', 'dx'] # Supported files format # loader for datafile -file = col1.file_uploader("Data file", type=["csv","dx"], help=" :mushroom: select a csv matrix with samples as rows and lambdas as columns", key=5) +file = c2.file_uploader("Data file", type=["csv","dx"], help=" :mushroom: select a csv matrix with samples as rows and lambdas as columns", key=5) ## Preallocation of data structure -spectra = pd.DataFrame() -meta_data = pd.DataFrame() -tcr=pd.DataFrame() -sam=pd.DataFrame() -sam1=pd.DataFrame() -selected_samples = pd.DataFrame() +spectra = DataFrame() +meta_data = DataFrame() +tcr=DataFrame() +sam=DataFrame() +sam1=DataFrame() +selected_samples = DataFrame() non_clustered = None l1 = [] labels = [] @@ -92,12 +89,12 @@ dr_model = None # dimensionality reduction model cl_model = None # clustering model selection = None selection_number = "None" -samples_df_chem = pd.DataFrame +samples_df_chem = DataFrame selected_samples = [] selected_samples_idx = [] if not file: - col1.info('Info: Please load data file !') + c2.info('Info: Please load data file !') else: extension = file.name.split(".")[-1] @@ -106,14 +103,14 @@ else: match extension: ## Load .csv file case 'csv': - with col1: + with c2: psep = st.radio("Select csv separator - _detected_: ", options = [";", ","],horizontal=True, key=9) phdr = st.radio("indexes column in csv? - _detected_: " , options = ["no", "yes"],horizontal=True, key=31) if phdr == 'yes':col = 0 else:col = False - # with col1: + # with c2: # # Select list for CSV delimiter # psep = st.radio("Select csv separator - _detected_: " + str(find_delimiter('data/'+file.name)), options = [";", ","], index = [";", ","].index(str(find_delimiter('data/'+file.name))),horizontal=True, key=9) # # Select list for CSV header True / False @@ -130,7 +127,7 @@ else: @st.cache_data def csv_loader(change): - imp = pd.read_csv(file, sep = psep, index_col=col) + imp = read_csv(file, sep = psep, index_col=col) spectra, md_df_st_ = col_cat(imp) meta_data = md_df_st_ return spectra, md_df_st_, meta_data, imp @@ -148,7 +145,7 @@ else: ## Load .dx file case 'dx': - with col1: + with c2: # Create a temporary file to save the uploaded file with NamedTemporaryFile(delete=False, suffix=".dx") as tmp: tmp.write(file.read()) @@ -187,47 +184,49 @@ if not spectra.empty: @st.cache_data def spectra_visualize(change): - fig, ax = plt.subplots(figsize = (30,7)) - if extension =='dx': - lab = ['Wavenumber (1/cm)' if meta_data.loc[:,'xunits'][0] == '1/cm' else 'Wavelength (nm)'] - if lab[0] =='Wavenumber (1/cm)': - spectra.T.plot(legend=False, ax = ax).invert_xaxis() - else : - spectra.T.plot(legend=False, ax = ax) - ax.set_xlabel(lab[0], fontsize=18) - else: - spectra.T.plot(legend=False, ax = ax) - ax.set_xlabel('Wavelength/Wavenumber', fontsize=18) + # fig, ax = plt.subplots(figsize = (30,7)) - ax.set_ylabel('Signal intensity', fontsize=18) - plt.margins(x = 0) - plt.tight_layout() + # if extension =='dx': + # lab = ['Wavenumber (1/cm)' if meta_data.loc[:,'xunits'][0] == '1/cm' else 'Wavelength (nm)'] + # if lab[0] =='Wavenumber (1/cm)': + # spectra.T.plot(legend=False, ax = ax).invert_xaxis() + # else : + # spectra.T.plot(legend=False, ax = ax) + # ax.set_xlabel(lab[0], fontsize=18) + # else: + # spectra.T.plot(legend=False, ax = ax) + # ax.set_xlabel('Wavelength/Wavenumber', fontsize=18) - data_info = pd.DataFrame({'Name': [file.name], + # ax.set_ylabel('Signal intensity', fontsize=18) + # plt.margins(x = 0) + # plt.tight_layout() + fig = plot_spectra(spectra, xunits = 'Wavelength/Wavenumber', yunits = "Signal intensity") + + data_info = DataFrame({'Name': [file.name], 'Number of scanned samples': [n_samples]}, index = ['Input file']) - # update lines size to export for report - for line in ax.get_lines(): - line.set_linewidth(0.8) # Set the desired line width here - - # Update the size of plot axis for exprotation to report - l, w = fig.get_size_inches() - fig.set_size_inches(8, 3) - for label in (ax.get_xticklabels()+ax.get_yticklabels()): - ax.xaxis.label.set_size(9.5) - ax.yaxis.label.set_size(9.5) - plt.tight_layout() - fig.set_size_inches(l, w)# reset the plot size to its original size + # # update lines size to export for report + # for line in ax.get_lines(): + # line.set_linewidth(0.8) # Set the desired line width here + + # # Update the size of plot axis for exprotation to report + # l, w = fig.get_size_inches() + # fig.set_size_inches(8, 3) + # for label in (ax.get_xticklabels()+ax.get_yticklabels()): + # ax.xaxis.label.set_size(9.5) + # ax.yaxis.label.set_size(9.5) + # plt.tight_layout() + # fig.set_size_inches(l, w)# reset the plot size to its original size return fig, data_info fig_spectra, data_info = spectra_visualize(change = hash_) - col1, col2 = st.columns([3, 1]) - with col1: + c3, c4 = st.columns([3, 1]) + with c3: st.pyplot(fig_spectra) - with col2: + with c4: st.info('Information on the loaded data file') st.write(data_info) ## table showing the number of samples in the data file @@ -237,13 +236,13 @@ if not spectra.empty: st.header("II - Exploratory Data Analysis-Multivariable Data Analysis", divider='blue') ###### 1- Dimensionality reduction ###### -t = pd.DataFrame # scores -p = pd.DataFrame # loadings +t = DataFrame # scores +p = DataFrame # loadings if not spectra.empty: xc = standardize(spectra, center=True, scale=False) - bb1, bb2, bb3, bb4, bb5, bb6, bb7 = st.columns([1,1,0.6,0.6,0.6,1.5,1.5]) - with bb1: + c5, c6, c7, c8, c9, c10, c11 = st.columns([1, 1, 0.6, 0.6, 0.6, 1.5, 1.5]) + with c5: dim_red_method = st.selectbox("Dimensionality reduction techniques: ", options = ['']+dim_red_methods, index = default_reduction_option, key = 37, format_func = lambda x: x if x else "<Select>") if dim_red_method == '': st.info('Info: Select a dimensionality reduction technique!') @@ -284,9 +283,9 @@ if not spectra.empty: if dr_model: - axis1 = bb3.selectbox("x-axis", options = dr_model.scores_.columns, index=0) - axis2 = bb4.selectbox("y-axis", options = dr_model.scores_.columns, index=1) - axis3 = bb5.selectbox("z-axis", options = dr_model.scores_.columns, index=2) + axis1 = c7.selectbox("x-axis", options = dr_model.scores_.columns, index=0) + axis2 = c8.selectbox("y-axis", options = dr_model.scores_.columns, index=1) + axis3 = c9.selectbox("z-axis", options = dr_model.scores_.columns, index=2) axis = np.unique([axis1, axis2, axis3]) p_hash(axis) t = dr_model.scores_.loc[:,np.unique(axis)] @@ -298,38 +297,26 @@ if not t.empty: non_clustered = None if dim_red_method == 'UMAP': - scores = st.container() + c12 = st.container() else: - scores, loadings= st.columns([3,3]) + c12, c13 = st.columns([3,3]) if not spectra.empty: - sel_ratio = bb2.number_input('Enter the number/fraction of samples to be selected:',min_value=0.01, max_value=float("{:.2f}".format(spectra.shape[0])), value=0.20, format="%.2f", disabled= disablewidgets) - if sel_ratio: - p_hash(sel_ratio) - if sel_ratio > 1.00: - ratio = int(sel_ratio) - elif sel_ratio < 1.00: - ratio = int(sel_ratio*spectra.shape[0]) -if dr_model and not clus_method: - clus_method = bb2.radio('Select samples selection strategy:', - options = ['RDM', 'KS'],) -elif dr_model and clus_method: - # sel_ratio = bb2.number_input('Enter the ratio/precentage of samples to be selected:',min_value=0.01, max_value=float("{:.2f}".format(spectra.shape[0])), value=0.20, format="%.2f") - # p_hash(sel_ratio) - # if sel_ratio > 1.00: - # ratio = int(sel_ratio) - # elif sel_ratio < 1.00: - # ratio = int(sel_ratio*spectra.shape[0]) - - if clus_method in cluster_methods: - selection = bb2.radio('Select samples selection strategy:', - options = selec_strategy, index = default_sample_selection_option,key=102,disabled = False) - else: - selection = bb2.radio('Select samples selection strategy:', - options = selec_strategy, horizontal=True, key=102,disabled = True) - + with c6: + sel_ratio = st.number_input('Enter the number/fraction of samples to be selected:',min_value=0.01, max_value=float("{:.2f}".format(spectra.shape[0])), value=0.20, format="%.2f", disabled= disablewidgets) + if sel_ratio: + if sel_ratio > 1.00: + ratio = int(sel_ratio) + elif sel_ratio < 1.00: + ratio = int(sel_ratio*spectra.shape[0]) + p_hash(sel_ratio) + if dr_model and not clus_method: + clus_method = st.radio('Select samples selection strategy:', options = ['RDM', 'KS']) + elif dr_model and clus_method: + disabled1 = False if clus_method in cluster_methods else True + selection = st.radio('Select samples selection strategy:', options = selec_strategy, index = default_sample_selection_option, key=102, disabled = disabled1) @@ -359,9 +346,6 @@ if dr_model and sel_ratio: case 'RDM': cl_model = RDM(x = tcr, rset = ratio) - # if clus_method in cluster_methods: - # inf.empty() - if clus_method in ['KS', 'RDM']: _, selected_samples_idx = cl_model.calset labels = ["ind"]*n_samples @@ -373,8 +357,6 @@ if dr_model and sel_ratio: # #################################################### III - Samples selection using the reduced data presentation ###### - - if not labels: custom_color_palette = px.colors.qualitative.Plotly[:1] elif labels: @@ -397,18 +379,14 @@ elif labels: for i in np.unique(s): C = np.where(np.array(labels) == i)[0] if C.shape[0] >= selection_number: - # scores.write(list(tcr.index)[labels== i]) km2 = KMeans(n_clusters = selection_number) km2.fit(tcr.iloc[C,:]) clos, _ = pairwise_distances_argmin_min(km2.cluster_centers_, tcr.iloc[C,:]) selected_samples_idx.extend(tcr.iloc[C,:].iloc[list(clos)].index) else: selected_samples_idx.extend(new_tcr.iloc[C,:].index.to_list()) - # list indexes of selected samples for colored plot - -# ################################ Plots visualization ############################################ - +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ results visualization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## Scores if not t.empty: if meta_data.empty and clus_method in cluster_methods: @@ -420,7 +398,7 @@ if not t.empty: elif meta_data.empty and not clus_method in cluster_methods: filter = [] - with scores: + with c12: st.write('Scores plot') tcr_plot = tcr.copy() colfilter = st.selectbox('Color by:', options= filter,format_func = lambda x: x if x else "<Select>") @@ -436,59 +414,58 @@ if not t.empty: n_categories = len(np.unique(tcr_plot[col_var_name])) custom_color_palette = px.colors.qualitative.Plotly[:n_categories] - with scores: - if selected_samples_idx:# color selected samples - t_selected = tcr_plot.iloc[selected_samples_idx,:] - match t.shape[1]: - case 3: - fig = px.scatter_3d(tcr_plot, x = axis[0], y = axis[1], z = axis[2], color = col_var_name ,color_discrete_sequence = custom_color_palette) - fig.update_traces(marker=dict(size=4)) - if selected_samples_idx:# color selected samples - fig.add_scatter3d(x = t_selected.loc[:,axis[0]], y = t_selected.loc[:,axis[1]], z = t_selected.loc[:,axis[2]], - mode ='markers', marker = dict(size = 5, color = 'black'), name = 'selected samples') - - case 2: - fig = px.scatter(tcr_plot, x = axis[0], y = axis[1], color = col_var_name ,color_discrete_sequence = custom_color_palette) - if selected_samples_idx:# color selected samples - fig.add_scatter(x = t_selected.loc[:,axis[0]], y = t_selected.loc[:,axis[1]], - mode ='markers', marker = dict(size = 5, color = 'black'), name = 'selected samples') - + if selected_samples_idx:# color selected samples + t_selected = tcr_plot.iloc[selected_samples_idx,:] + match t.shape[1]: + case 3: + fig = px.scatter_3d(tcr_plot, x = axis[0], y = axis[1], z = axis[2], color = col_var_name ,color_discrete_sequence = custom_color_palette) + fig.update_traces(marker=dict(size=4)) + if selected_samples_idx:# color selected samples + fig.add_scatter3d(x = t_selected.loc[:,axis[0]], y = t_selected.loc[:,axis[1]], z = t_selected.loc[:,axis[2]], + mode ='markers', marker = dict(size = 5, color = 'black'), name = 'selected samples') - case 1: - fig = px.scatter(tcr_plot, x = axis[0], y = [0]*tcr_plot.shape[0], color = col_var_name ,color_discrete_sequence = custom_color_palette) - fig.add_scatter(x = t_selected.loc[:,axis[0]], y = [0]*tcr_plot.shape[0], - mode ='markers', marker = dict(size = 5, color = 'black'), name = 'selected samples') - fig.update_yaxes(visible=False) - - st.plotly_chart(fig, use_container_width = True) - - if labels: - fig_export = {} - # export 2D scores plot - if len(axis)== 3: - comb = [i for i in combinations(np.arange(len(axis)), 2)] - subcap = ['a','b','c'] - for i in range(len(comb)): - fig_= px.scatter(tcr_plot, x = axis[(comb[i][0])], y=axis[(comb[i][1])],color = labels if list(labels) else None,color_discrete_sequence = custom_color_palette) - fig_.add_scatter(x = t_selected.loc[:,axis[(comb[i][0])]], y = t_selected.loc[:,axis[(comb[i][1])]], mode ='markers', marker = dict(size = 5, color = 'black'), - name = 'selected samples') - fig_.update_layout(font=dict(size=23)) - fig_.add_annotation(text= f'({subcap[i]})', align='center', showarrow= False, xref='paper', yref='paper', x=-0.13, y= 1, - font= dict(color= "black", size= 35), bgcolor ='white', borderpad= 2, bordercolor= 'black', borderwidth= 3) - fig_.update_traces(marker=dict(size= 10), showlegend= False) - fig_export[f'scores_pc{comb[i][0]}_pc{comb[i][1]}'] = fig_ - # fig_export.write_image(f'./report/out/figures/scores_pc{str(comb[i][0])}_pc{str(comb[i][1])}.png') - else: - fig_export['fig'] = fig + case 2: + fig = px.scatter(tcr_plot, x = axis[0], y = axis[1], color = col_var_name ,color_discrete_sequence = custom_color_palette) + if selected_samples_idx:# color selected samples + fig.add_scatter(x = t_selected.loc[:,axis[0]], y = t_selected.loc[:,axis[1]], + mode ='markers', marker = dict(size = 5, color = 'black'), name = 'selected samples') + + + case 1: + fig = px.scatter(tcr_plot, x = axis[0], y = [0]*tcr_plot.shape[0], color = col_var_name ,color_discrete_sequence = custom_color_palette) + fig.add_scatter(x = t_selected.loc[:,axis[0]], y = [0]*tcr_plot.shape[0], + mode ='markers', marker = dict(size = 5, color = 'black'), name = 'selected samples') + fig.update_yaxes(visible=False) + + st.plotly_chart(fig, use_container_width = True) + + if labels: + fig_export = {} + # export 2D scores plot + if len(axis)== 3: + comb = [i for i in combinations(np.arange(len(axis)), 2)] + subcap = ['a','b','c'] + for i in range(len(comb)): + fig_= px.scatter(tcr_plot, x = axis[(comb[i][0])], y=axis[(comb[i][1])],color = labels if list(labels) else None,color_discrete_sequence = custom_color_palette) + fig_.add_scatter(x = t_selected.loc[:,axis[(comb[i][0])]], y = t_selected.loc[:,axis[(comb[i][1])]], mode ='markers', marker = dict(size = 5, color = 'black'), + name = 'selected samples') + fig_.update_layout(font=dict(size=23)) + fig_.add_annotation(text= f'({subcap[i]})', align='center', showarrow= False, xref='paper', yref='paper', x=-0.13, y= 1, + font= dict(color= "black", size= 35), bgcolor ='white', borderpad= 2, bordercolor= 'black', borderwidth= 3) + fig_.update_traces(marker=dict(size= 10), showlegend= False) + fig_export[f'scores_pc{comb[i][0]}_pc{comb[i][1]}'] = fig_ + # fig_export.write_image(f'./report/out/figures/scores_pc{str(comb[i][0])}_pc{str(comb[i][1])}.png') + else: + fig_export['fig'] = fig if not spectra.empty: if dim_red_method in ['PCA','NMF']: - with loadings: + with c13: st.write('Loadings plot') p = dr_model.loadings_ - freq = pd.DataFrame(colnames, index=p.index) + freq = DataFrame(colnames, index=p.index) if extension =='dx': if meta_data.loc[:,'xunits'][0] == '1/cm': freq.columns = ['Wavenumber (1/cm)'] @@ -503,7 +480,7 @@ if not spectra.empty: xlab = 'Wavelength/Wavenumber' inv = None - pp = pd.concat([p, freq], axis=1) + pp = concat([p, freq], axis=1) ######################################### df1 = pp.melt(id_vars=freq.columns) loadingsplot = px.line(df1, x=freq.columns, y='value', color='variable', color_discrete_sequence=px.colors.qualitative.Plotly) @@ -516,8 +493,8 @@ if not spectra.empty: ############################################################################################################# if dim_red_method == 'PCA': - influence, hotelling = st.columns([3, 3]) - with influence: + c14, c15 = st.columns([3, 3]) + with c14: st.write('Influence plot') # Laverage Hat = t.to_numpy() @ np.linalg.inv(np.transpose(t.to_numpy()) @ t.to_numpy()) @ np.transpose(t.to_numpy()) @@ -588,7 +565,7 @@ if not spectra.empty: # influence_plot.write_image('./report/out/figures/influence_plot.png', engine = 'kaleido') - with hotelling: + with c15: st.write('T²-Hotelling vs Q-residuals plot') # Hotelling hotelling = t.var(axis = 1) @@ -635,11 +612,11 @@ if not spectra.empty: st.header('III - Selected Samples for Reference Analysis', divider='blue') if labels: - sel, info = st.columns([3, 1]) - sel.write("Tabular identifiers of selected samples for reference analysis:") + c16, c17 = st.columns([3, 1]) + c16.write("Tabular identifiers of selected samples for reference analysis:") if selected_samples_idx: if meta_data.empty: - sam1 = pd.DataFrame({'name': spectra.index[clustered][selected_samples_idx], + sam1 = DataFrame({'name': spectra.index[clustered][selected_samples_idx], 'cluster':np.array(labels)[clustered][selected_samples_idx]}, index = selected_samples_idx) else: @@ -647,18 +624,18 @@ if labels: sam1.insert(loc=0, column='index', value=selected_samples_idx) sam1.insert(loc=1, column='cluster', value=np.array(labels)[selected_samples_idx]) sam1.index = np.arange(len(selected_samples_idx))+1 - info.info(f'Information !\n - The total number of samples: {n_samples}.\n- The number of samples selected for reference analysis: {sam1.shape[0]}.\n - The proportion of samples selected for reference analysis: {round(sam1.shape[0]/n_samples*100)}%.') + with c17: + st.info(f'Information !\n - The total number of samples: {n_samples}.\n- The number of samples selected for reference analysis: {sam1.shape[0]}.\n - The proportion of samples selected for reference analysis: {round(sam1.shape[0]/n_samples*100)}%.') sam = sam1 - # if clus_method == cluster_methods[2]: - # unclus = sel.checkbox("Include non clustered samples (for HDBSCAN clustering)", value=True) - if clus_method == cluster_methods[2]: - unclus = sel.checkbox("Include non clustered samples (for HDBSCAN clustering)", value=True) + if clus_method =='HDBSCAN': + with c16: + unclus = st.checkbox("Include non clustered samples (for HDBSCAN clustering)", value=True) if selected_samples_idx: if unclus: if meta_data.empty: - sam2 = pd.DataFrame({'name': spectra.index[non_clustered], + sam2 = DataFrame({'name': spectra.index[non_clustered], 'cluster':['Non clustered']*len(spectra.index[non_clustered])}, index = spectra.index[non_clustered]) else : @@ -666,15 +643,18 @@ if labels: sam2.insert(loc=0, column='index', value= spectra.index[non_clustered]) sam2.insert(loc=1, column='cluster', value=['Non clustered']*len(spectra.index[non_clustered])) - sam = pd.concat([sam1, sam2], axis = 0) + sam = concat([sam1, sam2], axis = 0) sam.index = np.arange(sam.shape[0])+1 - info.info(f'- The number of Non-clustered samples: {sam2.shape[0]}.\n - The proportion of Non-clustered samples: {round(sam2.shape[0]/n_samples*100)}%') + with c17: + st.info(f'- The number of Non-clustered samples: {sam2.shape[0]}.\n - The proportion of Non-clustered samples: {round(sam2.shape[0]/n_samples*100)}%') else: sam = sam1 - sel.write(sam) + with c16: + st.write(sam) if not sam.empty: + zip_data = "" Nb_ech = str(n_samples) nb_clu = str(sam1.shape[0]) st.header('Download the analysis results') @@ -688,9 +668,9 @@ if not sam.empty: latex_report = report.report('Representative subset selection', file.name, dim_red_method, clus_method, Nb_ech, ncluster, selection, selection_number, nb_clu,tcr, sam) - @st.cache_data def preparing_results_for_downloading(change): + # path_to_report = Path("report")############################### i am here match extension: # load csv file case 'csv': @@ -699,32 +679,32 @@ if not sam.empty: with open('report/out/dataset/'+file.name, 'w') as dd: dd.write(dxdata) - fig_spectra.savefig("./report/out/figures/spectra_plot.png", dpi=400) ## Export report + fig_spectra.savefig(report_path_rel/"out/figures/spectra_plot.png", dpi=400) ## Export report if len(axis) == 3: for i in range(len(comb)): - fig_export[f'scores_pc{comb[i][0]}_pc{comb[i][1]}'].write_image(f'./report/out/figures/scores_pc{str(comb[i][0]+1)}_pc{str(comb[i][1]+1)}.png') + fig_export[f'scores_pc{comb[i][0]}_pc{comb[i][1]}'].write_image(report_path_rel/f'out/figures/scores_pc{str(comb[i][0]+1)}_pc{str(comb[i][1]+1)}.png') elif len(axis)==2 : - fig_export['fig'].write_image(f'./report/out/figures/scores_plot2D.png') + fig_export['fig'].write_image(report_path_rel/'out/figures/scores_plot2D.png') elif len(axis)==1 : - fig_export['fig'].write_image(f'./report/out/figures/scores_plot1D.png') + fig_export['fig'].write_image(report_path_rel/'out/figures/scores_plot1D.png') # Export du graphique if dim_red_method in ['PCA','NMF']: img = pio.to_image(loadingsplot, format="png") - with open("./report/out/figures/loadings_plot.png", "wb") as f: + with open(report_path_rel/"out/figures/loadings_plot.png", "wb") as f: f.write(img) if dim_red_method == 'PCA': - hotelling_plot.write_image("./report/out/figures/hotelling_plot.png", format="png") - influence_plot.write_image('./report/out/figures/influence_plot.png', engine = 'kaleido') + hotelling_plot.write_image(report_path_rel/"out/figures/hotelling_plot.png", format="png") + influence_plot.write_image(report_path_rel/'out/figures/influence_plot.png', engine = 'kaleido') - sam.to_csv('./report/out/Selected_subset_for_calib_development.csv', sep = ';') + sam.to_csv(report_path_rel/'out/Selected_subset_for_calib_development.csv', sep = ';') export_report(change = hash_) - if Path("./report/report.tex").exists(): + if Path(report_path_rel/"report.tex").exists(): report.generate_report(change = hash_) - if Path("./report/report.pdf").exists(): - shutil.move("./report/report.pdf", "./report/out/report.pdf") + if Path(report_path_rel/"report.pdf").exists(): + move(report_path_rel/"report.pdf", "./report/out/report.pdf") return change @@ -733,25 +713,28 @@ if not sam.empty: - import tempfile @st.cache_data def tempdir(change): - with tempfile.TemporaryDirectory( prefix="results", dir="./report") as temp_dir:# create a temp directory + with TemporaryDirectory( prefix="results", dir="./report") as temp_dir:# create a temp directory tempdirname = os.path.split(temp_dir)[1] - if len(os.listdir('./report/out/figures/'))>=2: - shutil.make_archive(base_name="./report/Results", format="zip", base_dir="out", root_dir = "./report")# create a zip file - shutil.move("./report/Results.zip", f"./report/{tempdirname}/Results.zip")# put the inside the temp dir - with open(f"./report/{tempdirname}/Results.zip", "rb") as f: + if len(os.listdir(report_path_rel/'out/figures/'))>=2: + make_archive(base_name= report_path_rel/"Results", format="zip", base_dir="out", root_dir = "./report")# create a zip file + move(report_path_rel/"Results.zip", f"./report/{tempdirname}/Results.zip")# put the inside the temp dir + with open(report_path_rel/f"{tempdirname}/Results.zip", "rb") as f: zip_data = f.read() return tempdirname, zip_data - - date_time = datetime.datetime.now().strftime('%y%m%d%H%M') + try : tempdirname, zip_data = tempdir(change = hash_) - st.download_button(label = 'Download', data = zip_data, file_name = f'Nirs_Workflow_{date_time}_SamSel_.zip', mime ="application/zip", - args = None, kwargs = None,type = "primary",use_container_width = True) + # st.download_button(label = 'Download', data = zip_data, file_name = f'Nirs_Workflow_{date_time}_SamSel_.zip', mime ="application/zip", + # args = None, kwargs = None,type = "primary",use_container_width = True) except: pass + date_time = datetime.now().strftime('%y%m%d%H%M') + disabled_down = True if zip_data == '' else False + st.download_button(label = 'Download', data = zip_data, file_name = f'Nirs_Workflow_{date_time}_SamSel_.zip', mime ="application/zip", + args = None, kwargs = None,type = "primary",use_container_width = True, disabled = disabled_down) + - delete_files(keep = ['.py', '.pyc','.bib']) \ No newline at end of file + delete_files(keep = ['.py', '.pyc','.bib']) \ No newline at end of file diff --git a/src/pages/2-model_creation.py b/src/pages/2-model_creation.py index 686d915..06b0554 100644 --- a/src/pages/2-model_creation.py +++ b/src/pages/2-model_creation.py @@ -12,7 +12,6 @@ local_css(css_file / "style_model.css")#load specific model page css - hash_ = '' def p_hash(add): global hash_ @@ -37,7 +36,7 @@ class lw: def __init__(self, Reg_json, pred): self.model_ = Reg_json['model'] self.best_hyperparams_ = Reg_json['best_lwplsr_params'] - self.pred_data_ = [pd.json_normalize(Reg_json[i]) for i in pred] + self.pred_data_ = [json_normalize(Reg_json[i]) for i in pred] ################ clean the results dir ############# @@ -49,58 +48,37 @@ if not dirpath.exists(): # ####################################### page preamble ####################################### st.title("Calibration Model Development") # page title st.markdown("Create a predictive model, then use it for predicting your target variable (chemical data) from NIRS spectra") -M0, M00 = st.columns([1, .4]) -M0.image("./images/model_creation.png", use_column_width = True) # graphical abstract +c0, c1 = st.columns([1, .4]) +c0.image("./images/model_creation.png", use_column_width = True) # graphical abstract ################################################################# Begin : I- Data loading and preparation ###################################### files_format = ['csv', 'dx'] # Supported files format -file = M00.radio('Select files format:', options = files_format,horizontal = True) # Select a file format +file = c1.radio('Select files format:', options = files_format,horizontal = True) # Select a file format -spectra = pd.DataFrame() # preallocate the spectral data block -y = pd.DataFrame() # preallocate the target(s) data block +spectra = DataFrame() # preallocate the spectral data block +y = DataFrame() # preallocate the target(s) data block match file: # load csv file case 'csv': - with M00: + with c1: # Load X-block data xcal_csv = st.file_uploader("Select NIRS Data", type = "csv", help = " :mushroom: select a csv matrix with samples as rows and lambdas as columns") if xcal_csv: - sepx = st.radio("Select separator (X file): " , - options = [";", ","], key = 0,horizontal = True) - hdrx = st.radio("samples name (X file): ", - options = ["no", "yes"], key = 1,horizontal = True) - - # sepx = st.radio("Select separator (X file) - _detected_: " + str(find_delimiter('data/'+xcal_csv.name)), - # options = [";", ","], index = [";", ","].index(str(find_delimiter('data/'+xcal_csv.name))), key = 0,horizontal = True) - # hdrx = st.radio("samples name (X file)? - _detected_: " + str(find_col_index('data/'+xcal_csv.name)), - # options = ["no", "yes"], index = ["no", "yes"].index(str(find_col_index('data/'+xcal_csv.name))), key = 1,horizontal = True) - - match hdrx: - case "yes":col = 0 - case "no":col = False - - + sepx = st.radio("Select separator (X file): " , options = [";", ","], key = 0,horizontal = True) + hdrx = st.checkbox("Samples name (X file): ") + colx = 0 if hdrx else False else: st.info('Info: Insert your spectral data file above!') # Load Y-block data ycal_csv = st.file_uploader("Select corresponding Chemical Data", type = "csv", help = " :mushroom: select a csv matrix with samples as rows and chemical values as a column") if ycal_csv: - sepy = st.radio("Select separator (Y file): " , - options = [";", ","], key = 2, horizontal = True) - hdry = st.radio("samples name (Y file)?: ", - options = ["no", "yes"], key = 3, horizontal = True) - - # sepy = st.radio("Select separator (Y file) - _detected_: " + str(find_delimiter('data/'+ycal_csv.name)), - # options = [";", ","], index = [";", ","].index(str(find_delimiter('data/'+ycal_csv.name))), key = 2, horizontal = True) - # hdry = st.radio("samples name (Y file)? - _detected_: " + str(find_col_index('data/'+ycal_csv.name)), - # options = ["no", "yes"], index = ["no", "yes"].index(str(find_col_index('data/'+ycal_csv.name))), key = 3, horizontal = True) - match hdry: - case "yes": - col = 0 - case "no": - col = False + sepy = st.radio("Select separator (Y file): ", options = [";", ","], key = 2, horizontal = True) + hdry = st.checkbox("samples name (Y file)?: ") + coly = 0 if hdry else False + + else: st.info('Info: Insert your target data file above!') @@ -121,8 +99,8 @@ match file: def csv_loader(change): delete_files(keep = ['.py', '.pyc','.bib']) file_name = str(xcal_csv.name) +' and '+ str(ycal_csv.name) - xfile = pd.read_csv(xcal_csv, decimal = '.', sep = sepx, index_col = col, header = 0) - yfile = pd.read_csv(ycal_csv, decimal = '.', sep = sepy, index_col = col) + xfile = read_csv(xcal_csv, decimal = '.', sep = sepx, index_col = colx, header = 0) + yfile = read_csv(ycal_csv, decimal = '.', sep = sepy, index_col = coly) return xfile, yfile, file_name xfile, yfile, file_name = csv_loader(change = hash_) @@ -136,7 +114,7 @@ match file: spectra, meta_data = col_cat(xfile) except: st.error('Error: The format of the X-file does not correspond to the expected dialect settings. To read the file correctly, please adjust the separator parameters.') - spectra = pd.DataFrame(spectra).astype(float) + spectra = DataFrame(spectra).astype(float) # prepare y data try: @@ -146,27 +124,28 @@ match file: if 'chem_data' in globals(): if chem_data.shape[1]>1: - yname = M00.selectbox('Select a target', options = ['']+chem_data.columns.tolist(), format_func = lambda x: x if x else "<Select>") + yname = c1.selectbox('Select a target', options = ['']+chem_data.columns.tolist(), format_func = lambda x: x if x else "<Select>") if yname: y = chem_data.loc[:, yname] else: - M00.info('Info: Select the target analyte from the drop down list!') - else: + c1.info('Info: Select the target analyte from the drop down list!') + elif chem_data.shape[1] == 1: y = chem_data.iloc[:, 0] + yname = chem_data.iloc[:, [0]].columns[0] ### warning if not y.empty: if spectra.shape[0] != y.shape[0]: st.error('Error: X and Y have different sample size') - y = pd.DataFrame - spectra = pd.DataFrame + y = DataFrame + spectra = DataFrame else: st.error('Error: The data has not been loaded successfully, please consider tuning the dialect settings!') # Load .dx file case 'dx': - with M00: + with c1: data_file = st.file_uploader("Select Data", type = ".dx", help = " :mushroom: select a dx file") if data_file: file_name = str(data_file.name) @@ -217,47 +196,31 @@ st.header("I - Data visualization", divider = 'blue') if not spectra.empty and not y.empty: p_hash(y) p_hash(np.mean(spectra)) - @st.cache_data(show_spinner =False) - def visualize(change): - if np.array(spectra.columns).dtype.kind in ['i', 'f']: - colnames = spectra.columns - else: - colnames = np.arange(spectra.shape[1]) - - - # Split data into training and test sets using the kennard_stone method and correlation metric, 25% of data is used for testing - train_index, test_index = train_test_split_idx(spectra, y = y, method = "kennard_stone", metric = "correlation", test_size = 0.25, random_state = 42) - - # Assign data to training and test sets - X_train, y_train = pd.DataFrame(spectra.iloc[train_index,:]), y.iloc[train_index] - X_test, y_test = pd.DataFrame(spectra.iloc[test_index,:]), y.iloc[test_index] - + if np.array(spectra.columns).dtype.kind in ['i', 'f']: + colnames = spectra.columns + else: + colnames = np.arange(spectra.shape[1]) + + X_train, X_test, y_train, y_test, train_index, test_index = data_split(x=spectra, y=y) + - #### insight on loaded data - # M0, M000 = st.columns([1, .4]) - fig1, ax1 = plt.subplots( figsize = (12, 3)) - spectra.T.plot(legend = False, ax = ax1, linestyle = '-', linewidth = 0.6) - ax1.set_ylabel('Signal intensity') - ax1.margins(0) - plt.tight_layout() - fig2, ax2 = plt.subplots(figsize = (12,3)) - sns.histplot(y, color = "deeppink", kde = True, label = "y", ax = ax2, fill = True) - sns.histplot(y_train, color = "blue", kde = True, label = "y (train)", ax = ax2, fill = True) - sns.histplot(y_test, color = "green", kde = True, label = "y (test)", ax = ax2, fill = True) - ax2.set_xlabel('y') - plt.legend() - plt.tight_layout() - stats = pd.DataFrame([desc_stats(y_train), desc_stats(y_test), desc_stats(y)], index =['train', 'test', 'total'] ).round(2) - return X_train, X_test, y_train, y_test, colnames, train_index, test_index, stats, fig1, fig2 + #### insight on loaded data + spectra_plot = plot_spectra(spectra, xunits = 'Wavelength/Wavenumber', yunits = "Signal intensity") + target_plot = hist(y = y, y_train = y_train, y_test = y_test, target_name=yname) + stats = DataFrame([desc_stats(y_train), desc_stats(y_test), desc_stats(y)], index =['train', 'test', 'total'] ).round(2) - X_train, X_test, y_train, y_test, colnames, train_index, test_index, stats, spectra_plot, target_plot = visualize(change = hash_) - M0, M000 = st.columns([1, .4]) - with M0: + # fig1, ax1 = plt.subplots( figsize = (12, 3)) + # spectra.T.plot(legend = False, ax = ax1, linestyle = '-', linewidth = 0.6) + # ax1.set_ylabel('Signal intensity') + # ax1.margins(0) + # plt.tight_layout() + c2, c3 = st.columns([1, .4]) + with c2: st.pyplot(spectra_plot) ######## Loaded graph st.pyplot(target_plot) - with M000: + with c3: st.write('Loaded data summary') st.write(stats) @@ -272,23 +235,46 @@ if not spectra.empty and not y.empty: # ################################################### BEGIN : Create Model #################################################### model_type = None # initialize the selected regression algorithm Reg = None # initialize the regression model object -# intervalls_with_cols = pd.DataFrame() +# intervalls_with_cols = DataFrame() st.header("II - Model creation", divider = 'blue') if not spectra.empty and not y.empty: - M10, M20, M30, M40, M50 = st.columns([1, 1, 1, 1, 1]) - - # select type of supervised modelling problem - modes = ['regression', 'classification'] - mode = M10.radio("Analysis Methods", options=modes) - p_hash(mode) - match mode: - case "regression": - reg_algo = ["", "PLS", "LW-PLS", "TPE-iPLS"] - model_type = M20.selectbox("Choose the regression algorithm", options = reg_algo, key = "model_type", format_func = lambda x: x if x else "<Select>") - case 'classification': - reg_algo = ["", "PLS", "LW-PLS", "TPE-iPLS", 'LDA'] - model_type = M20.selectbox("Choose the classification algorithm", options = reg_algo, key = 12, format_func = lambda x: x if x else "<Select>") + c4, c5, c6 = st.columns([1, 1, 3]) + with c4: + # select type of supervised modelling problem + var_nature = ['Continuous', 'Categorical'] + mode = c4.radio("The nature of the target variable :", options = var_nature) + p_hash(mode) + match mode: + case "Continuous": + reg_algo = ["", "PLS", "LW-PLS", "TPE-iPLS"] + st.markdown(f'Example1: Quantifying the volume of nectar consumed by a pollinator during a foraging session.') + st.markdown(f"Example2: Measure the sugar content, amino acids, or other compounds in nectar from different flower species.") + case 'Categorical': + reg_algo = ["", "PLS", "LW-PLS", "TPE-iPLS", 'LDA'] + st.markdown(f"Example1: Classifying pollinators into categories such as bees, butterflies, moths, and beetles.") + st.markdown(f"Example2: Classifying plants based on their health status, such as healthy, stressed, or diseased, using NIR spectral data.") + with c5: + model_type = c5.selectbox("Choose a modelling algorithm:", options = reg_algo, key = 12, format_func = lambda x: x if x else "<Select>") + + with c6: + st.markdown("-------------") + match model_type: + case "PLS": + st.markdown("#### For further details on the PLS (Partial Least Squares) algorithm, check the following reference:") + st.markdown('##### https://www.tandfonline.com/doi/abs/10.1080/03610921003778225') + + case "LW-PLS": + st.markdown("#### For further details on the LW-PLS (Locally Weighted - Partial Least Squares) algorithm, check the following reference:") + st.markdown('##### https://analyticalsciencejournals.onlinelibrary.wiley.com/doi/full/10.1002/cem.3117') + + case "TPE-iPLS": + st.markdown("#### For further details on the TPE-iPLS (Tree-structured Parzen Estimator based interval-Partial Least Squares) algorithm, which is a wrapper method for interval selection, check the following references:") + st.markdown("##### https://papers.nips.cc/paper_files/paper/2011/file/86e8f7ab32cfd12577bc2619bc635690-Paper.pdf") + st.markdown('##### https://www.tandfonline.com/doi/abs/10.1080/03610921003778225') + st.markdown('##### https://journals.sagepub.com/doi/abs/10.1366/0003702001949500') + st.markdown("-------------") + # if model_type != st.session_state.model_type: # st.session_state.model_type = model_type # increment() @@ -300,7 +286,7 @@ if not spectra.empty and not y.empty: nb_folds = 3 # Model creation-M20 columns - with M20: + with c5: @st.cache_data def RequestingModelCreation(change): # spectra_plot.savefig("./report/figures/spectra_plot.png") @@ -310,7 +296,7 @@ if not spectra.empty and not y.empty: match model_type: case 'PLS': - Reg = Plsr(train = [X_train, y_train], test = [X_test, y_test], n_iter = 10, cv = nb_folds) + Reg = Plsr(train = [X_train, y_train], test = [X_test, y_test], n_iter = 100, cv = nb_folds) # reg_model = Reg.model_ rega = Reg.selected_features_ @@ -360,11 +346,11 @@ if not spectra.empty and not y.empty: # global Reg # Reg = type('obj', (object,), {'model_' : Reg_json['model'], 'best_hyperparams_' : Reg_json['best_lwplsr_params'], - # 'pred_data_' : [pd.json_normalize(Reg_json[i]) for i in pred]}) + # 'pred_data_' : [json_normalize(Reg_json[i]) for i in pred]}) # global Reg Reg = lw(Reg_json = Reg_json, pred = pred) # reg_model = Reg.model_ - Reg.CV_results_ = pd.DataFrame() + Reg.CV_results_ = DataFrame() Reg.cv_data_ = {'YpredCV' : {}, 'idxCV' : {}} # set indexes to Reg.pred_data (train, test, folds idx) for i in range(len(pred)): @@ -380,7 +366,7 @@ if not spectra.empty and not y.empty: else: # CVi Reg.pred_data_[i].index = folds[list(folds)[i-2]] - # Reg.CV_results_ = pd.concat([Reg.CV_results_, Reg.pred_data_[i]]) + # Reg.CV_results_ = concat([Reg.CV_results_, Reg.pred_data_[i]]) Reg.cv_data_['YpredCV']['Fold' + str(i-1)] = np.array(Reg.pred_data_[i]).reshape(-1) Reg.cv_data_['idxCV']['Fold' + str(i-1)] = np.array(folds[list(folds)[i-2]]).reshape(-1) @@ -404,8 +390,8 @@ if not spectra.empty and not y.empty: # reg_model = Reg.model_ global intervalls, intervalls_with_cols - intervalls = Reg.selected_features_.T - intervalls_with_cols = Reg.selected_features_.T + intervalls = Reg.selected_features_.T.copy() + intervalls_with_cols = Reg.selected_features_.T.copy().astype(str) for i in range(intervalls.shape[0]): for j in range(intervalls.shape[1]): @@ -424,7 +410,7 @@ if not spectra.empty and not y.empty: info = st.info('Info: The model is being created. This may take a few minutes.') if model_type == 'TPE-iPLS':# if model type is ipls then ask for the number of iterations and intervalls s = st.number_input(label = 'Enter the maximum number of intervals', min_value = 1, max_value = 6) - it = st.number_input(label = 'Enter the number of iterations', min_value = 2, max_value = 500, value = 2) + it = st.number_input(label = 'Enter the number of iterations', min_value = 2, max_value = 500, value = 250) else: s, it = None, None p_hash(str(s)+str(it)) @@ -433,7 +419,7 @@ if not spectra.empty and not y.empty: p_hash(st.session_state.counter) Reg = RequestingModelCreation(change = hash_) reg_model = Reg.model_ - hash_ = joblib.hash(Reg) + hash_ = hash(Reg) else: st.info('Info: Choose a modelling algorithm from the dropdown list!') @@ -450,8 +436,6 @@ if not spectra.empty and not y.empty: intervalls = st.session_state.intervalls intervalls_with_cols = st.session_state.intervalls_with_cols - - if Reg: # remodel_button = st.button('re-model the data', key=4, help=None, type="primary", use_container_width=True) # if remodel_button:# remodel feature for re-tuning the model @@ -463,8 +447,8 @@ if Reg: yt = Reg.pred_data_[1] - M1, M2 = st.columns([2 ,4]) - with M1: + c7, c8 = st.columns([2 ,4]) + with c7: # Show and export the preprocessing methods st.write('-- Spectral preprocessing info --') st.write(Reg.best_hyperparams_print) @@ -477,9 +461,9 @@ if Reg: # Show the model performance table st.write("-- Model performance --") if model_type != reg_algo[2]: - model_per = pd.DataFrame(metrics(c = [y_train, yc], t = [y_test, yt], method = 'regression').scores_) + model_per = DataFrame(metrics(c = [y_train, yc], t = [y_test, yt], method = 'regression').scores_) else: - model_per = pd.DataFrame(metrics(c = [y_train, yc], t = [y_test, yt], method = 'regression').scores_) + model_per = DataFrame(metrics(c = [y_train, yc], t = [y_test, yt], method = 'regression').scores_) st.dataframe(model_per) @@ -518,7 +502,7 @@ if Reg: ax2.legend() return fig - with M2:## Visualize raw,preprocessed spectra, and selected intervalls(in case of ipls) + with c8:## Visualize raw,preprocessed spectra, and selected intervalls(in case of ipls) if model_type =='TPE-iPLS' : st.write('-- Important Spectral regions used for model creation --') st.table(intervalls_with_cols) @@ -547,7 +531,7 @@ if Reg: cv1, cv2 = st.columns([2, 2]) with cv2: - cv_results = pd.DataFrame(Reg.CV_results_).round(4)# CV table + cv_results = DataFrame(Reg.CV_results_).round(4)# CV table st.write('-- Cross-Validation Summary--') st.write(cv_results.astype(str).style.map(lambda _: "background-color: #cecece;", subset = (cv_results.index.drop(['sd', 'mean', 'cv']), slice(None)))) @@ -599,6 +583,7 @@ if Reg: ########################################################################################################################################## ########################################################################################################################################## if Reg: + zip_data = "" st.header('Download the analysis results') st.write("**Note:** Please check the box only after you have finished processing your data and are satisfied with the results. Checking the box prematurely may slow down the app and could lead to crashes.") decis = st.checkbox("Yes, I want to download the results") @@ -633,7 +618,7 @@ if Reg: dd.write(dxdata) with open('./report/out/model/'+ model_type + '.pkl','wb') as f:# export model - joblib.dump(reg_model, f) + dump(reg_model, f) figpath ='./report/out/figures/' spectra_plot.savefig(figpath + "spectra_plot.png") target_plot.savefig(figpath + "histogram.png") @@ -642,12 +627,12 @@ if Reg: fig0.write_image(figpath + "meas_vs_pred_cv_onebyone.png") measured_vs_predicted.savefig(figpath + 'measured_vs_predicted.png') residuals_plot.savefig(figpath + 'residuals_plot.png') - with open('report/out/Preprocessing.json', "w") as outfile: - json.dump(Reg.best_hyperparams_, outfile) + # with open('report/out/Preprocessing.json', "w") as outfile: + # json.dump(Reg.best_hyperparams_, outfile) if model_type == 'TPE-iPLS': # export selected wavelengths wlfilename = './report/out/model/'+ model_type+'-selected_wavelengths.xlsx' - all = pd.concat([intervalls_with_cols.T, Reg.selected_features_], axis = 0, ignore_index=True).T + all = concat([intervalls_with_cols.T, Reg.selected_features_], axis = 0, ignore_index=True).T all.columns=['wl_from','wl_to','idx_from', 'idx_to'] all.to_excel(wlfilename) @@ -655,30 +640,53 @@ if Reg: if Path("./report/report.tex").exists(): report.generate_report(change = hash_) if Path("./report/report.pdf").exists(): - shutil.move("./report/report.pdf", "./report/out/report.pdf") + move("./report/report.pdf", "./report/out/report.pdf") + + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# + # pklfile = {'model_': Reg.model_,"model_type" : model_type, 'training_data':{'raw-spectra':spectra,'target':y, }, + # 'spec-preprocessing':{"normalization": Reg.best_hyperparams_['normalization'], 'SavGol(polyorder,window_length,deriv)': [Reg.best_hyperparams_["polyorder"], + # Reg.best_hyperparams_['window_length'], + # Reg.best_hyperparams_['deriv']]}} + pklfile = {'model_': Reg.model_,"model_type" : model_type, 'data':{'raw-spectra':spectra,'target':y, 'training_data_idx':train_index,'testing_data_idx':test_index}, + 'spec-preprocessing':{"normalization": Reg.best_hyperparams_['normalization'], 'SavGol(polyorder,window_length,deriv)': [Reg.best_hyperparams_["polyorder"], + Reg.best_hyperparams_['window_length'], + Reg.best_hyperparams_['deriv']]}} + if model_type == 'TPE-iPLS': # export selected wavelengths + pklfile['selected-wls'] = {'idx':Reg.selected_features_.T , "wls":intervalls_with_cols } + else: + pklfile['selected-wls'] = {'idx':None, "wls":None } + + with open('./report/out/file_system.pkl', "wb") as pkl: + dump(pklfile, pkl) + + + + + return change preparing_results_for_downloading(change = hash_) - import tempfile @st.cache_data(show_spinner =False) def tempdir(change): - with tempfile.TemporaryDirectory( prefix="results", dir="./report") as temp_dir:# create a temp directory + with TemporaryDirectory( prefix="results", dir="./report") as temp_dir:# create a temp directory tempdirname = os.path.split(temp_dir)[1] if len(os.listdir('./report/out/figures/'))>2: - shutil.make_archive(base_name="./report/Results", format="zip", base_dir="out", root_dir = "./report")# create a zip file - shutil.move("./report/Results.zip", f"./report/{tempdirname}/Results.zip")# put the inside the temp dir + make_archive(base_name="./report/Results", format="zip", base_dir="out", root_dir = "./report")# create a zip file + move("./report/Results.zip", f"./report/{tempdirname}/Results.zip")# put the inside the temp dir with open(f"./report/{tempdirname}/Results.zip", "rb") as f: zip_data = f.read() return tempdirname, zip_data - date_time = datetime.datetime.now().strftime('%y%m%d%H%M') try : tempdirname, zip_data = tempdir(change = hash_) - st.download_button(label = 'Download', data = zip_data, file_name = f'Nirs_Workflow_{date_time}_Reg_.zip', mime ="application/zip", - args = None, kwargs = None,type = "primary",use_container_width = True) except: pass + date_time = datetime.now().strftime('%y%m%d%H%M') + disabled_down = True if zip_data=='' else False + st.download_button(label = 'Download', data = zip_data, file_name = f'Nirs_Workflow_{date_time}_Reg_.zip', mime ="application/zip", + args = None, kwargs = None,type = "primary",use_container_width = True, disabled = disabled_down) + - delete_files(keep = ['.py', '.pyc','.bib']) + delete_files(keep = ['.py', '.pyc','.bib']) diff --git a/src/pages/3-prediction.py b/src/pages/3-prediction.py index eb3cf20..3dce23a 100644 --- a/src/pages/3-prediction.py +++ b/src/pages/3-prediction.py @@ -1,7 +1,7 @@ from Packages import * st.set_page_config(page_title="NIRS Utils", page_icon=":goat:", layout="wide") from Modules import * -from Class_Mod.DATA_HANDLING import * +from utils.DATA_HANDLING import * # HTML pour le bandeau "CEFE - CNRS" # bandeau_html = """ # <div style="width: 100%; background-color: #4682B4; padding: 10px; margin-bottom: 10px;"> @@ -14,7 +14,6 @@ add_header() add_sidebar(pages_folder) local_css(css_file / "style_model.css") -import shutil hash_ = '' def p_hash(add): global hash_ @@ -23,8 +22,10 @@ def p_hash(add): dirpath = Path('Report/out/model') if dirpath.exists() and dirpath.is_dir(): - shutil.rmtree(dirpath) + rmtree(dirpath) +if 'Predict' not in st.session_state: + st.session_state['Predict'] = False # #################################### Methods ############################################## # empty temp figures def delete_files(keep): @@ -35,267 +36,333 @@ def delete_files(keep): if file != 'logo_cefe.png' and not any(file.endswith(ext) for ext in keep): os.remove(os.path.join(root, file)) ################################################################### + +st.title("Prediction making using a previously developed model") +c1, c2 = st.columns([2, 1]) +c1.image("./images/prediction making.png", use_column_width=True) +pred_data = DataFrame + + -st.title("Prediction making using a previously developed model") -M10, M20= st.columns([2, 1]) -M10.image("./images/prediction making.png", use_column_width=True) def preparespecdf(df): other = df.select_dtypes(exclude = 'float') - rownames = other.iloc[:,0] spec = df.select_dtypes(include='float') - spec.index = rownames + if other.shape[1] > 0: + rownames = other.iloc[:,0] + spec.index = rownames + else: + rownames = [str(i) for i in range(df.shape[0])] + if spec.shape[1]<60: + spec = DataFrame return spec, other, rownames def check_exist(var): out = var in globals() return out -files_format = ['.csv', '.dx'] -export_folder = './data/predictions/' -export_name = 'Predictions_of_' -reg_algo = ["Interval-PLS"] - +with c2: + zip = st.file_uploader("Load your zip file:", type = ['.zip'], help=" :mushroom: select a csv matrix with samples as rows and lambdas as columns") + if not zip: + st.info('Info: Insert your zip file above!') + + disable1 = False if zip else True + new_data = st.file_uploader("Load NIRS Data for prediction making:", type = ['csv', 'dx'], help=" :mushroom: select a csv matrix with samples as rows and lambdas as columns", disabled=disable1) + if not disable1 : + info1 = st.info('Info: Insert your NIRS data file above!') -with M20: - file = st.file_uploader("Load NIRS Data for prediction making:", type = files_format, help=" :mushroom: select a csv matrix with samples as rows and lambdas as columns") + if zip: + @st.cache_data + def tempdir(prefix, dir): + with TemporaryDirectory( prefix= prefix, dir= dir ) as temp_dir:# create a temp directory + tempdirname = os.path.split(temp_dir)[1] + return tempdirname + + temp_dir = tempdir(prefix = "pred_temp", dir = "./temp") + # Open and extract the zip file + from zipfile import ZipFile + with ZipFile(zip, 'r') as zip_ref: + zip_ref.extractall(temp_dir) - if not file: - st.info('Info: Insert your spectral data file above!') - else: - p_hash(file.name) - test = file.name[file.name.find('.'):] - export_name += file.name[:file.name.find('.')] - - if test == files_format[0]: - qsep = st.radio("Select csv separator - _detected_: " + str(find_delimiter('data/'+file.name)), options=[";", ","],index=[";", ","].index(str(find_delimiter('data/'+file.name))), key=2, horizontal= True) - qhdr = st.radio("indexes column in csv? - _detected_: " + str(find_col_index('data/'+file.name)), options=["no", "yes"], index=["no", "yes"].index(str(find_col_index('data/'+file.name))), key=3, horizontal= True) - col = 0 if qhdr == 'yes' else None - p_hash([qsep,qhdr]) - - df = pd.read_csv(file, sep=qsep, header= col) - pred_data, cat, rownames = preparespecdf(df) - - elif test == files_format[1]: - with NamedTemporaryFile(delete=False, suffix=".dx") as tmp: - tmp.write(file.read()) - tmp_path = tmp.name - with open(tmp.name, 'r') as dd: - dxdata = file.read() - p_hash(str(dxdata)+str(file.name)) - - ## load and parse the temp dx file - @st.cache_data - def dx_loader(change): - chem_data, spectra, meta_data, _ = read_dx(file = tmp_path) - return chem_data, spectra, meta_data, _ - chem_data, spectra, meta_data, _ = dx_loader(change = hash_) - st.success("The data have been loaded successfully", icon="✅") - if chem_data.to_numpy().shape[1]>0: - yname = st.selectbox('Select target', options=chem_data.columns) - measured = chem_data.loc[:,yname] == 0 - y = chem_data.loc[:,yname].loc[measured] - pred_data = spectra.loc[measured] - - else: - pred_data = spectra - os.unlink(tmp_path) + + def find_pkl_files(root_dir): + # List to store the paths of .pkl files + pkl_files = [] + + # Walk through the directory + for dirpath, dirnames, filenames in os.walk(root_dir): + for filename in filenames: + # Check if the file has a .pkl extension + if filename.endswith('.pkl'): + # Construct the full file path + file_path = os.path.join(dirpath, filename) + pkl_files.append(file_path) + return pkl_files + pkl = find_pkl_files(root_dir=temp_dir) + + system_file = [path for path in pkl if 'file_system' in path] + if len(system_file) ==1 : + with open(system_file[0], 'rb') as fi: + system_data = load(fi) + +if new_data: + info1.empty() + +with c2: + if new_data: + p_hash(new_data.name) + test = new_data.name.split('.')[-1] + export_name = 'Pred of' + export_name += new_data.name[:new_data.name.find('.')] + + match test: + case 'csv': + qsep = st.radio("Select csv separator : " , options = [';', ','], key = 2, horizontal = True) + qhdr = st.radio("indexes column in csv? : " , options = ['yes', 'no'], key = 3, horizontal = True) + col = 0 if qhdr == 'yes' else None + p_hash([qsep,qhdr]) + + df = read_csv(new_data, sep=qsep, header= col, decimal=".") + pred_data, cat, rownames = preparespecdf(df) + + case "dx": + with NamedTemporaryFile(delete=False, suffix=".dx") as tmp: + tmp.write(new_data.read()) + tmp_path = tmp.name + with open(tmp.name, 'r') as dd: + dxdata = new_data.read() + p_hash(str(dxdata)+str(new_data.name)) + + ## load and parse the temp dx file + @st.cache_data + def dx_loader(change): + chem_data, spectra, meta_data, _ = read_dx(file = tmp_path) + return chem_data, spectra, meta_data, _ + chem_data, spectra, meta_data, _ = dx_loader(change = hash_) + st.success("The data have been loaded successfully", icon="✅") + if chem_data.to_numpy().shape[1]>0: + yname = st.selectbox('Select target', options=chem_data.columns) + measured = chem_data.loc[:,yname] == 0 + y = chem_data.loc[:,yname].loc[measured] + pred_data = spectra.loc[measured] + + else: + pred_data = spectra + os.unlink(tmp_path) # Load parameters st.header("I - Spectral data preprocessing & visualization", divider='blue') -try: - if check_exist("pred_data"):# Load the model with joblib - @st.cache_data - def specplot_raw(change): - fig2 = plot_spectra(pred_data, xunits = 'lab', yunits = "meta_data.loc[:,'yunits'][0]") - return fig2 - rawspectraplot = specplot_raw(change = hash_) - M1, M2= st.columns([2, 1]) - with M1: - st.write('Raw spectra') - st.pyplot(rawspectraplot) - - with M2: - params = st.file_uploader("Load preprocessings params", type = '.json', help=" .json file") - if params: - prep = json.load(params) - p_hash(prep) - - @st.cache_data - def preprocess_spectra(change): - # M4.write(ProcessLookupError) - - if prep['normalization'] == 'Snv': - x1 = Snv(pred_data) - norm = 'Standard Normal Variate' - else: - norm = 'No Normalization was applied' - x1 = pred_data - x2 = savgol_filter(x1, - window_length = int(prep["window_length"]), - polyorder = int(prep["polyorder"]), - deriv = int(prep["deriv"]), - delta=1.0, axis=-1, mode="interp", cval=0.0) - preprocessed = pd.DataFrame(x2, index = pred_data.index, columns = pred_data.columns) - return norm, prep, preprocessed - norm, prep, preprocessed = preprocess_spectra(change= hash_) - - ################################################################################################ - ## plot preprocessed spectra - if check_exist("preprocessed"): - p_hash(preprocessed) - M3, M4= st.columns([2, 1]) - with M3: +# try: +if not pred_data.empty:# Load the model with joblib + @st.cache_data + def preprocess_spectra(change): + # M4.write(ProcessLookupError) + + if system_data['spec-preprocessing']['normalization'] == 'Snv': + x1 = Snv(pred_data) + norm = 'Standard Normal Variate' + else: + norm = 'No Normalization was applied' + x1 = pred_data + x2 = savgol_filter(x1, + window_length = int(system_data['spec-preprocessing']['SavGol(polyorder,window_length,deriv)'][1]), + polyorder = int(system_data['spec-preprocessing']['SavGol(polyorder,window_length,deriv)'][0]), + deriv = int(system_data['spec-preprocessing']['SavGol(polyorder,window_length,deriv)'][2]), + delta=1.0, axis=-1, mode="interp", cval=0.0) + preprocessed = DataFrame(x2, index = pred_data.index, columns = pred_data.columns) + return norm, preprocessed + norm, preprocessed = preprocess_spectra(change= hash_) + + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + # @st.cache_data + # def specplot_raw(change): + # fig2 = plot_spectra(pred_data, xunits = 'lab', yunits = "meta_data.loc[:,'yunits'][0]") + # return fig2 + # rawspectraplot = specplot_raw(change = hash_) + rawspectraplot = plot_spectra(pred_data, xunits = 'Wavelength/Wavenumber', yunits = "Signal intensity") + + c3, c4 = st.columns([2, 1]) + with c3: + st.write('Raw spectra') + st.pyplot(rawspectraplot) + + ## plot preprocessed spectra + if check_exist("preprocessed"): + # def specplot_prep(change): + # fig2 = plot_spectra(preprocessed, xunits = 'lab', yunits = "meta_data.loc[:,'yunits'][0]") + # return fig2 + # prepspectraplot = specplot_prep(change = hash_) + prepspectraplot = plot_spectra(preprocessed, xunits = 'Wavelength/Wavenumber', yunits = "Signal intensity") st.write('Preprocessed spectra') - def specplot_prep(change): - fig2 = plot_spectra(preprocessed, xunits = 'lab', yunits = "meta_data.loc[:,'yunits'][0]") - return fig2 - prepspectraplot = specplot_prep(change = hash_) st.pyplot(prepspectraplot) - - with M4: - @st.cache_data - def prep_info(change): - SG = r'''- Savitzky-Golay derivative parameters \:(Window_length:{prep['window_length']}; polynomial order: {prep['polyorder']}; Derivative order : {prep['deriv']})''' - Norm = r'''- Spectral Normalization \: {norm}''' - return SG, Norm - SG, Norm = prep_info(change = hash_) - st.info('The spectra were preprocessed using:\n'+SG+"\n"+Norm) + with c4: + @st.cache_data + def prep_info(change): + SG = f'- Savitzky-Golay derivative parameters \n:(Window_length:{system_data['spec-preprocessing']['SavGol(polyorder,window_length,deriv)'][1]}; polynomial order: {system_data['spec-preprocessing']['SavGol(polyorder,window_length,deriv)'][0]}; Derivative order : {system_data['spec-preprocessing']['SavGol(polyorder,window_length,deriv)'][2]})' + Norm = f'- Spectral Normalization \n: {system_data['spec-preprocessing']['normalization']}' + return SG, Norm + SG, Norm = prep_info(change = hash_) + st.info('The spectra were preprocessed using:\n'+SG+"\n"+Norm) ################### Predictions making ########################## st.header("II - Prediction making", divider='blue') - if check_exist("pred_data") and params:# Load the model with joblib - M5, M6 = st.columns([2, 1]) - model_file = M6.file_uploader("Load your model", type = '.pkl', help=" .pkl file") - if model_file: - with M6: - try: - model = joblib.load(model_file) - st.success("The model has been loaded successfully", icon="✅") - nvar = model.n_features_in_ - - except: - st.error("Error: Something went wrong, the model was not loaded !", icon="❌") - - with M6: - s = st.checkbox('Check this box if your model is of ipls type!', disabled = False if 'model' in globals() else True) - index = st.file_uploader("select wavelengths index file", type="csv", disabled = [False if s else True][0]) - if check_exist('preprocessed'): - if s: - if index: - intervalls = pd.read_csv(index, sep=';', index_col=0).to_numpy() - idx = [] - for i in range(intervalls.shape[0]): - idx.extend(np.arange(intervalls[i,2], intervalls[i,3]+1)) - if max(idx) <= preprocessed.shape[1]: - preprocesseddf = preprocessed.iloc[:,idx] ### get predictors - else: - st.error("Error: The number of columns in your data does not match the number of columns used to train the model. Please ensure they are the same.") - else: - preprocesseddf = preprocessed - - - - if check_exist("model") == False: - disable = True - elif check_exist("model") == True: - if s and not index : - disable = True - elif s and index: - disable = False - elif not s and not index: - disable = False - elif not s and index: - disable = True - - - pred_button = M6.button('Predict', type='primary', disabled= disable) - - if check_exist("preprocesseddf"): - if pred_button and nvar == preprocesseddf.shape[1]: - try: - result = pd.DataFrame(model.predict(preprocesseddf), index = rownames, columns = ['Results']) - except: - st.error(f'''Error: Length mismatch: the number of samples indices is {len(rownames)}, while the model produced - {len(model.predict(preprocesseddf))} values. correct the "indexes column in csv?" parameter''') - with M5: - if preprocesseddf.shape[1]>1 and check_exist('result'): - st.write('Predicted values distribution') - # Creating histogram - hist, axs = plt.subplots(1, 1, figsize =(15, 3), - tight_layout = True) - - # Add x, y gridlines - axs.grid( color ='grey', linestyle ='-.', linewidth = 0.5, alpha = 0.6) - # Remove axes splines - for s in ['top', 'bottom', 'left', 'right']: - axs.spines[s].set_visible(False) - # Remove x, y ticks - axs.xaxis.set_ticks_position('none') - axs.yaxis.set_ticks_position('none') - # Add padding between axes and labels - axs.xaxis.set_tick_params(pad = 5) - axs.yaxis.set_tick_params(pad = 10) - # Creating histogram - N, bins, patches = axs.hist(result, bins = 12) - # Setting color - fracs = ((N**(1 / 5)) / N.max()) - norm = colors.Normalize(fracs.min(), fracs.max()) - - for thisfrac, thispatch in zip(fracs, patches): - color = plt.cm.viridis(norm(thisfrac)) - thispatch.set_facecolor(color) - - st.pyplot(hist) - st.write('Predicted values table') - st.dataframe(result.T) - #################################3 - elif pred_button and nvar != preprocesseddf.shape[1]: - M6.error(f'Error: The model was trained on {nvar} wavelengths, but you provided {preprocessed.shape[1]} wavelengths for prediction. Please ensure they match!') - - - if check_exist('result'): - @st.cache_data(show_spinner =False) - def preparing_results_for_downloading(change): - match test: - # load csv file - case '.csv': - df.to_csv('Report/out/dataset/'+ file.name, sep = ';', encoding = 'utf-8', mode = 'a') - case '.dx': - with open('Report/out/dataset/'+file.name, 'w') as dd: - dd.write(dxdata) - - prepspectraplot.savefig('./Report/out/figures/raw_spectra.png') - rawspectraplot.savefig('./Report/out/figures/preprocessed_spectra.png') - hist.savefig('./Report/out/figures/histogram.png') - result.round(4).to_csv('./Report/out/The analysis result.csv', sep = ";", index_col=0) - - return change - preparing_results_for_downloading(change = hash_) - - import tempfile - @st.cache_data(show_spinner =False) - def tempdir(change): - with tempfile.TemporaryDirectory( prefix="results", dir="./Report") as temp_dir:# create a temp directory - tempdirname = os.path.split(temp_dir)[1] - if len(os.listdir('./Report/out/figures/'))==3: - shutil.make_archive(base_name="./Report/Results", format="zip", base_dir="out", root_dir = "./Report")# create a zip file - shutil.move("./Report/Results.zip", f"./Report/{tempdirname}/Results.zip")# put the inside the temp dir - with open(f"./Report/{tempdirname}/Results.zip", "rb") as f: - zip_data = f.read() - return tempdirname, zip_data - - date_time = datetime.datetime.now().strftime('%y%m%d%H%M') - try : - tempdirname, zip_data = tempdir(change = hash_) - st.download_button(label = 'Download', data = zip_data, file_name = f'Nirs_Workflow_{date_time}_Pred_.zip', mime ="application/zip", - args = None, kwargs = None,type = "primary",use_container_width = True) - except: - st.write('rtt') -except: - M20.error('''Error: Data loading failed. Please check your file. Consider fine-tuning the dialect settings or ensure the file isn't corrupted.''') - - + + disable2 = False if check_exist("pred_data") else True + pred_button = st.button('Predict', type='primary', disabled= disable2, use_container_width=False) + if pred_button:st.session_state['Predict'] = True + + if st.session_state['Predict']: + if check_exist("pred_data"):# Load the model with joblib + c5, c6 = st.columns([2, 1]) + with c6: + model = system_data['model_'] + if system_data['model_type'] in ['PLS','TPE-iPLS']: + nvar = system_data['model_'].n_features_in_ + elif system_data['model_type'] =='LW-PLS': + nvar = system_data['data']['raw-spectra'].shape[1] + + + if check_exist('preprocessed'): + if isinstance(system_data['selected-wls']['idx'], DataFrame): + idx = np.concatenate([np.arange(system_data['selected-wls']['idx'].values.reshape((-1,))[2*i],system_data['selected-wls']['idx'].values.reshape((-1,))[2*i+1]+1) for i in range(system_data['selected-wls']['idx'].shape[0])]) + else: + idx = np.arange(nvar) + + if np.max(idx) <= preprocessed.shape[1]: + preprocesseddf = preprocessed.iloc[:,idx] ### get predictors + else: + st.error("Error: The number of columns in your data does not match the number of columns used to train the model. Please ensure they are the same.") + + + if check_exist("preprocesseddf"): + if st.session_state['Predict'] and nvar == preprocesseddf.shape[1]: + # if nvar == preprocesseddf.shape[1]: + match system_data['model_type']: + case 'PLS'|'TPE-iPLS': + try: + result = DataFrame(system_data['model_'].predict(preprocesseddf), index = rownames, columns = ['Results']) + except: + st.error(f'''Error: Length mismatch: the number of samples indices is {len(rownames)}, while the model produced + {len(model.predict(preprocesseddf))} values. correct the "indexes column in csv?" parameter''') + case 'LW-PLS': + # export data to csv for Julia train/test + train_idx, test_idx = system_data['data']['training_data_idx'], system_data['data']['testing_data_idx'] + spectra = system_data['data']['raw-spectra'] + y = system_data['data']['target'] + X_train, y_train, X_test, y_test = spectra.iloc[train_idx,:], y.iloc[train_idx], spectra.iloc[test_idx,:], y.iloc[test_idx] + nb_folds = 3 + folds = KF_CV.CV(X_train, y_train, nb_folds) + #['raw-spectra', 'target', 'training_data_idx', 'testing_data_idx'] + data_to_work_with = ['x_train_np', 'y_train_np', 'x_test_np', 'y_test_np', 'x_pred'] + x_train_np, y_train_np, x_test_np, y_test_np = X_train.to_numpy(), y_train.to_numpy(), X_test.to_numpy(), y_test.to_numpy() + x_pred = pred_data.to_numpy() + # Cross-Validation calculation + d = {} + for i in range(nb_folds): + d["xtr_fold{0}".format(i+1)], d["ytr_fold{0}".format(i+1)], d["xte_fold{0}".format(i+1)], d["yte_fold{0}".format(i+1)] = np.delete(x_train_np, folds[list(folds)[i]], axis=0), np.delete(y_train_np, folds[list(folds)[i]], axis=0), x_train_np[folds[list(folds)[i]]], y_train_np[folds[list(folds)[i]]] + data_to_work_with.append("xtr_fold{0}".format(i+1)) + data_to_work_with.append("ytr_fold{0}".format(i+1)) + data_to_work_with.append("xte_fold{0}".format(i+1)) + data_to_work_with.append("yte_fold{0}".format(i+1)) + # check best pre-treatment with a global PLSR model + preReg = Plsr(train = [X_train, y_train], test = [X_test, y_test], n_iter=20) + temp_path = Path('temp/') + with open(temp_path / "lwplsr_preTreatments.json", "w+") as outfile: + json.dump(preReg.best_hyperparams_, outfile) + # export Xtrain, Xtest, Ytrain, Ytest and all CV folds to temp folder as csv files + for i in data_to_work_with: + if 'fold' in i: + j = d[i] + else: + j = globals()[i] + # st.write(j) + np.savetxt(temp_path / str(i + ".csv"), j, delimiter=",") + # run Julia Jchemo as subprocess + import subprocess + subprocess_path = Path("utils/") + subprocess.run([f"{sys.executable}", subprocess_path / "LWPLSR_Call.py"]) + # retrieve json results from Julia JChemo + try: + with open(temp_path / "lwplsr_outputs.json", "r") as outfile: + Reg_json = json.load(outfile) + # delete csv files + for i in data_to_work_with: os.unlink(temp_path / str(i + ".csv")) + # delete json file after import + os.unlink(temp_path / "lwplsr_outputs.json") + os.unlink(temp_path / "lwplsr_preTreatments.json") + # format result data into Reg object + pred = ['pred_data_train', 'pred_data_test']### keys of the dict + for i in range(nb_folds): + pred.append("CV" + str(i+1)) ### add cv folds keys to pred + except FileNotFoundError as e: + Reg = None + for i in data_to_work_with: os.unlink(temp_path / str(i + ".csv")) + + st.write(Reg_json) + + ################################### results display ################################### + if check_exist("preprocesseddf"): + if preprocesseddf.shape[1]>1 and check_exist('result'): + hist = pred_hist(pred=result) + with c5: + st.write('Predicted values distribution') + st.pyplot(hist) + st.write('Predicted values table') + st.dataframe(result.T) + with c6: + st.info('descriptive statistics for the model output') + st.write(DataFrame(desc_stats(result))) + + elif pred_button and nvar != preprocesseddf.shape[1]: + with c6: + st.error(f'Error: The model was trained on {nvar} wavelengths, but you provided {preprocessed.shape[1]} wavelengths for prediction. Please ensure they match!') + + ################################# Download results ################################# + if check_exist('result'): + @st.cache_data(show_spinner =False) + def preparing_results_for_downloading(change): + match test: + # load csv file + case 'csv': + df.to_csv('Report/out/dataset/'+ new_data.name, sep = ';', encoding = 'utf-8', mode = 'a') + case 'dx': + with open('Report/out/dataset/'+new_data.name, 'w') as dd: + dd.write(dxdata) + + prepspectraplot.savefig('./Report/out/figures/raw_spectra.png') + rawspectraplot.savefig('./Report/out/figures/preprocessed_spectra.png') + hist.savefig('./Report/out/figures/histogram.png') + result.round(4).to_csv('./Report/out/The analysis result.csv', sep = ";") + + return change + preparing_results_for_downloading(change = hash_) + + @st.cache_data(show_spinner =False) + def tempdir(change): + with TemporaryDirectory( prefix="results", dir="./Report") as temp_dir:# create a temp directory + tempdirname = os.path.split(temp_dir)[1] + if len(os.listdir('./Report/out/figures/'))==3: + make_archive(base_name="./Report/Results", format="zip", base_dir="out", root_dir = "./Report")# create a zip file + move("./Report/Results.zip", f"./Report/{tempdirname}/Results.zip")# put the inside the temp dir + with open(f"./Report/{tempdirname}/Results.zip", "rb") as f: + zip_data = f.read() + return tempdirname, zip_data + + date_time = datetime.now().strftime('%y%m%d%H%M') + try : + tempdirname, zip_data = tempdir(change = hash_) + st.download_button(label = 'Download', data = zip_data, file_name = f'Nirs_Workflow_{date_time}_Pred_.zip', mime ="application/zip", + args = None, kwargs = None,type = "primary",use_container_width = True) + except: + st.write('rtt') + # except: + # c2.error('''Error: Data loading failed. Please check your file. Consider fine-tuning the dialect settings or ensure the file isn't corrupted.''') + + +else: + with c2: + if new_data: + st.error("Error!:The The data you provided for making predictions doesn't appear to be multivariable.!") \ No newline at end of file diff --git a/src/pages/4-inputs.py b/src/pages/4-inputs.py index f7ab339..dea19c2 100644 --- a/src/pages/4-inputs.py +++ b/src/pages/4-inputs.py @@ -6,6 +6,7 @@ st.session_state["interface"] = st.session_state.get('interface') # from Modules import * from mod import * from utils.DATA_HANDLING import * +background_img(change=None) #Import Header diff --git a/src/report/report.py b/src/report/report.py index b2dccca..8fb1dfb 100644 --- a/src/report/report.py +++ b/src/report/report.py @@ -1,7 +1,7 @@ import subprocess from pathlib import Path import os -import pandas as pd +from pandas import DataFrame import os.path import re import streamlit as st @@ -34,7 +34,7 @@ def report(*args): to_report.append(str(arg)) elif isinstance(arg, list): to_report.extend(list(map(str, arg))) - elif isinstance(arg, pd.DataFrame): + elif isinstance(arg, DataFrame): df_name = 'df' + str(j) j+=1 globals()[df_name] = arg.select_dtypes(include=['float64', 'int64']) @@ -426,7 +426,6 @@ def report(*args): # create the Tex file - sections in args will be displayed: {'sample':'Sample Selection';'model':'Model Creation';'predict':'Predictions';'help':'LaTEX help for figs and tables';} # latex_report = report('sample', 'predict',) -import shutil @st.cache_data def generate_report(change): my = Path("./report/report.pdf") diff --git a/src/style/header.py b/src/style/header.py index fe93bca..577d955 100644 --- a/src/style/header.py +++ b/src/style/header.py @@ -2,14 +2,25 @@ from Packages import * def add_header(): st.markdown( """ - <div style="width: 100%;height: 170px; background-color: rgb(122,176,199); padding: 10px; margin-bottom: 10px; "> - <h1 style="text-align: center; color: green;">PACE - MEEB / CEFE</h1> - <h2 style="text-align: center; color: green;">NIRS Utils</h2> + <div style="width: 100%;height: 170px; background-color: rgb(0,0,0,0);border: 4px solid rgb(122,176,199); padding: 0px; margin-bottom: 10px;border-radius: 20%; "> + <h1 style="font-family: 'Arial',d;text-align: center; color: #39bf55;">PACE - MEEB / CEFE</h1> + <h2 style="font-family: 'Arial';text-align: center; color: #2cb048;">NIRS Utils</h2> </div> """, unsafe_allow_html=True, ) + st.markdown(""" + <style> + .block-container { + padding-top: 3rem; + padding-bottom: 0rem; + padding-left: 5rem; + padding-right: 5rem; + } + </style> + """, unsafe_allow_html=True) + def add_sidebar(pages_folder): if 'interface' not in st.session_state: @@ -28,7 +39,7 @@ def add_sidebar(pages_folder): ) with st.sidebar: - interface = st.selectbox(label="Interface", options=['simple', 'advanced'], key='interface') + interface = st.radio(label="Interface", options=['simple', 'advanced'], key='interface') # st.page_link(str(pages_folder / '1-samples_selection.py')) if st.session_state['interface'] == 'simple': # st.page_link(str(pages_folder / '2-model_creation.py')) diff --git a/src/utils/DATA_HANDLING.py b/src/utils/DATA_HANDLING.py index 7f73676..fe7bc00 100644 --- a/src/utils/DATA_HANDLING.py +++ b/src/utils/DATA_HANDLING.py @@ -13,7 +13,7 @@ def find_delimiter(filename): def find_col_index(filename): with open(filename) as fp: - lines = pd.read_csv(fp, skiprows=3, nrows=3, index_col=False, sep=find_delimiter(filename)) + lines = read_csv(fp, skiprows=3, nrows=3, index_col=False, sep=find_delimiter(filename)) col_index = 'yes' if lines.iloc[:,0].dtypes != np.float64 else 'no' return col_index @@ -22,7 +22,7 @@ def find_col_index(filename): def col_cat(data_import): """detect numerical and categorical columns in the csv""" # set first column as sample names - name_col = pd.DataFrame(list(data_import.index), index = list(data_import.index)) + name_col = DataFrame(list(data_import.index), index = list(data_import.index)) # name_col=name_col.rename(columns = {0:'name'}) numerical_columns_list = [] categorical_columns_list = [] @@ -35,12 +35,12 @@ def col_cat(data_import): empty = [0 for x in range(len(data_import))] numerical_columns_list.append(empty) if len(categorical_columns_list) > 0: - categorical_data = pd.concat(categorical_columns_list, axis=1) + categorical_data = concat(categorical_columns_list, axis=1) categorical_data.insert(0, 'name', name_col) if len(categorical_columns_list) == 0: - categorical_data = pd.DataFrame + categorical_data = DataFrame # Create numerical data matrix from the numerical columns list and fill na with the mean of the column - numerical_data = pd.concat(numerical_columns_list, axis=1) + numerical_data = concat(numerical_columns_list, axis=1) numerical_data = numerical_data.apply(lambda x: x.fillna(x.mean())) #np.mean(x))) return numerical_data, categorical_data @@ -57,13 +57,13 @@ def list_files(mypath, import_type): def standardize(X, center = True, scale = False): sk = StandardScaler(with_mean=center, with_std = scale) - sc = pd.DataFrame(sk.fit_transform(X), index = X.index, columns = X.columns) + sc = DataFrame(sk.fit_transform(X), index = X.index, columns = X.columns) return sc def MinMaxScale(X): t = X sk = MinMaxScaler(feature_range=(0,1)) - sc = pd.DataFrame(sk.fit_transform(X), index = t.index, columns = t.columns) + sc = DataFrame(sk.fit_transform(X), index = t.index, columns = t.columns) return sc ######################################## Spectral preprocessing @@ -73,8 +73,8 @@ def Detrend(X): def Snv(X): xt = np.array(X).T - c = (xt-xt.mean())/xt.std() - return pd.DataFrame(c.T, index=X.index, columns= X.columns) + c = (xt-xt.mean())/xt.std(axis = 0) + return DataFrame(c.T, index=X.index, columns= X.columns) def No_transformation(X): return X @@ -88,7 +88,7 @@ class KF_CV: def CV(x, y, n_folds:int): test_folds = {} folds_name = [f'Fold{i+1}' for i in range(n_folds)] - kf = ks.KFold(n_splits=n_folds, device='cpu') + kf = ks_KFold(n_splits=n_folds, device='cpu') for i in range(n_folds): d = [] for _, i_test in kf.split(x, y): @@ -129,19 +129,19 @@ class KF_CV: coeff = {} y = np.array(y) for i, Fname in enumerate(folds.keys()): - r = pd.DataFrame() + r = DataFrame() r['Predicted'] = ypcv[Fname] r['Measured'] = y[folds[Fname]] - ols = LinearRegression().fit(pd.DataFrame(y[folds[Fname]]), ypcv[Fname].reshape(-1,1)) + ols = LinearRegression().fit(DataFrame(y[folds[Fname]]), ypcv[Fname].reshape(-1,1)) r.index = folds[Fname] r['Folds'] = [f'{Fname} (Predicted = {np.round(ols.intercept_[0], 2)} + {np.round(ols.coef_[0][0],2)} x Measured'] * r.shape[0] cvcv[i] = r coeff[Fname] = [ols.coef_[0][0], ols.intercept_[0]] - data = pd.concat(cvcv, axis = 0) + data = concat(cvcv, axis = 0) data['index'] = [data.index[i][1] for i in range(data.shape[0])] data.index = data['index'] - coeff = pd.DataFrame(coeff, index = ['Slope', 'Intercept']) + coeff = DataFrame(coeff, index = ['Slope', 'Intercept']) return data, coeff ## returns values predicted in cross validation, ,coefficients of regression @staticmethod @@ -150,7 +150,7 @@ class KF_CV: e = {} for i in folds.keys(): e[i] = metrics().reg_(y[folds[i]],ypcv[i]) - r = pd.DataFrame(e) + r = DataFrame(e) r_print = r.copy() r_print['mean'] = r.mean(axis = 1) r_print['sd'] = r.std(axis = 1) @@ -167,7 +167,7 @@ class KF_CV: e = {} for i in folds.keys(): e[i] = metrics().reg_(y[folds[i]],ypcv[i]) - r = pd.DataFrame(e) + r = DataFrame(e) r_print = r r_print['mean'] = r.mean(axis = 1) r_print['sd'] = r.std(axis = 1) @@ -189,14 +189,14 @@ class KF_CV: def sel_ratio(model, x ): from scipy.stats import f - x = pd.DataFrame(x) + x = DataFrame(x) wtp = model.coef_.T/ np.linalg.norm(model.coef_.T) ttp = np.array(x @ wtp) ptp = np.array(x.T) @ np.array(ttp)/(ttp.T @ ttp) qexpi = np.linalg.norm(ttp @ ptp.T, axis = 0)**2 e = np.array(x-x.mean()) - ttp @ ptp.T qres = np.linalg.norm(e, axis = 0)**2 - sr = pd.DataFrame(qexpi/qres, index = x.columns, columns = ['sr']) + sr = DataFrame(qexpi/qres, index = x.columns, columns = ['sr']) fcr = f.ppf(0.05, sr.shape[0]-2, sr.shape[0]-3) c = sr > fcr diff --git a/src/utils/DxReader.py b/src/utils/DxReader.py index 9733727..8158228 100644 --- a/src/utils/DxReader.py +++ b/src/utils/DxReader.py @@ -44,8 +44,8 @@ class DxRead: } self.__met[f'{i}'] = block_met - self.metadata_ = pd.DataFrame(self.__met).T - self.spectra = pd.DataFrame(np.fliplr(specs), columns= self.__wl[::-1], index = self.metadata_['name']) # Storing spectra in a pd.dataframe + self.metadata_ = DataFrame(self.__met).T + self.spectra = DataFrame(np.fliplr(specs), columns= self.__wl[::-1], index = self.metadata_['name']) # Storing spectra in a dataframe @@ -67,7 +67,7 @@ class DxRead: cc[df.index[i]] = self.conc(df[str(i)]) ### dataframe conntaining chemical data - self.chem_data = pd.DataFrame(cc, index=elements_name).T.astype(float) + self.chem_data = DataFrame(cc, index=elements_name).T.astype(float) self.chem_data.index = self.metadata_['name'] ### Method for retrieving the concentration of a single sample diff --git a/src/utils/Evaluation_Metrics.py b/src/utils/Evaluation_Metrics.py index ebe94c0..ecbc6ab 100644 --- a/src/utils/Evaluation_Metrics.py +++ b/src/utils/Evaluation_Metrics.py @@ -1,7 +1,7 @@ from Packages import * class metrics: - def __init__(self, c:Optional[float] = None, cv:Optional[List] = None, t:Optional[List] = None, method = 'regression')-> pd.DataFrame: + def __init__(self, c:Optional[float] = None, cv:Optional[List] = None, t:Optional[List] = None, method = 'regression')-> DataFrame: phase = [c, cv, t] index = np.array(["train", "cv", "test"]) notnone = [i for i in range(3) if phase[i] != None] @@ -18,7 +18,7 @@ class metrics: if notnone == 1: self.ret = perf.T else: - self.ret = pd.DataFrame(perf).T + self.ret = DataFrame(perf).T @staticmethod def reg_(meas, pred): diff --git a/src/utils/HDBSCAN_Clustering.py b/src/utils/HDBSCAN_Clustering.py index a5d3bc0..b4dbfca 100644 --- a/src/utils/HDBSCAN_Clustering.py +++ b/src/utils/HDBSCAN_Clustering.py @@ -6,7 +6,7 @@ class Hdbscan: The HDBSCAN_scores_ @Property returns the cluster number of each sample (_labels) and the DBCV best score. Returns: - _labels (pd.DataFrame): DataFrame with the cluster belonging number for each sample + _labels (DataFrame): DataFrame with the cluster belonging number for each sample _hdbscan_score (float): a float with the best DBCV score after optimization Examples: @@ -18,9 +18,9 @@ class Hdbscan: """Initiate the HDBSCAN calculation Args: - data (pd.DataFrame): the Dimensionality reduced space, raw result of the UMAP.fit() + data (DataFrame): the Dimensionality reduced space, raw result of the UMAP.fit() param_dist (dictionary): the HDBSCAN optimization parameters to test - _score (pd.DataFrame): is a dataframe with the DBCV value for each combination of param_dist. We search for the higher value to then compute an HDBSCAN with the best parameters. + _score (DataFrame): is a dataframe with the DBCV value for each combination of param_dist. We search for the higher value to then compute an HDBSCAN with the best parameters. """ # Really fast self._param_dist = {'min_samples': [8], @@ -50,7 +50,7 @@ class Hdbscan: # return tunning # compute optimization. Test each combination of parameters and store DBCV score into _score. - # self._score = pd.DataFrame() + # self._score = DataFrame() # for i in self._param_dist.get('min_samples'): # for j in self._param_dist.get('min_cluster_size'): # self._ij_label = HDBSCAN(min_samples=i, min_cluster_size=j).fit_predict(self._clusterable_embedding) diff --git a/src/utils/Hash.py b/src/utils/Hash.py index fb41384..9cde141 100644 --- a/src/utils/Hash.py +++ b/src/utils/Hash.py @@ -2,7 +2,7 @@ from Packages import * def create_hash(to_hash): #using the md5 hash function. - hash_func = hashlib.md5() + hash_func = md5() to_hash = str(to_hash) encoded_to_hash = to_hash.encode() hash_func.update(encoded_to_hash) diff --git a/src/utils/KMEANS_.py b/src/utils/KMEANS_.py index 78cb732..ea1f5ea 100644 --- a/src/utils/KMEANS_.py +++ b/src/utils/KMEANS_.py @@ -3,22 +3,22 @@ class Sk_Kmeans: """K-Means clustering for Samples selection. Returns: - inertia_ (pd.DataFrame): DataFrame with ... - x (pd.DataFrame): Initial data - clu (pd.DataFrame): Cluster name for each sample - model.cluster_centers_ (pd.DataFrame): Coordinates of the center of each cluster + inertia_ (DataFrame): DataFrame with ... + x (DataFrame): Initial data + clu (DataFrame): Cluster name for each sample + model.cluster_centers_ (DataFrame): Coordinates of the center of each cluster """ def __init__(self, x, max_clusters): """Initiate the KMeans class. Args: - x (pd.DataFrame): the original reduced data to cluster + x (DataFrame): the original reduced data to cluster max_cluster (Int): the max number of desired clusters. """ self.x = x self.max_clusters = max_clusters - self.inertia = pd.DataFrame() + self.inertia = DataFrame() for i in range(1, max_clusters+1): model = KMeans(n_clusters = i, init = 'k-means++', random_state = 42) model.fit(x) diff --git a/src/utils/KennardStone.py b/src/utils/KennardStone.py index 3ad6c91..1fb8595 100644 --- a/src/utils/KennardStone.py +++ b/src/utils/KennardStone.py @@ -2,10 +2,10 @@ from Packages import * from typing import Sequence, Dict, Optional, Union class KS: - def __init__(self, x:Optional[Union[np.ndarray|pd.DataFrame]], rset:Optional[Union[float|int]]): + def __init__(self, x:Optional[Union[np.ndarray|DataFrame]], rset:Optional[Union[float|int]]): self.x = x self.ratio = rset - self._train, self._test = ks.train_test_split(self.x, train_size = self.ratio) + self._train, self._test = ks_train_test_split(self.x, train_size = self.ratio) @property def calset(self): @@ -13,7 +13,7 @@ class KS: return self.x, clu class RDM: - def __init__(self, x:Optional[Union[np.ndarray|pd.DataFrame]], rset:Optional[Union[float|int]]): + def __init__(self, x:Optional[Union[np.ndarray|DataFrame]], rset:Optional[Union[float|int]]): self.x = x self.ratio = rset self._train, self._test = train_test_split(self.x, train_size = self.ratio) diff --git a/src/utils/LWPLSR_.py b/src/utils/LWPLSR_.py index 2e6c7a7..db7902a 100644 --- a/src/utils/LWPLSR_.py +++ b/src/utils/LWPLSR_.py @@ -1,6 +1,7 @@ from juliacall import Main as jl import numpy as np import pandas as pd +from pandas import DataFrame class LWPLSR: """The lwpls regression model from Jchemo (M. Lesnoff) @@ -193,13 +194,13 @@ class LWPLSR: res.pred """) # save predicted values for each KFold in the predicted_results dictionary - self.predicted_results["CV" + str(i+1)] = pd.DataFrame(pred_cv) + self.predicted_results["CV" + str(i+1)] = DataFrame(pred_cv) @property def pred_data_(self): # convert predicted data from x_test to Pandas DataFrame - self.predicted_results["pred_data_train"] = pd.DataFrame(self.pred_train) - self.predicted_results["pred_data_test"] = pd.DataFrame(self.pred_test) + self.predicted_results["pred_data_train"] = DataFrame(self.pred_train) + self.predicted_results["pred_data_test"] = DataFrame(self.pred_test) return self.predicted_results @property diff --git a/src/utils/Miscellaneous.py b/src/utils/Miscellaneous.py index 42caf59..6f09fc1 100644 --- a/src/utils/Miscellaneous.py +++ b/src/utils/Miscellaneous.py @@ -14,7 +14,7 @@ def prediction(NIRS_csv, qsep, qhdr, model): col = 0 else: col = False - X_test = pd.read_csv(NIRS_csv, sep=qsep, index_col=col) + X_test = read_csv(NIRS_csv, sep=qsep, index_col=col) Y_preds = model.predict(X_test) # Y_preds = X_test return Y_preds @@ -38,8 +38,8 @@ def reg_plot( meas, pred, train_idx, test_idx): et = np.subtract(np.array(meas[1]).reshape(-1), np.array(pred[1]).reshape(-1)) fig, ax = plt.subplots(figsize = (12,4)) - sns.regplot(x = meas[0] , y = pred[0], color='blue', label = f'Calib (Predicted = {a0[0]} + {a1[0]} x Measured)') - sns.regplot(x = meas[1], y = pred[1], color='green', label = f'Test (Predicted = {a0[1]} + {a1[1]} x Measured)') + sns.regplot(x = meas[0] , y = pred[0], color="#2C6B6F", label = f'Cal (Predicted = {a0[0]} + {a1[0]} x Measured)', scatter_kws={'edgecolor': 'black'}) + sns.regplot(x = meas[1], y = pred[1], color='#d0f7be', label = f'Val (Predicted = {a0[1]} + {a1[1]} x Measured)', scatter_kws={'edgecolor': 'black'}) plt.plot([np.min(meas[0]) - 0.05, np.max([meas[0]]) + 0.05], [np.min(meas[0]) - 0.05, np.max([meas[0]]) + 0.05], color = 'black') for i, txt in enumerate(train_idx): @@ -72,8 +72,11 @@ def resid_plot( meas, pred, train_idx, test_idx): fig, ax = plt.subplots(figsize = (12,4)) - sns.scatterplot(x = pred[0], y = e[0], color='blue', label = f'Calib (Residual = {a0[0]} + {a1[0]} * Predicted)') - sns.scatterplot(x = pred[1], y = e[1], color='green', label = f'Test (Residual = {a0[1]} + {a1[1]} * Predicted)') + sns.scatterplot(x = pred[0], y = e[0], color="#2C6B6F", label = f'Cal', edgecolor="black") + sns.scatterplot(x = pred[1], y = e[1], color="#d0f7be", label = f'Val', edgecolor="black") + + # sns.scatterplot(x = pred[0], y = e[0], color='blue', label = f'Cal (Residual = {a0[0]} + {a1[0]} * Predicted)') + # sns.scatterplot(x = pred[1], y = e[1], color='green', label = f'Val (Residual = {a0[1]} + {a1[1]} * Predicted)') plt.axhline(y= 0, c ='black', linestyle = ':') lim = np.max(abs(np.concatenate([e[0], e[1]], axis = 0)))*1.1 plt.ylim(- lim, lim ) @@ -105,25 +108,72 @@ def download_results(data, export_name): with open(data) as f: st.download_button('Download', f, export_name, type='primary') -@st.cache_resource -def plot_spectra(df, xunits, yunits): +@st.cache_data +def plot_spectra(specdf, xunits, yunits): fig, ax = plt.subplots(figsize = (30,7)) - if isinstance(df.columns[0], str): - df.T.plot(legend=False, ax = ax, color = 'blue') + if isinstance(specdf.columns[0], str): + specdf.T.plot(legend=False, ax = ax, color = '#2474b4') min = 0 else: - min = np.max(df.columns) - df.T.plot(legend=False, ax = ax, color = 'blue').invert_xaxis() + min = np.max(specdf.columns) + specdf.T.plot(legend=False, ax = ax, color = '#2474b4').invert_xaxis() - ax.set_xlabel(xunits, fontsize=18) - ax.set_ylabel(yunits, fontsize=18) + ax.set_xlabel(xunits, fontsize=30) + ax.set_ylabel(yunits, fontsize=30) plt.margins(x = 0) plt.tight_layout() + return fig +@st.cache_data +def hist(y, y_train, y_test, target_name = 'y'): + fig, ax = plt.subplots(figsize = (12,3)) + sns.histplot(y, color = "#004e9e", kde = True, label = str(target_name), ax = ax, fill = True) + sns.histplot(y_train, color = "#2C6B6F", kde = True, label = str(target_name)+" (Cal)", ax = ax, fill = True) + sns.histplot(y_test, color = "#d0f7be", kde = True, label = str(target_name)+" (Val)", ax = ax, fill = True) + ax.set_xlabel(str(target_name)) + plt.legend() + plt.tight_layout() return fig +@st.cache_data +def pred_hist(pred): + # Creating histogram + hist, axs = plt.subplots(1, 1, figsize =(15, 3), + tight_layout = True) + + # Add x, y gridlines + axs.grid( color ='grey', linestyle ='-.', linewidth = 0.5, alpha = 0.6) + # Remove axes splines + for s in ['top', 'bottom', 'left', 'right']: + axs.spines[s].set_visible(False) + # Remove x, y ticks + axs.xaxis.set_ticks_position('none') + axs.yaxis.set_ticks_position('none') + # Add padding between axes and labels + axs.xaxis.set_tick_params(pad = 5) + axs.yaxis.set_tick_params(pad = 10) + # Creating histogram + N, bins, patches = axs.hist(pred, bins = 12) + return hist + +@st.cache_data +def fig_export(): + pass + + + +@st.cache_data(show_spinner =True) +def data_split(x, y): + # Split data into training and test sets using the kennard_stone method and correlation metric, 25% of data is used for testing + train_index, test_index = train_test_split_idx(x , y = y, method = "kennard_stone", metric = "correlation", test_size = 0.25, random_state = 42) + # Assign data to training and test sets + X_train, y_train = DataFrame(x.iloc[train_index,:]), y.iloc[train_index] + X_test, y_test = DataFrame(x.iloc[test_index,:]), y.iloc[test_index] + return X_train, X_test, y_train, y_test, train_index, test_index + ## descriptive stat +@st.cache_data(show_spinner =True) def desc_stats(x): a = {} a['N samples'] = x.shape[0] @@ -143,9 +193,9 @@ def hash_data(data): """Hash various data types using MD5.""" # Convert to a string representation - if isinstance(data, pd.DataFrame): + if isinstance(data, DataFrame): data_str = data.to_string() - elif isinstance(data, pd.Series): + elif isinstance(data, Series): data_str = data.to_string() elif isinstance(data, np.ndarray): data_str = np.array2string(data, separator=',') @@ -169,4 +219,35 @@ def hash_data(data): # Compute the MD5 hash md5_hash = xxhash.xxh32(data_bytes).hexdigest() - return str(md5_hash) \ No newline at end of file + return str(md5_hash) + + + + +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ style test + +@st.cache_data +def background_img(change): + import base64 + image_path = './images/img-sky.jpg' + with open(image_path, "rb") as image_file: + base64_image= base64.b64encode(image_file.read()).decode('utf-8') + + + # CSS code to set the background image + # Get the base64-encoded image + + # CSS code to set the background image + background_image_style = f""" + <style> + .stApp {{ + background-image: url("data:image/jpeg;base64,{base64_image}"); + background-size: cover; + background-repeat: no-repeat; + background-attachment: fixed; + }} + </style> + """ + + # Inject the CSS style + st.markdown(background_image_style, unsafe_allow_html=True) diff --git a/src/utils/NMF_.py b/src/utils/NMF_.py index fead5eb..8defac8 100644 --- a/src/utils/NMF_.py +++ b/src/utils/NMF_.py @@ -21,8 +21,8 @@ class Nmf: self._t = Mo.transform(self.__x) @property def scores_(self): - return pd.DataFrame(self._t) + return DataFrame(self._t) @property def loadings_(self): - return pd.DataFrame(self._p) \ No newline at end of file + return DataFrame(self._p) \ No newline at end of file diff --git a/src/utils/PCA_.py b/src/utils/PCA_.py index 0d2afdb..c5023a0 100644 --- a/src/utils/PCA_.py +++ b/src/utils/PCA_.py @@ -14,7 +14,7 @@ class LinearPCA: ######## results ######## # Results self.__pcnames = [f'PC{i+1}({100 * M.explained_variance_ratio_[i].round(2)}%)' for i in range(self.__ncp)] - self._Qexp_ratio = pd.DataFrame(100 * M.explained_variance_ratio_, columns = ["Qexp"], index= [f'PC{i+1}' for i in range(self.__ncp)]) + self._Qexp_ratio = DataFrame(100 * M.explained_variance_ratio_, columns = ["Qexp"], index= [f'PC{i+1}' for i in range(self.__ncp)]) self._p = M.components_.T self._t = M.transform(self.__x) @@ -40,14 +40,14 @@ class LinearPCA: @property def scores_(self): - return pd.DataFrame(self._t, columns= self.__pcnames) + return DataFrame(self._t, columns= self.__pcnames) @property def loadings_(self): - return pd.DataFrame(self._p, columns=self.__pcnames) + return DataFrame(self._p, columns=self.__pcnames) @property def residuals_(self): - res = pd.DataFrame(self._qres) + res = DataFrame(self._qres) res.columns=self.__pcnames return res \ No newline at end of file diff --git a/src/utils/PLSR_.py b/src/utils/PLSR_.py index 541d5c7..6f90bf4 100644 --- a/src/utils/PLSR_.py +++ b/src/utils/PLSR_.py @@ -32,9 +32,9 @@ class PinardPlsr: # fit scores # Predictions on test set - self.yc = pd.DataFrame(self.trained.predict(self.x_train)) # make predictions on test data and assign to Y_preds variable - self.ycv = pd.DataFrame(cross_val_predict(self.trained, self.x_train, self.y_train, cv = 3)) # make predictions on test data and assign to Y_preds variable - self.yt = pd.DataFrame(self.trained.predict(self.x_test)) # make predictions on test data and assign to Y_preds variable + self.yc = DataFrame(self.trained.predict(self.x_train)) # make predictions on test data and assign to Y_preds variable + self.ycv = DataFrame(cross_val_predict(self.trained, self.x_train, self.y_train, cv = 3)) # make predictions on test data and assign to Y_preds variable + self.yt = DataFrame(self.trained.predict(self.x_test)) # make predictions on test data and assign to Y_preds variable ################################################################################################################ diff --git a/src/utils/PLSR_Preprocess.py b/src/utils/PLSR_Preprocess.py index b70d2aa..f83260c 100644 --- a/src/utils/PLSR_Preprocess.py +++ b/src/utils/PLSR_Preprocess.py @@ -4,7 +4,7 @@ from utils.DATA_HANDLING import * class PlsProcess: SCORE = 100000000 - index_export = pd.DataFrame() + index_export = DataFrame() def __init__(self, x_train, x_test, y_train, y_test, scale, Kfold): PlsProcess.SCORE = 10000 @@ -36,9 +36,9 @@ class PlsProcess: self.x_train = self.xtrain self.x_test = self.xtest else: - self.x_train = pd.DataFrame(eval(f'savgol_filter(self.xtrain, polyorder={params['polyorder']}, deriv={params['deriv']}, window_length = {params['window_length']})'), + self.x_train = DataFrame(eval(f'savgol_filter(self.xtrain, polyorder={params['polyorder']}, deriv={params['deriv']}, window_length = {params['window_length']})'), columns = self.xtrain.columns, index= self.xtrain.index) - self.x_test = pd.DataFrame(eval(f'savgol_filter(self.xtest, polyorder={params['polyorder']}, deriv={params['deriv']}, window_length = {params['window_length']})'), columns = self.xtest.columns , index= self.xtest.index) + self.x_test = DataFrame(eval(f'savgol_filter(self.xtest, polyorder={params['polyorder']}, deriv={params['deriv']}, window_length = {params['window_length']})'), columns = self.xtest.columns , index= self.xtest.index) try: diff --git a/src/utils/RegModels.py b/src/utils/RegModels.py index a913e71..1b759f0 100644 --- a/src/utils/RegModels.py +++ b/src/utils/RegModels.py @@ -10,10 +10,10 @@ class Regmodel(object): self._nc, self._nt, self._p = train[0].shape[0], test[0].shape[0], train[0].shape[1] self._model, self._best = None, None self._yc, self._ycv, self._yt = None, None, None - self._cv_df = pd.DataFrame() - self._sel_ratio = pd.DataFrame() + self._cv_df = DataFrame() + self._sel_ratio = DataFrame() self._nfolds = nfolds - self._selected_bands = pd.DataFrame(index = ['from', 'to']) + self._selected_bands = DataFrame(index = ['from', 'to']) self.important_features = None self._hyper_params = {'polyorder': hp.choice('polyorder', [0, 1, 2]), 'deriv': hp.choice('deriv', [0, 1, 2]), @@ -135,7 +135,7 @@ class Plsr(Regmodel): except (TypeError, ValueError): params[key] = value self._best = params - self.pretreated = pd.DataFrame(x2[0]) + self.pretreated = DataFrame(x2[0]) self._sel_ratio = sel_ratio(Model, x2[0]) return score @@ -210,7 +210,7 @@ class TpeIpls(Regmodel): except (TypeError, ValueError): params[key] = value self._best = params - self.pretreated = pd.DataFrame(x2[0]) + self.pretreated = DataFrame(x2[0]) self.segments = arrays for i in range(len(self.segments)): diff --git a/src/utils/SK_PLSR_.py b/src/utils/SK_PLSR_.py index bafc8ce..c614311 100644 --- a/src/utils/SK_PLSR_.py +++ b/src/utils/SK_PLSR_.py @@ -58,9 +58,9 @@ class PlsR: self.trained = PLSRegression(n_components= self.best['n_components'], scale = False) self.trained.fit(x_train, self.y_train) - self.yc = pd.DataFrame(self.trained.predict(x_train)) # make predictions on test data and assign to Y_preds variable - self.ycv = pd.DataFrame(cross_val_predict(self.trained, x_train, self.y_train, cv = 3)) # make predictions on test data and assign to Y_preds variable - self.yt = pd.DataFrame(self.trained.predict(x_test)) # make predictions on test data and assign to Y_preds variable + self.yc = DataFrame(self.trained.predict(x_train)) # make predictions on test data and assign to Y_preds variable + self.ycv = DataFrame(cross_val_predict(self.trained, x_train, self.y_train, cv = 3)) # make predictions on test data and assign to Y_preds variable + self.yt = DataFrame(self.trained.predict(x_test)) # make predictions on test data and assign to Y_preds variable ####################################################################################################### def objective(self, params): diff --git a/src/utils/UMAP_.py b/src/utils/UMAP_.py index 7b0e41e..b4110d5 100644 --- a/src/utils/UMAP_.py +++ b/src/utils/UMAP_.py @@ -20,7 +20,7 @@ class Umap: self.model = UMAP(n_neighbors=20, n_components=3, min_dist=0.0, )#random_state=42,) self.model.fit(self.numerical_data, y = self.categorical_data_encoded) self.scores_raw = self.model.transform(self.numerical_data) - self.scores = pd.DataFrame(self.scores_raw) + self.scores = DataFrame(self.scores_raw) self.scores.columns = [f'axis_{i+1}' for i in range(self.scores_raw.shape[1])] @property diff --git a/src/utils/VarSel.py b/src/utils/VarSel.py index b23e2fc..001f56e 100644 --- a/src/utils/VarSel.py +++ b/src/utils/VarSel.py @@ -15,7 +15,7 @@ class TpeIpls: '''Optimization algorithms can be used to find the subset of variables that optimize a certain criterion (e.g., maximize predictive performance, minimize overfitting)''' SCORE = 100000000 - index_export = pd.DataFrame() + index_export = DataFrame() def __init__(self, x_train, x_test, y_train, y_test, scale, Kfold, n_intervall): TpeIpls.SCORE = 10000 @@ -58,10 +58,10 @@ class TpeIpls: pt = params['Preprocess'] - self.x_train = pd.DataFrame(eval(f"savgol_filter(xtrain1, polyorder=pt['deriv_sg'], deriv=pt['deriv_sg'], window_length = pt['window_length_sg'], delta=1.0, axis=-1, mode='interp', cval=0.0)") , + self.x_train = DataFrame(eval(f"savgol_filter(xtrain1, polyorder=pt['deriv_sg'], deriv=pt['deriv_sg'], window_length = pt['window_length_sg'], delta=1.0, axis=-1, mode='interp', cval=0.0)") , columns = self.xtrain.columns, index= self.xtrain.index) - self.x_test = pd.DataFrame(eval(f"savgol_filter(xtest1, polyorder=pt['deriv_sg'], deriv=pt['deriv_sg'], window_length = pt['window_length_sg'], delta=1.0, axis=-1, mode='interp', cval=0.0)") , + self.x_test = DataFrame(eval(f"savgol_filter(xtest1, polyorder=pt['deriv_sg'], deriv=pt['deriv_sg'], window_length = pt['window_length_sg'], delta=1.0, axis=-1, mode='interp', cval=0.0)") , columns = self.xtest.columns, index= self.xtest.index) @@ -93,7 +93,7 @@ class TpeIpls: self.nlv = params['n_components'] - TpeIpls.index_export = pd.DataFrame() + TpeIpls.index_export = DataFrame() TpeIpls.index_export["Vars"] = self.x_test.columns[id] TpeIpls.index_export.index = id self.best = params @@ -122,7 +122,7 @@ class TpeIpls: for i in range(len(self.segments)): ban[f'band{i+1}'] = [self.segments[i][0], self.segments[i][self.segments[i].shape[0]-1]] - self.bands = pd.DataFrame(ban).T + self.bands = DataFrame(ban).T self.bands.columns = ['from', 'to'] diff --git a/src/utils/__init__.py b/src/utils/__init__.py index c5434f5..1191fd2 100644 --- a/src/utils/__init__.py +++ b/src/utils/__init__.py @@ -8,7 +8,7 @@ from .PLSR_ import PinardPlsr from .LWPLSR_ import LWPLSR from .Evaluation_Metrics import metrics #from .VarSel import TpeIpls -from .Miscellaneous import resid_plot, reg_plot, desc_stats, hash_data +from .Miscellaneous import resid_plot, reg_plot, desc_stats, hash_data, hist, pred_hist, background_img from .DxReader import DxRead, read_dx from .HDBSCAN_Clustering import Hdbscan from .SK_PLSR_ import PlsR @@ -16,4 +16,4 @@ from .PLSR_Preprocess import PlsProcess from .NMF_ import Nmf from .Ap import AP from .RegModels import Plsr, TpeIpls -from .KennardStone import KS, RDM +from .KennardStone import KS, RDM \ No newline at end of file -- GitLab