Thread: Cutting down a month-long data file into daily files

Started: 2018-05-06 04:26:11
Last activity: 2018-05-06 04:26:11
Topics: SAC Help
George Helffrich
2018-05-06 04:26:11
Dear All -

Here’s a set of tested solutions to the earlier question about cutting a monthly SAC data file into daily files. It corrects flaws in the earlier solutions and tidies up the resulting file headers.

Test data: copy this into a file, say “generate”, then invoke it as a SAC macro.

funcgen line (1 / 86400) 0 npts 86400 delta 1; w /tmp/day ;* 1 day
do i = 1 , 31
merge checktimes off /tmp/day ;* append
enddo
ch nzyear 2000 nzjday 1 nzhour 00 nzmin 00 nzsec 00 nzmsec 00 ;* date
w /tmp/month
sc rm /tmp/day ;* tidy

Assuming your month-long data starts at midnight on the start of the month (the test data does), a straightforward way — but one that re-reads the monthly data file a lot — is to use a macro like this:

* SAC macro to cut monthly data file into days, re-reading monthly file
* Does not handle leap seconds; may fail with high sample rates
* due to loss of precision calculating npts.
* Usage: dodaily mdat <monthly> days <days>
$keys mdat days
rh $mdat$
setbb npts (86400 * &1,delta&)
do d = 1 , $days$
setbb strt (86400 * ($d$ - 1))
cut %strt% n %npts%
read $mdat$
cut off
synchronize
write day$d$
enddo
unsetbb strt npts

Copy/paste the data into a file, say “dodaily” and then invoke the macro in SAC supplying the monthly data file name (as mdat - the example uses the test data) and the number of days in the month (as days):

macro generate ;* only needed once for testing
macro dodaily mdat /tmp/month days 28

and it will leave a string of files named day1, day2, day3, … day28 in the directory where the macro is invoked. 28 days for Feb., 30 or 31 for the rest of the months.

A more complex solution reads the monthly data file once and uses CUTIM to make multiple cuts. It is not as clear as the previous solution ... and may cause some versions of SAC to choke on long command lines or odd statement syntax:

* SAC macro to cut monthly data file into days, monthly file read once
* Does not handle leap seconds; may fail with high sample rates
* due to loss of precision calculating npts.
* Usage: dodaily mdat <monthly> days <days>
$keys mdat days
rh $mdat$
setbb cuts "" files "" npts (86400 * &1,delta&)
do d = 1 , $days$
setbb cuts append " (86400 * ($d$ - 1)) n %npts%"
setbb files append " day$d$"
enddo
read $mdat$
cutim %cuts%
write %files%
do d = 1 , $days$
rh day$d$; synchronize; wh
enddo
unsetbb cuts files npts

Use it the same way as before.

You can verify in SAC by typing:

r day[,1,2,3][0,1,2,3,4,5,6,7,8,9] ;* or "r day*" (unordered)
p1

George Helffrich
george<at>elsi.jp


05:46:17 v.b4412d20