scilens 0.4.2__py3-none-any.whl → 0.4.4__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.
Files changed (37) hide show
  1. scilens/components/compare_2_files.py +34 -21
  2. scilens/components/compare_floats.py +14 -5
  3. scilens/components/compare_models.py +1 -1
  4. scilens/config/models/app.py +1 -1
  5. scilens/config/models/compare.py +3 -2
  6. scilens/config/models/compare_float_thresholds.py +3 -2
  7. scilens/config/models/execute.py +1 -1
  8. scilens/config/models/execute_and_compare.py +1 -1
  9. scilens/config/models/file_reader.py +1 -1
  10. scilens/config/models/reader_format_cols.py +8 -7
  11. scilens/config/models/reader_format_csv.py +3 -2
  12. scilens/config/models/reader_format_netcdf.py +1 -1
  13. scilens/config/models/reader_format_txt.py +6 -3
  14. scilens/config/models/reader_format_txt_fixed_cols.py +1 -1
  15. scilens/config/models/reader_metrics.py +4 -1
  16. scilens/config/models/readers.py +7 -6
  17. scilens/config/models/report.py +1 -1
  18. scilens/config/models/report_html.py +11 -10
  19. scilens/config/models/report_output.py +1 -1
  20. scilens/readers/cols_dataset.py +14 -13
  21. scilens/readers/reader_csv.py +33 -34
  22. scilens/readers/reader_txt.py +38 -21
  23. scilens/report/templates/body_02_tabs.html +2 -2
  24. scilens/report/templates/compare_11_summary.html +5 -69
  25. scilens/report/templates/compare_11_summary_datasets.html +71 -0
  26. scilens/report/templates/compare_11_summary_metrics copy.html +20 -0
  27. scilens/report/templates/compare_11_summary_metrics.html +25 -0
  28. scilens/report/templates/compare_13_section_numbers_table.html +2 -7
  29. scilens/report/templates/html_macros.html +33 -0
  30. scilens/report/templates/html_widget_err.html +5 -0
  31. scilens/report/templates/index.html +1 -0
  32. scilens/report/templates/js_com_page.js +4 -2
  33. scilens/report/templates/style.css +82 -1
  34. {scilens-0.4.2.dist-info → scilens-0.4.4.dist-info}/METADATA +1 -1
  35. {scilens-0.4.2.dist-info → scilens-0.4.4.dist-info}/RECORD +37 -32
  36. {scilens-0.4.2.dist-info → scilens-0.4.4.dist-info}/WHEEL +0 -0
  37. {scilens-0.4.2.dist-info → scilens-0.4.4.dist-info}/entry_points.txt +0 -0
@@ -4,6 +4,7 @@ _D=True
4
4
  _C=False
5
5
  _B='line'
6
6
  _A=None
7
+ import re
7
8
  from scilens.readers.reader_interface import ReaderInterface
8
9
  from scilens.readers.transform import string_2_floats
9
10
  from scilens.config.models import ReaderTxtConfig
@@ -12,35 +13,47 @@ from scilens.components.compare_floats import CompareFloats
12
13
  class ReaderTxt(ReaderInterface):
13
14
  configuration_type_code='txt';category='datalines';extensions=['TXT']
14
15
  def read(A,config):
15
- F='_';B=config;A.reader_options=B;A.get_lines_pre=1;A.get_lines_post=1
16
+ I='_';B=config;A.reader_options=B;A.get_lines_pre=1;A.get_lines_post=1
16
17
  if B.report_lines:
17
18
  C=_C
18
- for(I,G)in B.report_lines.items():
19
- if I==A.origin.short_name:C=_D;A.get_lines_pre=G.pre;A.get_lines_post=G.post
20
- if not C and B.report_lines.get(F):A.get_lines_pre=B.report_lines[F].pre;A.get_lines_post=B.report_lines[F].post
19
+ for(M,J)in B.report_lines.items():
20
+ if M==A.origin.short_name:C=_D;A.get_lines_pre=J.pre;A.get_lines_post=J.post
21
+ if not C and B.report_lines.get(I):A.get_lines_pre=B.report_lines[I].pre;A.get_lines_post=B.report_lines[I].post
21
22
  D=_A
22
23
  if B.ignore:
23
24
  C=_C
24
- for(I,G)in B.ignore.items():
25
- if I==A.origin.short_name:C=_D;D=G
26
- if not C and B.ignore.get(F):D=B.ignore[F]
27
- K=open(A.origin.path,'r',encoding=A.encoding);A.raw_lines=K.readlines();K.close();A.raw_lines_number=len(A.raw_lines);E=[]
25
+ for(M,J)in B.ignore.items():
26
+ if M==A.origin.short_name:C=_D;D=J
27
+ if not C and B.ignore.get(I):D=B.ignore[I]
28
+ P=open(A.origin.path,'r',encoding=A.encoding);A.raw_lines=P.readlines();P.close();A.raw_lines_number=len(A.raw_lines);E=[]
28
29
  if D:
29
- C,O=A.find_patterns_lines_nb([A.pattern for A in D])
30
- for(P,L)in enumerate(D):
31
- H=O[P][_E]
32
- if H:H=A.get_raw_siblings_nb(H,pre=L.pre,post=L.post);E+=H
30
+ C,R=A.find_patterns_lines_nb([A.pattern for A in D])
31
+ for(S,Q)in enumerate(D):
32
+ K=R[S][_E]
33
+ if K:K=A.get_raw_siblings_nb(K,pre=Q.pre,post=Q.post);E+=K
33
34
  E=list(set(E));E.sort()
34
- A.ignore_patterns=[A.pattern for A in D]if D else[];A.ignore_lines=E;A.ignore_lines_number=len(E);A.curves=A.curve_parser(A.raw_lines)if A.curve_parser else _A;J=[]
35
- for(Q,R)in enumerate(A.raw_lines):
36
- M=string_2_floats(R)
37
- if M:
38
- N=Q+1
39
- if not N in E:J.append({_B:N,_F:M})
40
- A.floats_lines=J;A.floats_lines_number=len(J)
35
+ A.ignore_patterns=[A.pattern for A in D]if D else[];A.ignore_lines=E;A.ignore_lines_number=len(E);A.curves=A.curve_parser(A.raw_lines)if A.curve_parser else _A;N=[]
36
+ for(T,L)in enumerate(A.raw_lines):
37
+ G=string_2_floats(L)
38
+ if G:
39
+ H=T+1
40
+ if not H in E:N.append({_B:H,_F:G})
41
+ A.floats_lines=N;A.floats_lines_number=len(N)
41
42
  if B.error_rule_patterns:
