You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -7,14 +7,16 @@ ScippNeutron can write and, to a limited degree, read SQW files using {mod}`scip
7
7
8
8
```{note}
9
9
There is no official specification for the format of SQW files.
10
-
The contents of this document are based the little bits of documentation that are available, from reading the source code of Horace, and from experimenting with Horace and SQW files.
11
-
It should *not* be regarded as authoritative.
10
+
The contents of this document are based on what documentation is available, on reading the source code of Horace, and on experiments with Horace and SQW files.
11
+
This document should *not* be regarded as authoritative.
12
12
```
13
13
14
+
See, e.g., [07-sqw_redesign.md](https://github.com/pace-neutrons/Horace/blob/3c00958d578c625a7f2274ef7b34557578abb934/documentation/add/07-sqw_redesign.md) for some documentation provided by the developers of Horace.
15
+
14
16
## Overview
15
17
16
18
SQW files are binary files that encode neutron counts both in a flexible binned format called 'pixels' and a multidimensional histogram called 'DND' (or D1D through D4D for concrete cases).
17
-
In addition to the data, SQW files store metadata that describe how the experiment was set up and how the data were binned.
19
+
In addition to the data, SQW files store metadata that describes how the experiment was set up and how the data was binned.
18
20
19
21
### Data Blocks
20
22
@@ -43,7 +45,7 @@ Block names are split into a 'name' and a 'level2_name' which in ScippNeutron ar
43
45
- Histogram data.
44
46
*- experiment_info
45
47
- instruments
46
-
- Information about the instrument where the data were measured. One {class}`SqwIXNullInstrument <scippneutron.io.sqw.SqwIXNullInstrument>` per [run](#Runs). (Horace defines several instrument classes but so far, we have only use the null instrument.)
48
+
- Information about the instrument where the data was measured. One {class}`SqwIXNullInstrument <scippneutron.io.sqw.SqwIXNullInstrument>` per [run](#Runs). (Horace defines several instrument classes. But so far, the null instrument has been sufficient.)
47
49
*- experiment_info
48
50
- samples
49
51
- Information on the sample that was measured. One {class}`SqwIXSample <scippneutron.io.sqw.SqwIXSample>` per [run](#Runs).
@@ -55,7 +57,7 @@ Block names are split into a 'name' and a 'level2_name' which in ScippNeutron ar
55
57
- Information about the pixel data. Largely hidden and automated in ScippNeutron.
56
58
*- pix
57
59
- data_wrap
58
-
- 'Pixel' data, i.e., binned observations as a function of momentum and energy transfer. Stored as a $9 \times N$ array with [rows](https://github.com/pace-neutrons/Horace/blob/master/documentation/add/05_file_formats.md):
60
+
- 'Pixel' data, i.e., binned observations as a function of momentum and energy transfer. Stored as a $9 \times N$ array with these [rows](https://github.com/pace-neutrons/Horace/blob/master/documentation/add/05_file_formats.md) in order:
59
61
-`u1`, `u2`, `u3`, `u4`: usually momentum transfers $Q_x$, $Q_y$, $Q_z$ and energy transfer $\Delta E$.
60
62
-`irun`: [Run](#Runs) index.
61
63
-`idet`: Detector (pixel) index.
@@ -66,11 +68,17 @@ Block names are split into a 'name' and a 'level2_name' which in ScippNeutron ar
66
68
67
69
### Runs
68
70
69
-
Data can be collected in multiple runs or 'settings' where each run has a fixed set of sample parameters.
71
+
Data can be collected in multiple runs or 'settings' where each run has a fixed set of sample and instrument parameters.
70
72
In SQW, runs are encoded by assigning a run index `irun` to each observation and providing an appropriate instrument, sample, and experiment object.
71
73
The instrument and sample objects are often the same for all runs.
72
74
This can be encoded by way of 'unique object containers' which store only one copy of each unique object and indices to associate these objects with runs.
73
75
76
+
### FORTRAN Layout
77
+
78
+
Horace, being a MATLAB program, uses FORTRAN order for arrays and 1-based indexing.
79
+
{mod}`scippneutron.io.sqw` converts between these conventions and the Python conventions automatically in most cases.
80
+
But some data, most notably the pixel array, must be provided with 1-based indices.
81
+
74
82
### Byte Order
75
83
76
84
SQW files do not have a dedicated mechanism for encoding or detecting byte order.
@@ -103,14 +111,14 @@ For Horace version 4.0, this header is
103
111
104
112
### Block Allocation Table
105
113
106
-
The block allocation table (BAT) encodes which data blocks exist and where they are located in the file.
114
+
The block allocation table (BAT) encodes which [data blocks](#data-blocks) exist and where they are located in the file.
Cell arrays are MATLAB’s way of encoding heterogeneous arrays where the elements can have different types.
274
+
Each element is encoded as an [object array](#object-array).
275
+
276
+
In SQW, cell arrays can occur either standalone or within an object array (by way of a struct).
277
+
Standalone cell arrays encode their shape in the same way as an object array.
278
+
Otherwise, they do *not* store their shape; it needs to be provided by the [object array](#object-array) that the cell array is part of.
279
+
280
+
### Object Array
281
+
282
+
Object arrays are homogeneous, multidimensional arrays of any object type.
283
+
They encode their element type using a type tag:
284
+
```text
285
+
| type_tag | shape | data |
286
+
| :uint8 | :Shape | :Any |
287
+
```
288
+
See ``TypeTag`` in the source code for a list of supported types and their tags.
289
+
290
+
Object arrays have some non-trivial interactions with different types.
291
+
292
+
- For **simple types** like numbers, logical, and strings, ``data`` is simply an array of the given type in FORTRAN layout.
293
+
- For **structs**, the data is encoded in a 'struct of arrays' fashion as described in the [Struct](#struct) section.
294
+
- For **cell arrays**, i.e., if the type tag indicated 'cell array', the entire object array is instead processed as a [cell array](#cell-array). This means that ``data`` is an array of object arrays.
295
+
- For **self-serializing** types, there is no shape and ``data`` has to encode how to read it.
296
+
297
+
### Self Serializing
298
+
299
+
Some data is 'self-serializing', meaning that it does not rely on an external type tag and shape to describe the data.
300
+
Instead, if used inside an object array, this data must contain its own type tag.
301
+
In ScippNeutron, this case is treated like a nested object array.
302
+
303
+
### Auxiliary Types
304
+
305
+
These types are not represented by type tags but occur in fixed locations in the file.
306
+
307
+
#### Shape
190
308
191
309
The shape of a multidimensional array.
192
310
Encoded as
@@ -196,10 +314,12 @@ Encoded as
196
314
```
197
315
where `ndim` is the number of dimensions and there are this many `length_i` entries.
198
316
199
-
###Struct
317
+
#### Data Block Type
200
318
201
-
TODO
319
+
Each data block is encoded as a struct with, among others, fields 'serial_name' and 'version' which together identify the block.
320
+
This is used to determine how to deserialize the block into a Python model.
202
321
203
-
###Object Array
322
+
#### Unique Object Container
204
323
205
-
### Self Serializing
324
+
'Unique object container' and 'Unique reference container' are always used together and represent an array of objects where duplicates are only stored once.
325
+
Each 'Unique reference container' contains a 'Unique object container' which in turn contains an array of indices that map from array index to a unique object.
0 commit comments