feat: Separate GUI callbacks for improved code readability
chore: Updated save/open function
This commit is contained in:
@ -29,3 +29,9 @@
|
||||
* Ajout des GNG
|
||||
* Ajout de config.json pour éditer la configuration de l'application plus facilement
|
||||
* Ajustement des callback pour éviter les bugs
|
||||
* Séparation des callbacks de la GUI pour faciliter la lecture du code
|
||||
|
||||
## V4.1
|
||||
|
||||
* Ajustement de la fonction d'enregistrement et d'ouverture des datasets
|
||||
* Ajout d'un bouton de sauvegarde pour les datasets filtrés
|
||||
|
@ -1,3 +1,18 @@
|
||||
# Test
|
||||
# 3D App
|
||||
|
||||
Ceci est un test
|
||||
## Pages description
|
||||
|
||||
**Home page**: On the home page, you will have the A-Scan, the two B-Scan and he 3D Plot. You can view them in fullscreen by clicking the fullscreen button on the top right of the card.
|
||||
|
||||
**A-Scan filters**: On this page, you can apply filters on the dataset with custom values and see the difference with the raw dataset on the A-Scan graph.
|
||||
|
||||
**GNG**: The GNG page is to reconstruct default of the dataset by neural network.
|
||||
|
||||
|
||||
## Navbar description
|
||||
|
||||
**Settings**: Open the settings modal taht allows you to change the sampling values, if the filters must be applied on the entire dataset and the usage of real values of the dataset
|
||||
|
||||
**Open**: Open a dataset present in `Dataset/saves` folder (only .npy files)
|
||||
|
||||
**Save**: Save the current dataset in `Dataset/saves` folder
|
||||
|
313
3D_app/callbacks/ascan.py
Normal file
313
3D_app/callbacks/ascan.py
Normal file
@ -0,0 +1,313 @@
|
||||
from re import I
|
||||
from dash import callback, Input, Output, State
|
||||
from selection_filtre import switch_case
|
||||
import plotly.graph_objects as go
|
||||
import plotly.express as px
|
||||
from Bscan_Cscan_trait import Cscant, Bscant
|
||||
from util import lire_fichier_csv
|
||||
import numpy as np
|
||||
|
||||
# on définit le dossier et les fichiers à lire
|
||||
dossier = "Dataset/Shear_Wave_Rot00_CSV_Data"
|
||||
fichiers_selectionnes = [
|
||||
"Shear_x001-x101_y{:03d}_Rot00.csv".format(i) for i in range(10, 13)
|
||||
]
|
||||
|
||||
# on lit les fichiers et on les met dans un tableau
|
||||
pre_volume = np.array(lire_fichier_csv(dossier, fichiers_selectionnes))
|
||||
volume = pre_volume[:, :, :]
|
||||
data_traits = volume
|
||||
dim_x, dim_y, dim_z = volume.shape
|
||||
|
||||
X, Y, Z = np.mgrid[0:dim_x, 0:dim_y, 0:dim_z]
|
||||
|
||||
|
||||
def get_callbacks():
|
||||
@callback(
|
||||
Output("store-filters", "data"),
|
||||
Input("button-validate-filter", "n_clicks"),
|
||||
[
|
||||
State("select-ascan-filter1", "value"),
|
||||
State("select-ascan-filter2", "value"),
|
||||
State("select-ascan-filter3", "value"),
|
||||
State("input-ascan-solo-fs", "value"),
|
||||
State("input-ascan-solo-cutoff", "value"),
|
||||
State("input-ascan-solo-order", "value"),
|
||||
State("input-ascan-solo-windowsize", "value"),
|
||||
State("input-ascan-solo-fs-2", "value"),
|
||||
State("input-ascan-solo-cutoff-2", "value"),
|
||||
State("input-ascan-solo-order-2", "value"),
|
||||
State("input-ascan-solo-windowsize-2", "value"),
|
||||
],
|
||||
)
|
||||
def store_settings(
|
||||
clicks,
|
||||
select_filtre_1,
|
||||
select_filtre_2,
|
||||
select_filtre_3,
|
||||
fs_filtre_1,
|
||||
cutoff_filtre_1,
|
||||
order_filtre_1,
|
||||
windowsize_filtre_1,
|
||||
fs_filtre_2,
|
||||
cutoff_filtre_2,
|
||||
order_filtre_2,
|
||||
windowsize_filtre_2,
|
||||
):
|
||||
if clicks:
|
||||
return {
|
||||
"select_filtre_1": select_filtre_1,
|
||||
"select_filtre_2": select_filtre_2,
|
||||
"select_filtre_3": select_filtre_3,
|
||||
"fs_filtre_1": fs_filtre_1,
|
||||
"cutoff_filtre_1": cutoff_filtre_1,
|
||||
"order_filtre_1": order_filtre_1,
|
||||
"windowsize_filtre_1": windowsize_filtre_1,
|
||||
"fs_filtre_2": fs_filtre_2,
|
||||
"cutoff_filtre_2": cutoff_filtre_2,
|
||||
"order_filtre_2": order_filtre_2,
|
||||
"windowsize_filtre_2": windowsize_filtre_2,
|
||||
}
|
||||
|
||||
# callback to update filter values
|
||||
@callback(
|
||||
[
|
||||
Output("input-ascan-solo-fs", "disabled"),
|
||||
Output("input-ascan-solo-cutoff", "disabled"),
|
||||
Output("input-ascan-solo-order", "disabled"),
|
||||
Output("input-ascan-solo-windowsize", "disabled"),
|
||||
Output("input-ascan-solo-fs-2", "disabled"),
|
||||
Output("input-ascan-solo-cutoff-2", "disabled"),
|
||||
Output("input-ascan-solo-order-2", "disabled"),
|
||||
Output("input-ascan-solo-windowsize-2", "disabled"),
|
||||
],
|
||||
[
|
||||
Input("select-ascan-filter2", "value"),
|
||||
Input("select-ascan-filter3", "value"),
|
||||
],
|
||||
)
|
||||
def update_filter_values(select_filtre_1, select_filtre_2):
|
||||
fs_1 = True
|
||||
cutoff_1 = True
|
||||
ordre_1 = True
|
||||
windowsize_1 = True
|
||||
fs_2 = True
|
||||
cutoff_2 = True
|
||||
ordre_2 = True
|
||||
windowsize_2 = True
|
||||
if int(select_filtre_1) == 3:
|
||||
fs_1 = False
|
||||
cutoff_1 = False
|
||||
ordre_1 = False
|
||||
if int(select_filtre_2) == 3:
|
||||
fs_2 = False
|
||||
cutoff_2 = False
|
||||
ordre_2 = False
|
||||
if int(select_filtre_1) in (4, 5, 6, 7):
|
||||
windowsize_1 = False
|
||||
if int(select_filtre_2) in (4, 5, 6, 7):
|
||||
windowsize_2 = False
|
||||
return [
|
||||
fs_1,
|
||||
cutoff_1,
|
||||
ordre_1,
|
||||
windowsize_1,
|
||||
fs_2,
|
||||
cutoff_2,
|
||||
ordre_2,
|
||||
windowsize_2,
|
||||
]
|
||||
|
||||
# callback to update the heatmap
|
||||
@callback(
|
||||
[
|
||||
Output("heatmap-ascan-solo", "figure"),
|
||||
Output("heatmap-bscan-solo", "figure"),
|
||||
Output("heatmap-fft-solo", "figure"),
|
||||
Output("loading", "children"),
|
||||
],
|
||||
[
|
||||
Input("layer-slider-ascan-solo-x", "value"),
|
||||
Input("layer-slider-ascan-solo-y", "value"),
|
||||
Input("layer-slider-ascan-solo-z", "value"),
|
||||
Input("button-validate-filter", "n_clicks"),
|
||||
],
|
||||
[
|
||||
State("select-ascan-filter1", "value"),
|
||||
State("select-ascan-filter2", "value"),
|
||||
State("select-ascan-filter3", "value"),
|
||||
State("input-ascan-solo-fs", "value"),
|
||||
State("input-ascan-solo-cutoff", "value"),
|
||||
State("input-ascan-solo-order", "value"),
|
||||
State("input-ascan-solo-windowsize", "value"),
|
||||
State("input-ascan-solo-fs-2", "value"),
|
||||
State("input-ascan-solo-cutoff-2", "value"),
|
||||
State("input-ascan-solo-order-2", "value"),
|
||||
State("input-ascan-solo-windowsize-2", "value"),
|
||||
],
|
||||
)
|
||||
def update_heatmap_ascan(
|
||||
select_ascan_x,
|
||||
select_ascan_y,
|
||||
select_ascan_z,
|
||||
n_clicks,
|
||||
selec_transforme_hilbert,
|
||||
select_filtre_1,
|
||||
select_filtre_2,
|
||||
fs_filtre_1,
|
||||
cutoff_filtre_1,
|
||||
order_filtre_1,
|
||||
windowsize_filtre_1,
|
||||
fs_filtre_2,
|
||||
cutoff_filtre_2,
|
||||
order_filtre_2,
|
||||
windowsize_filtre_2,
|
||||
):
|
||||
print("debut du traitement")
|
||||
data_avec_traitement = volume[
|
||||
int(select_ascan_y) - 1,
|
||||
select_ascan_z[0] : select_ascan_z[1],
|
||||
int(select_ascan_x) - 1,
|
||||
]
|
||||
data_sans_traitement = volume[
|
||||
int(select_ascan_y) - 1,
|
||||
select_ascan_z[0] : select_ascan_z[1],
|
||||
int(select_ascan_x) - 1,
|
||||
]
|
||||
|
||||
data_avec_traitement = switch_case(
|
||||
data_avec_traitement, int(selec_transforme_hilbert)
|
||||
)
|
||||
data_sans_traitement = switch_case(
|
||||
data_sans_traitement, int(selec_transforme_hilbert)
|
||||
)
|
||||
|
||||
data_avec_traitement = switch_case(
|
||||
data_avec_traitement,
|
||||
int(select_filtre_1),
|
||||
float(fs_filtre_1),
|
||||
float(cutoff_filtre_1),
|
||||
int(order_filtre_1),
|
||||
int(windowsize_filtre_1),
|
||||
)
|
||||
data_avec_traitement = switch_case(
|
||||
data_avec_traitement,
|
||||
int(select_filtre_2),
|
||||
float(fs_filtre_2),
|
||||
float(cutoff_filtre_2),
|
||||
int(order_filtre_2),
|
||||
int(windowsize_filtre_2),
|
||||
)
|
||||
print("fin du traitement")
|
||||
bouton = "Apply"
|
||||
if n_clicks != None:
|
||||
data_traits = Cscant(
|
||||
volume,
|
||||
int(selec_transforme_hilbert),
|
||||
int(select_filtre_1),
|
||||
int(select_filtre_2),
|
||||
float(fs_filtre_1),
|
||||
float(cutoff_filtre_1),
|
||||
int(order_filtre_1),
|
||||
int(windowsize_filtre_1),
|
||||
float(fs_filtre_2),
|
||||
float(cutoff_filtre_2),
|
||||
int(order_filtre_2),
|
||||
int(windowsize_filtre_2),
|
||||
)
|
||||
bouton = "Apply"
|
||||
fig = px.line(title="A-scan")
|
||||
new_trace = go.Scatter(y=data_avec_traitement, mode="lines", name="Ascan trait")
|
||||
fig.add_trace(new_trace)
|
||||
new_trace = go.Scatter(
|
||||
y=data_sans_traitement, mode="lines", name="Ascan (hilbert)"
|
||||
)
|
||||
fig.add_trace(new_trace)
|
||||
fig.update_layout(xaxis_title="Indix", yaxis_title="Amplitude")
|
||||
|
||||
data_bscan = Bscant(
|
||||
volume[select_ascan_y - 1, select_ascan_z[0] : select_ascan_z[1], :],
|
||||
int(selec_transforme_hilbert),
|
||||
int(select_filtre_1),
|
||||
int(select_filtre_2),
|
||||
float(fs_filtre_1),
|
||||
float(cutoff_filtre_1),
|
||||
int(order_filtre_1),
|
||||
int(windowsize_filtre_1),
|
||||
float(fs_filtre_2),
|
||||
float(cutoff_filtre_2),
|
||||
int(order_filtre_2),
|
||||
int(windowsize_filtre_2),
|
||||
)
|
||||
|
||||
fig2 = px.imshow(
|
||||
data_bscan,
|
||||
color_continuous_scale="Jet",
|
||||
aspect="auto",
|
||||
title="B-scan XZ",
|
||||
)
|
||||
fig2.update_layout(xaxis_title="Z", yaxis_title=" X")
|
||||
data_sans_traitement_fft = np.fft.fft(
|
||||
volume[
|
||||
int(select_ascan_y) - 1,
|
||||
select_ascan_z[0] : select_ascan_z[1],
|
||||
int(select_ascan_x) - 1,
|
||||
]
|
||||
)
|
||||
fig3 = px.line(title="FFT")
|
||||
trace3 = go.Scatter(
|
||||
y=np.abs(data_sans_traitement_fft), mode="lines", name=" FFT "
|
||||
)
|
||||
fig3.add_trace(trace3)
|
||||
fig3.update_layout(
|
||||
xaxis_title="FFT indix", yaxis_title="FFT of signal (Mangnitude)"
|
||||
)
|
||||
return [fig, fig2, fig3, bouton]
|
||||
|
||||
@callback(
|
||||
[
|
||||
Output("select-ascan-filter1", "value"),
|
||||
Output("select-ascan-filter2", "value"),
|
||||
Output("select-ascan-filter3", "value"),
|
||||
Output("input-ascan-solo-fs", "value"),
|
||||
Output("input-ascan-solo-cutoff", "value"),
|
||||
Output("input-ascan-solo-order", "value"),
|
||||
Output("input-ascan-solo-windowsize", "value"),
|
||||
Output("input-ascan-solo-fs-2", "value"),
|
||||
Output("input-ascan-solo-cutoff-2", "value"),
|
||||
Output("input-ascan-solo-order-2", "value"),
|
||||
Output("input-ascan-solo-windowsize-2", "value"),
|
||||
],
|
||||
Input("store-filters", "data"),
|
||||
)
|
||||
def load_filters(data):
|
||||
if data:
|
||||
return [
|
||||
data["select_filtre_1"],
|
||||
data["select_filtre_2"],
|
||||
data["select_filtre_3"],
|
||||
data["fs_filtre_1"],
|
||||
data["cutoff_filtre_1"],
|
||||
data["order_filtre_1"],
|
||||
data["windowsize_filtre_1"],
|
||||
data["fs_filtre_2"],
|
||||
data["cutoff_filtre_2"],
|
||||
data["order_filtre_2"],
|
||||
data["windowsize_filtre_2"],
|
||||
]
|
||||
return [1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
|
||||
@callback(
|
||||
[Output("modal-ascan-solo", "is_open"), Output("save-toast", "is_open", allow_duplicate=True)],
|
||||
[Input("save-ascan-solo", "n_clicks"), Input("button-save-data", "n_clicks")],
|
||||
[State("modal-ascan-solo", "is_open"), State("input-save-ascan", "value")],
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def toggle_modal(n1, n2, is_open, filename):
|
||||
if n1:
|
||||
np.save(f"Dataset/saves/{filename}.npy", data_traits)
|
||||
return [not is_open, True]
|
||||
elif n2:
|
||||
return [not is_open, False]
|
||||
|
||||
return [is_open, False]
|
82
3D_app/callbacks/gng.py
Normal file
82
3D_app/callbacks/gng.py
Normal file
@ -0,0 +1,82 @@
|
||||
from dash import callback_context as ctx
|
||||
from dash import callback, Output, Input
|
||||
import numpy as np
|
||||
import plotly.graph_objects as go
|
||||
from GNG_3D import *
|
||||
from pages.ascan import data_traits
|
||||
|
||||
def get_callbacks():
|
||||
@callback(
|
||||
[Output("gng-graph", "figure")],
|
||||
[
|
||||
Input("generate-gng", "n_clicks"),
|
||||
Input("seuil", "value"),
|
||||
Input("max_neurons", "value"),
|
||||
Input("Iterations", "value"),
|
||||
Input("Max_of_age", "value"),
|
||||
Input("eb", "value"),
|
||||
Input("en", "value"),
|
||||
Input("alpha", "value"),
|
||||
Input("beta", "value"),
|
||||
Input("l", "value"),
|
||||
],
|
||||
)
|
||||
def generate_gng(n_clicks, seuil, max_neurons, max_iter, max_age, eb, en, alpha, beta, l):
|
||||
|
||||
global clics
|
||||
if n_clicks:
|
||||
data=np.array(data_traits)
|
||||
fig = go.Figure()
|
||||
size_data=np.shape(data)
|
||||
x1=[]
|
||||
x2=[]
|
||||
x3=[]
|
||||
x4=[]
|
||||
for i in range(0,size_data[0]):
|
||||
res=data[i,:,:]
|
||||
res=position_point_espace(data=res,seuil=200,y=i)
|
||||
res = np.array(res)
|
||||
x1.append(res)
|
||||
gng = GrowingNeuralGas(int(max_neurons),int(max_iter),int(max_age), float(eb), float(en), float(alpha), float(beta),int(l), res)
|
||||
gng_graph = gng.learn()
|
||||
neuron_positions = np.array([vertex['weight'] for vertex in gng_graph.vs])
|
||||
neuron_edge= np.array([(edge.source, edge.target) for edge in gng_graph.es])
|
||||
for edge in gng_graph.es:
|
||||
src, tgt = edge.source, edge.target
|
||||
src_pos, tgt_pos = gng_graph.vs[src]['weight'], gng_graph.vs[tgt]['weight']
|
||||
x3.append(src_pos)
|
||||
x4.append(tgt_pos)
|
||||
|
||||
x2.append(neuron_positions)
|
||||
res=np.vstack(x1)
|
||||
neuron_positions=np.vstack(x2)
|
||||
src_pos=np.vstack(x3)
|
||||
tgt_pos=np.vstack(x4)
|
||||
fig.add_trace(go.Scatter3d(
|
||||
x=res[:, 0],
|
||||
y=res[:, 1],
|
||||
z=res[:, 2],
|
||||
mode='markers',
|
||||
marker=dict(size=1, color=res[:, 3], colorscale='Viridis', opacity=0.5),
|
||||
name='Data'
|
||||
))
|
||||
fig.add_trace(go.Scatter3d(
|
||||
x=neuron_positions[:, 0],
|
||||
y=neuron_positions[:, 1],
|
||||
z=neuron_positions[:, 2],
|
||||
mode='markers',
|
||||
marker=dict(size=4, color=neuron_positions[:,3]),
|
||||
name='Neurons'
|
||||
))
|
||||
for src, tgt in zip(src_pos, tgt_pos):
|
||||
fig.add_trace(go.Scatter3d(
|
||||
x=[src[0], tgt[0]],
|
||||
y=[src[1], tgt[1]],
|
||||
z=[src[2], tgt[2]],
|
||||
mode='lines',
|
||||
line=dict(color="black", width=1),
|
||||
showlegend=False,
|
||||
))
|
||||
clics = n_clicks
|
||||
return [fig]
|
||||
return [go.Figure().update_layout(title="No data", showlegend=False).update_xaxes(visible=False).update_yaxes(visible=False)]
|
532
3D_app/callbacks/home.py
Normal file
532
3D_app/callbacks/home.py
Normal file
@ -0,0 +1,532 @@
|
||||
from dash import State, Output, Input, callback
|
||||
import dash
|
||||
import numpy as np
|
||||
import plotly.graph_objects as go
|
||||
import plotly.express as px
|
||||
from os.path import join
|
||||
from util import lire_fichier_csv
|
||||
from selection_filtre import switch_case
|
||||
|
||||
# on définit le dossier et les fichiers à lire
|
||||
dossier = "Dataset/Shear_transform"
|
||||
fichiers_selectionnes = [
|
||||
"Shear_x001-x101_y{:03d}_Rot00_transform.csv".format(i) for i in range(10, 14)
|
||||
]
|
||||
|
||||
# valeurs d'échantillonage
|
||||
echantillonage_x = 1
|
||||
echantillonage_y = 32
|
||||
echantillonage_z = 1
|
||||
|
||||
pre_volume = np.array(lire_fichier_csv(dossier, fichiers_selectionnes))
|
||||
volume = pre_volume[::echantillonage_x, ::echantillonage_y, ::echantillonage_z]
|
||||
dim_x, dim_y, dim_z = volume.shape
|
||||
|
||||
X, Y, Z = np.mgrid[0:dim_x, 0:dim_y, 0:dim_z]
|
||||
|
||||
|
||||
def get_callbacks():
|
||||
@callback(
|
||||
[Output("3dplot", "figure"), Output("fade-3dplot", "is_in")],
|
||||
[
|
||||
Input("iso-slider", "value"),
|
||||
Input("y-slider", "value"),
|
||||
Input("store-settings", "data"),
|
||||
],
|
||||
[dash.dependencies.State("fade-3dplot", "is_in")],
|
||||
)
|
||||
def update_3dplot(iso_value, y_values, settings, is_in):
|
||||
if settings["use_real_values"]:
|
||||
y_min, y_max = y_values
|
||||
selected_volume = volume[0:dim_x, int(y_min) : int(y_max), 0:dim_z]
|
||||
X, Y, Z = [
|
||||
np.load("Dataset/npy/{}-values.npy".format(i)) for i in ["x", "y", "z"]
|
||||
]
|
||||
else:
|
||||
y_min, y_max = y_values
|
||||
selected_volume = volume[0:dim_x, int(y_min) : int(y_max), 0:dim_z]
|
||||
X, Y, Z = np.mgrid[
|
||||
0 : selected_volume.shape[0],
|
||||
0 : selected_volume.shape[1],
|
||||
0 : selected_volume.shape[2],
|
||||
]
|
||||
|
||||
fig = go.Figure(
|
||||
data=go.Volume(
|
||||
x=X.flatten(),
|
||||
y=Y.flatten(),
|
||||
z=Z.flatten(),
|
||||
value=selected_volume.flatten(),
|
||||
isomin=iso_value,
|
||||
isomax=selected_volume.max(),
|
||||
opacity=0.1,
|
||||
surface_count=20,
|
||||
colorscale="Jet",
|
||||
)
|
||||
)
|
||||
|
||||
return [fig, True]
|
||||
|
||||
# callback pour le plot 3D en plein écran
|
||||
@callback(
|
||||
Output("3dplot-fullscreen", "figure"),
|
||||
[
|
||||
Input("iso-slider-fullscreen", "value"),
|
||||
Input("y-slider-fullscreen", "value"),
|
||||
],
|
||||
)
|
||||
def update_3dplot_fullscreen(iso_value, y_values):
|
||||
y_min, y_max = y_values
|
||||
selected_volume = volume[0:dim_x, int(y_min) : int(y_max), 0:dim_z]
|
||||
X, Y, Z = np.mgrid[
|
||||
0 : selected_volume.shape[0],
|
||||
0 : selected_volume.shape[1],
|
||||
0 : selected_volume.shape[2],
|
||||
]
|
||||
|
||||
fig = go.Figure(
|
||||
data=go.Volume(
|
||||
x=X.flatten(),
|
||||
y=Y.flatten(),
|
||||
z=Z.flatten(),
|
||||
value=selected_volume.flatten(),
|
||||
isomin=iso_value,
|
||||
isomax=selected_volume.max(),
|
||||
opacity=0.1,
|
||||
surface_count=20,
|
||||
colorscale="Jet",
|
||||
)
|
||||
)
|
||||
|
||||
return fig
|
||||
|
||||
# callback pour le A-scan
|
||||
@callback(
|
||||
[Output("heatmap-ascan", "figure"), Output("fade-ascan", "is_in")],
|
||||
[
|
||||
Input("layer-slider-bscan-zx", "value"),
|
||||
Input("layer-slider-bscan-xy", "value"),
|
||||
],
|
||||
[dash.dependencies.State("fade-ascan", "is_in")],
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def update_heatmap_ascan(layer, layer1, is_in):
|
||||
fig = px.line(y=volume[layer - 1, :, layer1], title="A-scan")
|
||||
|
||||
return [fig, True]
|
||||
|
||||
# callback pour le A-scan en plein écran
|
||||
@callback(
|
||||
Output("heatmap-ascan-fullscreen", "figure"),
|
||||
Input("layer-slider-ascan-fullscreen", "value"),
|
||||
)
|
||||
def update_heatmap_ascan_fullscreen(layer):
|
||||
fig = px.line(y=volume[layer - 1, :, 5], title="A-scan")
|
||||
return fig
|
||||
|
||||
# callback pour les B-scan XY
|
||||
@callback(
|
||||
[
|
||||
Output("heatmap-bscan-zx", "figure"),
|
||||
Output("store-bscan-zx-layer", "data"),
|
||||
Output("fade-bscan-xy", "is_in"),
|
||||
],
|
||||
[Input("layer-slider-bscan-zx", "value")],
|
||||
[dash.dependencies.State("fade-bscan-zx", "is_in")],
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def update_heatmap_bscan_zx(layer, is_in):
|
||||
fig = px.imshow(
|
||||
volume[layer - 1, :, :],
|
||||
color_continuous_scale="Jet",
|
||||
aspect="auto",
|
||||
title="B-scan ZX",
|
||||
)
|
||||
|
||||
return [fig, layer, True]
|
||||
|
||||
# callback pour les B-scan ZX en plein écran
|
||||
@callback(
|
||||
Output("heatmap-bscan-zx-fullscreen", "figure"),
|
||||
Input("layer-slider-bscan-zx-fullscreen", "value"),
|
||||
)
|
||||
def update_heatmap_bscan_zx_fullscreen(layer):
|
||||
fig = px.imshow(
|
||||
volume[layer - 1, :, :],
|
||||
color_continuous_scale="Jet",
|
||||
aspect="auto",
|
||||
title="B-scan ZX",
|
||||
)
|
||||
|
||||
return fig
|
||||
|
||||
# callback pour les B-scan ZX
|
||||
@callback(
|
||||
[
|
||||
Output("heatmap-bscan-xy", "figure"),
|
||||
Output("store-bscan-xy-layer", "data"),
|
||||
Output("fade-bscan-zx", "is_in"),
|
||||
],
|
||||
[Input("layer-slider-bscan-xy", "value")],
|
||||
[dash.dependencies.State("fade-bscan-xy", "is_in")],
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def update_heatmap_bscan_xy(layer, is_in):
|
||||
fig = go.Figure(data=go.Heatmap(z=volume[:, :, layer], colorscale="Jet"))
|
||||
fig.update_layout(title="B-scan XY")
|
||||
|
||||
return [fig, layer, True]
|
||||
|
||||
# callback pour les B-scan ZX en plein écran
|
||||
@callback(
|
||||
Output("heatmap-bscan-xy-fullscreen", "figure"),
|
||||
Input("layer-slider-bscan-xy-fullscreen", "value"),
|
||||
)
|
||||
def update_heatmap_bscan_xy_fullscreen(layer):
|
||||
fig = go.Figure(data=go.Heatmap(z=volume[:, :, layer], colorscale="Jet"))
|
||||
fig.update_layout(title="B-scan XY")
|
||||
|
||||
return fig
|
||||
|
||||
# callback pour le plein écran du plot 3D
|
||||
@callback(
|
||||
Output("modal-3dplot", "is_open"),
|
||||
[Input("fullscreen-button-3dplot", "n_clicks")],
|
||||
[dash.dependencies.State("modal-3dplot", "is_open")],
|
||||
)
|
||||
def toggle_fullscreen_3dplot(n1, is_open):
|
||||
if n1:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
# callback pour le plein écran du A-scan
|
||||
@callback(
|
||||
Output("modal-ascan", "is_open"),
|
||||
[Input("fullscreen-button-ascan", "n_clicks")],
|
||||
[dash.dependencies.State("modal-ascan", "is_open")],
|
||||
)
|
||||
def toggle_fullscreen_ascan(n1, is_open):
|
||||
if n1:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
# callback pour le plein écran du B-scan XY
|
||||
@callback(
|
||||
Output("modal-bscan-xy", "is_open"),
|
||||
[Input("fullscreen-button-bscan-xy", "n_clicks")],
|
||||
[dash.dependencies.State("modal-bscan-xy", "is_open")],
|
||||
)
|
||||
def toggle_fullscreen_bscan_xy(n1, is_open):
|
||||
if n1:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
# callback pour le plein écran du B-scan ZX
|
||||
@callback(
|
||||
Output("modal-bscan-zx", "is_open"),
|
||||
[Input("fullscreen-button-bscan-zx", "n_clicks")],
|
||||
[dash.dependencies.State("modal-bscan-zx", "is_open")],
|
||||
)
|
||||
def toggle_fullscreen_bscan_zx(n1, is_open):
|
||||
if n1:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
@callback(
|
||||
[
|
||||
Output("3dplot", "clickData"),
|
||||
Output("layer-slider-bscan-xy", "value"),
|
||||
Output("layer-slider-bscan-zx", "value"),
|
||||
],
|
||||
Input("3dplot", "clickData"),
|
||||
)
|
||||
def display_3dplot_click_data(clickData):
|
||||
if clickData is None:
|
||||
return [None, 1, 1]
|
||||
|
||||
bscan_xy = clickData["points"][0]["z"]
|
||||
bscan_zx = clickData["points"][0]["x"]
|
||||
return [clickData, bscan_xy, bscan_zx]
|
||||
|
||||
@callback(
|
||||
[
|
||||
Output("heatmap-bscan-xy", "clickData"),
|
||||
Output("layer-slider-bscan-zx", "value", allow_duplicate=True),
|
||||
],
|
||||
[Input("heatmap-bscan-xy", "clickData")],
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def display_bscan_xy_click_data(clickData):
|
||||
if clickData is None:
|
||||
return [None, 1]
|
||||
|
||||
bscan_zx = clickData["points"][0]["y"]
|
||||
return [clickData, bscan_zx]
|
||||
|
||||
@callback(
|
||||
[
|
||||
Output("heatmap-bscan-zx", "clickData"),
|
||||
Output("layer-slider-bscan-xy", "value", allow_duplicate=True),
|
||||
],
|
||||
[Input("heatmap-bscan-zx", "clickData")],
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def display_bscan_zx_click_data(clickData):
|
||||
if clickData is None:
|
||||
return [None, 0]
|
||||
|
||||
bscan_xy = clickData["points"][0]["x"]
|
||||
return [clickData, bscan_xy]
|
||||
|
||||
@callback(
|
||||
[
|
||||
Output("heatmap-bscan-xy", "figure", allow_duplicate=True),
|
||||
Output("heatmap-bscan-zx", "figure", allow_duplicate=True),
|
||||
Output("heatmap-ascan", "figure", allow_duplicate=True),
|
||||
],
|
||||
[Input("store-bscan-xy-layer", "data"), Input("store-bscan-zx-layer", "data")],
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def update_bscan_layers(bscan_xy, bscan_zx):
|
||||
fig = go.Figure(data=go.Heatmap(z=volume[:, :, bscan_xy], colorscale="Jet"))
|
||||
fig.add_shape(
|
||||
type="line",
|
||||
x0=0 - 1,
|
||||
y0=bscan_zx,
|
||||
x1=dim_y,
|
||||
y1=bscan_zx,
|
||||
line=dict(color="white", width=1),
|
||||
)
|
||||
fig.update_layout(title="B-scan XY")
|
||||
|
||||
fig2 = px.imshow(
|
||||
volume[bscan_zx - 1, :, :],
|
||||
color_continuous_scale="Jet",
|
||||
aspect="auto",
|
||||
title="B-scan ZX",
|
||||
)
|
||||
fig2.add_shape(
|
||||
type="line",
|
||||
x0=bscan_xy,
|
||||
y0=0,
|
||||
x1=bscan_xy,
|
||||
y1=dim_y,
|
||||
line=dict(color="white", width=1),
|
||||
)
|
||||
|
||||
fig3 = px.line(y=volume[bscan_zx - 1, :, bscan_xy], title="A-scan")
|
||||
|
||||
return [fig, fig2, fig3]
|
||||
|
||||
@callback(
|
||||
[Output("store-settings", "data"), Output("settings-apply", "n_clicks")],
|
||||
[
|
||||
Input("settings-apply", "n_clicks"),
|
||||
],
|
||||
[
|
||||
State("use-real-values", "value"),
|
||||
State("apply-filters-everywhere", "value"),
|
||||
State("echantillonage-x", "value"),
|
||||
State("echantillonage-y", "value"),
|
||||
State("echantillonage-z", "value"),
|
||||
],
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def update_settings(
|
||||
clicks,
|
||||
use_real_values,
|
||||
apply_filters,
|
||||
echantillonage_x_value,
|
||||
echantillonage_y_value,
|
||||
echantillonage_z_value,
|
||||
):
|
||||
if clicks != None and clicks == 1:
|
||||
return [
|
||||
{
|
||||
"use_real_values": use_real_values,
|
||||
"use_filters": apply_filters,
|
||||
"echantillonage_x": echantillonage_x_value,
|
||||
"echantillonage_y": echantillonage_y_value,
|
||||
"echantillonage_z": echantillonage_z_value,
|
||||
},
|
||||
0,
|
||||
]
|
||||
|
||||
@callback(
|
||||
[
|
||||
Output("layer-slider-bscan-zx", "max"),
|
||||
Output("layer-slider-bscan-zx", "marks"),
|
||||
Output("layer-slider-bscan-xy", "max"),
|
||||
Output("layer-slider-bscan-xy", "marks"),
|
||||
Output("iso-slider", "min"),
|
||||
Output("iso-slider", "max"),
|
||||
Output("iso-slider", "marks"),
|
||||
Output("y-slider", "max"),
|
||||
Output("y-slider", "marks"),
|
||||
Output("layer-slider-ascan-fullscreen", "max"),
|
||||
Output("layer-slider-ascan-fullscreen", "marks"),
|
||||
Output("layer-slider-bscan-xy-fullscreen", "max"),
|
||||
Output("layer-slider-bscan-xy-fullscreen", "marks"),
|
||||
Output("layer-slider-bscan-zx-fullscreen", "max"),
|
||||
Output("layer-slider-bscan-zx-fullscreen", "marks"),
|
||||
Output("iso-slider-fullscreen", "min"),
|
||||
Output("iso-slider-fullscreen", "max"),
|
||||
Output("iso-slider-fullscreen", "marks"),
|
||||
Output("y-slider-fullscreen", "max"),
|
||||
Output("y-slider-fullscreen", "marks"),
|
||||
Output("settings-spinner", "children"),
|
||||
],
|
||||
Input("store-settings", "data"),
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def redef_data(data):
|
||||
global volume, pre_volume, dim_x, dim_y, dim_z, X, Y, Z
|
||||
volume = pre_volume[
|
||||
:: data["echantillonage_x"],
|
||||
:: data["echantillonage_y"],
|
||||
:: data["echantillonage_z"],
|
||||
]
|
||||
dim_x, dim_y, dim_z = volume.shape
|
||||
X, Y, Z = np.mgrid[0:dim_x, 0:dim_y, 0:dim_z]
|
||||
|
||||
return [
|
||||
dim_x - 1,
|
||||
{str(i): str(i) for i in range(0, dim_x, max(1, int(dim_x / 20)))},
|
||||
dim_z - 1,
|
||||
{str(i): str(i) for i in range(1, dim_z + 1, max(1, int(dim_z / 20)))},
|
||||
volume.min(),
|
||||
volume.max() / 2,
|
||||
{
|
||||
str(i): str(i)
|
||||
for i in range(
|
||||
int(volume.min()),
|
||||
int(volume.max() / 2) + 1,
|
||||
int((volume.max() / 2 - volume.min()) / 10),
|
||||
)
|
||||
},
|
||||
dim_y,
|
||||
{str(i): str(i) for i in range(0, int(dim_y) + 1, max(1, int(dim_y / 20)))},
|
||||
dim_x - 1,
|
||||
{str(i): str(i) for i in range(0, dim_x, max(1, int(dim_x / 20)))},
|
||||
dim_x - 1,
|
||||
{str(i): str(i) for i in range(0, dim_x, max(1, int(dim_x / 20)))},
|
||||
dim_z - 1,
|
||||
{str(i): str(i) for i in range(1, dim_z + 1, max(1, int(dim_z / 20)))},
|
||||
volume.min(),
|
||||
volume.max() / 2,
|
||||
{
|
||||
str(i): str(i)
|
||||
for i in range(
|
||||
int(volume.min()),
|
||||
int(volume.max() / 2) + 1,
|
||||
int((volume.max() / 2 - volume.min()) / 10),
|
||||
)
|
||||
},
|
||||
dim_y,
|
||||
{str(i): str(i) for i in range(0, int(dim_y) + 1, max(1, int(dim_y / 20)))},
|
||||
"Apply",
|
||||
]
|
||||
|
||||
@callback(
|
||||
Output("store-filters", "data", allow_duplicate=True),
|
||||
[Input("store-filters", "data"), Input("store-settings", "data")],
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def apply_filters(data, settings):
|
||||
global volume, pre_volume
|
||||
if settings["use_filters"]:
|
||||
select_filtre_1 = data["select_filtre_2"]
|
||||
select_filtre_2 = data["select_filtre_3"]
|
||||
fs_filtre_1 = data["fs_filtre_1"]
|
||||
cutoff_filtre_1 = data["cutoff_filtre_1"]
|
||||
order_filtre_1 = data["order_filtre_1"]
|
||||
windowsize_filtre_1 = data["windowsize_filtre_1"]
|
||||
fs_filtre_2 = data["fs_filtre_2"]
|
||||
cutoff_filtre_2 = data["cutoff_filtre_2"]
|
||||
order_filtre_2 = data["order_filtre_2"]
|
||||
windowsize_filtre_2 = data["windowsize_filtre_2"]
|
||||
selec_transforme_hilbert = data["select_filtre_1"]
|
||||
|
||||
volume = pre_volume[
|
||||
:: settings["echantillonage_x"],
|
||||
:: settings["echantillonage_y"],
|
||||
:: settings["echantillonage_z"],
|
||||
]
|
||||
|
||||
data_avec_traitement = switch_case(volume, int(selec_transforme_hilbert))
|
||||
|
||||
data_avec_traitement = switch_case(
|
||||
data_avec_traitement,
|
||||
int(select_filtre_1),
|
||||
int(fs_filtre_1),
|
||||
int(cutoff_filtre_1),
|
||||
int(order_filtre_1),
|
||||
int(windowsize_filtre_1),
|
||||
)
|
||||
data_avec_traitement = switch_case(
|
||||
data_avec_traitement,
|
||||
int(select_filtre_2),
|
||||
int(fs_filtre_2),
|
||||
int(cutoff_filtre_2),
|
||||
int(order_filtre_2),
|
||||
int(windowsize_filtre_2),
|
||||
)
|
||||
volume = data_avec_traitement
|
||||
redef_data(settings)
|
||||
else:
|
||||
volume = pre_volume[
|
||||
:: settings["echantillonage_x"],
|
||||
:: settings["echantillonage_y"],
|
||||
:: settings["echantillonage_z"],
|
||||
]
|
||||
return data
|
||||
|
||||
@callback(
|
||||
Output("store-files", "data", allow_duplicate=True),
|
||||
Input("store-files", "data"),
|
||||
State("store-settings", "data"),
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def update_files(data, settings):
|
||||
global pre_volume, volume, dim_x, dim_y, dim_z, X, Y, Z
|
||||
if data is None or data == "":
|
||||
return None
|
||||
|
||||
# Charger le nouveau volume
|
||||
pre_volume = np.load(join("Dataset/saves", data))
|
||||
print("New volume loaded:", pre_volume.shape)
|
||||
|
||||
# Appliquer les nouveaux paramètres d'échantillonnage
|
||||
volume = pre_volume[
|
||||
::settings["echantillonage_x"],
|
||||
::settings["echantillonage_y"],
|
||||
::settings["echantillonage_z"],
|
||||
]
|
||||
dim_x, dim_y, dim_z = volume.shape
|
||||
X, Y, Z = np.mgrid[0:dim_x, 0:dim_y, 0:dim_z]
|
||||
print("Volume updated with new dimensions:", volume.shape)
|
||||
|
||||
# Mettre à jour les graphiques
|
||||
update_3dplot(0, [0, dim_y // 2], settings, False)
|
||||
update_heatmap_ascan(0, 0, False)
|
||||
update_heatmap_bscan_zx(0, False)
|
||||
update_heatmap_bscan_xy(0, False)
|
||||
|
||||
return None
|
||||
|
||||
@callback(
|
||||
Output("save-toast", "is_open"),
|
||||
Input("save-save", "n_clicks"),
|
||||
[
|
||||
State("save-input", "value"),
|
||||
State("save-format", "value"),
|
||||
],
|
||||
)
|
||||
def save_data(n_clicks, filename, format):
|
||||
if n_clicks is None:
|
||||
return False
|
||||
if format == "raw":
|
||||
np.save(join("Dataset/saves", filename), pre_volume)
|
||||
else:
|
||||
np.save(join("Dataset/saves", filename), volume)
|
||||
return True
|
120
3D_app/callbacks/main.py
Normal file
120
3D_app/callbacks/main.py
Normal file
@ -0,0 +1,120 @@
|
||||
from dash import Input, Output, State, ALL, callback
|
||||
import dash
|
||||
from os import listdir
|
||||
from os.path import isfile, join
|
||||
import dash_bootstrap_components as dbc
|
||||
|
||||
def get_callbacks():
|
||||
# callback pour le modal
|
||||
@callback(
|
||||
Output("modal", "is_open"),
|
||||
[Input("howto-open", "n_clicks"), Input("howto-close", "n_clicks")],
|
||||
[dash.dependencies.State("modal", "is_open")],
|
||||
)
|
||||
def toggle_modal(n1, n2, is_open):
|
||||
if n1 or n2:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
|
||||
@callback(
|
||||
Output("settings-modal", "is_open"),
|
||||
[Input("settings-open", "n_clicks"), Input("settings-close", "n_clicks")],
|
||||
[dash.dependencies.State("settings-modal", "is_open")],
|
||||
)
|
||||
def toggle_settings(n1, n2, is_open):
|
||||
if n1 or n2:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
|
||||
# callback pour le navmenu
|
||||
@callback(
|
||||
Output("offcanvas-menu", "is_open"),
|
||||
[Input("navbar-toggler", "n_clicks")],
|
||||
[dash.dependencies.State("offcanvas-menu", "is_open")],
|
||||
)
|
||||
def toggle_offcanvas(n, is_open):
|
||||
if n:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
|
||||
@callback(
|
||||
Output("open-modal", "is_open"),
|
||||
[Input("open-button", "n_clicks"), Input("open-close", "n_clicks")],
|
||||
[dash.dependencies.State("open-modal", "is_open")],
|
||||
)
|
||||
def toggle_open(n1, n2, is_open):
|
||||
if n1 or n2:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
|
||||
@callback(
|
||||
Output("save-modal", "is_open"),
|
||||
[
|
||||
Input("save-button", "n_clicks"),
|
||||
Input("save-close", "n_clicks"),
|
||||
Input("save-save", "n_clicks"),
|
||||
],
|
||||
[dash.dependencies.State("save-modal", "is_open")],
|
||||
)
|
||||
def toggle_save(n1, n2, n3, is_open):
|
||||
if n1 or n2 or n3:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
|
||||
@callback(
|
||||
Output("file-list", "children"),
|
||||
[Input("open-refresh", "n_clicks")],
|
||||
)
|
||||
def refresh_files(n):
|
||||
files = listdir("Dataset/saves")
|
||||
return [
|
||||
dbc.ListGroupItem(
|
||||
f"{file}",
|
||||
action=True,
|
||||
style={"cursor": "pointer"},
|
||||
id={"type": "file-item", "index": i},
|
||||
)
|
||||
for i, file in enumerate(files)
|
||||
if isfile(join("Dataset/saves", file))
|
||||
]
|
||||
|
||||
|
||||
@callback(
|
||||
[
|
||||
Output("open-modal", "is_open", allow_duplicate=True),
|
||||
Output("store-files", "data"),
|
||||
],
|
||||
Input({"type": "file-item", "index": ALL}, "n_clicks"),
|
||||
State({"type": "file-item", "index": ALL}, "children"),
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def open_file(n, filenames):
|
||||
ctx = dash.callback_context
|
||||
if not ctx.triggered or all(click is None for click in n):
|
||||
return [None, ""]
|
||||
file_index = ctx.triggered[0]["prop_id"].split(".")[0]
|
||||
file_index = eval(file_index)
|
||||
filename = filenames[file_index["index"]]
|
||||
return [False, filename]
|
||||
|
||||
|
||||
@callback(
|
||||
Output("save-format", "options"),
|
||||
[Input("store-filters", "data")],
|
||||
)
|
||||
def update_save_format(filters):
|
||||
if filters != {}:
|
||||
return [
|
||||
{"label": "Save raw dataset", "value": "raw"},
|
||||
{"label": "Save filtered dataset", "value": "filt"},
|
||||
]
|
||||
return [
|
||||
{"label": "Save raw dataset", "value": "raw"},
|
||||
{"label": "Save filtered dataset", "value": "filt", "disabled": True},
|
||||
]
|
||||
|
121
3D_app/main.py
121
3D_app/main.py
@ -1,11 +1,11 @@
|
||||
import dash
|
||||
from dash import dcc, html, ALL, DiskcacheManager
|
||||
from dash.dependencies import Input, Output, State
|
||||
import dash_bootstrap_components as dbc
|
||||
from os import listdir, mkdir, getenv
|
||||
from os import listdir, mkdir
|
||||
from os.path import isfile, join
|
||||
import diskcache
|
||||
from json import load
|
||||
from callbacks.main import *
|
||||
|
||||
|
||||
# on crée l'application
|
||||
@ -373,121 +373,8 @@ app.layout = dbc.Container(
|
||||
fluid=True,
|
||||
)
|
||||
|
||||
|
||||
# callback pour le modal
|
||||
@app.callback(
|
||||
Output("modal", "is_open"),
|
||||
[Input("howto-open", "n_clicks"), Input("howto-close", "n_clicks")],
|
||||
[dash.dependencies.State("modal", "is_open")],
|
||||
)
|
||||
def toggle_modal(n1, n2, is_open):
|
||||
if n1 or n2:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
|
||||
@app.callback(
|
||||
Output("settings-modal", "is_open"),
|
||||
[Input("settings-open", "n_clicks"), Input("settings-close", "n_clicks")],
|
||||
[dash.dependencies.State("settings-modal", "is_open")],
|
||||
)
|
||||
def toggle_settings(n1, n2, is_open):
|
||||
if n1 or n2:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
|
||||
# callback pour le navmenu
|
||||
@app.callback(
|
||||
Output("offcanvas-menu", "is_open"),
|
||||
[Input("navbar-toggler", "n_clicks")],
|
||||
[dash.dependencies.State("offcanvas-menu", "is_open")],
|
||||
)
|
||||
def toggle_offcanvas(n, is_open):
|
||||
if n:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
|
||||
@app.callback(
|
||||
Output("open-modal", "is_open"),
|
||||
[Input("open-button", "n_clicks"), Input("open-close", "n_clicks")],
|
||||
[dash.dependencies.State("open-modal", "is_open")],
|
||||
)
|
||||
def toggle_open(n1, n2, is_open):
|
||||
if n1 or n2:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
|
||||
@app.callback(
|
||||
Output("save-modal", "is_open"),
|
||||
[
|
||||
Input("save-button", "n_clicks"),
|
||||
Input("save-close", "n_clicks"),
|
||||
Input("save-save", "n_clicks"),
|
||||
],
|
||||
[dash.dependencies.State("save-modal", "is_open")],
|
||||
)
|
||||
def toggle_save(n1, n2, n3, is_open):
|
||||
if n1 or n2 or n3:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
|
||||
@app.callback(
|
||||
Output("file-list", "children"),
|
||||
[Input("open-refresh", "n_clicks")],
|
||||
)
|
||||
def refresh_files(n):
|
||||
files = listdir("Dataset/saves")
|
||||
return [
|
||||
dbc.ListGroupItem(
|
||||
f"{file}",
|
||||
action=True,
|
||||
style={"cursor": "pointer"},
|
||||
id={"type": "file-item", "index": i},
|
||||
)
|
||||
for i, file in enumerate(files)
|
||||
if isfile(join("Dataset/saves", file))
|
||||
]
|
||||
|
||||
|
||||
@app.callback(
|
||||
[
|
||||
Output("open-modal", "is_open", allow_duplicate=True),
|
||||
Output("store-files", "data"),
|
||||
],
|
||||
Input({"type": "file-item", "index": ALL}, "n_clicks"),
|
||||
State({"type": "file-item", "index": ALL}, "children"),
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def open_file(n, filenames):
|
||||
ctx = dash.callback_context
|
||||
if not ctx.triggered or all(click is None for click in n):
|
||||
return [None, ""]
|
||||
file_index = ctx.triggered[0]["prop_id"].split(".")[0]
|
||||
file_index = eval(file_index)
|
||||
filename = filenames[file_index["index"]]
|
||||
return [False, filename]
|
||||
|
||||
|
||||
@app.callback(
|
||||
Output("save-format", "options"),
|
||||
[Input("store-filters", "data")],
|
||||
)
|
||||
def update_save_format(filters):
|
||||
if filters != {}:
|
||||
return [
|
||||
{"label": "Save raw dataset", "value": "raw"},
|
||||
{"label": "Save filtered dataset", "value": "filt"},
|
||||
]
|
||||
return [
|
||||
{"label": "Save raw dataset", "value": "raw"},
|
||||
{"label": "Save filtered dataset", "value": "filt", "disabled": True},
|
||||
]
|
||||
|
||||
get_callbacks()
|
||||
|
||||
# on lance l'application
|
||||
if __name__ == "__main__":
|
||||
app.run(debug=config["debug"] or False, port=config["port"] or "8051", threaded=True)
|
||||
app.run(debug=config["debug"] or False, port=config["port"] or "8051", threaded=True)
|
@ -9,10 +9,15 @@ from util import *
|
||||
from filtrage import *
|
||||
from selection_filtre import *
|
||||
from Bscan_Cscan_trait import *
|
||||
from callbacks.ascan import get_callbacks
|
||||
|
||||
|
||||
dash.register_page(
|
||||
__name__, path="/ascan", title="A-Scan filters", name="A-Scan filters"
|
||||
__name__,
|
||||
path="/ascan",
|
||||
title="A-Scan filters",
|
||||
name="A-Scan filters",
|
||||
description="Apply filters on the dataset",
|
||||
)
|
||||
|
||||
# on définit le dossier et les fichiers à lire
|
||||
@ -26,7 +31,7 @@ pre_volume = np.array(lire_fichier_csv(dossier, fichiers_selectionnes))
|
||||
volume = pre_volume[:, :, :]
|
||||
data_traits = volume
|
||||
dim_x, dim_y, dim_z = volume.shape
|
||||
click=None
|
||||
click = None
|
||||
X, Y, Z = np.mgrid[0:dim_x, 0:dim_y, 0:dim_z]
|
||||
# on définit le thème de l'application
|
||||
pio.templates.default = "plotly_dark"
|
||||
@ -43,6 +48,25 @@ configAScan = {
|
||||
}
|
||||
layout = html.Div(
|
||||
[
|
||||
dbc.Modal(
|
||||
[
|
||||
dbc.ModalHeader("Save data"),
|
||||
dbc.ModalBody(
|
||||
dbc.Input(
|
||||
id="input-save-ascan", placeholder="Filename", type="text"
|
||||
),
|
||||
),
|
||||
dbc.ModalFooter(
|
||||
[
|
||||
dbc.Button("Save", id="save-ascan-solo", className="ml-auto"),
|
||||
dbc.Button("Close", id="close-ascan-solo", className="ml-auto"),
|
||||
]
|
||||
),
|
||||
],
|
||||
id="modal-ascan-solo",
|
||||
centered=True,
|
||||
is_open=False,
|
||||
),
|
||||
dbc.Row(
|
||||
[
|
||||
dbc.Col(
|
||||
@ -50,29 +74,29 @@ layout = html.Div(
|
||||
dbc.Select(
|
||||
id="select-ascan-filter1",
|
||||
options=[
|
||||
{"label": "transformer du Hilbert", "value": "1"},
|
||||
{"label": "Transformer du Hilbert", "value": "1"},
|
||||
],
|
||||
value=1,
|
||||
style={"margin-bottom": "15px"},
|
||||
),
|
||||
],
|
||||
width=2,
|
||||
width=3,
|
||||
),
|
||||
dbc.Col(
|
||||
[
|
||||
dbc.Select(
|
||||
id="select-ascan-filter2",
|
||||
options=[
|
||||
{"label": "sans filtre ", "value": "2"},
|
||||
{"label": "filtre passe bas ", "value": "3"},
|
||||
{"label": "filtre de moyenne mobile", "value": "4"},
|
||||
{"label": "filtre adaptatif (wiener)", "value": "5"},
|
||||
{"label": "No filter ", "value": "2"},
|
||||
{"label": "Filtre passe bas ", "value": "3"},
|
||||
{"label": "Filtre de moyenne mobile", "value": "4"},
|
||||
{"label": "Filtre adaptatif (wiener)", "value": "5"},
|
||||
{
|
||||
"label": "filtre à réponse impulsionnelle infinie",
|
||||
"label": "Filtre à réponse impulsionnelle infinie",
|
||||
"value": "6",
|
||||
},
|
||||
{
|
||||
"label": "filtre à réponse impulsionnelle finie",
|
||||
"label": "Filtre à réponse impulsionnelle finie",
|
||||
"value": "7",
|
||||
},
|
||||
],
|
||||
@ -80,23 +104,23 @@ layout = html.Div(
|
||||
style={"margin-bottom": "15px"},
|
||||
),
|
||||
],
|
||||
width=2,
|
||||
width=3,
|
||||
),
|
||||
dbc.Col(
|
||||
[
|
||||
dbc.Select(
|
||||
id="select-ascan-filter3",
|
||||
options=[
|
||||
{"label": "sans filtre ", "value": "2"},
|
||||
{"label": "filtre passe bas ", "value": "3"},
|
||||
{"label": "filtre de moyenne mobile", "value": "4"},
|
||||
{"label": "filtre adaptatif (wiener)", "value": "5"},
|
||||
{"label": "No filter ", "value": "2"},
|
||||
{"label": "Filtre passe bas ", "value": "3"},
|
||||
{"label": "Filtre de moyenne mobile", "value": "4"},
|
||||
{"label": "Filtre adaptatif (wiener)", "value": "5"},
|
||||
{
|
||||
"label": "filtre à réponse impulsionnelle infinie",
|
||||
"label": "Filtre à réponse impulsionnelle infinie",
|
||||
"value": "6",
|
||||
},
|
||||
{
|
||||
"label": "filtre à réponse impulsionnelle finie",
|
||||
"label": "Filtre à réponse impulsionnelle finie",
|
||||
"value": "7",
|
||||
},
|
||||
],
|
||||
@ -104,12 +128,12 @@ layout = html.Div(
|
||||
style={"margin-bottom": "15px"},
|
||||
),
|
||||
],
|
||||
width=2,
|
||||
width=3,
|
||||
),
|
||||
dbc.Col(
|
||||
[
|
||||
dbc.Label(
|
||||
"apply the filters",
|
||||
"Apply the filters",
|
||||
style={"marginRight": "5px"},
|
||||
),
|
||||
dbc.Button(
|
||||
@ -132,26 +156,26 @@ layout = html.Div(
|
||||
dbc.Button(
|
||||
id="button-save-data",
|
||||
children=dbc.Spinner(
|
||||
html.Div("save", id="save"), show_initially=False
|
||||
html.Div("Save", id="save"), show_initially=False
|
||||
),
|
||||
color="primary",
|
||||
style={"marginBottom": "15px"},
|
||||
),
|
||||
],
|
||||
width=2,
|
||||
width=1,
|
||||
),
|
||||
]
|
||||
),
|
||||
dbc.Row(
|
||||
[
|
||||
dbc.Col(
|
||||
[html.Br(), html.B(" paramètre du 1er filtre ")],
|
||||
[html.Br(), html.B("Parameters of the 1st filter")],
|
||||
width=2,
|
||||
style={"textAlign": "center"},
|
||||
),
|
||||
dbc.Col(
|
||||
[
|
||||
dbc.Label("Fs ", html_for="Fs "),
|
||||
dbc.Label("Fs", html_for="Fs "),
|
||||
dbc.Input(
|
||||
id="input-ascan-solo-fs",
|
||||
type="number",
|
||||
@ -164,11 +188,11 @@ layout = html.Div(
|
||||
),
|
||||
dbc.Col(
|
||||
[
|
||||
dbc.Label("cut off ", html_for="cut off"),
|
||||
dbc.Label("Cut off", html_for="cut off"),
|
||||
dbc.Input(
|
||||
id="input-ascan-solo-cutoff",
|
||||
type="number",
|
||||
placeholder="cut_off",
|
||||
placeholder="Cut off",
|
||||
value=1,
|
||||
step=0.1,
|
||||
),
|
||||
@ -177,11 +201,11 @@ layout = html.Div(
|
||||
),
|
||||
dbc.Col(
|
||||
[
|
||||
dbc.Label("order ", html_for="order"),
|
||||
dbc.Label("Order", html_for="order"),
|
||||
dbc.Input(
|
||||
id="input-ascan-solo-order",
|
||||
type="number",
|
||||
placeholder="order",
|
||||
placeholder="Order",
|
||||
value=1,
|
||||
step=1,
|
||||
),
|
||||
@ -190,11 +214,11 @@ layout = html.Div(
|
||||
),
|
||||
dbc.Col(
|
||||
[
|
||||
dbc.Label("window size ", html_for="window size"),
|
||||
dbc.Label("Window size", html_for="window size"),
|
||||
dbc.Input(
|
||||
id="input-ascan-solo-windowsize",
|
||||
type="number",
|
||||
placeholder="window_size",
|
||||
placeholder="Window size",
|
||||
value=1,
|
||||
step=1,
|
||||
),
|
||||
@ -202,13 +226,13 @@ layout = html.Div(
|
||||
width=1,
|
||||
),
|
||||
dbc.Col(
|
||||
[html.Br(), html.B(" paramètre du 2e filtre ")],
|
||||
[html.Br(), html.B("Parameters of the 2nd filter")],
|
||||
width=2,
|
||||
style={"textAlign": "center"},
|
||||
),
|
||||
dbc.Col(
|
||||
[
|
||||
dbc.Label("Fs ", html_for="Fs "),
|
||||
dbc.Label("Fs", html_for="Fs "),
|
||||
dbc.Input(
|
||||
id="input-ascan-solo-fs-2",
|
||||
type="number",
|
||||
@ -221,11 +245,11 @@ layout = html.Div(
|
||||
),
|
||||
dbc.Col(
|
||||
[
|
||||
dbc.Label("cut off ", html_for="cut off"),
|
||||
dbc.Label("Cut off", html_for="cut off"),
|
||||
dbc.Input(
|
||||
id="input-ascan-solo-cutoff-2",
|
||||
type="number",
|
||||
placeholder="cut_off",
|
||||
placeholder="Cut off",
|
||||
value=1,
|
||||
step=0.1,
|
||||
),
|
||||
@ -234,11 +258,11 @@ layout = html.Div(
|
||||
),
|
||||
dbc.Col(
|
||||
[
|
||||
dbc.Label("order ", html_for="order"),
|
||||
dbc.Label("Order", html_for="order"),
|
||||
dbc.Input(
|
||||
id="input-ascan-solo-order-2",
|
||||
type="number",
|
||||
placeholder="order",
|
||||
placeholder="Order",
|
||||
value=1,
|
||||
step=1,
|
||||
),
|
||||
@ -247,11 +271,11 @@ layout = html.Div(
|
||||
),
|
||||
dbc.Col(
|
||||
[
|
||||
dbc.Label("window size ", html_for="window size"),
|
||||
dbc.Label("Window size", html_for="window size"),
|
||||
dbc.Input(
|
||||
id="input-ascan-solo-windowsize-2",
|
||||
type="number",
|
||||
placeholder="window_size",
|
||||
placeholder="Window size",
|
||||
value=1,
|
||||
step=1,
|
||||
),
|
||||
@ -325,267 +349,4 @@ layout = html.Div(
|
||||
style={"padding": "20px"},
|
||||
)
|
||||
|
||||
@callback(
|
||||
Output("store-filters", "data"),
|
||||
[
|
||||
Input("select-ascan-filter1", "value"),
|
||||
Input("select-ascan-filter2", "value"),
|
||||
Input("select-ascan-filter3", "value"),
|
||||
Input("input-ascan-solo-fs", "value"),
|
||||
Input("input-ascan-solo-cutoff", "value"),
|
||||
Input("input-ascan-solo-order", "value"),
|
||||
Input("input-ascan-solo-windowsize", "value"),
|
||||
Input("input-ascan-solo-fs-2", "value"),
|
||||
Input("input-ascan-solo-cutoff-2", "value"),
|
||||
Input("input-ascan-solo-order-2", "value"),
|
||||
Input("input-ascan-solo-windowsize-2", "value"),
|
||||
],
|
||||
)
|
||||
def store_settings(
|
||||
select_filtre_1,
|
||||
select_filtre_2,
|
||||
select_filtre_3,
|
||||
fs_filtre_1,
|
||||
cutoff_filtre_1,
|
||||
order_filtre_1,
|
||||
windowsize_filtre_1,
|
||||
fs_filtre_2,
|
||||
cutoff_filtre_2,
|
||||
order_filtre_2,
|
||||
windowsize_filtre_2,
|
||||
):
|
||||
return {
|
||||
"select_filtre_1": select_filtre_1,
|
||||
"select_filtre_2": select_filtre_2,
|
||||
"select_filtre_3": select_filtre_3,
|
||||
"fs_filtre_1": fs_filtre_1,
|
||||
"cutoff_filtre_1": cutoff_filtre_1,
|
||||
"order_filtre_1": order_filtre_1,
|
||||
"windowsize_filtre_1": windowsize_filtre_1,
|
||||
"fs_filtre_2": fs_filtre_2,
|
||||
"cutoff_filtre_2": cutoff_filtre_2,
|
||||
"order_filtre_2": order_filtre_2,
|
||||
"windowsize_filtre_2": windowsize_filtre_2,
|
||||
}
|
||||
|
||||
|
||||
# callback to update filter values
|
||||
@callback(
|
||||
[
|
||||
Output("input-ascan-solo-fs", "disabled"),
|
||||
Output("input-ascan-solo-cutoff", "disabled"),
|
||||
Output("input-ascan-solo-order", "disabled"),
|
||||
Output("input-ascan-solo-windowsize", "disabled"),
|
||||
Output("input-ascan-solo-fs-2", "disabled"),
|
||||
Output("input-ascan-solo-cutoff-2", "disabled"),
|
||||
Output("input-ascan-solo-order-2", "disabled"),
|
||||
Output("input-ascan-solo-windowsize-2", "disabled"),
|
||||
],
|
||||
[
|
||||
Input("select-ascan-filter2", "value"),
|
||||
Input("select-ascan-filter3", "value"),
|
||||
],
|
||||
)
|
||||
def update_filter_values(select_filtre_1, select_filtre_2):
|
||||
fs_1 = True
|
||||
cutoff_1 = True
|
||||
ordre_1 = True
|
||||
windowsize_1 = True
|
||||
fs_2 = True
|
||||
cutoff_2 = True
|
||||
ordre_2 = True
|
||||
windowsize_2 = True
|
||||
if int(select_filtre_1) == 3:
|
||||
fs_1 = False
|
||||
cutoff_1 = False
|
||||
ordre_1 = False
|
||||
if int(select_filtre_2) == 3:
|
||||
fs_2 = False
|
||||
cutoff_2 = False
|
||||
ordre_2 = False
|
||||
if int(select_filtre_1) in (4, 5, 6, 7):
|
||||
windowsize_1 = False
|
||||
if int(select_filtre_2) in (4, 5, 6, 7):
|
||||
windowsize_2 = False
|
||||
return [
|
||||
fs_1,
|
||||
cutoff_1,
|
||||
ordre_1,
|
||||
windowsize_1,
|
||||
fs_2,
|
||||
cutoff_2,
|
||||
ordre_2,
|
||||
windowsize_2,
|
||||
]
|
||||
|
||||
|
||||
|
||||
@callback(
|
||||
Output("loading", "children"),
|
||||
Input("button-validate-filter", "n_clicks"),
|
||||
[
|
||||
State("select-ascan-filter1", "value"),
|
||||
State("select-ascan-filter2", "value"),
|
||||
State("select-ascan-filter3", "value"),
|
||||
State("input-ascan-solo-fs", "value"),
|
||||
State("input-ascan-solo-cutoff", "value"),
|
||||
State("input-ascan-solo-order", "value"),
|
||||
State("input-ascan-solo-windowsize", "value"),
|
||||
State("input-ascan-solo-fs-2", "value"),
|
||||
State("input-ascan-solo-cutoff-2", "value"),
|
||||
State("input-ascan-solo-order-2", "value"),
|
||||
State("input-ascan-solo-windowsize-2", "value"),
|
||||
]
|
||||
)
|
||||
def load_button(n_clicks,
|
||||
selec_transforme_hilbert,
|
||||
select_filtre_1,select_filtre_2,
|
||||
fs_filtre_1,cutoff_filtre_1,
|
||||
order_filtre_1,windowsize_filtre_1,
|
||||
fs_filtre_2,cutoff_filtre_2,order_filtre_2,windowsize_filtre_2,
|
||||
):
|
||||
bouton = "Valider"
|
||||
global data_traits,click
|
||||
if n_clicks != click:
|
||||
data_traits=Cscant(data_input=data_traits,
|
||||
sel1=int(selec_transforme_hilbert),sel2=int(select_filtre_1),
|
||||
sel3=int(select_filtre_2),
|
||||
fs_1=int(fs_filtre_1),cut_off_1=float(cutoff_filtre_1),
|
||||
order_1=int(order_filtre_1),window_size_1=int(windowsize_filtre_1),
|
||||
fs_2=int(fs_filtre_2),cut_off_2=float(cutoff_filtre_2),
|
||||
order_2=int(order_filtre_2),window_size2=int(windowsize_filtre_2))
|
||||
bouton = "Valider"
|
||||
click=n_clicks
|
||||
return bouton
|
||||
|
||||
|
||||
@callback(
|
||||
Output("save", "children"),
|
||||
Input("button-save-data","n_clicks"),
|
||||
)
|
||||
def save_data(n_clicks):
|
||||
bouton = "save"
|
||||
global data_traits
|
||||
if n_clicks!=None:
|
||||
np.save('Dataset/saves/datat.npy',data_traits)
|
||||
bouton = "save"
|
||||
return bouton
|
||||
|
||||
|
||||
# callback to update the heatmap
|
||||
@callback(
|
||||
[
|
||||
Output("heatmap-ascan-solo", "figure"),
|
||||
Output("heatmap-bscan-solo", "figure"),
|
||||
Output("heatmap-fft-solo", "figure"),
|
||||
],
|
||||
[
|
||||
Input("layer-slider-ascan-solo-x", "value"),
|
||||
Input("layer-slider-ascan-solo-y", "value"),
|
||||
Input("layer-slider-ascan-solo-z", "value"),
|
||||
Input("button-validate-filter", "n_clicks"),
|
||||
],
|
||||
[
|
||||
State("select-ascan-filter1", "value"),
|
||||
State("select-ascan-filter2", "value"),
|
||||
State("select-ascan-filter3", "value"),
|
||||
State("input-ascan-solo-fs", "value"),
|
||||
State("input-ascan-solo-cutoff", "value"),
|
||||
State("input-ascan-solo-order", "value"),
|
||||
State("input-ascan-solo-windowsize", "value"),
|
||||
State("input-ascan-solo-fs-2", "value"),
|
||||
State("input-ascan-solo-cutoff-2", "value"),
|
||||
State("input-ascan-solo-order-2", "value"),
|
||||
State("input-ascan-solo-windowsize-2", "value"),
|
||||
]
|
||||
)
|
||||
def update_heatmap_ascan(
|
||||
select_ascan_x,
|
||||
select_ascan_y,
|
||||
select_ascan_z,
|
||||
n_clicks,
|
||||
selec_transforme_hilbert,
|
||||
select_filtre_1,
|
||||
select_filtre_2,
|
||||
fs_filtre_1,
|
||||
cutoff_filtre_1,
|
||||
order_filtre_1,
|
||||
windowsize_filtre_1,
|
||||
fs_filtre_2,
|
||||
cutoff_filtre_2,
|
||||
order_filtre_2,
|
||||
windowsize_filtre_2,
|
||||
):
|
||||
# TODO: implement the filter
|
||||
|
||||
print("debut du traitement")
|
||||
data_avec_traitement = volume[
|
||||
int(select_ascan_y) - 1,
|
||||
select_ascan_z[0] : select_ascan_z[1],
|
||||
int(select_ascan_x) - 1,
|
||||
]
|
||||
data_sans_traitement = volume[
|
||||
int(select_ascan_y) - 1,
|
||||
select_ascan_z[0] : select_ascan_z[1],
|
||||
int(select_ascan_x) - 1,
|
||||
]
|
||||
|
||||
data_avec_traitement = switch_case(
|
||||
data_avec_traitement, int(selec_transforme_hilbert)
|
||||
)
|
||||
data_sans_traitement = switch_case(
|
||||
data_sans_traitement, int(selec_transforme_hilbert)
|
||||
)
|
||||
|
||||
data_avec_traitement = switch_case(
|
||||
data_avec_traitement,
|
||||
int(select_filtre_1),
|
||||
float(fs_filtre_1),
|
||||
float(cutoff_filtre_1),
|
||||
int(order_filtre_1),
|
||||
int(windowsize_filtre_1),
|
||||
)
|
||||
data_avec_traitement = switch_case(
|
||||
data_avec_traitement,
|
||||
int(select_filtre_2),
|
||||
float(fs_filtre_2),
|
||||
float(cutoff_filtre_2),
|
||||
int(order_filtre_2),
|
||||
int(windowsize_filtre_2),
|
||||
)
|
||||
print("fin du traitement")
|
||||
|
||||
fig = px.line(title="A-scan")
|
||||
new_trace = go.Scatter(y=data_avec_traitement, mode="lines", name=" Ascan trait ")
|
||||
fig.add_trace(new_trace)
|
||||
new_trace = go.Scatter(
|
||||
y=data_sans_traitement, mode="lines", name=" Ascan (hilbert) "
|
||||
)
|
||||
fig.add_trace(new_trace)
|
||||
fig.update_layout(xaxis_title="indix", yaxis_title="amplitude")
|
||||
|
||||
|
||||
data_bscan=Bscant(volume[select_ascan_y - 1, select_ascan_z[0] : select_ascan_z[1], :],int(selec_transforme_hilbert),int(select_filtre_1),int(select_filtre_2),float(fs_filtre_1),
|
||||
float(cutoff_filtre_1),int(order_filtre_1),int(windowsize_filtre_1),float(fs_filtre_2),float(cutoff_filtre_2),int(order_filtre_2),int(windowsize_filtre_2),)
|
||||
|
||||
fig2 = px.imshow(
|
||||
data_bscan,
|
||||
color_continuous_scale="Jet",
|
||||
aspect="auto",
|
||||
title="B-scan XZ",
|
||||
)
|
||||
fig2.update_layout(xaxis_title="Z", yaxis_title=" X")
|
||||
data_sans_traitement_fft = np.fft.fft(
|
||||
volume[
|
||||
int(select_ascan_y) - 1,
|
||||
int(select_ascan_z[0]) : int(select_ascan_z[1]),
|
||||
int(select_ascan_x) - 1,
|
||||
]
|
||||
)
|
||||
fig3 = px.line(title="FFT")
|
||||
trace3 = go.Scatter(y=np.abs(data_sans_traitement_fft[int(select_ascan_z[0]) :int(int(select_ascan_z[1])/2)]), mode="lines", name=" FFT ")
|
||||
fig3.add_trace(trace3)
|
||||
fig3.update_layout(
|
||||
xaxis_title="FFT indix", yaxis_title="FFT of signal (Mangnitude)"
|
||||
)
|
||||
return [fig, fig2, fig3]
|
||||
get_callbacks()
|
||||
|
@ -1,18 +1,11 @@
|
||||
import dash
|
||||
import plotly.graph_objects as go
|
||||
from dash import html, dcc, callback, Input, Output
|
||||
from dash import html, dcc
|
||||
import dash_bootstrap_components as dbc
|
||||
import numpy as np
|
||||
from GNG_3D import *
|
||||
from sklearn import datasets as sk
|
||||
from pages.ascan import data_traits
|
||||
from callbacks.gng import get_callbacks
|
||||
|
||||
|
||||
dash.register_page(__name__, path="/gng", title="GNG", name="GNG")
|
||||
dash.register_page(__name__, path="/gng", title="GNG", name="GNG", description="Growing Neural Gas")
|
||||
|
||||
clics = None
|
||||
|
||||
# Create and fit the GNG model
|
||||
|
||||
layout = html.Div(
|
||||
[
|
||||
@ -138,76 +131,4 @@ layout = html.Div(
|
||||
)
|
||||
|
||||
|
||||
@callback(
|
||||
[Output("gng-graph", "figure")],
|
||||
[
|
||||
Input("generate-gng", "n_clicks"),
|
||||
Input("seuil", "value"),
|
||||
Input("max_neurons", "value"),
|
||||
Input("Iterations", "value"),
|
||||
Input("Max_of_age", "value"),
|
||||
Input("eb", "value"),
|
||||
Input("en", "value"),
|
||||
Input("alpha", "value"),
|
||||
Input("beta", "value"),
|
||||
Input("l", "value"),
|
||||
],
|
||||
)
|
||||
def generate_gng(n_clicks, seuil, max_neurons, max_iter, max_age, eb, en, alpha, beta, l):
|
||||
|
||||
global clics
|
||||
if n_clicks != clics:
|
||||
data=np.array(data_traits)
|
||||
fig = go.Figure()
|
||||
size_data=np.shape(data)
|
||||
x1=[]
|
||||
x2=[]
|
||||
x3=[]
|
||||
x4=[]
|
||||
for i in range(0,size_data[0]):
|
||||
res=data[i,:,:]
|
||||
res=position_point_espace(data=res,seuil=200,y=i)
|
||||
res = np.array(res)
|
||||
x1.append(res)
|
||||
gng = GrowingNeuralGas(int(max_neurons),int(max_iter),int(max_age), float(eb), float(en), float(alpha), float(beta),int(l), res)
|
||||
gng_graph = gng.learn()
|
||||
neuron_positions = np.array([vertex['weight'] for vertex in gng_graph.vs])
|
||||
neuron_edge= np.array([(edge.source, edge.target) for edge in gng_graph.es])
|
||||
for edge in gng_graph.es:
|
||||
src, tgt = edge.source, edge.target
|
||||
src_pos, tgt_pos = gng_graph.vs[src]['weight'], gng_graph.vs[tgt]['weight']
|
||||
x3.append(src_pos)
|
||||
x4.append(tgt_pos)
|
||||
|
||||
x2.append(neuron_positions)
|
||||
res=np.vstack(x1)
|
||||
neuron_positions=np.vstack(x2)
|
||||
src_pos=np.vstack(x3)
|
||||
tgt_pos=np.vstack(x4)
|
||||
fig.add_trace(go.Scatter3d(
|
||||
x=res[:, 0],
|
||||
y=res[:, 1],
|
||||
z=res[:, 2],
|
||||
mode='markers',
|
||||
marker=dict(size=1, color=res[:, 3], colorscale='Viridis', opacity=0.5),
|
||||
name='Data'
|
||||
))
|
||||
fig.add_trace(go.Scatter3d(
|
||||
x=neuron_positions[:, 0],
|
||||
y=neuron_positions[:, 1],
|
||||
z=neuron_positions[:, 2],
|
||||
mode='markers',
|
||||
marker=dict(size=4, color=neuron_positions[:,3]),
|
||||
name='Neurons'
|
||||
))
|
||||
for src, tgt in zip(src_pos, tgt_pos):
|
||||
fig.add_trace(go.Scatter3d(
|
||||
x=[src[0], tgt[0]],
|
||||
y=[src[1], tgt[1]],
|
||||
z=[src[2], tgt[2]],
|
||||
mode='lines',
|
||||
line=dict(color="black", width=1),
|
||||
showlegend=False,
|
||||
))
|
||||
clics = n_clicks
|
||||
return [fig]
|
||||
get_callbacks()
|
@ -1,19 +1,27 @@
|
||||
import dash
|
||||
from dash import html, callback, Input, Output, dcc, State, DiskcacheManager
|
||||
from dash import html, dcc, DiskcacheManager
|
||||
import dash_bootstrap_components as dbc
|
||||
import plotly.graph_objects as go
|
||||
import numpy as np
|
||||
import plotly.express as px
|
||||
import plotly.io as pio
|
||||
from util import *
|
||||
from selection_filtre import *
|
||||
from os.path import join
|
||||
import diskcache
|
||||
from pages.ascan import data_traits, pre_volume
|
||||
from callbacks.home import get_callbacks
|
||||
from pages.ascan import pre_volume
|
||||
|
||||
dash.register_page(__name__, path="/", description="The home page of the web app")
|
||||
|
||||
# on définit le dossier et les fichiers à lire
|
||||
dossier = "Dataset/Shear_transform"
|
||||
fichiers_selectionnes = [
|
||||
"Shear_x001-x101_y{:03d}_Rot00_transform.csv".format(i) for i in range(10, 14)
|
||||
]
|
||||
|
||||
dash.register_page(__name__, path="/")
|
||||
cache = diskcache.Cache("./cache")
|
||||
background_callback_manager = DiskcacheManager(cache)
|
||||
|
||||
# on charge le fichier numpy
|
||||
# fichiers = np.load("Dataset/npy/export.npy")
|
||||
|
||||
# valeurs d'échantillonage
|
||||
echantillonage_x = 1
|
||||
@ -97,26 +105,22 @@ mesh_card = dbc.Fade(
|
||||
[
|
||||
dbc.CardBody(
|
||||
[
|
||||
dbc.Row(
|
||||
html.Div(
|
||||
[
|
||||
dbc.Col(
|
||||
html.H2(
|
||||
"3D Plot",
|
||||
className="card-title",
|
||||
style={"textAlign": "left"},
|
||||
),
|
||||
width="4",
|
||||
html.H2(
|
||||
"3D Plot",
|
||||
className="card-title",
|
||||
style={"textAlign": "left"},
|
||||
),
|
||||
dbc.Col(
|
||||
dbc.Button(
|
||||
html.I(className="bi bi-arrows-fullscreen"),
|
||||
id="fullscreen-button-3dplot",
|
||||
className="mb-3",
|
||||
color="primary",
|
||||
style={"marginBottom": "15px"},
|
||||
),
|
||||
dbc.Button(
|
||||
html.I(className="bi bi-arrows-fullscreen"),
|
||||
id="fullscreen-button-3dplot",
|
||||
className="mb-3",
|
||||
color="primary",
|
||||
style={"marginBottom": "15px"},
|
||||
),
|
||||
],
|
||||
style={"display": "flex", "justifyContent": "space-between"},
|
||||
),
|
||||
dcc.Graph(
|
||||
id="3dplot",
|
||||
@ -215,26 +219,22 @@ Ascan_card = dbc.Fade(
|
||||
[
|
||||
dbc.CardBody(
|
||||
[
|
||||
dbc.Row(
|
||||
html.Div(
|
||||
[
|
||||
dbc.Col(
|
||||
html.H2(
|
||||
"A-scan",
|
||||
className="card-title",
|
||||
style={"textAlign": "left"},
|
||||
),
|
||||
width="4",
|
||||
html.H2(
|
||||
"A-scan",
|
||||
className="card-title",
|
||||
style={"textAlign": "left"},
|
||||
),
|
||||
dbc.Col(
|
||||
dbc.Button(
|
||||
html.I(className="bi bi-arrows-fullscreen"),
|
||||
id="fullscreen-button-ascan",
|
||||
className="mb-3",
|
||||
color="primary",
|
||||
style={"marginBottom": "15px"},
|
||||
),
|
||||
dbc.Button(
|
||||
html.I(className="bi bi-arrows-fullscreen"),
|
||||
id="fullscreen-button-ascan",
|
||||
className="mb-3",
|
||||
color="primary",
|
||||
style={"marginBottom": "15px"},
|
||||
),
|
||||
],
|
||||
style={"display": "flex", "justifyContent": "space-between"},
|
||||
),
|
||||
dcc.Graph(
|
||||
id="heatmap-ascan",
|
||||
@ -286,26 +286,22 @@ Bscan_card_xy = dbc.Fade(
|
||||
[
|
||||
dbc.CardBody(
|
||||
[
|
||||
dbc.Row(
|
||||
html.Div(
|
||||
[
|
||||
dbc.Col(
|
||||
html.H2(
|
||||
"B-scan ZX",
|
||||
className="card-title",
|
||||
style={"textAlign": "left"},
|
||||
),
|
||||
width="4",
|
||||
html.H2(
|
||||
"B-scan ZX",
|
||||
className="card-title",
|
||||
style={"textAlign": "left"},
|
||||
),
|
||||
dbc.Col(
|
||||
dbc.Button(
|
||||
html.I(className="bi bi-arrows-fullscreen"),
|
||||
id="fullscreen-button-bscan-zx",
|
||||
className="mb-3",
|
||||
color="primary",
|
||||
style={"marginBottom": "15px"},
|
||||
),
|
||||
dbc.Button(
|
||||
html.I(className="bi bi-arrows-fullscreen"),
|
||||
id="fullscreen-button-bscan-zx",
|
||||
className="mb-3",
|
||||
color="primary",
|
||||
style={"marginBottom": "15px"},
|
||||
),
|
||||
],
|
||||
style={"display": "flex", "justifyContent": "space-between"},
|
||||
),
|
||||
dcc.Graph(
|
||||
id="heatmap-bscan-zx",
|
||||
@ -367,26 +363,22 @@ Bscan_card_zx = dbc.Fade(
|
||||
[
|
||||
dbc.CardBody(
|
||||
[
|
||||
dbc.Row(
|
||||
html.Div(
|
||||
[
|
||||
dbc.Col(
|
||||
html.H2(
|
||||
"B-scan XY",
|
||||
className="card-title",
|
||||
style={"textAlign": "left"},
|
||||
),
|
||||
width="4",
|
||||
html.H2(
|
||||
"B-scan XY",
|
||||
className="card-title",
|
||||
style={"textAlign": "left"},
|
||||
),
|
||||
dbc.Col(
|
||||
dbc.Button(
|
||||
html.I(className="bi bi-arrows-fullscreen"),
|
||||
id="fullscreen-button-bscan-xy",
|
||||
className="mb-3",
|
||||
color="primary",
|
||||
style={"marginBottom": "15px"},
|
||||
),
|
||||
dbc.Button(
|
||||
html.I(className="bi bi-arrows-fullscreen"),
|
||||
id="fullscreen-button-bscan-xy",
|
||||
className="mb-3",
|
||||
color="primary",
|
||||
style={"marginBottom": "15px"},
|
||||
),
|
||||
],
|
||||
style={"display": "flex", "justifyContent": "space-between"},
|
||||
),
|
||||
dcc.Graph(
|
||||
id="heatmap-bscan-xy",
|
||||
@ -457,483 +449,4 @@ layout = html.Div(
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
# on défini les callbacks
|
||||
# callback pour le plot 3D
|
||||
@callback(
|
||||
[Output("3dplot", "figure")],
|
||||
[
|
||||
Input("iso-slider", "value"),
|
||||
Input("y-slider", "value"),
|
||||
Input("store-settings", "data"),
|
||||
],
|
||||
[dash.dependencies.State("fade-3dplot", "is_in")],
|
||||
running=[
|
||||
(Output("fade-3dplot", "is_in"), False, True),
|
||||
],
|
||||
)
|
||||
### a revoir###
|
||||
def update_3dplot(iso_value, y_values, settings, is_in):
|
||||
if settings["use_real_values"]:
|
||||
y_min, y_max = y_values
|
||||
selected_volume = volume[0:dim_x, int(y_min) : int(y_max), 0:dim_z]
|
||||
X, Y, Z = [
|
||||
np.load("Dataset/npy/{}-values.npy".format(i)) for i in ["x", "y", "z"]
|
||||
]
|
||||
else:
|
||||
y_min, y_max = y_values
|
||||
selected_volume = volume[0:dim_x, int(y_min) : int(y_max), 0:dim_z]
|
||||
X, Y, Z = np.mgrid[
|
||||
0 : selected_volume.shape[0],
|
||||
0 : selected_volume.shape[1],
|
||||
0 : selected_volume.shape[2],
|
||||
]
|
||||
|
||||
fig = go.Figure(
|
||||
data=go.Volume(
|
||||
x=X.flatten(),
|
||||
y=Y.flatten(),
|
||||
z=Z.flatten(),
|
||||
value=selected_volume.flatten(),
|
||||
isomin=iso_value,
|
||||
isomax=selected_volume.max(),
|
||||
opacity=0.1,
|
||||
surface_count=20,
|
||||
colorscale="Jet",
|
||||
)
|
||||
)
|
||||
|
||||
return [fig]
|
||||
|
||||
|
||||
# callback pour le plot 3D en plein écran
|
||||
@callback(
|
||||
Output("3dplot-fullscreen", "figure"),
|
||||
[Input("iso-slider-fullscreen", "value"), Input("y-slider-fullscreen", "value")],
|
||||
)
|
||||
### à revoir ###
|
||||
def update_3dplot_fullscreen(iso_value, y_values):
|
||||
y_min, y_max = y_values
|
||||
selected_volume = volume[0:dim_x, int(y_min) : int(y_max), 0:dim_z]
|
||||
X, Y, Z = np.mgrid[
|
||||
0 : selected_volume.shape[0],
|
||||
0 : selected_volume.shape[1],
|
||||
0 : selected_volume.shape[2],
|
||||
]
|
||||
|
||||
fig = go.Figure(
|
||||
data=go.Volume(
|
||||
x=X.flatten(),
|
||||
y=Y.flatten(),
|
||||
z=Z.flatten(),
|
||||
value=selected_volume.flatten(),
|
||||
isomin=iso_value,
|
||||
isomax=selected_volume.max(),
|
||||
opacity=0.1,
|
||||
surface_count=20,
|
||||
colorscale="Jet",
|
||||
)
|
||||
)
|
||||
|
||||
return fig
|
||||
|
||||
|
||||
# callback pour le A-scan
|
||||
@callback(
|
||||
[Output("heatmap-ascan", "figure")],
|
||||
[Input("layer-slider-bscan-zx", "value"), Input("layer-slider-bscan-xy", "value")],
|
||||
[dash.dependencies.State("fade-ascan", "is_in")],
|
||||
running=[
|
||||
(Output("fade-ascan", "is_in"), False, True),
|
||||
],
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def update_heatmap_ascan(layer, layer1, is_in):
|
||||
fig = px.line(y=volume[layer - 1, :, layer1], title="A-scan")
|
||||
|
||||
return [fig]
|
||||
|
||||
|
||||
# callback pour le A-scan en plein écran
|
||||
@callback(
|
||||
Output("heatmap-ascan-fullscreen", "figure"),
|
||||
Input("layer-slider-ascan-fullscreen", "value"),
|
||||
)
|
||||
def update_heatmap_ascan_fullscreen(layer):
|
||||
fig = px.line(y=volume[layer - 1, :, 5], title="A-scan")
|
||||
return fig
|
||||
|
||||
|
||||
# callback pour les B-scan XY
|
||||
@callback(
|
||||
[
|
||||
Output("heatmap-bscan-zx", "figure"),
|
||||
Output("store-bscan-zx-layer", "data"),
|
||||
],
|
||||
[Input("layer-slider-bscan-zx", "value")],
|
||||
[dash.dependencies.State("fade-bscan-zx", "is_in")],
|
||||
running=[
|
||||
(Output("fade-bscan-xy", "is_in"), False, True),
|
||||
],
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def update_heatmap_bscan_zx(layer, is_in):
|
||||
fig = px.imshow(
|
||||
volume[layer - 1, :, :],
|
||||
color_continuous_scale="Jet",
|
||||
aspect="auto",
|
||||
title="B-scan ZX",
|
||||
)
|
||||
|
||||
return [fig, layer]
|
||||
|
||||
|
||||
# callback pour les B-scan ZX en plein écran
|
||||
@callback(
|
||||
Output("heatmap-bscan-zx-fullscreen", "figure"),
|
||||
Input("layer-slider-bscan-zx-fullscreen", "value"),
|
||||
)
|
||||
def update_heatmap_bscan_zx_fullscreen(layer):
|
||||
fig = px.imshow(
|
||||
volume[layer - 1, :, :],
|
||||
color_continuous_scale="Jet",
|
||||
aspect="auto",
|
||||
title="B-scan ZX",
|
||||
)
|
||||
|
||||
return fig
|
||||
|
||||
|
||||
# callback pour les B-scan ZX
|
||||
@callback(
|
||||
[Output("heatmap-bscan-xy", "figure"), Output("store-bscan-xy-layer", "data")],
|
||||
[Input("layer-slider-bscan-xy", "value")],
|
||||
[dash.dependencies.State("fade-bscan-xy", "is_in")],
|
||||
running=[
|
||||
(Output("fade-bscan-zx", "is_in"), False, True),
|
||||
],
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def update_heatmap_bscan_xy(layer, is_in):
|
||||
fig = go.Figure(data=go.Heatmap(z=volume[:, :, layer], colorscale="Jet"))
|
||||
fig.update_layout(title="B-scan XY")
|
||||
|
||||
return [fig, layer]
|
||||
|
||||
|
||||
# callback pour les B-scan ZX en plein écran
|
||||
@callback(
|
||||
Output("heatmap-bscan-xy-fullscreen", "figure"),
|
||||
Input("layer-slider-bscan-xy-fullscreen", "value"),
|
||||
)
|
||||
def update_heatmap_bscan_xy_fullscreen(layer):
|
||||
fig = go.Figure(data=go.Heatmap(z=volume[:, :, layer], colorscale="Jet"))
|
||||
fig.update_layout(title="B-scan XY")
|
||||
|
||||
return fig
|
||||
|
||||
|
||||
# callback pour le plein écran du plot 3D
|
||||
@callback(
|
||||
Output("modal-3dplot", "is_open"),
|
||||
[Input("fullscreen-button-3dplot", "n_clicks")],
|
||||
[dash.dependencies.State("modal-3dplot", "is_open")],
|
||||
)
|
||||
def toggle_fullscreen_3dplot(n1, is_open):
|
||||
if n1:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
|
||||
# callback pour le plein écran du A-scan
|
||||
@callback(
|
||||
Output("modal-ascan", "is_open"),
|
||||
[Input("fullscreen-button-ascan", "n_clicks")],
|
||||
[dash.dependencies.State("modal-ascan", "is_open")],
|
||||
)
|
||||
def toggle_fullscreen_ascan(n1, is_open):
|
||||
if n1:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
|
||||
# callback pour le plein écran du B-scan XY
|
||||
@callback(
|
||||
Output("modal-bscan-xy", "is_open"),
|
||||
[Input("fullscreen-button-bscan-xy", "n_clicks")],
|
||||
[dash.dependencies.State("modal-bscan-xy", "is_open")],
|
||||
)
|
||||
def toggle_fullscreen_bscan_xy(n1, is_open):
|
||||
if n1:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
|
||||
# callback pour le plein écran du B-scan ZX
|
||||
@callback(
|
||||
Output("modal-bscan-zx", "is_open"),
|
||||
[Input("fullscreen-button-bscan-zx", "n_clicks")],
|
||||
[dash.dependencies.State("modal-bscan-zx", "is_open")],
|
||||
)
|
||||
def toggle_fullscreen_bscan_zx(n1, is_open):
|
||||
if n1:
|
||||
return not is_open
|
||||
return is_open
|
||||
|
||||
|
||||
@callback(
|
||||
[
|
||||
Output("3dplot", "clickData"),
|
||||
Output("layer-slider-bscan-xy", "value"),
|
||||
Output("layer-slider-bscan-zx", "value"),
|
||||
],
|
||||
Input("3dplot", "clickData"),
|
||||
)
|
||||
def display_3dplot_click_data(clickData):
|
||||
if clickData is None:
|
||||
return [None, 1, 1]
|
||||
|
||||
bscan_xy = clickData["points"][0]["z"]
|
||||
bscan_zx = clickData["points"][0]["x"]
|
||||
return [clickData, bscan_xy, bscan_zx]
|
||||
|
||||
|
||||
@callback(
|
||||
[
|
||||
Output("heatmap-bscan-xy", "clickData"),
|
||||
Output("layer-slider-bscan-zx", "value", allow_duplicate=True),
|
||||
],
|
||||
[Input("heatmap-bscan-xy", "clickData")],
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def display_bscan_xy_click_data(clickData):
|
||||
if clickData is None:
|
||||
return [None, 1]
|
||||
|
||||
bscan_zx = clickData["points"][0]["y"]
|
||||
return [clickData, bscan_zx]
|
||||
|
||||
|
||||
@callback(
|
||||
[
|
||||
Output("heatmap-bscan-zx", "clickData"),
|
||||
Output("layer-slider-bscan-xy", "value", allow_duplicate=True),
|
||||
],
|
||||
[Input("heatmap-bscan-zx", "clickData")],
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def display_bscan_zx_click_data(clickData):
|
||||
if clickData is None:
|
||||
return [None, 0]
|
||||
|
||||
bscan_xy = clickData["points"][0]["x"]
|
||||
return [clickData, bscan_xy]
|
||||
|
||||
|
||||
@callback(
|
||||
[
|
||||
Output("heatmap-bscan-xy", "figure", allow_duplicate=True),
|
||||
Output("heatmap-bscan-zx", "figure", allow_duplicate=True),
|
||||
Output("heatmap-ascan", "figure", allow_duplicate=True),
|
||||
],
|
||||
[Input("store-bscan-xy-layer", "data"), Input("store-bscan-zx-layer", "data")],
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def update_bscan_layers(bscan_xy, bscan_zx):
|
||||
fig = go.Figure(data=go.Heatmap(z=volume[:, :, bscan_xy], colorscale="Jet"))
|
||||
fig.add_shape(
|
||||
type="line",
|
||||
x0=0 - 1,
|
||||
y0=bscan_zx,
|
||||
x1=dim_y,
|
||||
y1=bscan_zx,
|
||||
line=dict(color="white", width=1),
|
||||
)
|
||||
fig.update_layout(title="B-scan XY")
|
||||
|
||||
fig2 = px.imshow(
|
||||
volume[bscan_zx - 1, :, :],
|
||||
color_continuous_scale="Jet",
|
||||
aspect="auto",
|
||||
title="B-scan ZX",
|
||||
)
|
||||
fig2.add_shape(
|
||||
type="line",
|
||||
x0=bscan_xy,
|
||||
y0=0,
|
||||
x1=bscan_xy,
|
||||
y1=dim_y,
|
||||
line=dict(color="white", width=1),
|
||||
)
|
||||
|
||||
fig3 = px.line(y=volume[bscan_zx - 1, :, bscan_xy], title="A-scan")
|
||||
|
||||
return [fig, fig2, fig3]
|
||||
|
||||
|
||||
@callback(
|
||||
[Output("store-settings", "data"), Output("settings-apply", "n_clicks")],
|
||||
[
|
||||
Input("settings-apply", "n_clicks"),
|
||||
],
|
||||
[
|
||||
State("use-real-values", "value"),
|
||||
State("apply-filters-everywhere", "value"),
|
||||
State("echantillonage-x", "value"),
|
||||
State("echantillonage-y", "value"),
|
||||
State("echantillonage-z", "value"),
|
||||
],
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def update_settings(
|
||||
clicks,
|
||||
use_real_values,
|
||||
apply_filters,
|
||||
echantillonage_x_value,
|
||||
echantillonage_y_value,
|
||||
echantillonage_z_value,
|
||||
):
|
||||
if clicks != None and clicks == 1:
|
||||
return [
|
||||
{
|
||||
"use_real_values": use_real_values,
|
||||
"use_filters": apply_filters,
|
||||
"echantillonage_x": echantillonage_x_value,
|
||||
"echantillonage_y": echantillonage_y_value,
|
||||
"echantillonage_z": echantillonage_z_value,
|
||||
},
|
||||
0,
|
||||
]
|
||||
|
||||
|
||||
@callback(
|
||||
[
|
||||
Output("layer-slider-bscan-zx", "max"),
|
||||
Output("layer-slider-bscan-zx", "marks"),
|
||||
Output("layer-slider-bscan-xy", "max"),
|
||||
Output("layer-slider-bscan-xy", "marks"),
|
||||
Output("iso-slider", "min"),
|
||||
Output("iso-slider", "max"),
|
||||
Output("iso-slider", "marks"),
|
||||
Output("y-slider", "max"),
|
||||
Output("y-slider", "marks"),
|
||||
Output("settings-spinner", "children"),
|
||||
],
|
||||
Input("store-settings", "data"),
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def redef_data(data):
|
||||
global volume, dim_x, dim_y, dim_z, X, Y, Z
|
||||
volume = pre_volume[
|
||||
:: data["echantillonage_x"],
|
||||
:: data["echantillonage_y"],
|
||||
:: data["echantillonage_z"],
|
||||
]
|
||||
dim_x, dim_y, dim_z = volume.shape
|
||||
X, Y, Z = np.mgrid[0:dim_x, 0:dim_y, 0:dim_z]
|
||||
|
||||
return [
|
||||
dim_x - 1,
|
||||
{str(i): str(i) for i in range(0, dim_x, max(1, int(dim_x / 20)))},
|
||||
dim_z - 1,
|
||||
{str(i): str(i) for i in range(1, dim_z + 1, max(1, int(dim_z / 20)))},
|
||||
volume.min(),
|
||||
volume.max() / 2,
|
||||
{
|
||||
str(i): str(i)
|
||||
for i in range(
|
||||
int(volume.min()),
|
||||
int(volume.max() / 2) + 1,
|
||||
int((volume.max() / 2 - volume.min()) / 10),
|
||||
)
|
||||
},
|
||||
dim_y,
|
||||
{str(i): str(i) for i in range(0, int(dim_y) + 1, max(1, int(dim_y / 20)))},
|
||||
"Apply",
|
||||
]
|
||||
|
||||
"""
|
||||
@callback(
|
||||
[Input("store-filters", "data"), Input("store-settings", "data")],
|
||||
)
|
||||
def apply_filters(data, settings):
|
||||
global volume
|
||||
if settings["use_filters"]:
|
||||
select_filtre_1 = data["select_filtre_2"]
|
||||
select_filtre_2 = data["select_filtre_3"]
|
||||
fs_filtre_1 = data["fs_filtre_1"]
|
||||
cutoff_filtre_1 = data["cutoff_filtre_1"]
|
||||
order_filtre_1 = data["order_filtre_1"]
|
||||
windowsize_filtre_1 = data["windowsize_filtre_1"]
|
||||
fs_filtre_2 = data["fs_filtre_2"]
|
||||
cutoff_filtre_2 = data["cutoff_filtre_2"]
|
||||
order_filtre_2 = data["order_filtre_2"]
|
||||
windowsize_filtre_2 = data["windowsize_filtre_2"]
|
||||
selec_transforme_hilbert = data["select_filtre_1"]
|
||||
|
||||
volume = pre_volume[
|
||||
:: settings["echantillonage_x"],
|
||||
:: settings["echantillonage_y"],
|
||||
:: settings["echantillonage_z"],
|
||||
]
|
||||
|
||||
data_avec_traitement = switch_case(volume, int(selec_transforme_hilbert))
|
||||
|
||||
data_avec_traitement = switch_case(
|
||||
data_avec_traitement,
|
||||
int(select_filtre_1),
|
||||
int(fs_filtre_1),
|
||||
int(cutoff_filtre_1),
|
||||
int(order_filtre_1),
|
||||
int(windowsize_filtre_1),
|
||||
)
|
||||
data_avec_traitement = switch_case(
|
||||
data_avec_traitement,
|
||||
int(select_filtre_2),
|
||||
int(fs_filtre_2),
|
||||
int(cutoff_filtre_2),
|
||||
int(order_filtre_2),
|
||||
int(windowsize_filtre_2),
|
||||
)
|
||||
volume = data_avec_traitement
|
||||
else:
|
||||
volume = pre_volume[
|
||||
:: settings["echantillonage_x"],
|
||||
:: settings["echantillonage_y"],
|
||||
:: settings["echantillonage_z"],
|
||||
]
|
||||
return None
|
||||
"""
|
||||
|
||||
@callback(
|
||||
Output("store-files", "data", allow_duplicate=True),
|
||||
Input("store-files", "data"),
|
||||
State("store-settings", "data"),
|
||||
prevent_initial_call=True,
|
||||
)
|
||||
def update_files(data, settings):
|
||||
global pre_volume, volume, dim_x, dim_y, dim_z, X, Y, Z
|
||||
if data is None or data == "":
|
||||
return None
|
||||
|
||||
# Charger le nouveau volume
|
||||
pre_volume = np.load(join("Dataset/saves", data))
|
||||
print("New volume loaded:", pre_volume.shape)
|
||||
|
||||
# Appliquer les nouveaux paramètres d'échantillonnage
|
||||
volume = pre_volume[
|
||||
::settings["echantillonage_x"],
|
||||
::settings["echantillonage_y"],
|
||||
::settings["echantillonage_z"],
|
||||
]
|
||||
dim_x, dim_y, dim_z = volume.shape
|
||||
X, Y, Z = np.mgrid[0:dim_x, 0:dim_y, 0:dim_z]
|
||||
print("Volume updated with new dimensions:", volume.shape)
|
||||
|
||||
# Mettre à jour les graphiques
|
||||
update_3dplot(0, [0, dim_y // 2], settings, False)
|
||||
update_heatmap_ascan(0, 0, False)
|
||||
update_heatmap_bscan_zx(0, False)
|
||||
update_heatmap_bscan_xy(0, False)
|
||||
|
||||
return None
|
||||
get_callbacks()
|
Reference in New Issue
Block a user