42
- C,S=A.find_patterns_lines_nb(B.error_rule_patterns);A.read_data['error_rule_patterns']={'found':C,'data':S}
43
+ C,U=A.find_patterns_lines_nb(B.error_rule_patterns);A.read_data['error_rule_patterns']={'found':C,'data':U}
43
44
  if C:A.read_error='String error pattern found'
45
+ A.metrics=_A
46
+ if B.metrics:
47
+ O={}
48
+ for F in B.metrics:
49
+ L,H=A.find_pattern_first_line(F.pattern)
50
+ if L:
51
+ G=string_2_floats(L)
52
+ if not G:raise ValueError(f"Metric pattern '{F.pattern}' found but no float values in the line number: {H}")
53
+ try:V=G[F.number_position-1]
54
+ except IndexError:raise ValueError(f"Metric pattern '{F.pattern}' found but no float value at position {F.number_position} in the line number: {H}")
55
+ O[F.name or F.pattern]=V
56
+ if O:A.metrics=O
44
57
  def compare(I,compare_floats,param_reader,param_is_ref=_D):
45
58
  U='diff';K=param_is_ref;J=param_reader;A=compare_floats;V,L=A.compare_errors.add_group('node','txt');V,B=A.compare_errors.add_group(_E,_E,parent=L);C=I if K else J;D=I if not K else J;E=_C
46
59
  if C.floats_lines_number!=D.floats_lines_number:L.error=f"Nb number lines 1: {C.floats_lines_number} 2: {D.floats_lines_number} different"
@@ -64,6 +77,10 @@ class ReaderTxt(ReaderInterface):
64
77
  for C in A:
65
78
  if F.find(C)!=-1:map[C].append(E+1);B=_D
66
79
  return B,[{'pattern':A,_E:map[A]}for A in A]
80
+ def find_pattern_first_line(B,pattern):
81
+ for(C,A)in enumerate(B.raw_lines):
82
+ D=re.search(pattern,A)
83
+ if D:return A.strip(),C+1
67
84
  def get_raw_siblings_nb(A,lines_nb_array,pre=_A,post=_A):
68
85
  B=[]
69
86
  for C in lines_nb_array:
@@ -78,4 +95,4 @@ class ReaderTxt(ReaderInterface):
78
95
  if min<0:min=0
79
96
  if max>A.raw_lines_number:max=A.raw_lines_number
80
97
  return''.join([A.raw_lines[B]for B in range(min,max)])
81
- def class_info(A):return{'raw_lines_number':A.raw_lines_number,'ignore_patterns':A.ignore_patterns,'ignore_lines_number':A.ignore_lines_number,'ignore_lines':A.ignore_lines,'floats_lines_number':A.floats_lines_number,'curves':A.curves}
98
+ def class_info(A):return{'raw_lines_number':A.raw_lines_number,'ignore_patterns':A.ignore_patterns,'ignore_lines_number':A.ignore_lines_number,'ignore_lines':A.ignore_lines,'floats_lines_number':A.floats_lines_number,'curves':A.curves,'metrics':A.metrics}
@@ -1,8 +1,8 @@
1
1
  <div id="tabs" class="tabs noselect" style="display: none;">
2
- <div class="tab active" onclick="actions.click_tab(event, 0)">Summary</div>
2
+ <div class="tab active" data-tab-index="0" onclick="actions.click_tab(event, 0)">Summary</div>
3
3
  {% for file in data.files %}
4
4
  {% if not file.skipped %}
5
- <div class="tab {{ ns.statuses[loop.index] }}" onclick="actions.click_tab(event, {{ loop.index }})"><span class="">{{ file.name }}</span></div>
5
+ <div class="tab {{ ns.statuses[loop.index] }}" data-tab-index="{{ loop.index }}" onclick="actions.click_tab(event, {{ loop.index }})"><span class="">{{ file.name }}</span></div>
6
6
  {% endif %}
7
7
  {% endfor %}
8
8
  <div class="tabend"></div>
@@ -13,77 +13,11 @@
13
13
  <!-- EXTRA HTML -->
14
14
  {% if meta.config.extra_html_summary %}{{ meta.config.extra_html_summary }}{% endif %}
15
15
 
16
+ <!-- METRICS -->
17
+ {% include 'compare_11_summary_metrics.html' %}
16
18
  <!-- DATASETS -->
17
- <h3>
18
- Datasets <action data-command="toogle" data-args="section_summary_datasets"></action>
19
- </h3>
19
+ {% include 'compare_11_summary_datasets.html' %}
20
20
 
