#!/bin/bash ######################################################################## ### Reads label to get data offsets in FITS ### Read FITS data to make table ### Usage: newrex_bash.bash __rawdata/rex_003031500?_0x7b3_eng_*.lbl ######################################################################## ### Extract ordinal-1 of 2880-byte FITS record from PDS label file ### e.g. extract the "13" from a line like this: ### ### ^EXTENSION_IQVALS_TABLE = ("REX_0030315000_0X7B3_ENG_1.FIT", 13) function getifitrec() { line=( `head -1 | tr '\" (),\r' ' '` ) echo "${line[3]}-1" } ######################################################################## ### Usage: headfit file.fit 12880 10000 ### - output 10000 bytes, starting at an offset of 2880 bytes past the ### 1st byte (ordinal byte 2881), from file file.fit start function headfit() { fit="$1" rtheadbytes="$2" rtbytes="$3" head -${rtheadbytes}c $fit \ | tail -c -$rtbytes } ######################################################################## ### ASCII codes for A and B are odd and even, respectively ### So if 2-byte string AB is interpreded as 2-byte integer, it will ### be odd if the local system is LSByte-first, and it will be even ### if the local system is MSByte-first. unset lsbfirst unset msbfirst echo "AB" \ | od -w2 -t d2 \ | head -1 \ | ( read a b ; let b=$b%2 ; [ $b -eq 1 ] ) \ && lsbfirst=yes || msbfirst=yes ### lsbfirst=yes if local system is LSByte-first: ### - [ "$lsbfirst" ] evaluates true ### - [ "$msbfirst" ] evaluates false ### msbfirst=yes if local system is MSByte-first: ### - [ "$lsbfirst" ] evaluates false ### - [ "$msbfirst" ] evaluates true #################################### ### Function to swap, if necessary, ### N MSByte-first bytes at a time ### from STDIN to local byte order ### ### Usage: doNswap 12 < MSByte-firstStream.dat > LocalByteOrderStream.dat ### ### - N is $1; N <= 32 ### - Input stream length must be a multiple of N ### - This routine does nothing if local architecture ### is already MSByte-first function doNswap() { if [ "$lsbfirst" ] ; then let n=$1 let rn=32-$n fwd="0123456789abcdefghijklmnopqrstuv" bck="vutsrqponmlkjihgfedcba9876543210" fwd=${fwd:0:n} bck=${bck:$rn:$n} od -b -v -w$n \ | sed -e 's/^[0-9]* *//' \ | grep . \ | while read octal3s ; do to=`echo " $octal3s" | sed -e 's/ */\\\\/g'` echo -n $fwd | tr $bck $to done else cat fi } function OBSOLETE_doNswap() { [ "$lsbfirst" ] && ./nswap $1 || cat } ######################################################################## ### Temporary files tmppfx=/tmp/newrex_bash.$$.`date +%Y%m%d%H%M%S` tmprad="$tmppfx.rad" tmprt="$tmppfx.rt" ### Main function while [ $# -gt 0 ] ; do ### Get and consume first command-line argument lbl="$1" ; shift ### Ensure end in .lbl [ "${lbl%.lbl}" == "$lbl" ] && ( echo "### Skipping $lbl" 1>&2 || true ) && continue ### Build FITS pathname from PDS label path name fit="${lbl%lbl}fit" ### Determine if FitS file is Raw or Calibrated [ "${fit/_0x7b?_sci_[1-9]*.fit}" == "$fit" ] && isRaw=yes || unset isRaw ### Get 2880-byte FITS record offsets to ### IQ and Radiometry/TimeTag BINTABLES let iqoffset=`grep '^ *[\^]EXTENSION_IQVALS_TABLE *= *(' "$lbl" | getifitrec` let rtoffset=`grep '^ *[\^]EXTENSION_RAD_TIME_TAGS_TABLE *= *(' "$lbl" | getifitrec` ###OBSOLETE### ### Ensure nswap application exists ###OBSOLETE### make nswap > /dev/null ### Calculate byte offsets let iqbyteoffset=2880*$iqoffset let rtbyteoffset=2880*$rtoffset ### Determine BINTABLE data lengths and other parameters ### - rtbytes: Radiometry and Time Tags; 10 rows x [12(Raw) or 8(Cal.)] bytes/row ### - iqbytes: IQ; 1250 rows x [4(Raw) or 8(Cal.)] bytes/row ### - iqtype: IQ data type for od: d2(Raw; int16) or f4(Cal.; float32) ### - NEWREXFMT: gawk format for output columns, environment variable if [ "$isRaw" ] ; then let rtbytes=120 let iqbytes=5000 iqtype=d2 export NEWREXFMT="%16d" else let rtbytes=80 let iqbytes=10000 iqtype=f4 export NEWREXFMT="%16.4f" fi ### Calculate total number of bytes from start of file to end of ### each BINTABLE let iqheadbytes=$iqbyteoffset+$iqbytes let rtheadbytes=$rtbyteoffset+$rtbytes if [ "$isRaw" ] ; then ### Raw: Radiometry (int64) and Time Tags (int32) ### Stored in FITS BINTABLE as RRRRRRRRTTTTrrrrrrrrtttt... MSByte-first ### Byteswap - if local system is LSByte-first - using doNswap 12 ### Will change that to this: ### TTTTRRRRRRRRttttrrrrrrrr... LSByte-first [ "$lsbfirst" ] && skip=4 || skip=0 ### Extract 8-byte Radiometry values in two passes ### - Rows 1,3,5,7,9 ### - Rows 2,4,6,8,10 for rtidx0 in 1 2 ; do rtidx=$rtidx0 headfit $fit $rtheadbytes $rtbytes \ | doNswap 12 \ | od -v --skip-bytes=$skip -w24 -t d8 \ | while read pfx d8 xxx ; do [ "$d8" ] && echo $rtidx $d8 let rtidx=$rtidx+2 done let skip=$skip+12 done \ | sort -n \ | while read nnn d8 ; do echo $d8 ; done \ > "$tmprad" [ "$lsbfirst" ] && skip=0 || skip=8 ### Extract 4-byte Time Tag values in one pass ### - Rows are 12 bytes each; every third int32 is a Time Tag headfit $fit $rtheadbytes $rtbytes \ | doNswap 12 \ | od -v --skip-bytes=$skip -w12 -t d4 \ | while read pfx d4 xxx ; do echo $d4 ; done \ | paste $tmprad - rm -f "$tmprad" 1>/dev/null 2>&1 else ### Calibrated: Radiometry and Time Tags as float32s headfit $fit $rtheadbytes $rtbytes \ | doNswap 8 \ | od -v -w8 -t f4 \ | head -10 \ | while read pfx ttg rad xxx ; do echo $rad $ttg ; done \ \ fi \ > "$tmprt" ### Raw or Calibrated IQ BINTABLE ### - paste 10 lines of Radiometry/TimeTag BINTABLE to ### first 10 lines of IQ BINTABLE ### - Use GAWK and NEWREXFMT envvvar to output columns let iqbyteperrow=$iqbytes/1250 headfit $fit $iqheadbytes $iqbytes \ | doNswap $iqbyteperrow \ | od -v -w$iqbyteperrow -t $iqtype \ | head -1250 \ | while read pfx qval ival xxx ; do echo $ival $qval ; done \ | paste - "$tmprt" \ | tr \\t \ \ | sed 's/ *$//' \ | gawk ' BEGIN { fmt=ENVIRON["NEWREXFMT"] } { printf "%5d", FNR for (i=1; i<=NF; ++i) { printf fmt, $i } print "" } ' rm -f "$tmprt" 1>/dev/null 2>&1 done exit 0