scilens 0.3.0__py3-none-any.whl → 0.3.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  _C='amplitude'
2
2
  _B=False
3
3
  _A=None
4
- from scilens.components.compare_models import SEVERITY_ERROR,SEVERITY_WARNING,CompareFloatsErr,Compare2ValuesResults
4
+ from scilens.components.compare_models import SEVERITY_ERROR,SEVERITY_WARNING,CompareGroup,CompareFloatsErr,Compare2ValuesResults
5
5
  from scilens.components.compare_errors import CompareErrors
6
6
  from scilens.config.models import CompareFloatThresholdsConfig
7
7
  try:from scilens_compare import vectors as CheckVectors
@@ -21,10 +21,10 @@ class CompareFloats:
21
21
  if err<thr.absolute_error_max:
22
22
  if err>thr.absolute_error_min:return Compare2ValuesResults(SEVERITY_WARNING,f"Abs. err. > {thr.absolute_error_min} and < {thr.absolute_error_max}",comp_err)
23
23
  else:return Compare2ValuesResults(SEVERITY_ERROR,f"Abs. err. > {thr.absolute_error_max}",comp_err)
24
- def compare_vectors(self,test_vector,reference_vector,group_id,info_vector=_A):
25
- B='ignore';A='RIAE_trapezoid';group=self.compare_errors.groups[group_id]
24
+ def compare_vectors(self,test_vector,reference_vector,group,info_vector=_A):
25
+ B='ignore';A='RIAE_trapezoid'
26
26
  if len(test_vector)!=len(reference_vector):raise Exception('Vectors have different lengths')
27
- diffs_count=0;err_limit_reached=_B;ponderation_method=self.thresholds.vectors.ponderation_method
27
+ diffs_count=0;err_limit_reached=_B;ponderation_method=self.thresholds.vectors.ponderation_method if self.thresholds.vectors else _A
28
28
  if ponderation_method=='RIAE':ponderation_method=A
29
29
  amplitude_compare=_A
30
30
  if self.thresholds.vectors and ponderation_method=='amplitude_moderation':amplitude=vector_get_amplitude(test_vector)[_C];amplitude_compare=amplitude*self.thresholds.vectors.amplitude_moderation_multiplier;reduction_method=self.thresholds.vectors.reduction_method
@@ -54,8 +54,9 @@ class CompareFloats:
54
54
  if info_vector:info['info']=info_vector[idx]
55
55
  err_limit_reached=self.compare_errors.add(group,res_compare,info=info)
56
56
  return err_limit_reached,diffs_count
57
- def compare_matrices(self,test_mat,ref_mat,group_id,x_vector=_A,y_vector=_A):
58
- group=self.compare_errors.groups[group_id];info={};diffs_count=0;err_limit_reached=_B;test_nb_lines=len(test_mat);test_nb_columns=len(test_mat[0])if test_nb_lines>0 else 0;ref_nb_lines=len(ref_mat);ref_nb_columns=len(ref_mat[0])if ref_nb_lines>0 else 0
57
+ def add_group_and_compare_vectors(self,group_name,parent_group,group_data,test_vector,reference_vector,info_vector=_A):_,group=self.compare_errors.add_group('vectors',group_name,parent=parent_group,data=group_data);return(group,)+self.compare_vectors(test_vector,reference_vector,group,info_vector=info_vector)
58
+ def compare_matrices(self,test_mat,ref_mat,group,x_vector=_A,y_vector=_A):
59
+ diffs_count=0;err_limit_reached=_B;test_nb_lines=len(test_mat);test_nb_columns=len(test_mat[0])if test_nb_lines>0 else 0;ref_nb_lines=len(ref_mat);ref_nb_columns=len(ref_mat[0])if ref_nb_lines>0 else 0
59
60
  if test_nb_lines!=ref_nb_lines or test_nb_columns!=ref_nb_columns:raise Exception('Matrices have different dimensions')
60
61
  for i in range(test_nb_lines):
61
62
  for j in range(test_nb_columns):
@@ -69,4 +70,5 @@ class CompareFloats:
69
70
  if x_vector:info['x']=x_vector[j]
70
71
  if y_vector:info['y']=y_vector[i]
71
72
  err_limit_reached=self.compare_errors.add(group,res_compare,info=info)
72
- return err_limit_reached,diffs_count
73
+ return err_limit_reached,diffs_count
74
+ def add_group_and_compare_matrices(self,group_name,parent_group,group_data,test_mat,ref_mat,x_vector=_A,y_vector=_A):_,group=self.compare_errors.add_group('matrix',group_name,parent=parent_group,data=group_data);return(group,)+self.compare_matrices(test_mat,ref_mat,group,x_vector=x_vector,y_vector=y_vector)
@@ -5,25 +5,31 @@ from scilens.utils.web import Web
5
5
  def unzip_file(zip_file_path,extract_to_path):
6
6
  with zipfile.ZipFile(zip_file_path,'r')as A:A.extractall(extract_to_path)
7
7
  def find_command(command_path,working_dirs,guess_os_extension=False):
8
- F='.bash';E='.sh';A=[]
8
+ J='.bash';I='.sh';G=working_dirs;A=command_path;H=os.path.isabs(A);C=[]
9
9
  if guess_os_extension:
