SPECtrum Processing Routines Data Format 3/4/88: GraphViz block diagram (.dot) source

Specpr records are fixed format, 1536 bytes/record. Record number counting starts at 0. Binary data are in IEEE format real numbers and non-byte swapped integers (compatiible with all Sun Microsystems, and Hewlett Packard workstations (Intel and some DEC machines are byte swapped relative to Suns and HPs). Each record may contain different information according to the following scheme.

You can get some library of spectra from ftp://ftpext.cr.usgs.gov/pub/cr/co/denver/speclab/pub/spectral.library/splib06.library/

File extension

spec

KS implementation details

License: Unlicense

This page hosts a formal specification of SPECtrum Processing Routines Data Format 3/4/88 using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

GraphViz block diagram source

specpr.dot

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

		specpr__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="records_pos">0</TD><TD PORT="records_size">...</TD><TD>Record</TD><TD PORT="records_type">records</TD></TR>
			<TR><TD COLSPAN="4" PORT="records__repeat">repeat to end of stream</TD></TR>
		</TABLE>>];
		subgraph cluster__data_initial {
			label="Specpr::DataInitial";
			graph[style=dotted];

			data_initial__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="ids_pos">0</TD><TD PORT="ids_size">48</TD><TD>Identifiers</TD><TD PORT="ids_type">ids</TD></TR>
				<TR><TD PORT="iscta_pos">48</TD><TD PORT="iscta_size">4</TD><TD>CoarseTimestamp</TD><TD PORT="iscta_type">iscta</TD></TR>
				<TR><TD PORT="isctb_pos">52</TD><TD PORT="isctb_size">4</TD><TD>CoarseTimestamp</TD><TD PORT="isctb_type">isctb</TD></TR>
				<TR><TD PORT="jdatea_pos">56</TD><TD PORT="jdatea_size">4</TD><TD>s4be</TD><TD PORT="jdatea_type">jdatea</TD></TR>
				<TR><TD PORT="jdateb_pos">60</TD><TD PORT="jdateb_size">4</TD><TD>s4be</TD><TD PORT="jdateb_type">jdateb</TD></TR>
				<TR><TD PORT="istb_pos">64</TD><TD PORT="istb_size">4</TD><TD>CoarseTimestamp</TD><TD PORT="istb_type">istb</TD></TR>
				<TR><TD PORT="isra_pos">68</TD><TD PORT="isra_size">4</TD><TD>s4be</TD><TD PORT="isra_type">isra</TD></TR>
				<TR><TD PORT="isdec_pos">72</TD><TD PORT="isdec_size">4</TD><TD>s4be</TD><TD PORT="isdec_type">isdec</TD></TR>
				<TR><TD PORT="itchan_pos">76</TD><TD PORT="itchan_size">4</TD><TD>s4be</TD><TD PORT="itchan_type">itchan</TD></TR>
				<TR><TD PORT="irmas_pos">80</TD><TD PORT="irmas_size">4</TD><TD>s4be</TD><TD PORT="irmas_type">irmas</TD></TR>
				<TR><TD PORT="revs_pos">84</TD><TD PORT="revs_size">4</TD><TD>s4be</TD><TD PORT="revs_type">revs</TD></TR>
				<TR><TD PORT="iband_pos">88</TD><TD PORT="iband_size">4</TD><TD>s4be</TD><TD PORT="iband_type">iband</TD></TR>
				<TR><TD COLSPAN="4" PORT="iband__repeat">repeat 2 times</TD></TR>
				<TR><TD PORT="irwav_pos">96</TD><TD PORT="irwav_size">4</TD><TD>s4be</TD><TD PORT="irwav_type">irwav</TD></TR>
				<TR><TD PORT="irespt_pos">100</TD><TD PORT="irespt_size">4</TD><TD>s4be</TD><TD PORT="irespt_type">irespt</TD></TR>
				<TR><TD PORT="irecno_pos">104</TD><TD PORT="irecno_size">4</TD><TD>s4be</TD><TD PORT="irecno_type">irecno</TD></TR>
				<TR><TD PORT="itpntr_pos">108</TD><TD PORT="itpntr_size">4</TD><TD>s4be</TD><TD PORT="itpntr_type">itpntr</TD></TR>
				<TR><TD PORT="ihist_pos">112</TD><TD PORT="ihist_size">60</TD><TD>str(ascii)</TD><TD PORT="ihist_type">ihist</TD></TR>
				<TR><TD PORT="mhist_pos">172</TD><TD PORT="mhist_size">74</TD><TD>str(ascii)</TD><TD PORT="mhist_type">mhist</TD></TR>
				<TR><TD COLSPAN="4" PORT="mhist__repeat">repeat 4 times</TD></TR>
				<TR><TD PORT="nruns_pos">468</TD><TD PORT="nruns_size">4</TD><TD>s4be</TD><TD PORT="nruns_type">nruns</TD></TR>
				<TR><TD PORT="siangl_pos">472</TD><TD PORT="siangl_size">4</TD><TD>IllumAngle</TD><TD PORT="siangl_type">siangl</TD></TR>
				<TR><TD PORT="seangl_pos">476</TD><TD PORT="seangl_size">4</TD><TD>IllumAngle</TD><TD PORT="seangl_type">seangl</TD></TR>
				<TR><TD PORT="sphase_pos">480</TD><TD PORT="sphase_size">4</TD><TD>s4be</TD><TD PORT="sphase_type">sphase</TD></TR>
				<TR><TD PORT="iwtrns_pos">484</TD><TD PORT="iwtrns_size">4</TD><TD>s4be</TD><TD PORT="iwtrns_type">iwtrns</TD></TR>
				<TR><TD PORT="itimch_pos">488</TD><TD PORT="itimch_size">4</TD><TD>s4be</TD><TD PORT="itimch_type">itimch</TD></TR>
				<TR><TD PORT="xnrm_pos">492</TD><TD PORT="xnrm_size">4</TD><TD>f4be</TD><TD PORT="xnrm_type">xnrm</TD></TR>
				<TR><TD PORT="scatim_pos">496</TD><TD PORT="scatim_size">4</TD><TD>f4be</TD><TD PORT="scatim_type">scatim</TD></TR>
				<TR><TD PORT="timint_pos">500</TD><TD PORT="timint_size">4</TD><TD>f4be</TD><TD PORT="timint_type">timint</TD></TR>
				<TR><TD PORT="tempd_pos">504</TD><TD PORT="tempd_size">4</TD><TD>f4be</TD><TD PORT="tempd_type">tempd</TD></TR>
				<TR><TD PORT="data_pos">508</TD><TD PORT="data_size">4</TD><TD>f4be</TD><TD PORT="data_type">data</TD></TR>
				<TR><TD COLSPAN="4" PORT="data__repeat">repeat 256 times</TD></TR>
			</TABLE>>];
			data_initial__inst__phase_angle_arcsec [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
				<TR><TD>phase_angle_arcsec</TD><TD>(sphase / 1500)</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__coarse_timestamp {
			label="Specpr::CoarseTimestamp";
			graph[style=dotted];

			coarse_timestamp__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="scaled_seconds_pos">0</TD><TD PORT="scaled_seconds_size">4</TD><TD>s4be</TD><TD PORT="scaled_seconds_type">scaled_seconds</TD></TR>
			</TABLE>>];
			coarse_timestamp__inst__seconds [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
				<TR><TD>seconds</TD><TD>(scaled_seconds * 24000)</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__icflag {
			label="Specpr::Icflag";
			graph[style=dotted];

			icflag__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="reserved_pos">0</TD><TD PORT="reserved_size">26b</TD><TD>b26</TD><TD PORT="reserved_type">reserved</TD></TR>
				<TR><TD PORT="isctb_type_pos">3:2</TD><TD PORT="isctb_type_size">1b</TD><TD>BitsType1</TD><TD PORT="isctb_type_type">isctb_type</TD></TR>
				<TR><TD PORT="iscta_type_pos">3:3</TD><TD PORT="iscta_type_size">1b</TD><TD>BitsType1</TD><TD PORT="iscta_type_type">iscta_type</TD></TR>
				<TR><TD PORT="coordinate_mode_pos">3:4</TD><TD PORT="coordinate_mode_size">1b</TD><TD>BitsType1</TD><TD PORT="coordinate_mode_type">coordinate_mode</TD></TR>
				<TR><TD PORT="errors_pos">3:5</TD><TD PORT="errors_size">1b</TD><TD>BitsType1</TD><TD PORT="errors_type">errors</TD></TR>
				<TR><TD PORT="text_pos">3:6</TD><TD PORT="text_size">1b</TD><TD>BitsType1</TD><TD PORT="text_type">text</TD></TR>
				<TR><TD PORT="continuation_pos">3:7</TD><TD PORT="continuation_size">1b</TD><TD>BitsType1</TD><TD PORT="continuation_type">continuation</TD></TR>
			</TABLE>>];
			icflag__inst__type [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
				<TR><TD>type</TD><TD>Kaitai::Struct::Stream::resolve_enum(RECORD_TYPE, (((text ? 1 : 0) * 1) + ((continuation ? 1 : 0) * 2)))</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__data_continuation {
			label="Specpr::DataContinuation";
			graph[style=dotted];

			data_continuation__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="cdata_pos">0</TD><TD PORT="cdata_size">4</TD><TD>f4be</TD><TD PORT="cdata_type">cdata</TD></TR>
				<TR><TD COLSPAN="4" PORT="cdata__repeat">repeat 383 times</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__identifiers {
			label="Specpr::Identifiers";
			graph[style=dotted];

			identifiers__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="ititle_pos">0</TD><TD PORT="ititle_size">40</TD><TD>str(ascii)</TD><TD PORT="ititle_type">ititle</TD></TR>
				<TR><TD PORT="usernm_pos">40</TD><TD PORT="usernm_size">8</TD><TD>str(ascii)</TD><TD PORT="usernm_type">usernm</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__illum_angle {
			label="Specpr::IllumAngle";
			graph[style=dotted];

			illum_angle__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="angl_pos">0</TD><TD PORT="angl_size">4</TD><TD>s4be</TD><TD PORT="angl_type">angl</TD></TR>
			</TABLE>>];
			illum_angle__inst__seconds_total [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
				<TR><TD>seconds_total</TD><TD>(angl / 6000)</TD></TR>
			</TABLE>>];
			illum_angle__inst__minutes_total [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
				<TR><TD>minutes_total</TD><TD>(seconds_total / 60)</TD></TR>
			</TABLE>>];
			illum_angle__inst__degrees_total [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
				<TR><TD>degrees_total</TD><TD>(minutes_total / 60)</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__text_initial {
			label="Specpr::TextInitial";
			graph[style=dotted];

			text_initial__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="ids_pos">0</TD><TD PORT="ids_size">48</TD><TD>Identifiers</TD><TD PORT="ids_type">ids</TD></TR>
				<TR><TD PORT="itxtpt_pos">48</TD><TD PORT="itxtpt_size">4</TD><TD>u4be</TD><TD PORT="itxtpt_type">itxtpt</TD></TR>
				<TR><TD PORT="itxtch_pos">52</TD><TD PORT="itxtch_size">4</TD><TD>s4be</TD><TD PORT="itxtch_type">itxtch</TD></TR>
				<TR><TD PORT="itext_pos">56</TD><TD PORT="itext_size">1476</TD><TD>str(ascii)</TD><TD PORT="itext_type">itext</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__record {
			label="Specpr::Record";
			graph[style=dotted];

			record__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="icflag_pos">0</TD><TD PORT="icflag_size">4</TD><TD>Icflag</TD><TD PORT="icflag_type">icflag</TD></TR>
				<TR><TD PORT="content_pos">4</TD><TD PORT="content_size">...</TD><TD>switch (icflag.type)</TD><TD PORT="content_type">content</TD></TR>
			</TABLE>>];
record__seq_content_switch [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
	<TR><TD BGCOLOR="#F0F2E4">case</TD><TD BGCOLOR="#F0F2E4">type</TD></TR>
	<TR><TD>:record_type_data_initial</TD><TD PORT="case0">DataInitial</TD></TR>
	<TR><TD>:record_type_data_continuation</TD><TD PORT="case1">DataContinuation</TD></TR>
	<TR><TD>:record_type_text_continuation</TD><TD PORT="case2">TextContinuation</TD></TR>
	<TR><TD>:record_type_text_initial</TD><TD PORT="case3">TextInitial</TD></TR>
</TABLE>>];
		}
		subgraph cluster__text_continuation {
			label="Specpr::TextContinuation";
			graph[style=dotted];

			text_continuation__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="tdata_pos">0</TD><TD PORT="tdata_size">1532</TD><TD>str(ascii)</TD><TD PORT="tdata_type">tdata</TD></TR>
			</TABLE>>];
		}
	}
	specpr__seq:records_type -> record__seq [style=bold];
	data_initial__seq:ids_type -> identifiers__seq [style=bold];
	data_initial__seq:iscta_type -> coarse_timestamp__seq [style=bold];
	data_initial__seq:isctb_type -> coarse_timestamp__seq [style=bold];
	data_initial__seq:istb_type -> coarse_timestamp__seq [style=bold];
	data_initial__seq:siangl_type -> illum_angle__seq [style=bold];
	data_initial__seq:seangl_type -> illum_angle__seq [style=bold];
	data_initial__seq:sphase_type -> data_initial__inst__phase_angle_arcsec [color="#404040"];
	coarse_timestamp__seq:scaled_seconds_type -> coarse_timestamp__inst__seconds [color="#404040"];
	icflag__seq:text_type -> icflag__inst__type [color="#404040"];
	icflag__seq:continuation_type -> icflag__inst__type [color="#404040"];
	illum_angle__seq:angl_type -> illum_angle__inst__seconds_total [color="#404040"];
	illum_angle__inst__seconds_total:seconds_total_type -> illum_angle__inst__minutes_total [color="#404040"];
	illum_angle__inst__minutes_total:minutes_total_type -> illum_angle__inst__degrees_total [color="#404040"];
	text_initial__seq:ids_type -> identifiers__seq [style=bold];
	record__seq:icflag_type -> icflag__seq [style=bold];
	record__seq:content_type -> record__seq_content_switch [style=bold];
	record__seq_content_switch:case0 -> data_initial__seq [style=bold];
	record__seq_content_switch:case1 -> data_continuation__seq [style=bold];
	record__seq_content_switch:case2 -> text_continuation__seq [style=bold];
	record__seq_content_switch:case3 -> text_initial__seq [style=bold];
	icflag__inst__type:type_type -> record__seq:content_type [color="#404040"];
}