AnalyseMorphologique/utils/data_processing/data_processing.py
Djalim Simaila aeb8c6ed44 🔨 refactor(data_processing.py): rename function parameter to improve semantics
The function parameter `update_progress_bar` has been renamed to `progressbar_placeholder` to improve the semantics of the function. This change does not affect the functionality of the code.

 feat(data_processing.py): add new morphological indicators to the output of the `get_advanced_data` function
The `get_advanced_data` function now calculates and returns the following morphological indicators:
- MI_mR: the ratio of the maximum radius to the mean radius
- MI_mH: the ratio of the maximum radius to the height of the object
- V_scan: the volume of the scanned object
- R_V_scan: the radius of a sphere with the same volume as the scanned object
- S_V_scan: the surface area of a sphere with the same volume as the scanned object
- R_h: the hydraulic radius of the object
- HI: the hydraulic index of the object
2023-05-10 15:43:01 +02:00

188 lines
7.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Created on Mon Apr 24 2023
@name: data_processing.py
@desc: A module to process the data
@auth: Djalim Simaila
@e-mail: djalim.simaila@inrae.fr
"""
from utils.math import data_extraction as de
import numpy as np
from utils.files.input import ScannedObject
def progressbar_placeholder(percent:int):
"""
This function is a placeholder for a progressbar function
"""
def get_raw_data(obj:ScannedObject, ndigits:int,delta_z:float=1,update_progress_bar = progressbar_placeholder)->dict:
"""
Calculates data from the given object
:param obj: Object to analyse
:param ndigits: Number of digits to keep after the comma
:param delta_z: Delta z to use for the discretisation
:param update_progress_bar: Function to update the progress bar
:return: dict(str:list) with the following keys:
- X (en mm) : list of x values
- Y (en mm) : list of y values
- Z (en mm) : list of z values
- theta (en rad) : list of theta values
- rayon (en mm) : list of radius values
- Xi-Xmoy : list of Xi-Xmoy values
- Yi-Ymoy : list of Yi-Ymoy values
"""
# Create the data dict
colones = ["X (en mm)",
"Y (en mm)",
"Z (en mm)",
"theta (en rad)",
"rayon (en mm)",
"Xi-Xmoy",
"Yi-Ymoy"]
data = {}
for colone in colones:
data[colone] = []
# Get the discrete vertices
discrete_vertices = obj.get_discrete_vertices(delta_z)
progress = 0
# Calculate the data for each discrete vertex
for discrete_values in discrete_vertices:
mean_x ,mean_y, mean_z = de.get_x_y_z_mean(discrete_values)
for x,y,z in discrete_values:
data["X (en mm)"].append(round(x, ndigits))
data["Y (en mm)"].append(round(y, ndigits))
data["Z (en mm)"].append(round(z, ndigits))
data["theta (en rad)"].append(round(de.get_theta_from_x_y(x,y,mean_x,mean_y), ndigits))
data["rayon (en mm)"].append(round(de.get_radius_from_x_y(x,y,mean_x,mean_y), ndigits))
data["Xi-Xmoy"].append(round(x-mean_x, ndigits))
data["Yi-Ymoy"].append(round(y-mean_y, ndigits))
update_progress_bar(int(progress/len(discrete_vertices)*100))
progress += 1
return data
def get_discrete_data(obj:ScannedObject, ndigits:int, delta_z:float=1, update_progress_bar= progressbar_placeholder)->dict:
"""
Calculates data from the given object
:param obj: Object to analyse
:param ndigits: Number of digits to keep after the comma
:param delta_z: Delta z to use for the discretisation
:param update_progress_bar: Function to update the progress bar
:return: dict(str:list) with the following keys:
- X moy (en mm) : list of x mean values
- Y moy (en mm) : list of y mean values
- Z moy (en mm) : list of z mean values
- Rayon moyen (en mm) : list of mean radius values
- Rayon ecart type (en mm) : list of radius standard deviation values
"""
# Create the data dict
colones = ["X moy (en mm)",
"Y moy (en mm)",
"Z moy (en mm)",
"Discretisation(en mm)",
"Rayon moyen (en mm)",
"Rayon ecart type (en mm)"]
data = {}
for colone in colones:
data[colone] = []
# Get the discrete vertices
discrete_vertices = obj.get_discrete_vertices(delta_z)
progress = 0
for discrete_values in discrete_vertices:
x,y,z = de.get_x_y_z_mean(discrete_values)
data["X moy (en mm)"].append(round(x, ndigits))
data["Y moy (en mm)"].append(round(y, ndigits))
data["Z moy (en mm)"].append(round(z, ndigits))
first = discrete_values[0]
last = discrete_values[-1]
data["Discretisation(en mm)"].append(round(last[2]-first[2],ndigits))
data["Rayon moyen (en mm)"].append(round(de.get_mean_radius(discrete_values), ndigits))
data["Rayon ecart type (en mm)"].append(round(de.get_radius_std(discrete_values), ndigits))
update_progress_bar(int(progress/len(discrete_vertices)*100))
progress += 1
return data
def get_advanced_data(discrete_data:dict, V_scan = 0, update_progress_bar= progressbar_placeholder)->dict:
"""
Calculates morphological indicators from the given discrete data
:param discrete_data: dict(str:list) with the following keys:
- X moy (en mm) : list of x mean values
- Y moy (en mm) : list of y mean values
- Z moy (en mm) : list of z mean values
- Rayon moyen (en mm) : list of mean radius values
- Rayon ecart type (en mm) : list of radius standard deviation values
:param update_progress_bar: Function to update the progress bar
:return: dict with the following keys:
- Tortuosite
- Volume en mm3
- Surface en mm2
- Moyenne des rayons moyens 〈R〉
- Ecart-type des rayons moyens σ_〈R〉
- σ_〈R〉^tot
- MI_l
- MI_p
- Rayon hydraulique R_h
"""
all_R = discrete_data["Rayon moyen (en mm)"]
# Tortusity
l = 0
L = 0
vertices = list(zip(discrete_data["X moy (en mm)"],
discrete_data["Y moy (en mm)"],
discrete_data["Z moy (en mm)"]))
for index in range(len(vertices)-1):
l += de.get_distance_between_two_vertices(vertices[index], vertices[index+1])
L = de.get_distance_between_two_vertices(vertices[0], vertices[-1])
T = l/L
update_progress_bar(10)
# Volume and surface
H = discrete_data["Z moy (en mm)"][-1] - discrete_data["Z moy (en mm)"][0]
R2_mean = de.get_mean([np.power(r,2) for r in all_R])
V = np.pi * R2_mean * H
S = 2 * np.pi * R2_mean * H
update_progress_bar(30)
# Morphological indicators
R_mean = de.get_mean(all_R)
R_mean_std = de.get_standard_deviation(all_R)
mean_sigma_r_squared = de.get_mean([np.power(r,2) for r in discrete_data["Rayon ecart type (en mm)"]])
sigma_r_tot = np.sqrt(np.power(R_mean_std,2) + mean_sigma_r_squared )
MI_l = R_mean_std/R_mean
MI_p = np.sqrt(mean_sigma_r_squared)/R_mean
R_max = max(all_R)
MI_mR = R_max/R_mean
MI_mH = R_max/H
#MI_mr_in = R_max/R_in
# TODO understand what is R_in
R_V_scan = np.sqrt(V_scan/np.pi*H)
S_V_scan = 2 * np.sqrt(np.pi * H * V_scan)
R_h = R2_mean/ R_mean
HI = R_mean * R_V_scan / R2_mean
update_progress_bar(100)
return {
"Tortuosité":T,
"Volume en mm3":V,
"Surface en mm2":S,
"Moyenne des rayons moyens 〈R〉":R_mean,
"Ecart-type des rayons moyens σ_〈R〉":R_mean_std,
"σ_〈R〉^tot":sigma_r_tot,
"MI_l":MI_l,
"MI_p":MI_p,
"MI_mR":MI_mR,
"MI_mH":MI_mH,
# "MI_mr_in":MI_mr_in,
"V_scan":V_scan,
"R_V_scan":R_V_scan,
"S_V_scan":S_V_scan,
"Rayon hydraulique R_h":R_h,
"HI":HI
}