10
- B=platform.system().lower()
11
- if B=='windows':A=['.exe','.bat','.cmd']
12
- elif B=='linux':A=[E,F,'.bin']
13
- elif B=='darwin':A=[E,F]
14
- else:logging.warning(f"Unknown system {B}")
15
- for G in working_dirs:
16
- C=os.path.join(G,command_path)
17
- if os.path.exists(C):return C
10
+ D=platform.system().lower()
11
+ if D=='windows':C=['.exe','.bat','.cmd']
12
+ elif D=='linux':C=[I,J,'.bin']
13
+ elif D=='darwin':C=[I,J]
14
+ else:logging.warning(f"Unknown system {D}")
15
+ if H:
16
+ if os.path.exists(A):return A
17
+ else:
18
+ for E in G:
19
+ B=os.path.join(E,A)
20
+ if os.path.exists(B):return B
21
+ for K in C:
22
+ F=A+K
23
+ if H:
24
+ if os.path.exists(F):return F
18
25
  else:
19
- for H in A:
20
- D=C+H
21
- if os.path.exists(D):return D
26
+ for E in G:
27
+ B=os.path.join(E,F)
28
+ if os.path.exists(B):return B
22
29
  class Executor:
23
30
  def __init__(A,absolute_working_dir,config,alternative_working_dir=None):
24
- B=config;A.working_dir=absolute_working_dir;A.config=B;A.alternative_working_dir=alternative_working_dir;A.command_path=None;A.temp_dir=None
25
- if B.exe_url and B.exe_path:raise ValueError('Executable URL and Path are defined. Only one can be defined.')
26
- if not B.exe_url and not B.exe_path:raise ValueError('Executable URL and Path are not defined. One must be defined.')
31
+ D=alternative_working_dir;C=absolute_working_dir;B=config;A.config=B;A.working_dir=C;A.dirs=[C]+([D]if D else[]);A.command_path=None;A.temp_dir=None
32
+ if not bool(B.exe_url)+bool(B.exe_url)!=1:raise Exception('exe_url and exe_path are mutually exclusive.')
27
33
  if not os.path.exists(A.working_dir):logging.info(f"Creating working directory {A.working_dir}");dir_create(A.working_dir)
28
34
  def __enter__(A):return A
29
35
  def __exit__(A,exc_type,exc_value,traceback):A._cleanup()
@@ -33,26 +39,20 @@ class Executor:
33
39
  for dir in A.config.pre_folder_delete or[]:dir_remove(os.path.join(A.working_dir,dir))
34
40
  logging.info(f"Folders creation")
35
41
  for dir in A.config.pre_folder_creation or[]:dir_create(os.path.join(A.working_dir,dir))
36
- if A.config.exe_url:logging.info(f"Download executable {A.config.exe_url}");A.temp_dir=tempfile.mkdtemp();E='executable';B=os.path.join(A.temp_dir,E);Web().download_progress(A.config.exe_url,B,headers=A.config.exe_url_headers,callback100=lambda percentage:logging.info(f"Downloaded {percentage}%"));logging.info(f"Download completed")
37
- else:B=A.config.exe_path
38
- if A.config.exe_unzip_and_use:logging.info(f"Unzip archive");C=os.path.dirname(B);unzip_file(B,C);B=os.path.join(C,A.config.exe_unzip_and_use);print(f"executable_path {B}");logging.info(f"Unzip completed")
39
- if not os.path.exists(B):
40
- if not A.config.exe_guess_os_extension:raise FileNotFoundError(f"Command not found: {B}")
41
- else:
42
- logging.info(f"Guess OS extension");D=[A.working_dir]
43
- if A.alternative_working_dir:D.append(A.alternative_working_dir)
44
- B=find_command(B,D,guess_os_extension=True)
45
- if not B:raise FileNotFoundError(f"Command not found: {B}")
46
- logging.info(f"Add executable permissions");F=os.stat(B).st_mode;os.chmod(B,F|stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH);A.command_path=B
42
+ if A.config.exe_url or A.config.exe_path:
43
+ logging.info(f"Executable file preparation")
44
+ if A.config.exe_url:
45
+ logging.info(f"Download executable {A.config.exe_url}");A.temp_dir=tempfile.mkdtemp();E='executable';B=os.path.join(A.temp_dir,E)
46
+ try:Web().download_progress(A.config.exe_url,B,headers=A.config.exe_url_headers,callback100=lambda percentage:logging.info(f"Downloaded {percentage}%"))
47
+ except Exception as F:raise ValueError(f"Error downloading executable: {F}")
48
+ logging.info(f"Download completed")
49
+ elif A.config.exe_path:B=A.config.exe_path
50
+ if A.config.exe_unzip_and_use:logging.info(f"Unzip archive");D=os.path.dirname(B);unzip_file(B,D);B=os.path.join(D,A.config.exe_unzip_and_use);logging.info(f"Unzip completed")
51
+ C=find_command(B,A.dirs,guess_os_extension=A.config.exe_guess_os_extension)
52
+ if not C:raise FileNotFoundError(f"Command not found: {B}")
53
+ logging.info(f"Command path resolved: {C}");logging.info(f"Add executable permissions");G=os.stat(C).st_mode;os.chmod(C,G|stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH)
54
+ elif A.config.exe_command:logging.info(f"Command path: {A.config.exe_command}");C=A.config.exe_command
55
+ A.command_path=C
47
56
  def _post_operations(A):logging.info(f"Execute - Post Operations")
