diff --git a/README.md b/README.md index cc9c29fe64dfb8b86d65e2565f29b7e6421d64d3..ae7fb90a88b005af80744358b0fc0ead39c35e41 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,8 @@ If one wants to use data stored in a SQL database, the config file is in the con ## Installation This package is written in python. You can clone the repository: git clone https://src.koda.cnrs.fr/CEFE/PACE/nirs_workflow.git -Then install the requirements: pip install -r requirements.txt -(OPTIONNAL) To use Locally weighted PLS Regression for creation model, you will need to install Jchemo.jl (https://github.com/mlesnoff/Jchemo.jl), a Julia package. +Then install the requirements: pip install -r requirements.txt +(OPTIONNAL) To use Locally weighted PLS Regression for creation model, you will need to install Jchemo.jl (https://github.com/mlesnoff/Jchemo.jl), a Julia package. From the CLI: python > python '>>> import julia @@ -29,7 +29,7 @@ From the CLI: python To check if Jchemo is installed without errors: > '>>> Pkg.status() -You can then run (CLI): streamlit run ./app.py from within your folder. +You can then run (CLI): streamlit run ./app.py from within your src/ folder. The app will open in your default browser. diff --git a/Sample_test.txt b/Sample_test.txt deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/Class_Mod/LWPLSR_.py b/src/Class_Mod/LWPLSR_.py index e5682ac39c37e85dd6871faf0e1646b5c5626e30..5e86c902e4926d77b818531284492abffa9d584c 100644 --- a/src/Class_Mod/LWPLSR_.py +++ b/src/Class_Mod/LWPLSR_.py @@ -1,19 +1,44 @@ -import pandas as pd -import streamlit from Packages import * from Class_Mod.Miscellaneous import * class LWPLSR: """ - The UMAP dimension reduction algorithm from scikit learn + The lwpls regression model from Jchemo (M. Lesnoff) """ - def __init__(self, x_train, x_test, y_train, y_test): + def __init__(self, x_train, y_train, x_test, y_test): """Initiate the LWPLSR and prepare data for Julia computing.""" - self.x_train, self.y_train, self.x_test, self.y_test = x_train, x_test, y_train, y_test + self.x_train, self.y_train, self.x_test, self.y_test = x_train, y_train, x_test, y_test # prepare to send dataframes to julia and Jchemo - jl.x_train,jl.y_train,jl.x_test,jl.y_test = self.x_train, self.y_train, self.x_test, self.y_test + jl.x_train, jl.y_train, jl.x_test, jl.y_test = self.x_train, self.y_train, self.x_test, self.y_test + # Pre-treatment of x_train and x_test + jl.seval(""" + # using DataFrames + # using Pandas + using Jchemo + mod1 = Jchemo.model(snv; centr = true, scal = true) + mod2 = Jchemo.model(savgol; npoint = 15, deriv = 1, degree = 2) + mod = Jchemo.pip(mod1, mod2) + Jchemo.fit!(mod, x_train) + x_train = Jchemo.transf(mod1, x_train) + Jchemo.fit!(mod, x_test) + x_test = Jchemo.transf(mod1, x_test) + """) + jl.seval(""" + ntrain = nro(x_train) + segm = segmkf(ntrain, 4; rep = 5) + nlvdis = [5; 10; 15] ; metric = [:mah] + h = [1; 2; 6; Inf] ; k = [10; 30; 100] + nlv = 0:15 + pars = mpar(nlvdis = nlvdis, metric = metric, h = h, k = k) + println(pars) + """) + + # initialize vars from the class + y_shape = y_test.shape self.scores = pd.DataFrame self.predicted_results_on_test = pd.DataFrame + self.pred = np.zeros(shape=(y_shape[0], 1)) + self.mod = "" def Jchemo_lwplsr(self): """Send data to Julia to compute lwplsr. @@ -29,38 +54,70 @@ class LWPLSR: self.predicted_results_on_test (DataFrame): """ # launch Julia Jchemo lwplsr - jl.eval(""" - using Pandas + jl.seval(""" using DataFrames + using Pandas using Jchemo - nlvdis = 5 ; metric = :mah - h = 1 ; k = 200 ; nlv = 15 #; scal = true - mod = Jchemo.model(Jchemo.lwplsr; nlvdis, metric, h, k, nlv) - Jchemo.fit!(mod, X_train, y_train) - # Jchemo.pnames(mod) - # Jchemo.pnames(mod.fm) - # predictions on test data calculation - res = Jchemo.predict(mod, X_test) - # Jchemo.pnames(res) + x_train |> Pandas.DataFrame |> DataFrames.DataFrame + y_train |> Pandas.DataFrame |> DataFrames.DataFrame + x_test |> Pandas.DataFrame |> DataFrames.DataFrame + y_test |> Pandas.DataFrame |> DataFrames.DataFrame """) - resjp = jl.seval(""" - Pandas.DataFrame(res.pred) + # Create LWPLSR model and fit + # jl.seval(""" + # nlvdis = 5 ; metric = :mah + # h = 1 ; k = 200 ; nlv = 15 #; scal = true + # mod = Jchemo.model(Jchemo.lwplsr; nlvdis, metric, h, k, nlv) + # # Fit model + # Jchemo.fit!(mod, x_train, y_train) + # """) + + jl.seval(""" + mod = Jchemo.model(Jchemo.lwplsr) + res = Jchemo.gridcv(mod, x_train, y_train; segm, score = Jchemo.rmsep, pars, nlv, verbose = true).res + # u = findall(res.y1 .== minimum(res.y1))[1] + # mod = Jchemo.model(lwplsr; nlvdis = res.nlvdis[u], metric = res.metric[u], h = res.h[u], k = res.k[u], nlv = res.nlv[u]) ; + # Jchemo.fit!(mod, x_train, y_train) """) - scoresjp = jl.seval(""" - Jchemo.mse(res.pred, y_test) + self.mod = jl.mod + + def Jchemo_lwplsr_predict(self): + # Predictions on x_test and store in self.pred + self.pred = jl.seval(""" + res = Jchemo.predict(mod, x_test) + res.pred """) - self.scores = pd.Dataframe(scoresjp) - self.predicted_results_on_test = pd.Dataframe(resjp) + # convert predicted data from x_test to Pandas DataFrame + self.predicted_results_on_test = pd.DataFrame(self.pred) @property def pred_data_(self): return self.predicted_results_on_test, self.predicted_results_on_test, self.predicted_results_on_test - # @property - # def model_(self): - # return self.trained + @property + def model_(self): + return self.mod @property def metrics_(self): - # self.scores = pd.DataFrame(self.scores, index=['test']) - return self.scores \ No newline at end of file + jl.pred = self.pred + st.dataframe(self.pred) + st.dataframe(self.predicted_results_on_test) + st.write('starting metrics') + jl.seval(""" + using Jchemo + """) + scorermsep = jl.seval(""" + first(Jchemo.rmsep(pred, y_test)) + """) + scoremr2 = jl.seval(""" + first(Jchemo.r2(pred, y_test)) + """) + scorerpd = jl.seval(""" + first(Jchemo.rpd(pred, y_test)) + """) + scoremsep = jl.seval(""" + first(Jchemo.sep(pred, y_test)) + """) + self.scores = pd.DataFrame([[scoremr2, scorermsep, scoremsep, scorerpd]], columns=['r2', 'rmsep', 'msep', 'rpd'], index=['scores']) + return self.scores diff --git a/src/Class_Mod/Miscellaneous.py b/src/Class_Mod/Miscellaneous.py index 0d726113ce995ce0dde5e53054cccb98765a568e..706a61de7a3d7a14f8867e1cdda7366796ae6464 100644 --- a/src/Class_Mod/Miscellaneous.py +++ b/src/Class_Mod/Miscellaneous.py @@ -6,7 +6,6 @@ from Packages import * def local_css(file_name): with open(file_name) as f: st.markdown(f"<style>{f.read()}</style>", unsafe_allow_html=True) -local_css("style/style.css") # predict module def prediction(NIRS_csv, qsep, qhdr, model): diff --git a/src/Modules.py b/src/Modules.py index d5a0e2a3d3f0b7e2416c4cd7e980426ad3284ee7..cb51a5c8e3fc5e3b62af93dedb35b8b3eb0dc639 100644 --- a/src/Modules.py +++ b/src/Modules.py @@ -1,5 +1,6 @@ from Class_Mod import PlsR, LinearPCA, Umap, find_col_index, PinardPlsr from Class_Mod import LWPLSR, list_files, metrics, TpeIpls, reg_plot, resid_plot, Sk_Kmeans, DxRead, Hdbscan, read_dx, PlsProcess -from Class_Mod.Miscellaneous import prediction, download_results, plot_spectra -from style.header import add_header \ No newline at end of file +from Class_Mod.Miscellaneous import prediction, download_results, plot_spectra, local_css +from style.header import add_header +local_css("style/style.css") \ No newline at end of file diff --git a/src/Packages.py b/src/Packages.py index 5c1d19856500b2d04cd3b8e439af9323a5311888..bc4f15307d8cc98a24ffb6a07e0eb8df6e4ee115 100644 --- a/src/Packages.py +++ b/src/Packages.py @@ -8,8 +8,6 @@ import random import datetime import numpy as np import pandas as pd -from os import listdir -from os.path import isfile, join from sklearn.preprocessing import StandardScaler, MinMaxScaler, LabelEncoder import time from scipy.stats import skew, kurtosis @@ -38,7 +36,7 @@ from sklearn.compose import TransformedTargetRegressor from sklearn.metrics import mean_absolute_error, mean_squared_error, mean_absolute_percentage_error, r2_score from sklearn.cross_decomposition import PLSRegression -## Images and plots +## Images and plots from PIL import Image import plotly.express as px import plotly.graph_objects as go diff --git a/src/app.py b/src/app.py index 0ec3af010fb29c358eb9c9c12601849bf8a37c59..bfe8cb84b57d1d877904927ffb96f3f041af6e2b 100644 --- a/src/app.py +++ b/src/app.py @@ -6,15 +6,6 @@ from Modules import * from Class_Mod.DATA_HANDLING import * -# HTML pour le bandeau "CEFE - CNRS" -# bandeau_html = """ -# <div style="width: 100%; background-color: #4682B4; padding: 10px; margin-bottom: 10px;"> -# <h1 style="text-align: center; color: white;">CEFE - CNRS</h1> -# </div> -# """ - -# Injecter le code HTML du bandeau -# st.markdown(bandeau_html, unsafe_allow_html=True) add_header() # # TOC menu on the left @@ -27,10 +18,6 @@ show_pages( ] ) -# hide_pages("Samples Selection") -# hide_pages("Models Creation") -# hide_pages("Predictions") - with st.sidebar: interface = st.selectbox(label="Interface", options=['simple', 'advanced'], key='interface') @@ -54,22 +41,6 @@ with st.sidebar: # Page header with st.container(): - # Centrer les boutons - CODE DEPLACE dans le style/style.css - # st.markdown( - # """ - # <style> - # .stButton>button { - # display: block; - # margin: 0 auto; - # width: 200px; - # height: 50px; - # font-size: 16px; - # } - # </style> - # """, - # unsafe_allow_html=True - # ) - header1, header2, header3,header4 = st.columns(4) if header1.button("Inputs"): st.switch_page('pages\\4-inputs.py') @@ -83,4 +54,4 @@ with st.container(): st.title("NIRS Utils") st.write("Samples selection (PCA, [UMAP](https://umap-learn.readthedocs.io/en/latest/how_umap_works.html), ...), Predictive Modelling ([Pinard](https://github.com/GBeurier/pinard), [LWPLSR](https://doi.org/10.1002/cem.3209), ...), and Predictions using your data (CSV or DX files) and/or PACE NIRS Database.") #st.image(img_general) - st.markdown("### We could add documentation here ###") \ No newline at end of file + st.markdown("### We could add documentation here ###") diff --git a/src/pages/2-model_creation.py b/src/pages/2-model_creation.py index cfed211cd23bdeb57c997ec2eb27fa521bfdcd57..986d249bb2c254db09665c5e6137f7d70b88824b 100644 --- a/src/pages/2-model_creation.py +++ b/src/pages/2-model_creation.py @@ -134,9 +134,13 @@ if not spectra.empty and not y.empty: reg_model = Reg.model_ #M2.dataframe(Pin.pred_data_) elif regression_algo == reg_algo[2]: - # Reg = LWPLSR(x_train = X_train, x_test = X_test, y_train = y_train, y_test = y_test) - # LWPLSR.Jchemo_lwplsr(Reg) - pass + x_train, y_train, x_test, y_test = X_train.to_numpy(), y_train.to_numpy(), X_test.to_numpy(), y_test.to_numpy() + Reg = LWPLSR(x_train, y_train, x_test, y_test) + LWPLSR.Jchemo_lwplsr(Reg) + reg_model = Reg.model_ + # LWPLSR.Jchemo_lwplsr_predict(Reg) + # st.dataframe(Reg.pred_data_) + # st.dataframe(Reg.metrics_) elif regression_algo == reg_algo[3]: s = M1.number_input(label='Enter the maximum number of intervals', min_value=1, max_value=6, value=3) diff --git a/src/pages/4-inputs.py b/src/pages/4-inputs.py index 59fbb88694103f31806b91c16ed2510a18215e03..a32790659064caf4eb47158303ddd3b4e362d672 100644 --- a/src/pages/4-inputs.py +++ b/src/pages/4-inputs.py @@ -1,21 +1,10 @@ -import streamlit as st - from Packages import * -st.set_page_config(page_title="NIRS Utils", page_icon=":goat:", layout="wide",) -if 'interface' not in st.session_state: - st.session_state['interface'] = 'simple' +st.set_page_config(page_title="NIRS Utils", page_icon=":goat:", layout="wide") from Modules import * from Class_Mod.DATA_HANDLING import * -# HTML for the banner "CEFE - CNRS" -# bandeau_html = """ -# <div style="width: 100%; background-color: #4682B4; padding: 10px; margin-bottom: 10px;"> -# <h1 style="text-align: center; color: white;">CEFE - CNRS</h1> -# </div> -# """ -# -# -# # Inject the HTML code for the banner -# st.markdown(bandeau_html, unsafe_allow_html=True) +if 'interface' not in st.session_state: + st.session_state['interface'] = 'simple' + add_header() @@ -26,22 +15,6 @@ if 'form_submitted' not in st.session_state: # Page header with st.container(): - # Center the buttons - st.markdown( - """ - <style> - .stButton>button { - display: block; - margin: 0 auto; - width: 200px; - height: 50px; - font-size: 16px; - } - </style> - """, - unsafe_allow_html=True - ) - # Text input fields with st.form(key='my_form'): @@ -108,10 +81,3 @@ with st.container(): if header5.button("Prediction"): st.session_state['current_page'] = 'pages\\3-prediction.py' st.switch_page('pages\\3-prediction.py') - - - -# Bouton de retour à la page d'accueil -st.markdown('<div style="text-align: left;"><a href="/"> <img src="house.jpg" alt="Home" style="width:50px;height:50px;"> </a></div>', unsafe_allow_html=True) - - diff --git a/src/plot_axe1_axe2.png b/src/plot_axe1_axe2.png deleted file mode 100644 index a52dfe7b11df2b892ef0bf0b54e86c47fd0714b9..0000000000000000000000000000000000000000 Binary files a/src/plot_axe1_axe2.png and /dev/null differ