21
- <div id="section_summary_datasets">
22
- <table class="shadow-lg">
23
- <tr>
24
- <th class="p-2" rowspan="2">#</th>
25
- <th class="p-2" rowspan="2">Status</th>
26
- <th class="p-2" rowspan="2">Name</th>
27
- <th class="p-2" rowspan="2">Details</th>
28
- <th class="p-2" rowspan="2" class="test-bg-50">Open test</th>
29
- <th class="p-2" rowspan="2" class="refe-bg-50">Open Ref</th>
30
- <th class="p-2" rowspan="2">Error</th>
31
- <th class="p-2" colspan="3" >&nbsp;&nbsp;Comparison&nbsp;&nbsp;</th>
32
- <th class="p-2" colspan="2">Nb Lines - Raw&nbsp;&nbsp;&nbsp;</th>
33
- <th class="p-2" colspan="2">Nb Lines - Ignore</th>
34
- <th class="p-2" colspan="2">Nb Lines - Number</th>
35
- <th class="p-2" rowspan="2">Reader</th>
36
- </tr>
37
- <tr>
38
- <th class="p-2" >Err.</th>
39
- <th class="p-2" >Warn.</th>
40
- <th class="p-2" >Diff.</th>
41
- <th class="p-2 test-bg-50">Test</th>
42
- <th class="p-2 refe-bg-50">Ref.</th>
43
- <th class="p-2 test-bg-50">Test</th>
44
- <th class="p-2 refe-bg-50">Ref.</th>
45
- <th class="p-2 test-bg-50">Test</th>
46
- <th class="p-2 refe-bg-50">Ref.</th>
47
- </tr>
48
- {% for file in data.files %}
49
- <tr>
50
- <td>{{ loop.index }}</td>
51
- <td class="{{ ns.statuses[loop.index] }}">{{ ns.statuses[loop.index] }}</td>
52
- <td>{{ file.name }}</td>
53
- <td class="center">{% if not file.skipped %}<button onclick="actions.see_details({{ loop.index }})">[...]</button>{% endif %}</td>
54
- <td class="center test-bg-20">
55
- {% if file.test.origin and file.test.origin.path %}<action data-command="open_file" data-args="{{ file.test.origin.path.replace(meta.execution_dir, "") }}" data-label="[...]"></action>{% endif %}
56
- </td>
57
- <td class="center refe-bg-20">
58
- {% if file.ref.origin and file.ref.origin.path %}<action data-command="open_file" data-args="{{ file.ref.origin.path.replace(meta.execution_dir, "") }}" data-label="[...]"></action>{% endif %}
59
- </td>
60
- <td class="{{ 'ERROR' if file.error else '' }}">
61
- {% if file.error %}<span>{{ file.error }}</span>{% endif %}
62
- </td>
63
- {% if file.comparison_errors and file.comparison %}
64
- <td class="number {{ 'ERROR' if file.comparison_errors.error_nb else '' }}">{{ file.comparison_errors.error_nb }}</td>
65
- <td class="number {{ 'WARNING' if file.comparison_errors.warning_nb else '' }}">{{ file.comparison_errors.warning_nb }}</td>
66
- <td class="number">{{ file.comparison.total_diffs }}</td>
67
- {% elif not file.skipped %}
68
- <td class="ERROR">ERROR</td>
69
- <td class="ERROR">ERROR</td>
70
- <td class="ERROR">ERROR</td>
71
- {% else %}
72
- <td></td>
73
- <td></td>
74
- <td></td>
75
- {% endif %}
76
- <td class="number test-bg-20">{{ file.test.raw_lines_number }}</td>
77
- <td class="number refe-bg-20">{{ file.ref.raw_lines_number }}</td>
78
- <td class="number test-bg-20">{{ file.test.ignore_lines_number }}</td>
79
- <td class="number refe-bg-20">{{ file.ref.ignore_lines_number }}</td>
80
- <td class="number test-bg-20">{{ file.test.floats_lines_number }}</td>
81
- <td class="number refe-bg-20">{{ file.ref.floats_lines_number }}</td>
82
- <td class="">{{ file.test.reader }}</td>
83
- </tr>
84
- {% endfor %}
85
- </table>
86
- </div>
87
21
 
88
22
  <!-- INFO -->
89
23
 
@@ -93,4 +27,6 @@
93
27
  </h3>
94
28
  <div id="section_variables_and_rules" style="display:none;"></div> -->
95
29
 
30
+
31
+
96
32
  </section>