48
- def _run_command(A):
49
- logging.info(f"Execute - Run Command");C=A.command_path;B=C
50
- if os.path.isabs(B):
51
- if not os.path.exists(B):raise FileNotFoundError(f"Command not found: {B}")
52
- else:
53
- D=[A.working_dir]
54
- if A.alternative_working_dir:D.append(A.alternative_working_dir)
55
- B=find_command(C,D,guess_os_extension=A.config.exe_guess_os_extension)
56
- if not B:raise FileNotFoundError(f"Command not found: {C}")
57
- E=f"{B}{A.config.command_suffix or''}";logging.info(f"RUN COMMAND {E} in {A.working_dir}");subprocess.run(E,shell=True,check=True,cwd=A.working_dir)
57
+ def _run_command(A):logging.info(f"Execute - Run Command");C=A.command_path;B=f"{C}{A.config.command_suffix or''}";logging.info(f"RUN COMMAND {B} in {A.working_dir}");subprocess.run(B,shell=True,check=True,cwd=A.working_dir)
58
58
  def process(A):logging.info(f"Execute");A._pre_operations();A._run_command();A._post_operations();A._cleanup()
@@ -1,4 +1,3 @@
1
- _B="Url de l'exécutable à télécharger avant de l'exécuter. Ex : `https://github.com/org/app/releases/download/v3.31.5/app-2.12.2-linux-x86-64`."
2
1
  _A=None
3
2
  from pydantic import BaseModel,Field
4
- class ExecuteConfig(BaseModel):pre_folder_delete:list[str]|_A=Field(default=_A,description='Liste de répertoire à supprimer avant l\'éxecution. Ex: `["DEBUG", "LOG", "OUT"]`');pre_folder_creation:list[str]|_A=Field(default=_A,description='Liste de répertoire à créeravant l\'éxecution. Ex : `["INI", "DAT"]`');exe_path:str|_A=Field(default=_A,description="Chemin de l'exécutable. Ex : `/absolute/path/executable` or `relative/path/executable`. Dans le cas, d'un chemin relatif, il testera le `working directory` et le `origin working directory`.");exe_url:str|_A=Field(default=_A,description=_B);exe_url_headers:dict[str,str]|_A=Field(default=_A,description=_B);exe_unzip_and_use:str|_A=Field(default=_A,description="Si l'exécutable (path ou url) est zippé, alors décompresse et utilise le fichier spécifié. Ex : `app-2.12.2-linux-x86-64`");exe_guess_os_extension:bool=Field(default=False,description="Si la commande à exécuter n'est pas trouvée, cherche avec des extensions en fonction de l'OS. Ex : `.exe`, `.bat` pour windows");command_suffix:str|_A=Field(default=_A,description='Suffixe à ajouter à la commande. Typiquemnt des secrets. Ex : ` --token DGDFGDFGDH`');working_dir:str|_A=Field(default=_A,description="Chemin relatif du répertoire de travail pour l'éxecution de la commande. Dans le contexte processeur `ExecuteAndCompare` si non défini, récupère respectivement la valeur de `compare.sources.test_folder_relative_path` ou `compare.sources.reference_folder_relative_path`")
3
+ class ExecuteConfig(BaseModel):pre_folder_delete:list[str]|_A=Field(default=_A,description='Liste de répertoire à supprimer avant l\'éxecution. Ex: `["DEBUG", "LOG", "OUT"]`');pre_folder_creation:list[str]|_A=Field(default=_A,description='Liste de répertoire à créeravant l\'éxecution. Ex : `["INI", "DAT"]`');exe_path:str|_A=Field(default=_A,description="Chemin de l'exécutable. Ex : `/absolute/path/executable` or `relative/path/executable`. Dans le cas, d'un chemin relatif, il testera le `working directory` et le `origin working directory` (exclusif avec `exe_url` et `exe_command`).");exe_url:str|_A=Field(default=_A,description="Url de l'exécutable à télécharger avant de l'exécuter. Ex : `https://github.com/org/app/releases/download/v3.31.5/app-2.12.2-linux-x86-64` (exclusif avec `exe_path` et `exe_command`).");exe_command:str|_A=Field(default=_A,description='Commande à exécuter sans résolution de chemin. Ex : `./app-2.12.2-linux-x86-64` ou `python3 app.py` (exclusif avec `exe_path` et `exe_url`).');exe_url_headers:dict[str,str]|_A=Field(default=_A,description='Si `exe_url` les en-têtes à ajouter à la requête de téléchargement de l\'exécutable. Ex : `{"Authorization": "Bearer token"}`');exe_unzip_and_use:str|_A=Field(default=_A,description="Si l'exécutable (`exe_path` ou `exe_url`) est zippé, alors décompresse et utilise le fichier spécifié. Ex : `app-2.12.2-linux-x86-64`");exe_guess_os_extension:bool=Field(default=False,description="Si l'exécutable (`exe_path` ou `exe_url`) n'est pas trouvée, cherche avec des extensions en fonction de l'OS. Ex : `.exe`, `.bat` pour windows");command_suffix:str|_A=Field(default=_A,description='Suffixe à ajouter à la commande. Typiquemnt des secrets. Ex : ` --token DGDFGDFGDH`');working_dir:str|_A=Field(default=_A,description="Chemin relatif du répertoire de travail pour l'éxecution de la commande. Dans le contexte processeur `ExecuteAndCompare` si non défini, récupère respectivement la valeur de `compare.sources.test_folder_relative_path` ou `compare.sources.reference_folder_relative_path`")
@@ -3,4 +3,4 @@ from pydantic import BaseModel,Field
3
3
  class ReportParameterPageModeConfig(BaseModel):is_user_preference:bool=Field(default=True,description=_A);default_value:str=Field(default='onepage',description='`tabs` ou `onepage`')
