#!/usr/bin/perl =head1 NAME reformat.pl - EDR2 reformatter =head1 SYNOPSIS ./reformat.pl FILE.DAT =head1 DESCRIPTION The reformat.pl converts EDR2 separated data to reformatted text. =cut use strict; my $filepath = $ARGV[0]; sub main { my $index; my $count; my $data; my (%info, %info1, %info2, %info3); my (@ixa,@ixz,@iya,@iyz,@iza,@izz)=(); my $line_num=-1; while(my $line=<>) { if ($line =~ /HZ/) { $line_num = 0; } if ($line_num == 0) { if ($index > 0) { %info = (%info1, %info2, %info3); &dump(\%info); } $index = 0; %info1 = &parse_first_line($line); $count = $info1{'NDATA'}; } elsif ($line_num == 1) { %info2 = &parse_second_line($line); # Add SOL information my $doy = &get_sequential_days_from_1976($info2{'IYEAR'},$info1{'IDAY'}); my ($sol, $hour, $min, $csec) = &gcsc2llt($info2{'IGCSC'},$doy); $info2{'LLT'} = sprintf("%2d/%02d:%02d:%02d\n", $sol, $hour, $min, int($csec/100.0)); # Add file information $info2{'FILE'} = &predict_filename($filepath); } else { # FORMAT: 4X,12(I4,I2) if ($line_num == 2) { $data = substr($line,10); } else { $data = substr($line,6); } my $loop = $count; if ($count > 4) { $loop = 4; } $count -= $loop; for(my $i=0; $i<$loop; ++$i) { $ixa[$index]=substr($data,$i*18+0,4); $ixz[$index]=substr($data,$i*18+4,2); $iya[$index]=substr($data,$i*18+6,4); $iyz[$index]=substr($data,$i*18+10,2); $iza[$index]=substr($data,$i*18+12,4); $izz[$index]=substr($data,$i*18+16,2); $index++; } $info3{'IXA'} = \@ixa; $info3{'IXZ'} = \@ixz; $info3{'IYA'} = \@iya; $info3{'IYZ'} = \@iyz; $info3{'IZA'} = \@iza; $info3{'IZZ'} = \@izz; } $line_num++; } if ($index > 0) { %info = (%info1, %info2, %info3); &dump(\%info); } } sub dump { my ($info) = @_; my @items = ('FILE','ISAS','LNDR','ISDR','IDEC','IDAY','ITIME', 'IRUN','NDATA','IMODE','MODE','VATTEN','HATTEN', 'TLEVEL','FILT','FMODE','XTRIG','YTRIG','ZTRIG', 'CAL','IYEAR','IGCSC','SEC','LLT'); foreach my $item (@items) { chomp(${$info}{$item}); ${$info}{$item} =~ s/ //g; print "#$item: " . ${$info}{$item} . "\n"; } print "# IXA IXZ IYA IYZ IZA IZZ\n"; for(my $i=0; $i<${$info}{'NDATA'}; $i++) { printf(" %4d %4d %4d %4d %4d %4d\n", ${$info}{'IXA'}[$i], ${$info}{'IXZ'}[$i], ${$info}{'IYA'}[$i], ${$info}{'IYZ'}[$i], ${$info}{'IZA'}[$i], ${$info}{'IZZ'}[$i]); } } sub parse_first_line { my $first = shift; my $offset = 7; my (%data)=(); # LNDR(integer) Lander. Allowed values, 1=VL1, 2=VL2. # FORMAT: I1 $data{'LNDR'} = substr($first,$offset,1); $offset += 1; # ISAS(integer) Buffer number assigned by program SASEIS. should # start at 1000 and increment by 10. # FORMAT: I7 $data{'ISAS'} = substr($first,$offset,7); $offset += 7; # ISDR(integer) No meaning. Apparently usually 0. # FORMAT: I5 $data{'ISDR'} = substr($first,$offset,5); $offset += 5; # IDEC(integer) Program DECSET sequence number. Little meaning. # FORMAT: I5 $data{'IDEC'} = substr($first,$offset,5); $offset += 5; # IDAY(integer) GMT day of first data sample, x-component. # FORMAT: I3 $data{'IDAY'} = substr($first,$offset,3); $offset += 3; # ITIME(integer) GMT time in milliseconds (apparently after the # nearest hour) of earth receipt of first bit of # the buffer. # FORMAT: I10 $data{'ITIME'} = substr($first,$offset,10); $offset += 10; # IRUN(integer) Run number. Little meaning. # FORMAT: I3 $data{'IRUN'} = substr($first,$offset,3); $offset += 3; # NDATA(integer) # FORMAT: I2 $data{'NDATA'} = substr($first,$offset,2); $offset += 2; # IMODE(integer) Integer code denoting mode of operation of # seismometer. 1 = normal mode, 2 = event mode, # 3 = high data mode. # FORMAT: I1 $data{'IMODE'} = substr($first,$offset,1); $offset += 1; # MODE(hollerith) Mode of operation of seismometer, allowed value, # 'NORMAL', 'EVENT', 'HIGH'. # FORMAT: A6 $data{'MODE'} = substr($first,$offset,6); $offset += 6; # VATTEN('') Vertical (x-component) attenuation. Allowed # values ' 0DB', ' 6DB', '12DB', '18DB', '24DB', # '30DB', '36DB' # FORMAT: A6 $data{'VATTEN'} = substr($first,$offset,6); $offset += 6; # HATTEN('') Horizontal (y- and z-component) attenuation. # Allowed values as for VATTEN. # FORMAT: A6 $data{'HATTEN'} = substr($first,$offset,6); $offset += 6; # TLEVEL('') Trigger level (see report on operation of the # instrument). Signal must rise above background # by this factor to trigger into EVENT mode. Has # no meaning if trigger is not set. Allowed values # ' X4', ' X8', ' X12', ' X16', ' X20'. # FORMAT: A6 $data{'TLEVEL'} = substr($first,$offset,6); $offset += 6; # FILT('') Rollover point for the hi-pass filter. Has no # meaning for EVENT mode (filter cannot be used in # this mode). Allowed values '.5Hz'. '1.HZ', '2.HZ', # '4.HZ', ' ' $data{'FILT'} = substr($first,$offset,6); $offset += 6; return (%data); } sub parse_second_line { my $second = shift; my $offset = 7; my (%data)=(); # FMODE ('') Indicates status of filter range. Allowed values # 'FIX', 'STEP', 'FIX' indicates IFILT value holds # for entire buffer. 'STEP' (only allowable in # NORMAL mode) indicates that first 8 data samples # are at IFILT setting; filter the cycles through # all possible values in the sense .5HZ -> 1.HZ -> 2.HZ # -> 4.HZ -> .5HZ, etc. at 8 data sample intervals. Has # no meaning in EVENT mode. # FORMAT: A6 $data{'FMODE'} = substr($second,$offset,6); $offset += 6; # XTRIG ('') Trigger status of x-component (any or all of the # tirggers may be enabled at any time). Allowed # values 'XON', 'XOFF'. # FORMAT: A6 $data{'XTRIG'} = substr($second,$offset,6); $offset += 6; # YTRIG ('') Trigger status of y-component Allowed values # 'YON', 'YOFF'. # FORMAT: A6 $data{'YTRIG'} = substr($second,$offset,6); $offset += 6; # ZTRIG ('') Trigger status of z-component Allowed values # 'ZON', 'ZOFF'. # FORMAT: A6 $data{'ZTRIG'} = substr($second,$offset,6); $offset += 6; # CAL('') Calibration status. Only has meaning in high # data rate. Allowed values 'CALON' (indicating # calibration sequence), 'CALOFF'. # FORMAT: A6 $data{'CAL'} = substr($second,$offset,6); $offset += 6; # IYEAR(integer) Year # FORMAT: I5 $data{'IYEAR'} = substr($second,$offset,5); $offset += 5; # IGCSC(integer) Integer count kept by the GCSC (Guidance command # and sequencing computer) for timing. One bit in # this count represents 160 milliseconds (nominal). # Note that because of limitations on the number # of bits available, this number cycles throught 0 # approximately every 31 days. This number is the # original source for IDAY and SEC. # FORMAT: I10 $data{'IGCSC'} = substr($second,$offset,10); $offset += 10; # SEC(real) Seconds into GMT day of first sample, x-component. # FORMAT: E16.8 $data{'SEC'} = substr($second,$offset,16); $offset += 16; return (%data); } sub gcsc2llt { my $gcsc = shift; my $doy = shift; my $SOL_CSEC = 8877525; my $lo0 = 2344400.0; my @maxg = (11242789,36555517,67108864,93338597,134217728,201326592,320000000); my @cg = (8.4276E-6,8.99984E-6,1.01318E-5,1.81923E-5,1.38394E-5,1.36977E-5,1.47743E-5); my @lo = (0,103,765,9420,2919,2614,6082); my ($ige,$ge16,$t,$tr); my ($sol,$hour,$min,$csec); my $i; $ige = ($doy-232)*540000-$gcsc; $ige &= 0xff000000; $ige += $gcsc; for ($i=0; $i<7; ++$i) { if ($ige <= $maxg[$i]) { last; } } $ge16 = $ige * 16.0; $t = ($ge16-$cg[$i]*$ge16+$lo[$i]+$lo0)/$SOL_CSEC; $sol = int($t); $tr = ($t-$sol)*($SOL_CSEC/360000.0); $hour = int($tr); $tr=($tr-$hour)*60; $min = int($tr); $csec = int(($tr-$min)*6000+0.5); return ($sol,$hour,$min,$csec); } sub get_sequential_days_from_1976 { my $year = shift; my $doy = shift; my $ret = -1; if ($year == 1976) { $ret = $doy; } elsif ($year == 1977) { $ret = 366 + $doy; } elsif ($year == 1978) { $ret = 366 + 365 + $doy; } return $ret; } sub predict_filename { my $path = shift; if ($path =~ /(DD[0-9]+_F.?)/) { return $1; } return ""; } &main; __END__ =head1 AUTHOR Yukio Yamamoto (Japan Aerospace Exploration Agency) =cut