.roh file format: GraphViz block diagram (.dot) source

Avantes USB spectrometers are supplied with a Windows binary which generates one ROH and one RCM file when the user clicks "Save experiment". In the version of 6.0, the ROH file contains a header of 22 four-byte floats, then the spectrum as a float array and a footer of 3 floats. The first and last pixel numbers are specified in the header and determine the (length+1) of the spectral data. In the tested files, the length is (2032-211-1)=1820 pixels, but Kaitai determines this automatically anyway.

The wavelength calibration is stored as a polynomial with coefficients of 'wlintercept', 'wlx1', ... 'wlx4', the argument of which is the (pixel number + 1), as found out by comparing with the original Avantes converted data files. There is no intensity calibration saved, but it is recommended to do it in your program - the CCD in the spectrometer is so uneven that one should prepare exact pixel-to-pixel calibration curves to get reasonable spectral results.

The rest of the header floats is not known to the author. Note that the newer version of Avantes software has a different format, see also https://kr.mathworks.com/examples/matlab/community/20341-reading-spectra-from-avantes-binary-files-demonstration

The RCM file contains the user-specified comment, so it may be useful for automatic conversion of data.

Written and tested by Filip Dominec, 2017

File extension

roh

KS implementation details

License: CC0-1.0

This page hosts a formal specification of .roh file format using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

GraphViz block diagram source

avantes_roh60.dot

digraph {
	rankdir=LR;
	node [shape=plaintext];
	subgraph cluster__avantes_roh60 {
		label="AvantesRoh60";
		graph[style=dotted];

		avantes_roh60__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
			<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
			<TR><TD PORT="unknown1_pos">0</TD><TD PORT="unknown1_size">4</TD><TD>f4le</TD><TD PORT="unknown1_type">unknown1</TD></TR>
			<TR><TD PORT="wlintercept_pos">4</TD><TD PORT="wlintercept_size">4</TD><TD>f4le</TD><TD PORT="wlintercept_type">wlintercept</TD></TR>
			<TR><TD PORT="wlx1_pos">8</TD><TD PORT="wlx1_size">4</TD><TD>f4le</TD><TD PORT="wlx1_type">wlx1</TD></TR>
			<TR><TD PORT="wlx2_pos">12</TD><TD PORT="wlx2_size">4</TD><TD>f4le</TD><TD PORT="wlx2_type">wlx2</TD></TR>
			<TR><TD PORT="wlx3_pos">16</TD><TD PORT="wlx3_size">4</TD><TD>f4le</TD><TD PORT="wlx3_type">wlx3</TD></TR>
			<TR><TD PORT="wlx4_pos">20</TD><TD PORT="wlx4_size">4</TD><TD>f4le</TD><TD PORT="wlx4_type">wlx4</TD></TR>
			<TR><TD PORT="unknown2_pos">24</TD><TD PORT="unknown2_size">4</TD><TD>f4le</TD><TD PORT="unknown2_type">unknown2</TD></TR>
			<TR><TD COLSPAN="4" PORT="unknown2__repeat">repeat 9 times</TD></TR>
			<TR><TD PORT="ipixfirst_pos">60</TD><TD PORT="ipixfirst_size">4</TD><TD>f4le</TD><TD PORT="ipixfirst_type">ipixfirst</TD></TR>
			<TR><TD PORT="ipixlast_pos">64</TD><TD PORT="ipixlast_size">4</TD><TD>f4le</TD><TD PORT="ipixlast_type">ipixlast</TD></TR>
			<TR><TD PORT="unknown3_pos">68</TD><TD PORT="unknown3_size">4</TD><TD>f4le</TD><TD PORT="unknown3_type">unknown3</TD></TR>
			<TR><TD COLSPAN="4" PORT="unknown3__repeat">repeat 4 times</TD></TR>
			<TR><TD PORT="spectrum_pos">84</TD><TD PORT="spectrum_size">4</TD><TD>f4le</TD><TD PORT="spectrum_type">spectrum</TD></TR>
			<TR><TD COLSPAN="4" PORT="spectrum__repeat">repeat (((ipixlast).to_i - (ipixfirst).to_i) - 1) times</TD></TR>
			<TR><TD PORT="unknown4_pos">...</TD><TD PORT="unknown4_size">4</TD><TD>f4le</TD><TD PORT="unknown4_type">unknown4</TD></TR>
			<TR><TD COLSPAN="4" PORT="unknown4__repeat">repeat 3 times</TD></TR>
		</TABLE>>];
	}
	avantes_roh60__seq:ipixlast_type -> avantes_roh60__seq:spectrum__repeat [color="#404040"];
	avantes_roh60__seq:ipixfirst_type -> avantes_roh60__seq:spectrum__repeat [color="#404040"];
}