4
4
  class ReportParameterOpenFileInConfig(BaseModel):is_user_preference:bool=Field(default=True,description=_A);default_value:str=Field(default='browser',description='`browser` ou `vscode`')
5
5
  class ReportHtmlCurvesConfig(BaseModel):display_on_load:bool=Field(default=False,description="Si `true`, affiche tous les graphiques courbes à l'ouverture du rapport.");init_width:int=Field(default=600,description='Largeur initiale des graphiques courbes.');init_height:int=Field(default=400,description='Hauteur initiale des graphiques courbes.')
6
- class ReportHtmlConfig(BaseModel):compare_color_test:str=Field(default='1982c4',description='Couleur pour les données de test.');compare_color_reference:str=Field(default='6a4c93',description='Couleur pour les données de référence.');collapse_if_successful:bool=Field(default=True,description="N'affiche par défaut les sections de comparaison sans erreur.");parameter_page_mode:ReportParameterPageModeConfig=ReportParameterPageModeConfig();parameter_open_file_in:ReportParameterOpenFileInConfig=ReportParameterOpenFileInConfig();curves:ReportHtmlCurvesConfig=ReportHtmlCurvesConfig()
6
+ class ReportHtmlConfig(BaseModel):logo_height:int=Field(default=40,description='Hauteur du logo dans le titre.');compare_color_test:str=Field(default='1982c4',description='Couleur pour les données de test.');compare_color_reference:str=Field(default='6a4c93',description='Couleur pour les données de référence.');collapse_if_successful:bool=Field(default=True,description="N'affiche par défaut les sections de comparaison sans erreur.");parameter_page_mode:ReportParameterPageModeConfig=ReportParameterPageModeConfig();parameter_open_file_in:ReportParameterOpenFileInConfig=ReportParameterOpenFileInConfig();curves:ReportHtmlCurvesConfig=ReportHtmlCurvesConfig()
@@ -6,12 +6,12 @@ from scilens.components.executor import Executor
6
6
  from scilens.components.compare_folders import CompareFolders
7
7
  class ExecuteAndCompare:
8
8
  def __init__(A,context):B=context;A.context=B;A.compare_folders=CompareFolders(B)
9
- def process(D):
10
- L='error';J='dir';I='label';B='config';H=ProcessorResults();E=D.context.config.execute;F=D.context.config.execute_and_compare;M=os.path.join(D.context.working_dir,F.test.working_dir)if F.test.working_dir else D.compare_folders.test_base;N=os.path.join(D.context.working_dir,F.reference.working_dir)if F.reference.working_dir else D.compare_folders.ref_base;G=[{I:'test',J:M,B:F.test}]
9
+ def process(E):
10
+ L='error';J='dir';I='label';B='config';H=ProcessorResults();D=E.context.config.execute;F=E.context.config.execute_and_compare;M=os.path.join(E.context.working_dir,F.test.working_dir)if F.test.working_dir else E.compare_folders.test_base;N=os.path.join(E.context.working_dir,F.reference.working_dir)if F.reference.working_dir else E.compare_folders.ref_base;G=[{I:'test',J:M,B:F.test}]
11
11
  if not F.test_only:G.append({I:'reference',J:N,B:F.reference})
12
12
  for A in G:
13
- if not A[B]:C=E
14
- else:C=ExecuteConfig();C.pre_folder_delete=A[B].pre_folder_delete or E.pre_folder_delete;C.pre_folder_creation=A[B].pre_folder_creation or E.pre_folder_creation;C.exe_path=A[B].exe_path or E.exe_path;C.exe_url=A[B].exe_url or E.exe_url;C.exe_url_headers=A[B].exe_url_headers or E.exe_url_headers;C.exe_unzip_and_use=A[B].exe_unzip_and_use or E.exe_unzip_and_use;C.exe_guess_os_extension=A[B].exe_guess_os_extension or E.exe_guess_os_extension;C.command_suffix=A[B].command_suffix or E.command_suffix
13
+ if not A[B]:C=D
14
+ else:C=ExecuteConfig();C.pre_folder_delete=A[B].pre_folder_delete or D.pre_folder_delete;C.pre_folder_creation=A[B].pre_folder_creation or D.pre_folder_creation;C.exe_path=A[B].exe_path or D.exe_path;C.exe_url=A[B].exe_url or D.exe_url;C.exe_command=A[B].exe_command or D.exe_command;C.exe_url_headers=A[B].exe_url_headers or D.exe_url_headers;C.exe_unzip_and_use=A[B].exe_unzip_and_use or D.exe_unzip_and_use;C.exe_guess_os_extension=A[B].exe_guess_os_extension or D.exe_guess_os_extension;C.command_suffix=A[B].command_suffix or D.command_suffix
15
15
  logging.info(f"Execute {A[I]} Command")
16
- with Executor(A[J],C,alternative_working_dir=D.context.origin_working_dir)as O:O.process()
17
- G=D.compare_folders.compute_list_filenames();logging.info(f"Number files to compare: {len(G)}");K=D.compare_folders.compute_comparison(G);H.warnings=[A[L]for A in K if A.get(L)];H.data=K;return H
16
+ with Executor(A[J],C,alternative_working_dir=E.context.origin_working_dir)as O:O.process()
17
+ G=E.compare_folders.compute_list_filenames();logging.info(f"Number files to compare: {len(G)}");K=E.compare_folders.compute_comparison(G);H.warnings=[A[L]for A in K if A.get(L)];H.data=K;return H
@@ -26,22 +26,22 @@ def cols_dataset_get_curves_col_x(cols_dataset,col_x):
26
26
  for D in J:B=A.data[C];K=A.data[D];L={I:A.names[D],'short_title':A.names[D],'series':[[B[A],K[A]]for A in range(A.rows_count)],_C:D};F+=[L];M={I:A.names[D],'type':'simple','xaxis':A.names[C],'yaxis':A.names[D],_B:[len(F)-1]};H+=[M]
