AnalyseMorphologique/integration_tests/data_test.py

264 lines
12 KiB
Python

"""
This module gives functions to assist tests
"""
import os
import time
import numpy as np
from main import get_discrete_data, get_raw_data
from utils.files import output
from utils.files.input import ScannedObject, parse_result_file
def check_discrete_data(expected_file: str, actual_file: str, ndigits=7, eps=0.00001, silent: bool = False) -> dict:
"""
Compares the output of the main process with the reference output for the same file,
This function assume the passed paramters are the discretised one and not the raw,
this function will not test that for the user>
:param expected_file: The reference file, the one we assume is correct
:param actual_file: The output of the main process
:param ndigits: The number of values to keep after the dot
:param eps: the degree of precision we consider two values different
:return: dict containing the average difference for each variable
"""
output_file = "check_discrete_data_full.txt"
minimal_output_file = "check_discrete_data_minimal.txt"
minimal_output_data = ""
output_data = ""
expected = []
list_x_diffs, list_y_diffs, list_z_diffs, list_r_diffs, list_std_diffs = [], [], [], [], []
with open(expected_file, "r") as f:
expected = f.readlines()[1:]
expected = [line.replace(',', '.').split('\t') for line in expected]
expected = [[float(x) for x in line] for line in expected]
actual = []
with open(actual_file, "r") as f:
actual = f.readlines()[1:]
actual = [line.split('\t') for line in actual]
actual = [[float(x) for x in line if x != '\n'] for line in actual]
for point in range(min(len(expected), len(actual))):
# Calculate the difference for each variable
x_diff, y_diff, z_diff, r_diff, std_diff = round(abs(expected[point][0] - actual[point][0]), ndigits), round(abs(expected[point][1] - actual[point][1]), ndigits), round(
abs(expected[point][2] - actual[point][2]), ndigits), round(abs(expected[point][3] - actual[point][3]), ndigits), round(abs(expected[point][4] - actual[point][4]), ndigits)
# Add the difference to their respective list
list_x_diffs.append(x_diff)
list_y_diffs.append(y_diff)
list_z_diffs.append(z_diff)
list_r_diffs.append(r_diff)
list_std_diffs.append(std_diff)
# Format the line
line = f"{str(point).rjust(4)}:\t X: {str(x_diff).rjust(8)}\t Y: {str(y_diff).rjust(8)}\t Z: {str(z_diff).rjust(8)}\t R: {str(r_diff).rjust(8)}\t STD: {str(std_diff).rjust(8)}"
output_data += line + "\n"
# If one of the values is greater than epsilon, add the line to the minimal output file
if x_diff > eps or y_diff > eps or z_diff > eps or r_diff > eps or std_diff > eps:
minimal_output_data += line + "\n"
# Save output to file
output.save_output_file(output_file, output_data)
output.save_output_file(minimal_output_file, minimal_output_data)
# Print the results
if not silent:
x = round(sum(list_x_diffs)/len(expected), ndigits)
y = round(sum(list_y_diffs)/len(expected), ndigits)
z = round(sum(list_z_diffs)/len(expected), ndigits)
r = round(sum(list_r_diffs)/len(expected), ndigits)
std = round(sum(list_std_diffs)/len(expected), ndigits)
print()
print("Analyse données discretisées:")
print(f"difference moyenne X: {x}")
print(f"difference moyenne Y: {y}")
print(f"difference moyenne Z: {z}")
print(f"difference moyenne R: {r}")
print(f"difference moyenne STD: {std}")
print(f"diff globale des fichiers: {(x+y+z+r+std)/5}")
print(f"Voir {output_file} pour plus de détails")
print(f"Voir {minimal_output_file} pour les différences significatives")
print("_"*80)
return {
"x": x,
"y": y,
"z": z,
"r": r,
"std": std}
def check_raw_data(expected_file, actual_file, ndigits=7, eps=0.00001, silent: bool = False) -> dict:
"""
Compares the output of the main process with the reference output for the same file,
This function assume the passed paramters are the raw one and not the discretised,
this function will not test that for the user.
:param expected_file: The reference file, the one we assume is correct
:param actual_file: The output of the main process
:param ndigits: The number of values to keep after the dot
:param eps: the degree of precision we consider two values different
:return: dict containing the average difference for each variable
"""
output_file = "check_raw_data_full.txt"
minimal_output_file = "check_raw_data_minimal.txt"
minimal_output_data = ""
output_data = ""
expected = []
list_x_diffs, list_y_diffs, list_z_diffs, list_teta_diffs, list_radius_diffs, list_xmoy_diffs, list_ymoy_diffs = [], [], [], [], [], [], []
with open(expected_file, "r") as f:
expected = f.readlines()[1:]
expected = [line.replace(',', '.').split('\t') for line in expected]
expected = [[float(x) for x in line] for line in expected]
actual = []
with open(actual_file, "r") as f:
actual = f.readlines()[1:]
actual = [line.split('\t') for line in actual]
actual = [[float(x) for x in line if x != '\n'] for line in actual]
for i in range(min(len(expected), len(actual))):
# Calculate the absolute difference between expected and actual
x_diff, y_diff, z_diff, t_diff, r_diff, xmoy_diff, ymoy_diff = round(abs(expected[i][0] - actual[i][0]), ndigits), round(abs(expected[i][1] - actual[i][1]), ndigits), round(abs(expected[i][2] - actual[i][2]), ndigits), round(
abs(expected[i][3] - actual[i][3]), ndigits), round(abs(expected[i][4] - actual[i][4]), ndigits), round(abs(expected[i][5] - actual[i][5]), ndigits), round(abs(expected[i][6] - actual[i][6]), ndigits)
# Add each difference to its respctive list
list_x_diffs.append(x_diff)
list_y_diffs.append(y_diff)
list_z_diffs.append(z_diff)
list_teta_diffs.append(t_diff)
list_radius_diffs.append(r_diff)
list_xmoy_diffs.append(xmoy_diff)
list_ymoy_diffs.append(ymoy_diff)
# Format the line
line = f"{str(i).rjust(4)}:\t X: {str(x_diff).rjust(8)}\t Y: {str(y_diff).rjust(8)}\t Z: {str(z_diff).rjust(8)}\t T: {str(t_diff).rjust(8)}\t R: {str(r_diff).rjust(8)}\t Xmoy: {str(xmoy_diff).rjust(8)}\t Ymoy: {str(ymoy_diff).rjust(8)}"
output_data += line + "\n"
# If the diff is greater than epsilon, add it to the minimal output file
if x_diff > eps:
minimal_output_data += f"{i} : X diff {x_diff}\n"
if y_diff > eps:
minimal_output_data += f"{i} : Y diff {y_diff}\n"
if z_diff > eps:
minimal_output_data += f"{i} : Z diff {z_diff}\n"
if t_diff > eps:
minimal_output_data += f"{i} : teta diff{ t_diff}\n"
if r_diff > eps:
minimal_output_data += f"{i} : R diff {r_diff}\n"
if xmoy_diff > eps:
minimal_output_data += f"{i} : Xi-Xmoy diff {xmoy_diff}\n"
if ymoy_diff > eps:
minimal_output_data += f"{i} : Yi-Ymoy diff{ymoy_diff}\n"
# Save output to file
output.save_output_file(output_file, output_data)
output.save_output_file(minimal_output_file, minimal_output_data)
# Print the output
if not silent:
sum_x_diff = round(sum(list_x_diffs)/len(expected), ndigits)
sum_y_diff = round(sum(list_y_diffs)/len(expected), ndigits)
sum_z_diff = round(sum(list_z_diffs)/len(expected), ndigits)
sum_teta_diff = round(sum(list_teta_diffs)/len(expected), ndigits)
sum_radius_diff = round(sum(list_radius_diffs)/len(expected), ndigits)
sum_xmoy_diff = round(sum(list_xmoy_diffs)/len(expected), ndigits)
sum_ymoy_diffs = round(sum(list_ymoy_diffs)/len(expected), ndigits)
print()
print("Analyse données brutes :")
print(f"diff moyenne de x : {sum_x_diff}")
print(f"diff moyenne de y : {sum_y_diff}")
print(f"diff moyenne de z : {sum_z_diff}")
print(f"diff moyenne de t : {sum_teta_diff}")
print(f"diff moyenne de r : {sum_radius_diff}")
print(f"diff moyenne de xmoy : {sum_xmoy_diff}")
print(f"diff moyenne de ymoy : {sum_ymoy_diffs}")
print(
f"diff gloabale des fichiers : {(sum_x_diff+sum_y_diff+sum_z_diff+sum_teta_diff+sum_radius_diff+sum_xmoy_diff+sum_ymoy_diffs)/7}")
print(f"Voir {output_file} pour plus de détails")
print(f"Voir {minimal_output_file} pour les différences significatives")
print("_"*80)
return {"x": list_x_diffs,
"y": list_y_diffs,
"z": list_z_diffs,
"teta": list_teta_diffs,
"radius": list_radius_diffs,
"xmoy": list_xmoy_diffs,
"ymoy": list_ymoy_diffs}
def check_consistency(obj: ScannedObject, discretised_file_path: str):
"""
This function takes a obj file, and checks if the discretised result file
respect what should be the correct discritisation
:param obj: The object to check
:param discretised_file_path: The discetised file output
"""
obj.export_xyz("verification.txt")
mean_list = []
moyx, moyy, moyz = parse_result_file(discretised_file_path)
moy = moyy
verticies = obj.get_vertices(sort=True)
position = 0
while position < len(verticies) and len(moy) > 0:
xi_value = verticies[position][0]
yi_value = verticies[position][1]
zi_value = verticies[position][2]
mean_list.append(yi_value)
mean = np.mean(mean_list)
print(f"searching for {moy[0]}, currently at {position}", end="\r")
if abs(mean - moy[0]) < 0.000001:
moy.pop(0)
mean_list = []
copyposition = position
if int(verticies[copyposition][2]) >= int(verticies[copyposition+1][2]):
while int(verticies[copyposition][2]) == int(verticies[copyposition-1][2]):
copyposition -= 1
# Position +1 pour l'allignement des indices avec le numero de ligne
# Position - copyposition + 1 car on se deplace seulement si, la condition est fasse aka, on bouge pas si on est aussi de la ou on doit etre
print("line position :", position+1, "|should have stoped :", position - copyposition + 1,
"position higher| Z difference :", verticies[position][2] - verticies[copyposition-1][2])
position += 1
def test_get_raw_data(obj: ScannedObject, expected_file: str, ndigits: int = 6, eps: float = 0.0001):
"""
Test the get_raw_data function, mesure how long it takes to run it then
checks if the values match with the exepected values
:param obj: the object to calculate the data from
:param expected_file: reference output to check data against
:param ndigits: The number of digits to keep after the comma
:param eps: the degree of precision we consider two values different
"""
# Calculate raw data and save it in a file
now = time.time()
data = get_raw_data(obj, ndigits)
print()
print("Time to calculate raw data: ", time.time() - now)
output.save_output_file('tmp_analyse_brute.txt', output.format_data(data, '\t', [
"X (en mm)", "Y (en mm)", "Z (en mm)", "teta (en rad)", "rayon (en mm)", "Xi-Xmoy", "Yi-Ymoy"]))
check_raw_data(expected_file, 'tmp_analyse_brute.txt', ndigits, eps)
os.remove('tmp_analyse_brute.txt')
def test_get_discrete_data(obj: ScannedObject, expected_file: str, ndigits: int = 6, eps: float = 0.0001):
"""
Test the get_discrete_data function mesure how long it takes to run it then
checks if the values match with the exepected values
:param obj: the object to calculate the data from
:param expected_file: reference output to check data against
:param ndigits: The number of digits to keep after the comma
:param eps: the degree of precision we consider two values different
"""
# Calculate discrete data and save it in a file
now = time.time()
data = get_discrete_data(obj, ndigits)
print()
print("Time to calculate discrete data: ", time.time() - now)
output.save_output_file('tmp_analyse_discrete.txt', output.format_data(data, '\t', [
"X moy (en mm)", "Y moy (en mm)", "Z moy (en mm)", "Rayon moyen (en mm)", "Rayon ecart type (en mm)"]))
check_discrete_data(
expected_file, 'tmp_analyse_discrete.txt', ndigits, eps)
os.remove('tmp_analyse_discrete.txt')