✨ feat(data_processing.py): add raw_data parameter to get_advanced_data function to improve flexibility The L variable was not being computed in the get_advanced_data function, which is necessary for the calculation of the tortuosity. The raw_data parameter was added to the get_advanced_data function to improve flexibility and allow for more advanced calculations to be performed. 🐛 fix(input.py): add filename attribute to ScannedObject class The filename attribute was not being set in the ScannedObject class, which is necessary for generating the output file headers. ✨ feat(output.py): add function to generate headers for output file The generate_headers function was added to generate the headers for the output file. The headers include the filename, date, version, discretisation method, and whether the data was verticalised. 🚀 chore(MainWindow.py): enable process_advanced_data function 🎨 style(MainWindow.ui, UI_MainWindow.py): adjust GUI layout and label text for better user experience The GUI layout has been adjusted to improve the user experience. The window width has been reduced from 1419 to 1336 pixels to better fit the screen. The minimum and maximum sizes of the MainSettings widget have been increased from 518 to 600 pixels to allow for more space for the labels. The labels have been updated to include the units of measurement to improve clarity. 🐛 fix(AdvancedDataWorker.py): add raw_data parameter to __init__ method ✨ feat(AdvancedDataWorker.py): add support for raw data processing in get_advanced_data method The AdvancedDataWorker class now has a raw_data parameter in its __init__ method, which is used in the get_advanced_data method. This allows for raw data processing in addition to the existing discrete data processing. 🐛 fix(DiscreteDataWorker.py): generate headers before formatting data ✨ feat(DiscreteDataWorker.py): add support for generating headers in output file The DiscreteDataWorker class now generates headers for the output file if the add_headers setting is enabled. The headers are generated before formatting the data to ensure that the headers are included in the output file. 🐛 fix(PreProcessWorker.py): set filename of ScannedObject The PreProcessWorker class now sets the filename of the ScannedObject to the basename 🎨 style(UI_Settings.py): reorganize widgets in the settings UI for better readability 🐛 fix(data_extraction.py): fix standard deviation calculation to use unbiased estimator 🔧 chore(SettingManager.py): add "add_headers" setting with default value of True The changes in UI_Settings.py are purely cosmetic and do not affect the functionality of the code. The fix in data_extraction.py corrects the standard deviation calculation to use the unbiased estimator. The addition of the "add_headers" setting in SettingManager.py allows for the addition of headers to output files.
195 lines
5.2 KiB
Python
195 lines
5.2 KiB
Python
"""
|
|
Created on Mon Apr 17 2023
|
|
@name: data_extraction.py
|
|
@desc: This module contains some utility functions for math operations.
|
|
@auth: Djalim Simaila
|
|
@e-mail: djalim.simaila@inrae.fr
|
|
"""
|
|
import numpy as np
|
|
import math
|
|
|
|
def get_mean(values:list):
|
|
"""
|
|
Get the mean of the values.
|
|
|
|
:param values: values
|
|
:return: mean of the values
|
|
|
|
:Example:
|
|
>>> get_mean([1,2,3,4,5])
|
|
3.0
|
|
"""
|
|
return np.mean(values)
|
|
|
|
def get_standard_deviation(values:list):
|
|
"""
|
|
Get the standard deviation of the values.
|
|
|
|
:param values: values
|
|
:return: standard deviation of the values
|
|
|
|
:Example:
|
|
>>> get_standard_deviation([1,2,3,4,5])
|
|
1.4142135623730951
|
|
"""
|
|
mean = get_mean(values)
|
|
sum = 0
|
|
for i in values:
|
|
sum += np.power(i - mean,2)
|
|
sum /= len(values) - 1
|
|
return np.sqrt(sum)
|
|
|
|
|
|
|
|
def get_x_y_z_mean(discrete_values:list):
|
|
"""
|
|
Get the mean of the x and y coordinates in the discrete range.
|
|
|
|
:param x: x coordinates
|
|
:param y: y coordinates
|
|
:return: mean of x and y coordinates in the discrete range
|
|
|
|
:Example:
|
|
>>> get_x_y_z_mean([(1,2,3),(4,5,6),(7,8,9)])
|
|
(4.0, 5.0, 6.0)
|
|
"""
|
|
x = [vertex[0] for vertex in discrete_values]
|
|
y = [vertex[1] for vertex in discrete_values]
|
|
z = [vertex[2] for vertex in discrete_values]
|
|
return get_mean(x), get_mean(y), get_mean(z)
|
|
|
|
def get_radius_from_x_y(xi:float, yi:float, x_mean:float, y_mean:float):
|
|
"""
|
|
Get the radius from the x and y coordinates.
|
|
|
|
:param xi: x coordinate
|
|
:param yi: y coordinate
|
|
:param x_mean: mean of x coordinates in the discrete range
|
|
:param y_mean: mean of y coordinates in the discrete range
|
|
:return: radius for this point
|
|
|
|
:Example:
|
|
>>> get_radius_from_x_y(1,2,3,4)
|
|
2.8284271247461903
|
|
"""
|
|
return np.sqrt(np.power((xi - x_mean), 2) + np.power((yi - y_mean), 2))
|
|
|
|
def get_mean_radius(discrete_values:list):
|
|
"""
|
|
Get the mean of the radius in the discrete range.
|
|
|
|
:param discrete_values: discrete values
|
|
:return: mean of the radius in the discrete range
|
|
|
|
:Example:
|
|
>>> get_mean_radius([(1,2,3),(4,5,6),(7,8,9)])
|
|
2.82842712474619
|
|
"""
|
|
x_mean, y_mean, z_mean = get_x_y_z_mean(discrete_values)
|
|
radius = []
|
|
for x,y,z in discrete_values:
|
|
radius.append(get_radius_from_x_y(x,y,x_mean,y_mean))
|
|
return get_mean(radius)
|
|
|
|
def get_radius_std(discrete_values:list):
|
|
"""
|
|
Get the standard deviation of the radius in the discrete range.
|
|
|
|
:param discrete_values: discrete values
|
|
:return: standard deviation of the radius in the discrete range
|
|
|
|
:Example:
|
|
>>> get_radius_std([(1,2,3),(4,5,6),(7,8,9)])
|
|
2.8284271247461903
|
|
"""
|
|
x_mean, y_mean, z_mean = get_x_y_z_mean(discrete_values)
|
|
radius = []
|
|
for x,y,z in discrete_values:
|
|
radius.append(get_radius_from_x_y(x,y,x_mean,y_mean))
|
|
return get_standard_deviation(radius)
|
|
|
|
def get_mean_theta(discrete_values:list):
|
|
"""
|
|
Get the mean of the theta in the discrete range.
|
|
|
|
:param discrete_values: discrete values
|
|
:return: mean of the theta in the discrete range
|
|
|
|
:Example:
|
|
>>> get_mean_theta([(1,2,3),(4,5,6),(7,8,9)])
|
|
0.7853981633974483
|
|
"""
|
|
x_mean, y_mean, z_mean = get_x_y_z_mean(discrete_values)
|
|
theta = []
|
|
for x,y,z in discrete_values:
|
|
theta.append(get_theta_from_x_y(x,y,x_mean,y_mean))
|
|
return get_mean(theta)
|
|
|
|
def get_theta_from_x_y(xi:float, yi:float, x_mean:float, y_mean:float):
|
|
"""
|
|
Get the theta from the x and y coordinates.
|
|
|
|
:param xi: x coordinate
|
|
:param yi: y coordinate
|
|
:param x_mean: mean of x coordinates in the discrete range
|
|
:param y_mean: mean of y coordinates in the discrete range
|
|
:return: theta for this point
|
|
|
|
:Example:
|
|
>>> get_theta_from_x_y(1,2,3,4)
|
|
0.7853981633974483
|
|
"""
|
|
return math.atan((xi-x_mean)/(yi-y_mean))
|
|
|
|
def get_true_theta_from_x_y(xi:float, yi:float, x_mean:float, y_mean:float):
|
|
"""
|
|
Get the theta from the x and y coordinates.
|
|
|
|
:param xi: x coordinate
|
|
:param yi: y coordinate
|
|
:param x_mean: mean of x coordinates in the discrete range
|
|
:param y_mean: mean of y coordinates in the discrete range
|
|
:return: theta for this point
|
|
|
|
:Example:
|
|
>>> get_true_theta_from_x_y(1,2,3,4)
|
|
0.7853981633974483
|
|
"""
|
|
return math.atan2((xi-x_mean),(yi-y_mean))
|
|
|
|
|
|
def get_difference_from_mean_value(values:list, mean_value:float):
|
|
"""
|
|
Get the difference from the mean value.
|
|
|
|
:param values: values
|
|
:param mean_value: mean value
|
|
:return: difference from the mean value
|
|
|
|
:Example:
|
|
>>> get_difference_from_mean_value([1,2,3,4,5], 3)
|
|
[-2.0, -1.0, 0.0, 1.0, 2.0]
|
|
"""
|
|
return [value - mean_value for value in values]
|
|
|
|
def get_distance_between_two_vertices(vertex_1,vertex_2):
|
|
"""
|
|
Get the distance between two vertices.
|
|
|
|
:param vertex_1: vertex 1
|
|
:param vertex_2: vertex 2
|
|
:return: distance between two vertices
|
|
|
|
:Example:
|
|
>>> get_distance_between_two_vertices((1,2,3),(4,5,6))
|
|
5.196152422706632
|
|
"""
|
|
return np.sqrt(np.power((vertex_1[0] - vertex_2[0]), 2) + np.power((vertex_1[1] - vertex_2[1]), 2) + np.power((vertex_1[2] - vertex_2[2]), 2))
|
|
|
|
|
|
#todo fix examples
|
|
if __name__ == "__main__":
|
|
import doctest
|
|
doctest.testmod()
|
|
|