27
27
  return{_B:F,_E:H},E
28
28
  def compare(group,compare_floats,reader_test,reader_ref,cols_curve):
29
- L=compare_floats;K='Errors limit reached';G=reader_ref;E=group;C=cols_curve;A=reader_test;logging.debug(f"compare cols: {E.name}")
30
- if len(A.numeric_col_indexes)!=len(G.numeric_col_indexes):E.error=f"Number Float columns indexes are different: {len(A.numeric_col_indexes)} != {len(G.numeric_col_indexes)}";return
31
- D=[''for A in range(A.cols_count)];M=_A;H=_A
32
- if C and C.type==ReaderCurveParserNameConfig.COL_X:N=C.info[_D];M=A.data[N];H=A.names[N]
33
- I=False
29
+ J='Errors limit reached';F=reader_ref;E=group;C=cols_curve;A=reader_test;logging.debug(f"compare cols: {E.name}")
30
+ if len(A.numeric_col_indexes)!=len(F.numeric_col_indexes):E.error=f"Number Float columns indexes are different: {len(A.numeric_col_indexes)} != {len(F.numeric_col_indexes)}";return
31
+ D=[''for A in range(A.cols_count)];K=_A;G=_A
32
+ if C and C.type==ReaderCurveParserNameConfig.COL_X:L=C.info[_D];K=A.data[L];G=A.names[L]
33
+ H=False
34
34
  for B in range(A.cols_count):
35
35
  if B not in A.numeric_col_indexes:continue
36
- if I:D[B]=K;continue
37
- Q=A.data[B];R=G.data[B];U,F=L.compare_errors.add_group('vectors',A.names[B],parent=E,data={'info_prefix':H}if H else _A);logging.debug(f"compare cols: {F.name}");S,V=L.compare_vectors(Q,R,group_id=F.id,info_vector=M)
38
- if S:I=True;D[B]=K;continue
39
- if F.total_errors>0:D[B]=f"{F.total_errors} comparison errors"
36
+ if H:D[B]=J;continue
37
+ P=A.data[B];Q=F.data[B];logging.debug(f"compare cols: {A.names[B]}");M,R,T=compare_floats.add_group_and_compare_vectors(A.names[B],E,{'info_prefix':G}if G else _A,P,Q,info_vector=K)
38
+ if R:H=True;D[B]=J;continue
39
+ if M.total_errors>0:D[B]=f"{M.total_errors} comparison errors"
40
40
  if C:
41
- for O in C.curves[_E]:
42
- P=0
43
- for T in O[_B]:
44
- J=C.curves[_B][T]
45
- if D[J[_C]]:J['comparison_error']=D[J[_C]];P+=1
46
- O['comparison']={'curves_nb_with_error':P}
47
- E.error=K if I else _A;E.info={'cols_has_error':D}
41
+ for N in C.curves[_E]:
42
+ O=0
43
+ for S in N[_B]:
44
+ I=C.curves[_B][S]
45
+ if D[I[_C]]:I['comparison_error']=D[I[_C]];O+=1
46
+ N['comparison']={'curves_nb_with_error':O}
47
+ E.error=J if H else _A;E.info={'cols_has_error':D}
@@ -19,4 +19,4 @@ def from_reader(reader,x_value_line=_A,has_header=False,has_y=False):
19
19
  else:
20
20
  for C in B:G=[float(A)for A in C];A.append(G)
21
21
  return MatDataset(nb_lines=len(A),nb_columns=len(A[0])if len(A)>0 else 0,data=A,x_values=H,y_values=I)
22
- def compare(parent_group,compare_floats,test,ref,group_name=''):C=compare_floats;B=parent_group;A=test;F,D=C.compare_errors.add_group('matrix',group_name,parent=B);E,G=C.compare_matrices(A.data,ref.data,D.id,x_vector=A.x_values,y_vector=A.y_values);B.error='Errors limit reached'if E else _A
22
+ def compare(parent_group,compare_floats,test,ref,group_name=''):B=parent_group;A=test;D,C,E=compare_floats.add_group_and_compare_matrices(group_name,B,group_data=_A,test_mat=A.data,ref_mat=ref.data,x_vector=A.x_values,y_vector=A.y_values);B.error='Errors limit reached'if C else _A
@@ -8,19 +8,20 @@ from scilens.utils.time_tracker import TimeTracker
8
8
  class HtmlReport:
9
9
  def __init__(A,config,alt_config_dirs,working_dir=None):A.config=config;A.alt_config_dirs=alt_config_dirs;A.working_dir=working_dir
10
10
  def process(A,processor,data,task_name):
11
- G='meta';F='date';logging.info(f"Processing html report");H=TimeTracker();C=H.get_data()['start']
11
+ I='meta';H='date';logging.info(f"Processing html report");J=TimeTracker();B=J.get_data()['start']
12
12
  if A.config.logo and A.config.logo_file:raise ValueError('logo and logo_file are exclusive.')
