Skip to content

Commit df0393a

Browse files
authored
upload new docu for operators and update links (#12)
* upload new docu for operators and update links * just a random new profile for IR-data * <hr> fix
1 parent 853164f commit df0393a

3 files changed

Lines changed: 512 additions & 0 deletions

File tree

docs/all-pages.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ <h2>docs root</h2>
1919
<li><a href="impressum-en.html">impressum-en.html</a></li>
2020
<li><a href="index.html">index.html</a></li>
2121
<li><a href="loop_docu.html">loop_docu.html</a></li>
22+
<li><a href="operator_docu.html">operator_docu.html</a></li>
2223
</ul>
2324
<h2>docs/atch (without docs/atch/server)</h2>
2425
<ul>

docs/operator_docu.html

Lines changed: 379 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,379 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Operator Docu</title>
6+
<meta name="viewport" content="width=device-width, initial-scale=1">
7+
<link rel="stylesheet" href="global.css" />
8+
</head>
9+
<body class="loop-docu">
10+
<h1>Converter Operator Documentation</h1>
11+
<hr />
12+
<h1>Backend</h1>
13+
<h2>Overview</h2>
14+
<p>The converter can apply additional calculations to the selected <strong>x-values</strong> and <strong>y-values</strong>. These calculations are stored in <code>xOperations</code> and <code>yOperations</code> and are executed when an output table is processed.</p>
15+
<p>There are two layers involved:</p>
16+
<ol>
17+
<li><strong>Four operation types</strong>, which define <em>where</em> the right-hand value comes from.</li>
18+
<li><strong>Four mathematical operators</strong>, which define <em>how</em> that value is applied to the current x- or y-value.</li>
19+
</ol>
20+
<p>The four operation types are:</p>
21+
<ul>
22+
<li><code>column</code></li>
23+
<li><code>value</code></li>
24+
<li><code>metadata_value</code></li>
25+
<li><code>header_value</code></li>
26+
</ul>
27+
<p>The four mathematical operators are:</p>
28+
<ul>
29+
<li><code>+</code> addition</li>
30+
<li><code>-</code> subtraction</li>
31+
<li><code>*</code> multiplication</li>
32+
<li><code>:</code> division</li>
33+
</ul>
34+
<p>In other words:<br />
35+
A profile can say things like:</p>
36+
<ul>
37+
<li>“Take the x-values and add a fixed number.”</li>
38+
<li>“Take the y-values and multiply them by values from another column.”</li>
39+
<li>“Take the y-values and divide them by a value found in metadata.”</li>
40+
<li>“Take the x-values and subtract a number extracted from the table header.”</li>
41+
</ul>
42+
<hr />
43+
<h2>Data Structures Involved</h2>
44+
<p>For each output table, the converter uses these fields in the table configuration:</p>
45+
<ul>
46+
<li><code>xColumn</code><br />
47+
The base source of the x-values.</li>
48+
<li><code>yColumn</code><br />
49+
The base source of the y-values.</li>
50+
<li><code>xOperations</code><br />
51+
A list of operations that are applied to all x-values.</li>
52+
<li><code>yOperations</code><br />
53+
A list of operations that are applied to all y-values.</li>
54+
<li><code>xOperationsDescription</code> and <code>yOperationsDescription</code><br />
55+
Auto-generated and user-editable descriptions of the configured operations.</li>
56+
</ul>
57+
<p>Each entry in <code>xOperations</code> or <code>yOperations</code> contains at least:</p>
58+
<ul>
59+
<li><code>type</code> – the operation type</li>
60+
<li><code>operator</code> – one of <code>+</code>, <code>-</code>, <code>*</code>, <code>:</code></li>
61+
</ul>
62+
<p>Depending on the type, additional fields are used, such as <code>column</code>, <code>value</code>, <code>table</code>, <code>regex</code>, <code>line</code>, and <code>ignore_missing_values</code>.</p>
63+
<hr />
64+
<h2>Method: <code>process(self)</code></h2>
65+
<h3>Purpose</h3>
66+
<p>Prepare the raw x/y data, apply all configured x/y operations, and build the final output table.</p>
67+
<h3>Step-by-step behavior</h3>
68+
<ol>
69+
<li><strong>Read the base x and y columns</strong><br />
70+
The converter reads the values from <code>xColumn</code> into <code>x_rows</code> and from <code>yColumn</code> into <code>y_rows</code>.</li>
71+
<li><strong>Prepare data for column-based operations</strong><br />
72+
If an operation has type <code>column</code>, the converter preloads the referenced column values into <code>operation['rows']</code>.</li>
73+
<li><strong>Apply x-operations</strong><br />
74+
All entries from <code>xOperations</code> are executed in their stored order.</li>
75+
<li><strong>Apply y-operations</strong><br />
76+
All entries from <code>yOperations</code> are executed in their stored order.</li>
77+
<li><strong>Handle calculation failures</strong><br />
78+
If an operation fails and the failure must not be ignored, the converter marks the calculation as failed and clears the output rows.</li>
79+
</ol>
80+
<h3>Important consequence</h3>
81+
<p><strong>The order of operations matters.</strong><br />
82+
If several operations are configured, each one works on the result of the previous one. So <code>* 2</code> followed by <code>+ 5</code> is not the same as <code>+ 5</code> followed by <code>* 2</code>.</p>
83+
<hr />
84+
<h2>Method: <code>_run_operation(self, rows, operation)</code></h2>
85+
<h3>Purpose</h3>
86+
<p>Execute one configured operation on all values of one target row set, meaning either all x-values or all y-values.</p>
87+
<p>For each row, the method first determines the right-hand operand based on <code>operation.type</code>. Then it applies the selected mathematical operator by calling <code>apply_operation</code>.</p>
88+
<hr />
89+
<h3>The four operation types</h3>
90+
<h4>1. <code>column</code> – Value from another table column</h4>
91+
<ul>
92+
<li>The operation points to a column using <code>operation.column.tableIndex</code> and <code>operation.column.columnIndex</code>.</li>
93+
<li>During preparation, all values from that referenced column are stored in <code>operation['rows']</code>.</li>
94+
<li>During execution, the converter reads the value at the same row position from that preloaded list.</li>
95+
</ul>
96+
<p><strong>Plain-language interpretation:</strong><br />
97+
The current x- or y-value is combined with the value from another column at the same row index.</p>
98+
<hr />
99+
<h4>2. <code>value</code> – Fixed scalar value</h4>
100+
<ul>
101+
<li>The operation stores a direct numeric value in <code>operation.value</code>.</li>
102+
<li>The same number is used for every row.</li>
103+
</ul>
104+
<p><strong>Plain-language interpretation:</strong><br />
105+
All x- or y-values are modified by the same fixed number, such as <code>+ 5</code> or <code>* 1000</code>.</p>
106+
<hr />
107+
<h4>3. <code>metadata_value</code> – Value from table metadata</h4>
108+
<ul>
109+
<li>The operation stores a metadata key in <code>operation.value</code> and a reference table index in <code>operation.table</code>.</li>
110+
<li>The converter reads the metadata value from <code>self.input_tables[int(operation.table)]['metadata']</code>.</li>
111+
<li>That metadata value is then used as the right-hand operand for all rows.</li>
112+
<li>If the metadata value is missing or not numeric, behavior depends on <code>ignore_missing_values</code>.</li>
113+
</ul>
114+
<p><strong>Plain-language interpretation:</strong><br />
115+
The current x- or y-value is combined with a numeric value taken from the metadata of a selected input table.</p>
116+
<hr />
117+
<h4>4. <code>header_value</code> – Value extracted from the table header via regex</h4>
118+
<ul>
119+
<li>The operation stores a table index, an optional line number, and a regex pattern.</li>
120+
<li>The helper method <code>_search_regex</code> searches either a specific header line or the whole header text.</li>
121+
<li>If a regex match is found and the regex contains a capture group, the first capture group is used.</li>
122+
<li>If there is no capture group, the full match is used.</li>
123+
<li>The extracted text must be numeric to be usable in the calculation.</li>
124+
</ul>
125+
<p><strong>Plain-language interpretation:</strong><br />
126+
The current x- or y-value is combined with a number that is found somewhere in the selected table header.</p>
127+
<hr />
128+
<h3>How missing or invalid values are handled</h3>
129+
<p>After the right-hand value has been determined, the converter tries to convert it to a float.</p>
130+
<ul>
131+
<li>If conversion succeeds, the operation can continue.</li>
132+
<li>If conversion fails and <code>ignore_missing_values</code> is <strong>false</strong>, a <code>CalculationError</code> is raised.</li>
133+
<li>If conversion fails and <code>ignore_missing_values</code> is <strong>true</strong>, that operation is skipped.</li>
134+
</ul>
135+
<p>This special handling is mainly relevant for <code>metadata_value</code> and <code>header_value</code>, because those two types may depend on metadata or free text that is missing or non-numeric.</p>
136+
<hr />
137+
<h2>Method: <code>apply_operation(self, value, op_value, op_operator)</code></h2>
138+
<h3>Purpose</h3>
139+
<p>Apply the mathematical operator to the current row value (<code>value</code>) and the resolved operation value (<code>op_value</code>).</p>
140+
<h3>Supported operators</h3>
141+
<pre><code class="language-python">if op_operator == '+':
142+
return float_value + float(op_value)
143+
if op_operator == '-':
144+
return float_value - float(op_value)
145+
if op_operator == '*':
146+
return float_value * float(op_value)
147+
if op_operator == ':':
148+
return float_value / float(op_value)
149+
</code></pre>
150+
<h3>Meaning of the operators</h3>
151+
<ul>
152+
<li><strong><code>+</code></strong><br />
153+
Adds the operation value to the current x/y value.</li>
154+
<li><strong><code>-</code></strong><br />
155+
Subtracts the operation value from the current x/y value.</li>
156+
<li><strong><code>*</code></strong><br />
157+
Multiplies the current x/y value by the operation value.</li>
158+
<li><strong><code>:</code></strong><br />
159+
Divides the current x/y value by the operation value.</li>
160+
</ul>
161+
<h3>Important implementation detail</h3>
162+
<p>The current implementation only applies the operation when <code>op_value</code> is truthy. This means that a right-hand value of <code>0</code> will not be applied and will leave the current row unchanged.</p>
163+
<hr />
164+
<h2>Overall Summary</h2>
165+
<ul>
166+
<li><code>process(self)</code> prepares the x/y data and executes all configured operations in order.</li>
167+
<li><code>_run_operation(self, rows, operation)</code> determines the right-hand value depending on the operation type.</li>
168+
<li><code>apply_operation(self, value, op_value, op_operator)</code> performs the actual mathematical calculation.</li>
169+
</ul>
170+
<p>So the backend logic can be summarized like this:</p>
171+
<ol>
172+
<li>Start with the selected x/y column values.</li>
173+
<li>For each configured operation, determine where the right-hand value comes from.</li>
174+
<li>Apply one of the four mathematical operators.</li>
175+
<li>Store the updated x/y values in the final output table.</li>
176+
</ol>
177+
178+
<hr />
179+
<h1>Frontend</h1>
180+
<p>This part of the frontend is the visual configuration for the x/y operations you saw in the backend.</p>
181+
<p>It lets a user decide:</p>
182+
<ol>
183+
<li><strong>Which column should be used as the base x- or y-values</strong>, and</li>
184+
<li><strong>Which additional operations should be applied to those values before export.</strong></li>
185+
</ol>
186+
<hr />
187+
<h2>1. Choosing the base x- and y-columns</h2>
188+
<pre><code class="language-jsx">&lt;TableColumn
189+
table={table.table}
190+
label="Which column should be used as x-values?"
191+
columnKey="xColumn"
192+
operationsKey="xOperations"
193+
...
194+
/&gt;
195+
196+
&lt;TableColumn
197+
table={table.table}
198+
label="Which column should be used as y-values?"
199+
columnKey="yColumn"
200+
operationsKey="yOperations"
201+
...
202+
/&gt;
203+
</code></pre>
204+
<h3>What the user sees</h3>
205+
<p>A selection field for the x-column and a selection field for the y-column.</p>
206+
<p>These define the <strong>starting values</strong> before any operation is applied.</p>
207+
<h3>How this relates to the backend</h3>
208+
<p>The selections are stored as:</p>
209+
<ul>
210+
<li><code>table.xColumn</code></li>
211+
<li><code>table.yColumn</code></li>
212+
</ul>
213+
<p>The backend reads these values first, then applies <code>xOperations</code> and <code>yOperations</code> on top of them.</p>
214+
<p><strong>Special case:</strong><br />
215+
If the table header says <code>DATA CLASS = XYDATA</code>, the x-values are configured differently in the frontend, via metadata-related identifiers such as <code>FIRSTX</code>, <code>LASTX</code>, and <code>DELTAX</code>, instead of the normal x-column operation block.</p>
216+
<hr />
217+
<h2>2. The operator dropdown</h2>
218+
<pre><code class="language-jsx">&lt;Form.Select size="sm" value={value} onChange={event =&gt; onChange(event.target.value)}&gt;
219+
&lt;option value="+"&gt;+&lt;/option&gt;
220+
&lt;option value="-"&gt;-&lt;/option&gt;
221+
&lt;option value="*"&gt;*&lt;/option&gt;
222+
&lt;option value=":"&gt;:&lt;/option&gt;
223+
&lt;/Form.Select&gt;
224+
</code></pre>
225+
<h3>What the user sees</h3>
226+
<p>Each configured operation row starts with a small dropdown containing:</p>
227+
<ul>
228+
<li><code>+</code></li>
229+
<li><code>-</code></li>
230+
<li><code>*</code></li>
231+
<li><code>:</code></li>
232+
</ul>
233+
<h3>How this relates to the backend</h3>
234+
<p>The selected symbol is stored in <code>operation.operator</code>. In the backend, this value is passed to <code>apply_operation</code>, where it determines whether the calculation becomes addition, subtraction, multiplication, or division.</p>
235+
<hr />
236+
<h2>3. The four operation types</h2>
237+
<p>The frontend offers four buttons for creating operations. Each new operation is added either to <code>xOperations</code> or to <code>yOperations</code>.</p>
238+
<pre><code class="language-jsx">&lt;Button onClick={() =&gt; addOperation(operationsKey, 'column')}&gt;
239+
Add column operation
240+
&lt;/Button&gt;
241+
&lt;Button onClick={() =&gt; addOperation(operationsKey, 'value')}&gt;
242+
Add scalar operation
243+
&lt;/Button&gt;
244+
&lt;Button onClick={() =&gt; addOperation(operationsKey, 'metadata_value')}&gt;
245+
Add table metadata operation
246+
&lt;/Button&gt;
247+
&lt;Button onClick={() =&gt; addOperation(operationsKey, 'header_value')}&gt;
248+
Add table header operation
249+
&lt;/Button&gt;
250+
</code></pre>
251+
<p>These correspond directly to the four backend operation types.</p>
252+
<hr />
253+
<h3>3.1 Column operation: <code>column</code></h3>
254+
<h4>What the user sees</h4>
255+
<p>After adding a column operation, the user sees:</p>
256+
<ul>
257+
<li>the operator dropdown</li>
258+
<li>a column selector listing available input columns</li>
259+
<li>a red remove button</li>
260+
</ul>
261+
<h4>How this relates to the backend</h4>
262+
<p>The selected column is stored in:</p>
263+
<pre><code class="language-js">operation = {
264+
type: 'column',
265+
operator: '+',
266+
column: {
267+
tableIndex: ...,
268+
columnIndex: ...
269+
}
270+
}
271+
</code></pre>
272+
<p>The backend then reads the referenced column values row by row and combines them with the current x- or y-values.</p>
273+
<hr />
274+
<h3>3.2 Scalar operation: <code>value</code></h3>
275+
<h4>What the user sees</h4>
276+
<p>After adding a scalar operation, the user sees:</p>
277+
<ul>
278+
<li>the operator dropdown</li>
279+
<li>a text input for entering a fixed numeric value</li>
280+
<li>a red remove button</li>
281+
</ul>
282+
<h4>How this relates to the backend</h4>
283+
<p>The entered value is stored in:</p>
284+
<pre><code class="language-js">operation = {
285+
type: 'value',
286+
operator: '+',
287+
value: '...'
288+
}
289+
</code></pre>
290+
<p>The backend uses this same scalar for every row.</p>
291+
<hr />
292+
<h3>3.3 Table metadata operation: <code>metadata_value</code></h3>
293+
<h4>What the user sees</h4>
294+
<p>After adding a metadata operation, the user sees:</p>
295+
<ul>
296+
<li>the operator dropdown</li>
297+
<li>a dropdown of available metadata fields</li>
298+
<li>a checkbox for <code>ignore_missing_values</code></li>
299+
<li>a preview of the current numeric value</li>
300+
<li>a warning that metadata-based calculations should be used with caution</li>
301+
<li>a red remove button</li>
302+
</ul>
303+
<h4>How this relates to the backend</h4>
304+
<p>The selected metadata field is stored using fields such as <code>metadata</code>, <code>value</code>, and <code>table</code>. The backend uses <code>value</code> as the metadata key and <code>table</code> as the table reference.</p>
305+
<p>If the metadata is missing or not numeric:</p>
306+
<ul>
307+
<li>with <code>ignore_missing_values = true</code>, the operation is skipped</li>
308+
<li>with <code>ignore_missing_values = false</code>, the calculation fails</li>
309+
</ul>
310+
<hr />
311+
<h3>3.4 Table header operation: <code>header_value</code></h3>
312+
<h4>What the user sees</h4>
313+
<p>After adding a header operation, the user sees:</p>
314+
<ul>
315+
<li>the operator dropdown</li>
316+
<li>a dropdown to choose the input table</li>
317+
<li>a text field for <strong>Line</strong></li>
318+
<li>a text field for <strong>Regex</strong></li>
319+
<li>a checkbox for <code>ignore_missing_values</code></li>
320+
<li>a preview of the current extracted numeric value</li>
321+
<li>a warning that header-based calculations should be used with caution</li>
322+
<li>a red remove button</li>
323+
</ul>
324+
<h4>How this relates to the backend</h4>
325+
<p>The entered fields are stored in something like:</p>
326+
<pre><code class="language-js">operation = {
327+
type: 'header_value',
328+
operator: '+',
329+
table: '0',
330+
line: '...',
331+
regex: '...',
332+
ignore_missing_values: false
333+
}
334+
</code></pre>
335+
<p>The backend uses <code>_search_regex</code> to search the selected table header. If the regex returns a numeric match, that value is used in the calculation.</p>
336+
<hr />
337+
<h2>4. Operation description</h2>
338+
<p>The frontend also shows an operation description area when operations are configured.</p>
339+
<h3>What the user sees</h3>
340+
<ul>
341+
<li>An automatically generated summary of the configured operations</li>
342+
<li>A text area where the user can add a manual explanation</li>
343+
</ul>
344+
<h3>How this relates to the backend</h3>
345+
<p>The summary is stored in:</p>
346+
<ul>
347+
<li><code>xOperationsDescription</code></li>
348+
<li><code>yOperationsDescription</code></li>
349+
</ul>
350+
<p>This description is later included in the exported JCAMP comment.</p>
351+
<hr />
352+
<h2>Putting it all together</h2>
353+
<p>From the user’s perspective:</p>
354+
<ol>
355+
<li>Select the base x-column and y-column.</li>
356+
<li>Add zero or more operations to x and/or y.</li>
357+
<li>For each operation, choose:</li>
358+
<li>which mathematical operator should be used, and</li>
359+
<li>which kind of source should provide the right-hand value:
360+
<ul>
361+
<li>another column</li>
362+
<li>a fixed scalar</li>
363+
<li>a metadata field</li>
364+
<li>a header regex match</li>
365+
</ul>
366+
</li>
367+
<li>Optionally provide an explanation of the operation chain.</li>
368+
</ol>
369+
<p>From the backend’s perspective:</p>
370+
<ul>
371+
<li>The selected base columns fill <code>xColumn</code> and <code>yColumn</code>.</li>
372+
<li>The added operation rows fill <code>xOperations</code> and <code>yOperations</code>.</li>
373+
<li>Each operation is executed in order.</li>
374+
<li>The final transformed values are stored in the output table as <code>x</code> and <code>y</code>.</li>
375+
</ul>
376+
<p>In short:<br />
377+
The frontend provides a user-friendly way to build a calculation chain for x- and y-values, while the backend executes that chain using one of four operation types and one of four mathematical operators.</p>
378+
</body>
379+
</html>

0 commit comments

Comments
 (0)