AnalyseMorphologique/utils/data_processing/data_processing.py
Djalim Simaila 914d6bb7cb 📝 docs(README.md): capitalize the first letter of the title
The first letter of the title "Analyse morphologique" was not capitalized, which is inconsistent with the usual capitalization rules for titles.

🖼️ chore(README.md): update image and fix typo in rotation instructions
The image in the README.md file was updated to reflect the correct rotation instructions. A typo in the rotation instructions was also fixed.

👥 chore(README.md): fix typo in contributor's role
A typo in the role of one of the contributors was fixed.

🐛 fix(data_processing.py): add missing half discretisation values to L calculation
The calculation of L in the get_advanced_data function of data_processing.py was missing half the discretisation values at the beginning and end of the object.

🐛 fix(input.py): remove print statement
A print statement was accidentally left in the from_xyz_file method of the ScannedObject class in input
2023-05-12 09:13:21 +02:00

191 lines
7.1 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]) + discrete_data["Discretisation(en mm)"][-1] /2 + discrete_data["Discretisation(en mm)"][0] /2
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,
"H": H,
"L": L,
"l":l,
"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
}