13
- I=A.config.logo;B=None
13
+ K=A.config.logo;C=None
14
14
  if A.config.logo_file:
15
15
  D=A.config.logo_file
16
- if os.path.isabs(D):B=D
16
+ if os.path.isabs(D):
17
+ C=D
18
+ if not os.path.isfile(E):raise FileNotFoundError(f"Logo file '{A.config.logo_file}' not found.")
17
19
  else:
18
- B=os.path.join(A.working_dir,D)
19
- if not os.path.isfile(B):
20
- for J in A.alt_config_dirs:
21
- B=os.path.join(J,D)
22
- if os.path.isfile(B):break
23
- if not os.path.isfile(B):raise FileNotFoundError(f"Derived Logo file '{A.config.logo_file}' not found.")
24
- K=A.config.title if A.config.title else A.config.title_prefix+' '+task_name;L={'app_name':product_name,'app_version':pkg_version,'app_homepage':pkg_homepage,'app_copyright':f"© {C[F][:4]} {powered_by['name']}. All rights reserved",'app_powered_by':powered_by,'execution_utc_datetime':C['datetime'],'execution_utc_date':C[F],'execution_utc_time':C['time'],'execution_dir':A.working_dir,'title':K,'image':I or get_logo_image_src(B),'config':A.config.html,'config_json':A.config.html.model_dump_json()};E=None
25
- if A.config.debug:E=A.config.model_dump_json(indent=4)
26
- return template_render_infolder('index.html',{G:L,'task':data.get(G),'data':{'files':data.get('processor_results')},'debug':E})
20
+ F=list(set([A.working_dir]+A.alt_config_dirs))
21
+ for L in F:
22
+ E=os.path.join(L,D)
23
+ if os.path.isfile(E):C=E;break
24
+ if not C:raise FileNotFoundError(f"Logo file '{A.config.logo_file}' not found in {F}.")
25
+ M=A.config.title if A.config.title else A.config.title_prefix+' '+task_name;N={'app_name':product_name,'app_version':pkg_version,'app_homepage':pkg_homepage,'app_copyright':f"© {B[H][:4]} {powered_by['name']}. All rights reserved",'app_powered_by':powered_by,'execution_utc_datetime':B['datetime'],'execution_utc_date':B[H],'execution_utc_time':B['time'],'execution_dir':A.working_dir,'title':M,'image':K or get_logo_image_src(C),'config':A.config.html,'config_json':A.config.html.model_dump_json()};G=None
26
+ if A.config.debug:G=A.config.model_dump_json(indent=4)
27
+ return template_render_infolder('index.html',{I:N,'task':data.get(I),'data':{'files':data.get('processor_results')},'debug':G})
@@ -1,6 +1,6 @@
1
1
  <!-- TITLE -->
2
2
  <h1>
3
- {% if meta.image %}<img height="40" src="{{ meta.image }}"/>{% endif %}
3
+ {% if meta.image %}<img height="{{ meta.config.logo_height }}" src="{{ meta.image }}"/>{% endif %}
4
4
  {{ meta.title }}
5
5
  {{ data.name }}
6
6
  </h1>
scilens/utils/web.py CHANGED
@@ -8,13 +8,15 @@ class Web:
8
8
  C=requests.get(url,headers=B);C.raise_for_status()
9
9
  with open(filename,'wb')as D:D.write(C.content)
10
10
  def download_progress(L,url,filename,headers=None,callback100=None):
11
- D=callback100;C=headers;E=BASE_HEADERS.copy()
12
- if C:E.update(C)
13
- F=requests.get(url,headers=E,stream=True);I=int(F.headers.get('Content-Length',0));G=0;J=I//100;A=0
11
+ E=callback100;D=headers;F=BASE_HEADERS.copy()
12
+ if D:F.update(D)
13
+ A=requests.get(url,headers=F,stream=True)
14
+ if A.status_code>299:raise ValueError(f"Error downloading file: {A.status_code} - {A.text}")
15
+ I=int(A.headers.get('Content-Length',0));G=0;J=I//100;B=0
14
16
  with open(filename,'wb')as K:
15
- for B in F.iter_content(chunk_size=1024):
16
- if B:
17
- K.write(B);G+=len(B);H=G//J
18
- if H>A:
19
- A=H
20
- if D:D(A)
17
+ for C in A.iter_content(chunk_size=1024):
18
+ if C:
19
+ K.write(C);G+=len(C);H=G//J
20
+ if H>B:
21
+ B=H
22
+ if E:E(B)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: scilens
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: A CesGensLaB framework for data collecting and deep analysis
5
5
  Home-page: https://scilens.dev
6
6
  License: Proprietary
@@ -10,10 +10,10 @@ scilens/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF
10
10
  scilens/components/analyse_folder.py,sha256=yqc-dscKaHLZJCYeXGak2v0c3F2aeX0E11AFPfya6r0,208
11
11
  scilens/components/compare_2_files.py,sha256=U4xumE28ijFbnrTPH8FgRyR_b5f04jOjaCmegJvCvSE,1483
12
12
  scilens/components/compare_errors.py,sha256=Kw_zpVmA3Fb7yVDXog2poLaTsV_K81eLqv-z-b73Nlw,1495
13
- scilens/components/compare_floats.py,sha256=GF4kKvkSKqCLLrx-BnmGi7yWTEBkYZjlCim7B9NBWxc,5028
13
+ scilens/components/compare_floats.py,sha256=zMrFmlGr97kfRUrw2A9cJiO9I-RIoQMgaWRZwNEJQ0k,5598
14
14
  scilens/components/compare_folders.py,sha256=LZ1AuYxLVHMNbtXWXQrdms4vZgOQthvDy-8NFD_EFjc,2617