@@ -0,0 +1,71 @@
1
+ <!-- DATASETS -->
2
+ <h3>
3
+ Datasets <action data-command="toogle" data-args="section_summary_datasets"></action>
4
+ </h3>
5
+
6
+ <div id="section_summary_datasets">
7
+ <table class="shadow-lg">
8
+ <tr>
9
+ <th class="p-2" rowspan="2">#</th>
10
+ <th class="p-2" rowspan="2">Status</th>
11
+ <th class="p-2" rowspan="2">Name</th>
12
+ <th class="p-2" rowspan="2">Details</th>
13
+ <th class="p-2" rowspan="2" class="test-bg-50">Open test</th>
14
+ <th class="p-2" rowspan="2" class="refe-bg-50">Open Ref</th>
15
+ <th class="p-2" rowspan="2">Error</th>
16
+ <th class="p-2" colspan="3" >&nbsp;&nbsp;Comparison&nbsp;&nbsp;</th>
17
+ <th class="p-2" colspan="2">Nb Lines - Raw&nbsp;&nbsp;&nbsp;</th>
18
+ <th class="p-2" colspan="2">Nb Lines - Ignore</th>
19
+ <th class="p-2" colspan="2">Nb Lines - Number</th>
20
+ <th class="p-2" rowspan="2">Reader</th>
21
+ </tr>
22
+ <tr>
23
+ <th class="p-2" >Err.</th>
24
+ <th class="p-2" >Warn.</th>
25
+ <th class="p-2" >Diff.</th>
26
+ <th class="p-2 test-bg-50">Test</th>
27
+ <th class="p-2 refe-bg-50">Ref.</th>
28
+ <th class="p-2 test-bg-50">Test</th>
29
+ <th class="p-2 refe-bg-50">Ref.</th>
30
+ <th class="p-2 test-bg-50">Test</th>
31
+ <th class="p-2 refe-bg-50">Ref.</th>
32
+ </tr>
33
+ {% for file in data.files %}
34
+ <tr>
35
+ <td>{{ loop.index }}</td>
36
+ <td class="{{ ns.statuses[loop.index] }}">{{ ns.statuses[loop.index] }}</td>
37
+ <td>{{ file.name }}</td>
38
+ <td class="center">{% if not file.skipped %}<button onclick="actions.see_details({{ loop.index }})">[...]</button>{% endif %}</td>
39
+ <td class="center test-bg-20">
40
+ {% if file.test.origin and file.test.origin.path %}<action data-command="open_file" data-args="{{ file.test.origin.path.replace(meta.execution_dir, "") }}" data-label="[...]"></action>{% endif %}
41
+ </td>
42
+ <td class="center refe-bg-20">
43
+ {% if file.ref.origin and file.ref.origin.path %}<action data-command="open_file" data-args="{{ file.ref.origin.path.replace(meta.execution_dir, "") }}" data-label="[...]"></action>{% endif %}
44
+ </td>
45
+ <td class="{{ 'ERROR' if file.error else '' }}">
46
+ {% if file.error %}<span>{{ file.error }}</span>{% endif %}
47
+ </td>
48
+ {% if file.comparison_errors and file.comparison %}
49
+ <td class="number {{ 'ERROR' if file.comparison_errors.error_nb else '' }}">{{ file.comparison_errors.error_nb }}</td>
50
+ <td class="number {{ 'WARNING' if file.comparison_errors.warning_nb else '' }}">{{ file.comparison_errors.warning_nb }}</td>
51
+ <td class="number">{{ file.comparison.total_diffs }}</td>
52
+ {% elif not file.skipped %}
53
+ <td class="ERROR">ERROR</td>
54
+ <td class="ERROR">ERROR</td>
55
+ <td class="ERROR">ERROR</td>
56
+ {% else %}
57
+ <td></td>
58
+ <td></td>
59
+ <td></td>
60
+ {% endif %}
61
+ <td class="number test-bg-20">{{ file.test.raw_lines_number }}</td>
62
+ <td class="number refe-bg-20">{{ file.ref.raw_lines_number }}</td>
63
+ <td class="number test-bg-20">{{ file.test.ignore_lines_number }}</td>
64
+ <td class="number refe-bg-20">{{ file.ref.ignore_lines_number }}</td>
65
+ <td class="number test-bg-20">{{ file.test.floats_lines_number }}</td>
66
+ <td class="number refe-bg-20">{{ file.ref.floats_lines_number }}</td>
67
+ <td class="">{{ file.test.reader }}</td>
68
+ </tr>
69
+ {% endfor %}
70
+ </table>
71
+ </div>
@@ -0,0 +1,20 @@
1
+
2
+ <h3>
3
+ Metrics <action data-command="toogle" data-args="section_summary_metrics"></action>
4
+ </h3>
5
+ <div id="section_summary_metrics">
6
+
7
+ <div style="display: flex; flex-wrap: wrap;">
8
+
9
+ <div class="shadow-md p-4 rounded-lg " style="width:200px;height: 100px; border: 1px solid #eee;">
10
+ <div class="text-xs text-gray-500">Débit Massique Entrant (kg/s)</div>
11
+ <div class="text-xl font-bold">2.80 / 2.80</div>
12
+ <div class="w-full bg-gray-200 rounded-full h-2.5 dark:bg-gray-700">
13
+ <div class="bg-blue-600 h-2.5 rounded-full" style="width: 45%"></div>
14
+ </div>
15
+ </div>
16
+
17
+ </div>
18
+
19
+ </div>
20
+
@@ -0,0 +1,25 @@
1
+ {% for file in data.files %}
2
+ {% if file.test.metrics %}
3
+ <h3>Metrics <action data-command="toogle" data-args="section_summary_metrics"></action></h3>
4
+ <div id="section_summary_metrics">
5
+ <div style="display: flex; flex-wrap: wrap;">
6
+ <!-- <div class="kpi-container"> -->
7
+ {% for metric_k, metric_test in file.test.metrics.items() %}
8
+ {% set metric_status = file.comparison.metrics[metric_k].status if file.comparison.metrics else None %}
9
+ {% set metric_err_index = file.comparison.metrics[metric_k].err_index if metric_status else None %}
10
+ {% set metric_err = file.comparison_errors[metric_status][metric_err_index].err if metric_err_index else None %}
11
+ {{ macros.kpi_card(
12
+ metric_k,
13
+ metric_test,
14
+ file.ref.metrics[metric_k],
15
+ metric_status,
16
+ metric_err
17
+ ) }}
18
+ {% endfor %}
19
+ </div>
20
+ </div>
21
+ {% endif %}
22
+ {% endfor %}
23
+
24
+
25
+
@@ -10,7 +10,7 @@
10
10
  <th class="p-2" rowspan="2">Message</th>
11
11
  <th class="p-2" colspan="2">Value</th>
12
12
  <th class="p-2" rowspan="2">Error</th>
13
- <th class="p-2" rowspan="2">Visu</th>
13
+ <th class="p-2" rowspan="2">Diff. Visu.</th>
14
14
  {% if group.type == "lines" %}
15
15
  <th class="p-2" colspan="2">Line Number</th>
16
16
  <th class="p-2" colspan="2">Line(s)</th>
@@ -57,12 +57,7 @@
57
57
  {% endif %}
58
58
  </td>
59
59
  <td>
60
- {% if item.err.test and item.err.reference %}
61
- <div style="width:200px;height:20px">
62
- <div class="test-bg-80" style="width:{{100*(item.err.test|abs)/([(item.err.test|abs), (item.err.reference|abs)]|max)}}%;height:10px"></div>
63
- <div class="refe-bg-80" style="width:{{100*(item.err.reference|abs)/([(item.err.test|abs), (item.err.reference|abs)]|max)}}%; height:10px"></div>
64
- </div>
65
- {% endif %}
60
+ {{ macros.compare_visu(item.err.test, item.err.reference) }}
66
61
  </td>
67
62
 
68
63
 
@@ -0,0 +1,33 @@
1
+ {% macro compare_visu(test, reference) %}
2
+ {% if test and reference %}
3
+ <div style="width:100%;height:20px">
4
+ <div class="test-bg-80" style="width:{{100*(test|abs)/([(test|abs), (reference|abs)]|max)}}%;height:10px"></div>
5
+ <div class="refe-bg-80" style="width:{{100*(reference|abs)/([(test|abs), (reference|abs)]|max)}}%; height:10px"></div>
6
+ </div>
7
+ {% endif %}
8
+ {% endmacro %}
9
+
10
+ {% macro kpi_card(name, test, reference, status, err) %}
11
+ <div class="kpi-card">
12
+ <div class="text-xs text-gray-500">{{ name }}</div>
13
+ <div>
14
+ <div class="kpi kpi-{{ status }} text-2xl">
15
+ {% if test == reference %}
16
+ =
17
+ {% elif err %}
18
+ {% if err.is_relative %}
19
+ {% set err_per = err.value*100 %}
20
+ {{ ("%." + ( "2" if err_per < 1 else "0" ) + "f")|format(err.value*100) }}%
21
+ {% else %}
22
+ {{ err.value }}
23
+ {% endif %}
24
+ {% else %}
25
+
26
+ {% endif %}
27
+ </div>
28
+ </div>
29
+ <div class="py-2">{{ compare_visu(test, reference) }}</div>
30
+ <div class="kpi number test-bg-20" title="Test">{{test}}</div>
31
+ <div class="kpi number refe-bg-20" title="Reference">{{reference}}</div>
32
+ </div>
33
+ {% endmacro %}
@@ -0,0 +1,5 @@
1
+
2
+ <div style="width:200px;height:20px">
3
+ <div class="test-bg-80" style="width:{{100*(item.err.test|abs)/([(item.err.test|abs), (item.err.reference|abs)]|max)}}%;height:10px"></div>
4
+ <div class="refe-bg-80" style="width:{{100*(item.err.reference|abs)/([(item.err.test|abs), (item.err.reference|abs)]|max)}}%; height:10px"></div>
5
+ </div>
@@ -1,3 +1,4 @@
1
+ {% import "html_macros.html" as macros %}
1
2
  {% macro but2(action) %}