15
15
  scilens/components/compare_models.py,sha256=SCPd747h_nd4ewZsqLB6CFr27v6q99NELJb-gpkdj0o,918
16
- scilens/components/executor.py,sha256=8ZZq9wwoiMr7ys9LXv1pEg5Zc06QatT9PGIigMsDAB8,3620
16
+ scilens/components/executor.py,sha256=j5xejkCaaPyl3V38Q4HxxXcAx4Tnj8CILAjSJ1G7OIE,3417
17
17
  scilens/components/file_reader.py,sha256=7SbKCqb4Co_pqAKX3wweYhqAcVkU7BDlT903sLd76Kc,1407
18
18
  scilens/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  scilens/config/cli_run_options.py,sha256=Ls7yK5QDUPFbk73nbjGuPvuRbBRYw4Miag5ISpu3prg,281
@@ -23,7 +23,7 @@ scilens/config/models/__init__.py,sha256=eLCW1OLVINewGFy5GXSrOk8Rab_QsgKAuoErBjp
23
23
  scilens/config/models/app.py,sha256=JltWRjjqXYkH6rg3OHYhMfkBqHFhZEZdthqES3LxvzY,1453
24
24
  scilens/config/models/compare.py,sha256=_SLMxf81fpuod8izZm72Jn12euRPxB0wHJSfUuIANbE,1639
25
25
  scilens/config/models/compare_float_thresholds.py,sha256=J5XBK1dAnmU-i2uA2bsaHnTM_m07_i17wsO8UiCw46o,1844
26
- scilens/config/models/execute.py,sha256=pFY-gZuBvLbcjTEcoNhPPO7FMFmKa6_TU5IXyKaf81A,1706
26
+ scilens/config/models/execute.py,sha256=8issd_hg49SdVkDq2TLDB1vBJY4M1t279XERNUd3VVs,2142
27
27
  scilens/config/models/execute_and_compare.py,sha256=TWL6yXGvQSaaV6nhHqWLvtr3v396APIoDNt0U1TbMro,582
28
28
  scilens/config/models/file_reader.py,sha256=c18vKhVcBX4ufpbnCBJyVyAsQtlxpwx0lGVuf1i8EGA,1176
29
29
  scilens/config/models/reader_format_cols_curve.py,sha256=eKLvifq1xuN8sPds9ijfru3vgMZ3Odv5tGfeiK4Sfk4,1860
@@ -33,7 +33,7 @@ scilens/config/models/reader_format_txt.py,sha256=eHg90gwEI_VpqwqEjMRhwlS8dHcl5G
33
33
  scilens/config/models/reader_format_txt_fixed_cols.py,sha256=xHD1_JOoRZow8lSNaDSYFeNckojctkT4C61mbBcjeKg,1079
34
34
  scilens/config/models/readers.py,sha256=Pq5kOGW3b6g1x5cp_BbwUF7LUB_P3m9bHDYLSTVXNBY,1769
35
35
  scilens/config/models/report.py,sha256=nTmP2nIwL2Ku5IH9QMwYLPKmfsK2ttu9UK0GnzPUHeM,870
36
- scilens/config/models/report_html.py,sha256=9I9iKRDOoLMZRBY0lQV4UFtg5-D-VDfYiFGF1VFAnQ8,1389
36
+ scilens/config/models/report_html.py,sha256=WiUPD38NCmBYHQdYyMb1-713kVNq7dm5pe8chlhuoyM,1468
37
37
  scilens/config/models/report_output.py,sha256=XoqUe-t-y8GRbUR3_bDwwaWf6hif-rZ-5pKDGdCMugw,875
38
38
  scilens/helpers/assets.py,sha256=XphDA3-yE1PPKw4XFZhDrlLQjMZfGMlpOBXa8uy_xX0,1552
39
39
  scilens/helpers/search_and_index.py,sha256=kXZ7124ra_SGAdKUZ7msy55UOWQ9dCSuPuNoU-NdUyM,1522
@@ -42,14 +42,14 @@ scilens/helpers/templates/style.css,sha256=2_IndKW2qtGhuoU9T3Sru4NkHR5CXTTs5_nc9
42
42
  scilens/processors/__init__.py,sha256=x6bmqQVCcdJ7R2oG-_xTVtvl9qRleliEZlZR-Hq9Yc0,105
43
43
  scilens/processors/analyse.py,sha256=hG2jALUqtoEwTPiLxDGV9Nbv6TU_SrfzwV_-1RkuiKw,828
44
44
  scilens/processors/compare.py,sha256=wCdtDC8nJUeG9dolu2B6rTg4-jW0MYllPbvXFBX64nU,529
45
- scilens/processors/execute_and_compare.py,sha256=oUaI8kh8pkR86kGvN2EXtq-tbgphkzKiURcrhjXbnL4,1736
45
+ scilens/processors/execute_and_compare.py,sha256=KX0bVSLzsc2VvxivTksGoLg8612WRjPkFAMWqB0hfYg,1784
46
46
  scilens/processors/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
47
  scilens/processors/models/results.py,sha256=KoWxh13Zgi7PuPql8hkf4VjCis42ZxAuzIgJxBWVaX8,119
48
48
  scilens/processors/processor_interface.py,sha256=jzMp1529JXnMGTJijVy6b_1zmARAMNv70f2lgys7vn4,452