2
3
  <button onclick="{{ action }}" type="button" class="px-1 py-1 text-xs text-white bg-blue-700 rounded-lg hover:bg-blue-800">
3
4
  Show/Hide
@@ -152,8 +152,10 @@
152
152
  case "tabs":
153
153
  // tabs active
154
154
  var children = dom.get("tabs").children;
155
- for (i = 0; i < children.length; i++) { children[i].className = children[i].className.replace(" active", "") }
156
- children[parseInt(index)].className += " active";
155
+ for (i = 0; i < children.length; i++) {
156
+ children[i].className = children[i].className.replace(" active", "");
157
+ if (children[i].dataset.tabIndex == index) { children[i].className += " active"; }
158
+ }
157
159
  // display section
158
160
  for (i = 0; i < NB_SECTIONS; i++) {
159
161
  const section = dom.get("section_"+i);
@@ -104,11 +104,20 @@ button {border: 0;user-select: none; /* Standard syntax */ cursor: pointer;}
104
104
 
105
105
  .text-white { color: rgb(255 255 255); }
106
106
 
107
- .text-xs { font-size: .75rem; line-height: 1rem; }
107
+ .text-xs { font-size: .75rem; line-height: 1rem; }
108
+ .text-lg { font-size: 1.125rem; line-height: 1.75rem; }
109
+ .text-xl { font-size: 1.25rem; line-height: 1.75rem; }
110
+ .text-2xl { font-size: 1.5rem; line-height: 2rem; }
111
+ .text-4xl { font-size: 2rem; line-height: 2.5rem; }
112
+
113
+ .text-gray-500 { color: rgb(107 114 128) }
114
+
115
+ .font-bold { font-weight: 700; }
108
116
 
109
117
  .p-1 { padding: .25rem; }
110
118
  .p-2 { padding: .5rem; }
111
119
  .p-3 { padding: .75rem; }
120
+ .p-4 { padding: 1rem; }
112
121
 
113
122
  .py-1 { padding-bottom: .25rem; padding-top: .25rem; }
114
123
  .py-2 { padding-bottom: .5rem; padding-top: .5rem; }
@@ -142,6 +151,8 @@ button {border: 0;user-select: none; /* Standard syntax */ cursor: pointer;}
142
151
  .hover\:bg-blue-800:hover { background-color: rgb(30 66 159); }
143
152
 
144
153
 
154
+ .w-xs { width: 20rem; }
155
+
145
156
  .shadow-sm { box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); }
146
157
  .shadow { box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); }
147
158
  .shadow-md { box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); }
@@ -150,3 +161,73 @@ button {border: 0;user-select: none; /* Standard syntax */ cursor: pointer;}
150
161
  .shadow-2xl { box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25); }
151
162
  .shadow-inner { box-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.05); }
152
163
  .shadow-none { box-shadow: 0 0 #0000; }
164
+
165
+
166
+ .kpi-container::after {
167
+ content: "";
168
+ display: table;
169
+ clear: both;
170
+ }
171
+ .kpi-card {
172
+ width: 200px;
173
+ float: left;
174
+ border-radius: 12px;
175
+ padding: 20px;
176
+ margin: 10px;
177
+ box-sizing: border-box;
178
+ box-shadow: 0 0 10px rgba(0,0,0,0.08);
179
+ text-align: center;
180
+ }
181
+ .kpi {
182
+ font-weight: bold;
183
+ padding: 6px 12px;
184
+ border-radius: 20px;
185
+ display: inline-block;
186
+ margin-top: 10px;
187
+ }
188
+ .kpi-success {
189
+ background: #e6f4ea;
190
+ color: #2e7d32;
191
+ }
192
+ .kpi-error {
193
+ background: #fbe9e7;
194
+ color: #c62828;
195
+ }
196
+ .kpi-warning {
197
+ background: #f9fbe7;
198
+ color: #e4d831;
199
+ }
200
+ .gauge {
201
+ width: 80px;
202
+ height: 80px;
203
+ margin: 10px auto;
204
+ }
205
+
206
+ .gauge circle {
207
+ fill: none;
208
+ stroke-width: 10;
209
+ }
210
+
211
+ .gauge-bg {
212
+ stroke: #eee;
213
+ }
214
+
215
+ .gauge-success {
216
+ stroke: #_4caf50;
217
+ }
218
+
219
+ .gauge-failure {
220
+ stroke: #f44336;
221
+ }
222
+ .gauge-over {
223
+ stroke-linecap: round;
224
+ transform: rotate(-90deg);
225
+ transform-origin: center;
226
+ stroke-width: 11 !important;
227
+ }
228
+
229
+ .gauge-text {
230
+ font-size: 14px;
231
+ fill: #333;
232
+ }
233
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: scilens
3
- Version: 0.4.2
3
+ Version: 0.4.4
4
4
  Summary: A CesGensLaB framework for data collecting and deep analysis
5
5
  Home-page: https://scilens.dev
6
6
  License: Proprietary
@@ -8,11 +8,11 @@ scilens/cli/info.py,sha256=xE7q9epjrCQRL6Agi3nhKsG6Mr3B8HSUFMti-epMoXA,1929
8
8
  scilens/cli/main.py,sha256=C8EWm6JfTBBH74pR3J-O2ZuPX78VcQ5MWC5iqNUFN6Y,6332
9
9
  scilens/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  scilens/components/analyse_folder.py,sha256=yqc-dscKaHLZJCYeXGak2v0c3F2aeX0E11AFPfya6r0,208
11
- scilens/components/compare_2_files.py,sha256=jbZNLbRj3x8TxUADM5QC2u_TGl4I7u5OdaEMh-gMBUk,1713
11
+ scilens/components/compare_2_files.py,sha256=rxP4EgbaWryQxtsFLoSI0D68PuXCKOHM3C-NGu7WiKU,2309
12
12
  scilens/components/compare_errors.py,sha256=vGb4DWP89HMIeBm0dZU2nt-ksppAs_37xtCHaPd0w5Y,1640
13
- scilens/components/compare_floats.py,sha256=yYJZ_QpAZUhP1uwNtGshXQLIzKtki9ifCN3hd9AFj2U,5916
13
+ scilens/components/compare_floats.py,sha256=_FyB5UjFsmZ8tlg6w5dneSvkUeij4UjzXuQERDxFpW0,6465
14
14
  scilens/components/compare_folders.py,sha256=s7cgo2JhZi8F7tt3lGbPhkaO2726Lz3c4LYGP2HbWtA,2773
15
- scilens/components/compare_models.py,sha256=SCPd747h_nd4ewZsqLB6CFr27v6q99NELJb-gpkdj0o,918
15
+ scilens/components/compare_models.py,sha256=pQSM-gXv4zNH_xA1xlJU1jeYDG_3HJ9vYnlDGbvsM4g,928
16
16
  scilens/components/executor.py,sha256=PLeKolzPd4wPX8e6DdfOb0uHGky3DxTcKN9QtB6oe3Q,3712
17
17
  scilens/components/file_reader.py,sha256=7SbKCqb4Co_pqAKX3wweYhqAcVkU7BDlT903sLd76Kc,1407
18
18
  scilens/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -20,23 +20,23 @@ scilens/config/cli_run_options.py,sha256=Ls7yK5QDUPFbk73nbjGuPvuRbBRYw4Miag5ISpu
20
20
  scilens/config/env_var.py,sha256=NqNBoIfngJEXaGEm7jGqre5pmkJ9eUjiWzbDrTVfi2c,292
21
21
  scilens/config/load.py,sha256=ltcv90GlsMJR2FE2ZL_jDscL7k5aGoHoMatWw61lrTw,1672
22
22
  scilens/config/models/__init__.py,sha256=eLCW1OLVINewGFy5GXSrOk8Rab_QsgKAuoErBjphHRs,673
23
- scilens/config/models/app.py,sha256=JltWRjjqXYkH6rg3OHYhMfkBqHFhZEZdthqES3LxvzY,1453
23
+ scilens/config/models/app.py,sha256=T3zCqJKmRw8jwtmAdIogOfmuds1EI6hzhxGix-q5hRA,1468
24
24
  scilens/config/models/base.py,sha256=k92CR8TA5L8dZJtg28c8albk16AK9-3umdosA7aYsxw,499
25
- scilens/config/models/compare.py,sha256=veI5yFZ422i7NNBf6yH_3mk17jk1WNNzhcxb4XuIJBI,1860
26
- scilens/config/models/compare_float_thresholds.py,sha256=mHu48-70i3o_qUw6x-1A7XeRwFUNAO6WP6qNPGwAew0,2097
27
- scilens/config/models/execute.py,sha256=Hx3DoDJ0fq7bZruqwtPtSKL6PVOF_LpsaDCLrn5klLk,2325
28
- scilens/config/models/execute_and_compare.py,sha256=TWL6yXGvQSaaV6nhHqWLvtr3v396APIoDNt0U1TbMro,582
29
- scilens/config/models/file_reader.py,sha256=c18vKhVcBX4ufpbnCBJyVyAsQtlxpwx0lGVuf1i8EGA,1176
30
- scilens/config/models/reader_format_cols.py,sha256=Ec6K52pNvwRAPmgCnq87qSmG2wAZIz4lrGZBgOp4-3k,3295
31
- scilens/config/models/reader_format_csv.py,sha256=zxysiAAQitdBjh1mTlzQR0YafmLyIdEm2qarNh98ST8,1590
32
- scilens/config/models/reader_format_netcdf.py,sha256=k-AMdm239T6I42R8jzyRlPKKJ8zkRrN8XS8yU6ZkFu0,1256
33
- scilens/config/models/reader_format_txt.py,sha256=eHg90gwEI_VpqwqEjMRhwlS8dHcl5G4ow-37HjQq_zY,1168
34
- scilens/config/models/reader_format_txt_fixed_cols.py,sha256=EmnXcCyvG9J6tTEIgldSD2zZEVotcINM1Yzmtqs9foA,1136
35
- scilens/config/models/reader_metrics.py,sha256=oWzQPM5EO05QYwJiqeeTX-c4tuoiYBrR_q-meaoGTzA,572
36
- scilens/config/models/readers.py,sha256=oWdE4AkckvwN6boln55orq3hUeAt6S9IdQAZkGROR6E,1657
37
- scilens/config/models/report.py,sha256=6mzqZMJnS_z5Rs01ISo8L8HRcWvmiQrK0dYqu8a58vM,993
38
- scilens/config/models/report_html.py,sha256=OU_df-IwopOILbWgNHImTtZf7Yhj_fsD0lpRQB8-bP8,3728
39
- scilens/config/models/report_output.py,sha256=XoqUe-t-y8GRbUR3_bDwwaWf6hif-rZ-5pKDGdCMugw,875
25
+ scilens/config/models/compare.py,sha256=IiH1wJWYVnPnUJ3BiMeGDy8CFHwPOw1nQS2wfk-0p44,2152
26
+ scilens/config/models/compare_float_thresholds.py,sha256=M8flQmu5B-Lc-RStn-kcQJZum_kZxj591w8myyQQuEY,2127
27
+ scilens/config/models/execute.py,sha256=yF_q8swd4-s2KyT_RwtSzOW41AY5GiEZaLhGUGJBU0Y,2340
28
+ scilens/config/models/execute_and_compare.py,sha256=aIWF1NIgdq5USS9ZVWOKgpEyMagCvqYYWYSXWvBBgjg,597
29
+ scilens/config/models/file_reader.py,sha256=0-ldLt4YVmb2IwdfEHiIqDsioyXwqSkxrlfuEOmcyrA,1191
30
+ scilens/config/models/reader_format_cols.py,sha256=-nvPjZImao_RFVAlyvTZG1fCXa3hhkH9th4lOD3ZLT4,3382
31
+ scilens/config/models/reader_format_csv.py,sha256=KWEH0c12n6hdaWAKdHXYMT5SvH4UqBFvP7d3ZkJr7r8,1620
32
+ scilens/config/models/reader_format_netcdf.py,sha256=Skr5lZACqVRrrlvs7R1RVFBpMTDthLJN-Fbs24jtb7o,1271
33
+ scilens/config/models/reader_format_txt.py,sha256=35rvhg311DN9miE47QM9NN_gcZHglYG2lBZPLJy4iyg,1462
34
+ scilens/config/models/reader_format_txt_fixed_cols.py,sha256=b6qprM_Ns30X6a3Jq20oK-bslR3g-njRW7pCZl7LKvY,1151
35
+ scilens/config/models/reader_metrics.py,sha256=qJBnq6gix-vkNeCz7LuVu04n8q6Rx1KUmkqy-J6BCDY,900
36
+ scilens/config/models/readers.py,sha256=NpEjXbLv11k9N8UsnuS55KEYlRijF9C3eOrI0SB9dqM,1723
37
+ scilens/config/models/report.py,sha256=_4W96v5izWCC_CrMzh3PM0mZIUAa3L26ZQqjV0Mv0f4,1008
38
+ scilens/config/models/report_html.py,sha256=IsKlmE7QbSTiPrOaxPc48Ne7xPE5yqTcLjxqN_i-unY,3803
39
+ scilens/config/models/report_output.py,sha256=XfzTsd1G3QjbZFer9dkWa1pa3HKbmK85UcHg6A7loOQ,890
40
40
  scilens/helpers/assets.py,sha256=XphDA3-yE1PPKw4XFZhDrlLQjMZfGMlpOBXa8uy_xX0,1552
41
41
  scilens/helpers/search_and_index.py,sha256=kXZ7124ra_SGAdKUZ7msy55UOWQ9dCSuPuNoU-NdUyM,1522
42
42
  scilens/helpers/templates/index.html,sha256=hwoABZ7mWbN92VZhAMrloTdm_-leW8aQRbRfyafXl3Q,490
@@ -49,13 +49,13 @@ scilens/processors/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
49
49
  scilens/processors/models/results.py,sha256=KoWxh13Zgi7PuPql8hkf4VjCis42ZxAuzIgJxBWVaX8,119
50
50
  scilens/processors/processor_interface.py,sha256=jzMp1529JXnMGTJijVy6b_1zmARAMNv70f2lgys7vn4,452
51
51
  scilens/readers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
- scilens/readers/cols_dataset.py,sha256=KENQLhlAjktOTPymqokJLp_mBOsMFq8GRy_cs9b3wjU,3151
52
+ scilens/readers/cols_dataset.py,sha256=OpCTS9FmJxCHLoCrrD56sHY3f9dxwTsw2Xyxf_vNv_8,3270
53
53
  scilens/readers/exceptions.py,sha256=JzmxcjnR5sH-IOWVeCC5A1bSwxv-jCAtIJvDjzx1CTI,32
54
54
  scilens/readers/mat_dataset.py,sha256=Z9TYDWaH2aqdniLNDjlpR6VVNHMSARjh52clhdMyOn4,1496
55
- scilens/readers/reader_csv.py,sha256=yCaJGxG9xow1BUUavdSVJKKl8nRRUtfYMk_sYkOW4-U,5470
55
+ scilens/readers/reader_csv.py,sha256=5TQ9TAVSNUje7Mbqy9T1SfJ1f4Ic_bFBTD9S5OuMrGU,5539
56
56
  scilens/readers/reader_interface.py,sha256=nnttHL7wt4MOXpi-SBkk8DYxVWscOPG8JFl_z12mIAo,922
57
57
  scilens/readers/reader_manager.py,sha256=DFinxIk3IIIcB6JxybGcv-mXt3jhXgCwUtzR0TqhB2Q,2684
58
- scilens/readers/reader_txt.py,sha256=WPsFunEA_idzAKkD3UJQbLnaOzG2U03P3gY4gphuIw0,3868
58
+ scilens/readers/reader_txt.py,sha256=U3hGIorj-Nv-jq6zYtvbDv2LQBHTgW52PHbV8A5FMA8,4526
59
59
  scilens/readers/reader_txt_fixed_cols.py,sha256=Ec4J34M770akw8i07BC2zahVuS8pezP31BsHoS4NyNE,4528
60
60
  scilens/readers/transform.py,sha256=kppfgPkXymF0qtquFivuosLVfF66L9bE-wGx-3bMHv8,307
61
61
  scilens/report/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -66,22 +66,27 @@ scilens/report/html_report.py,sha256=ml_paRkzI81irpeWNtEkBOHkK0W7veNU6RbVM6RLM6E
66
66
  scilens/report/report.py,sha256=aS7ktJ2u0IAMMk-HwqqSsRkr77ZBQyYT4wXJ7djQvAk,1811
67
67
  scilens/report/template.py,sha256=cPs5gd3uEwb-6JgitGQD_i4IiUxigBTlZLNRS9KVuos,581
68
68
  scilens/report/templates/body_01_title.html,sha256=LJOWO6ImNPW9cg3tCDlgdllVTwnFGWcb2qvA3yv6wNk,1758
69
- scilens/report/templates/body_02_tabs.html,sha256=oOFslWcfNsWpCX12GECZDzdR5uAHE54HPP6IYUf7y0U,412
69
+ scilens/report/templates/body_02_tabs.html,sha256=hooRO_OJPwAQSa6GBsPLca-OnpiHkr3wZ_0NoXGKGR0,465
70
70
  scilens/report/templates/body_99_footer.html,sha256=8cWebeWfZwZ-9bYAMZkZj8rbCWq3BLIMjKQThWQxoQM,362
71
- scilens/report/templates/compare_11_summary.html,sha256=xpqii8f2sWqa3weQ6BRuLaD1loCJsoQ5MnDTUObRbQo,4104
71
+ scilens/report/templates/compare_11_summary.html,sha256=Goknx4slzt8JX2rq05hf31HTXjkOHUX8u2jYazaUkmc,751
72
+ scilens/report/templates/compare_11_summary_datasets.html,sha256=iUhOhZpAc4yLsHqDinx30xQDjLcbXRXU72Ud6n29GBQ,3495
73
+ scilens/report/templates/compare_11_summary_metrics copy.html,sha256=y8hfw8W5GXR7CRDEmlgk_IN100gfF3-67UqvAIMrxPA,623
74
+ scilens/report/templates/compare_11_summary_metrics.html,sha256=2qi2ME6VrV68mxnTZq3zS-GEPc5vwhFgswswXEpt_34,966
72
75
  scilens/report/templates/compare_12_sections.html,sha256=mHO8efJ2YOV-dC4B4E0VlcAnLbdIvgx5D-RlYRk8idY,6411
73
76
  scilens/report/templates/compare_13_section_numbers copy.html,sha256=0PWK_I2kNX3LjPLkkY4eSYIeB7YFkA28nk-PPLDhnaY,1753
74
77
  scilens/report/templates/compare_13_section_numbers.html,sha256=9etEMSqwrDyJIn_nMbKEVaDgnFL_hBxSjPR-hU2wgDI,851
75
- scilens/report/templates/compare_13_section_numbers_table.html,sha256=Bbcv7311WhhNXNIjPPS9ho-CHzNpikjCs4la6G4274M,3288
76
- scilens/report/templates/index.html,sha256=ilvsUfuINb7bDP8X1UgjhxPqtQJ4pq6pgPXWnkLaaFU,5969
78
+ scilens/report/templates/compare_13_section_numbers_table.html,sha256=pME7vkcPpP2YF0X_jPeD8hEyjA4i-11slfwuQkfUNNI,2927
79
+ scilens/report/templates/html_macros.html,sha256=jKatNSn4nX_72_wHl0-0dhxZZZBoGDGpOg7E7TMZSGs,1185
80
+ scilens/report/templates/html_widget_err.html,sha256=sjbtooSh7RGFs8kcct4_tMi_n8FQiaoqRhUjBzHduZM,336
81
+ scilens/report/templates/index.html,sha256=UazWYLeHn3KdnQ8cTtMkuKOLeC-d1CdRzl2C0hmHV3k,6011
77
82
  scilens/report/templates/js_chartlibs_echarts.js,sha256=6YicVhTNIBmmBpV31XCVN5oBeiD0t29JIosJZRUv01M,907
78
83
  scilens/report/templates/js_chartlibs_plotly.js,sha256=MQGpYtBc1gKtu98BcfVOx_W0TktABqanxDjK9YaVqNE,2649
79
- scilens/report/templates/js_com_page.js,sha256=Q-_Smn77IYIAdlrS1zJtsVIYBOL1t-J1AYYJKji4eL0,6864
84
+ scilens/report/templates/js_com_page.js,sha256=miSPJuzb5hD6sX7b5RYMWoCv9pg2CraHuIfXVFYmUU8,6922
80
85
  scilens/report/templates/js_curvemgr.js,sha256=gnRLO6HbZOMLIBQKjVhV2PciqXtuNKxpGx4boijV2Qc,12175
81
86
  scilens/report/templates/js_dom.js,sha256=r5fNSEdeHopMUjSaYtuAIBNRhvSIPoQ9HzAtxvLZcuk,1363
82
87
  scilens/report/templates/js_palette.js,sha256=HeewAmkR67QiqXSanJS3cCgp6IPKomlULUTKt55F6es,218
83
88
  scilens/report/templates/models.js,sha256=MrgnVxPnoimLbR_Eb7Rq3OoNlT89m4PYk6vqt-D7KyY,715
84
- scilens/report/templates/style.css,sha256=WN8Fi3s6PiuExuDiQHHXCB6sFWwjVnGO5VSk0u-E1sI,4216
89
+ scilens/report/templates/style.css,sha256=H0jL7lztlXgE_oUmd0ukHScjZ-eOKmfFq7ppV41pi2U,5459
85
90
  scilens/report/templates/uti_frameseries.js,sha256=2edOgmgEfD9F7wYvcB1ZAELnLRq43tcxYMhERnNC5NY,6282
86
91
  scilens/report/templates/uti_matrix.js,sha256=wD9vZ9aMq897XupXDmGYkiUQl8behMAYDjcfDvxGwQ0,3441
87
92
  scilens/report/templates/uti_spectrograms.js,sha256=qE2wdit6Zq8AxShtV9FdA2pRTk4KY9zZUZ58ccYj_Ow,4311
@@ -106,7 +111,7 @@ scilens/utils/template.py,sha256=9dlXX3nmfzDRUwzPJOkoxk15UXivZ2SW-McdCwokFa4,443
106
111
  scilens/utils/time_tracker.py,sha256=DdVBoMpVLXrX0qZZXyLm4g38EwDVLlRcBqcpNex1mYY,545
107
112
  scilens/utils/vectors.py,sha256=4N2BZSC5n3HgZqPujDGF5NdjVmSL1rOHb_qw4OoABQY,103
108
113
  scilens/utils/web.py,sha256=MAFWpIFOKz7QhqDoFh-Qwstvc76KpcxstSgHFT8FOL4,901
109
- scilens-0.4.2.dist-info/METADATA,sha256=B7ilZcElulU0oj8X8g9odlZHfrkQZuN6WNX5bcE1DNs,1367
110
- scilens-0.4.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
111
- scilens-0.4.2.dist-info/entry_points.txt,sha256=DaKGgxUEUv34GJAoXtta6ecL37ercejep9sCSSRQK2s,48
112
- scilens-0.4.2.dist-info/RECORD,,
114
+ scilens-0.4.4.dist-info/METADATA,sha256=cDh5banWrNt3b15baIxTmsgE6uE5-mhWfxl6JR1l9Nk,1367
115
+ scilens-0.4.4.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
116
+ scilens-0.4.4.dist-info/entry_points.txt,sha256=DaKGgxUEUv34GJAoXtta6ecL37ercejep9sCSSRQK2s,48
117
+ scilens-0.4.4.dist-info/RECORD,,