49
49
  scilens/readers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
- scilens/readers/cols_dataset.py,sha256=JIfPBzQZml6VlykbrMcCanR12eEnjY1A-ECgXs8wtZ4,2527
50
+ scilens/readers/cols_dataset.py,sha256=V4tAokAwY9_eVfyH-UINztxzJUcLJRk1CdaZprs8Wfk,2475
51
51
  scilens/readers/exceptions.py,sha256=JzmxcjnR5sH-IOWVeCC5A1bSwxv-jCAtIJvDjzx1CTI,32
52
- scilens/readers/mat_dataset.py,sha256=vUEjAK6nuY7miLJvjSkiHAU64KaNa1VCx7EhGPazp-U,1190
52
+ scilens/readers/mat_dataset.py,sha256=-2NJJxOu8qEMhni-kGT9F-MwDA98_Nrt2cC0TYMUNvw,1180
53
53
  scilens/readers/reader_csv.py,sha256=aPd2IxFiUXYmH_EpNZkCHV1oMWctZW7YSPwC8q75SIo,3490
54
54
  scilens/readers/reader_interface.py,sha256=nnttHL7wt4MOXpi-SBkk8DYxVWscOPG8JFl_z12mIAo,922
55
55
  scilens/readers/reader_manager.py,sha256=DFinxIk3IIIcB6JxybGcv-mXt3jhXgCwUtzR0TqhB2Q,2684
@@ -60,10 +60,10 @@ scilens/report/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
60
  scilens/report/assets/logo.svg,sha256=W-1OVqcvdBjf-1AHHcV6WciIUqBoVFUh52Tc3o_jqtA,4519
61
61
  scilens/report/assets/logo_cglb.svg,sha256=tEpkSr2h-jjQMecqiHef98Mxod4GD5j5nCQaFloTYso,2411
62
62
  scilens/report/assets.py,sha256=CcfGc9NNGnPVinkHZkEyN2S_BGKNIyMFvVdA__-M6-0,532
63
- scilens/report/html_report.py,sha256=PGbaar0UTUsHrH9HxSibLi7lEv6cean0-yKEhmSAKzQ,1845
63
+ scilens/report/html_report.py,sha256=ajNDTfEu06fs2h1SF4nTP1MvZmYwMcLieeSngyuH-qE,1905
64
64
  scilens/report/report.py,sha256=aS7ktJ2u0IAMMk-HwqqSsRkr77ZBQyYT4wXJ7djQvAk,1811
65
65
  scilens/report/template.py,sha256=cPs5gd3uEwb-6JgitGQD_i4IiUxigBTlZLNRS9KVuos,581
66
- scilens/report/templates/body_01_title.html,sha256=59BmETKHqRO1T_xYp0XLKx3Vha9hU9bu7yaUTVt2p9Y,2146
66
+ scilens/report/templates/body_01_title.html,sha256=0mrMM62TSBdPOpPNCcam0bZsZtM0GjoMQ-jrSqI8HCw,2173
67
67
  scilens/report/templates/body_99_footer.html,sha256=8cWebeWfZwZ-9bYAMZkZj8rbCWq3BLIMjKQThWQxoQM,362
68
68
  scilens/report/templates/compare_11_summary.html,sha256=4rxBlOxTcn59ztYtqDbi6SRQXlaz30HkVl7dJpzCmZE,3776
69
69
  scilens/report/templates/compare_12_sections.html,sha256=HWsfCmfdleyRK6IHJeMEheenOuyA0mLzOZ-0qLcuzJU,5952
@@ -96,8 +96,8 @@ scilens/utils/system.py,sha256=drXp_Vdv2dP9wFQoEQZIhxyCJhFliBLFPylGwv89FF4,182
96
96
  scilens/utils/template.py,sha256=9dlXX3nmfzDRUwzPJOkoxk15UXivZ2SW-McdCwokFa4,443
97
97
  scilens/utils/time_tracker.py,sha256=DdVBoMpVLXrX0qZZXyLm4g38EwDVLlRcBqcpNex1mYY,545
98
98
  scilens/utils/vectors.py,sha256=4N2BZSC5n3HgZqPujDGF5NdjVmSL1rOHb_qw4OoABQY,103
99
- scilens/utils/web.py,sha256=E4T8Fra65u9g_BpcFANPk4ORvsYavAeiSgWA3vRca2E,804
100
- scilens-0.3.0.dist-info/METADATA,sha256=zvMTkfew0QXwM9EzvFc4bu1oeo4XZCAo1GonbGZ4LtI,1367
101
- scilens-0.3.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
102
- scilens-0.3.0.dist-info/entry_points.txt,sha256=DaKGgxUEUv34GJAoXtta6ecL37ercejep9sCSSRQK2s,48
103
- scilens-0.3.0.dist-info/RECORD,,
99
+ scilens/utils/web.py,sha256=MAFWpIFOKz7QhqDoFh-Qwstvc76KpcxstSgHFT8FOL4,901
100
+ scilens-0.3.2.dist-info/METADATA,sha256=Ai0hRZvMpFmjtACkOdVl9WPycq1MjI9Ih_s1AbAiqjI,1367
101
+ scilens-0.3.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
102
+ scilens-0.3.2.dist-info/entry_points.txt,sha256=DaKGgxUEUv34GJAoXtta6ecL37ercejep9sCSSRQK2s,48
103
+ scilens-0.3.2.dist-info/RECORD,,