├── scripts
├── NCISP6.xls
├── stainfo.lst
├── reftek2sac_clean.py
├── reftek2sac_p_clean.py
├── reftek2sac2_p_clean.py
├── cutdata.py
├── cutdata_p.py
├── cutdata2_p.py
├── cutdata2.py
├── reftek2sac.py
└── reftek2sac_p.py
├── makePZfiles
├── NCISP6.xls
├── DAS_RESP_pool.zip
├── Sensor_RESP_pool.zip
├── das_used.lst
├── sensor_used.lst
└── README
├── .editorconfig
├── ANCC
├── config.guess
├── src
│ ├── TF_PWS
│ │ ├── Makefile
│ │ ├── sacrw.c
│ │ └── mysac.h
│ ├── AFTAN
│ │ ├── Makefile
│ │ ├── swapn.c
│ │ ├── ftfilt.f90
│ │ ├── trigger.f90
│ │ ├── fmax.f90
│ │ ├── pred_cur.f90
│ │ ├── tapers.f90
│ │ ├── aftan.h
│ │ ├── fftw3.f
│ │ ├── phtovel.f90
│ │ ├── taper.f90
│ │ ├── tgauss.f90
│ │ ├── AFTAN.f90
│ │ ├── cucss2sac.h
│ │ ├── dispio.f90
│ │ └── misc.c
│ └── ANCC
│ │ ├── Makefile
│ │ ├── fftw3.f
│ │ ├── math.f90
│ │ ├── db_m.f90
│ │ ├── date_time.f90
│ │ ├── bindata_io.f90
│ │ └── string.f90
├── Makefile
├── guess.flags
└── README
├── run
├── ref1Dmod.dat
├── input.dat
└── run.py
└── README.md
/scripts/NCISP6.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YoushanLiu/ANCC/HEAD/scripts/NCISP6.xls
--------------------------------------------------------------------------------
/makePZfiles/NCISP6.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YoushanLiu/ANCC/HEAD/makePZfiles/NCISP6.xls
--------------------------------------------------------------------------------
/makePZfiles/DAS_RESP_pool.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YoushanLiu/ANCC/HEAD/makePZfiles/DAS_RESP_pool.zip
--------------------------------------------------------------------------------
/makePZfiles/Sensor_RESP_pool.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/YoushanLiu/ANCC/HEAD/makePZfiles/Sensor_RESP_pool.zip
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # top-most EditorConfig file
2 | root = true
3 |
4 | # all files
5 | [*]
6 | indent_style = tab
7 | indent_size = 4
8 |
--------------------------------------------------------------------------------
/makePZfiles/das_used.lst:
--------------------------------------------------------------------------------
1 | das_resp_file das_type das_gain das_sampling_rate
2 | RESP.XX.NR006..BHZ.130.1.40 130 1 40.0
3 |
--------------------------------------------------------------------------------
/makePZfiles/sensor_used.lst:
--------------------------------------------------------------------------------
1 | PZ_filename keyword1 keyword2
2 | CMG3ESP.30.2000 ESP 30
3 | CMG3ESP.60.2000 ESP 60
4 | CMG3T.120.1500 3T
5 |
6 |
--------------------------------------------------------------------------------
/ANCC/config.guess:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 |
4 | MPIFC=$1
5 |
6 | rm -rf config.h
7 |
8 | # configure config.h using the flags in guess.flags
9 | source ./guess.flags
10 | guess_flags $MPIFC
11 | if [[ $? != 1 ]]; then
12 | exit -1
13 | fi
14 |
--------------------------------------------------------------------------------
/ANCC/src/TF_PWS/Makefile:
--------------------------------------------------------------------------------
1 | include ../../config.h
2 |
3 | LIBS = -lfftw3f
4 |
5 |
6 | ifeq ($(findstring gcc, $(CC)), gcc)
7 | LIBS += -lm
8 | endif
9 |
10 |
11 | BIN = TF_PWS
12 |
13 | OBJS = sacrw.o st.o tf_pws.o
14 |
15 |
16 | build: $(BIN)
17 | $(BIN): $(OBJS)
18 | -rm -rf $(INST_DIR)/$(BIN)
19 | $(CC) $(CFLAGS) $(OBJS) $(LIBS) -o $(INST_DIR)/$(BIN)
20 |
21 |
22 | clean:
23 | rm -rf *.o
24 |
25 | cleanall: clean
26 | rm -rf $(INST_DIR)/$(BIN)
27 |
28 |
29 | %.o: %.c
30 | $(CC) $(CFLAGS) -c $< -o $@
31 |
32 |
33 | # dependencies
34 | tf_pws.o: sacrw.o st.o
35 |
--------------------------------------------------------------------------------
/makePZfiles/README:
--------------------------------------------------------------------------------
1 | A script to generate instrument response automatically.
2 |
3 | After you download this script, you should first uncompress the DAS_RESP_Pool and Sensor_RESP_Pool.
4 |
5 | In this folder, you can generate automatically instrument response polezero files using resp2pz.py or makePZs.py
6 | once fill an Excel sheet, /DAS_RESP_Pool/das_used.lst, /Sensor_RESP_Pool/sensor_used.lst based on your project log.
7 | The former can take the responses of the sensor and DAS into consideration, it will merge them into one PZ file.
8 | And both das_used.lst and sensor_used.lst are required.
9 | While the latter only takes the response of the sensor into consideration,
10 | then generte corresponding PZ files automatically. Thus, only sensor_used.lst is required.
11 |
--------------------------------------------------------------------------------
/ANCC/src/AFTAN/Makefile:
--------------------------------------------------------------------------------
1 | include ../../config.h
2 |
3 | BIN = AFTAN
4 |
5 | LIBS = -lfftw3
6 |
7 | OBJS = misc.o swapn.o taper.o dispio.o ftfilt.o fmax.o trigger.o tapers.o tgauss.o mspline.o pred_cur.o phtovel.o aftanpg.o aftanipg.o AFTAN.o
8 |
9 |
10 | build: $(BIN)
11 | $(BIN): $(OBJS)
12 | -rm -rf $(INST_DIR)/$(BIN)
13 | ifeq ($(wildcard $(INST_DIR)),)
14 | mkdir $(INST_DIR)
15 | endif
16 | $(FC) $(FFLAGS) $(OBJS) $(LIBS) -o $(INST_DIR)/$(BIN)
17 |
18 | clean:
19 | rm -rf $(OBJS) *.mod *__genmod.f90
20 |
21 | cleanall:
22 | rm -rf $(INST_DIR)/$(BIN)
23 |
24 |
25 | # C
26 | %.o: %.c
27 | $(CC) $(CFLAGS) -c $< -o $@
28 |
29 | # Fortran
30 | %.o: %.f90
31 | $(FC) $(FFLAGS) -c $< -o $@
32 | %.o: %.f
33 | $(FC) $(FFLAGS) -c $< -o $@
34 |
35 |
36 | # dependencies
37 | misc.o: swapn.o
38 | dispio.o: misc.o
39 |
--------------------------------------------------------------------------------
/ANCC/src/ANCC/Makefile:
--------------------------------------------------------------------------------
1 | include ../../config.h
2 |
3 | BIN = ANCC
4 |
5 | LIBS = -lfftw3f
6 |
7 |
8 | OBJS = db_m.o string.o sac_io.o date_time.o bindata_io.o math.o xcc.o ANCC.o butter.o
9 |
10 |
11 | build: $(BIN)
12 | $(BIN): $(OBJS)
13 | -rm -rf $(INST_DIR)/$(BIN)
14 | $(MPIFC) $(FFLAGS) $(OBJS) $(LIBS) -o $(INST_DIR)/$(BIN)
15 |
16 | clean:
17 | rm -rf *.o *.mod *_genmod.f90
18 |
19 | cleanall: clean
20 | rm -rf $(INST_DIR)/$(BIN)
21 |
22 |
23 | %.o: %.f90
24 | $(MPIFC) $(FFLAGS) -c $< -o $@
25 | %.o: %.for
26 | $(MPIFC) $(FFLAGS) -c $< -o $@
27 | %.o: %.f
28 | $(MPIFC) $(FFLAGS) -c $< -o $@
29 |
30 |
31 | # dependencies
32 | ANCC.o: db_m.o xcc.o
33 | math.o: db_m.o
34 | sac_io.o: db_m.o
35 | date_time.o: db_m.o
36 | bindata_io.o: db_m.o sac_io.o
37 | xcc.o: db_m.o math.o sac_io.o string.o date_time.o bindata_io.o
38 |
--------------------------------------------------------------------------------
/run /ref1Dmod.dat:
--------------------------------------------------------------------------------
1 | 2.0 2.9800
2 | 3.0 2.9999
3 | 4.0 3.0200
4 | 5.0 3.0984
5 | 6.0 3.1067
6 | 7.0 3.1273
7 | 8.0 3.1457
8 | 9.0 3.1716
9 | 10.0 3.2055
10 | 11.0 3.2437
11 | 12.0 3.2827
12 | 13.0 3.3197
13 | 14.0 3.3559
14 | 15.0 3.3929
15 | 16.0 3.4305
16 | 17.0 3.4678
17 | 18.0 3.5044
18 | 19.0 3.5396
19 | 20.0 3.5728
20 | 21.0 3.6035
21 | 22.0 3.6318
22 | 23.0 3.6579
23 | 24.0 3.6815
24 | 25.0 3.7022
25 | 26.0 3.7206
26 | 27.0 3.7372
27 | 28.0 3.7520
28 | 29.0 3.7650
29 | 30.0 3.7767
30 | 31.0 3.7875
31 | 32.0 3.7973
32 | 33.0 3.8058
33 | 34.0 3.8132
34 | 35.0 3.8199
35 | 36.0 3.8261
36 | 37.0 3.8318
37 | 38.0 3.8372
38 | 39.0 3.8422
39 | 40.0 3.8469
40 | 41.0 3.8513
41 | 42.0 3.8556
42 | 43.0 3.8597
43 | 44.0 3.8639
44 | 45.0 3.8683
45 | 46.0 3.8729
46 | 47.0 3.8778
47 | 48.0 3.8831
48 | 49.0 3.8888
49 | 50.0 3.8949
50 | 51.0 3.9015
51 | 52.0 3.9081
52 | 53.0 3.9145
53 | 54.0 3.9202
54 | 55.0 3.9247
55 | 56.0 3.9279
56 | 57.0 3.9300
57 | 58.0 3.9316
58 | 59.0 3.9331
59 | 60.0 3.9351
60 | 61.0 3.9379
61 | 62.0 3.9414
62 | 63.0 3.9455
63 | 64.0 3.9500
64 | 65.0 3.9546
65 | 66.0 3.9592
66 | 67.0 3.9636
67 | 68.0 3.9676
68 | 69.0 3.9710
69 | 70.0 3.9736
70 |
--------------------------------------------------------------------------------
/ANCC/src/AFTAN/swapn.c:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of ANCC.
3 |
4 | AFTAN is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 3 of the License, or
7 | (at your option) any later version.
8 |
9 | AFTAN is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License
15 | along with this program. If not, see .
16 |
17 | */
18 | /*
19 | * Byte swap an array of length n of N byte integer*4 or real*4 elements.
20 | * A good compiler should unroll the inner loops. Letting the compiler do it
21 | * gives us portability. Note that we might want to isolate the
22 | * cases N = 2, 4, 8 (and 16 for long double and perhaps long long)
23 | */
24 | #define SWAP2(a, b) \
25 | { \
26 | (a) ^= (b); \
27 | (b) ^= (a); \
28 | (a) ^= (b); \
29 | }
30 |
31 | void swapn(unsigned char *b, int N, int n)
32 | {
33 |
34 | int i, j;
35 |
36 | for (i = 0; i < (n) * (N); i += N)
37 | for (j = 0; j < N / 2; j++)
38 | SWAP2(b[i + j], b[i + N - j - 1]);
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/ANCC/src/AFTAN/ftfilt.f90:
--------------------------------------------------------------------------------
1 | ! This file is part of ANCC.
2 | !
3 | ! AFTAN is free software: you can redistribute it and/or modify
4 | ! it under the terms of the GNU General Public License as published by
5 | ! the Free Software Foundation, either version 3 of the License, or
6 | ! (at your option) any later version.
7 | !
8 | ! AFTAN is distributed in the hope that it will be useful,
9 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | ! GNU General Public License for more details.
12 | !
13 | ! You should have received a copy of the GNU General Public License
14 | ! along with this program. If not, see .
15 | !
16 | !
17 | !
18 | !-------------------------------------------------
19 | ! FTAN filter: y = x*exp(-alpha*((om-om0)/om0)**2)
20 | !-------------------------------------------------
21 | subroutine ftfilt(alpha, om0, dom, n, a, fs)
22 |
23 | implicit none
24 |
25 | integer(4), intent(in) :: n
26 |
27 | real(8), intent(in) :: alpha, om0, dom
28 |
29 | complex(8), intent(in) :: a(n)
30 |
31 |
32 | complex(8), intent(out) :: fs(n)
33 |
34 |
35 |
36 | integer(4) k
37 |
38 | complex(8), parameter :: czero = dcmplx(0.d0,0.d0)
39 |
40 |
41 | real(8) ome, om2, b
42 |
43 |
44 |
45 | do k = 1, n, 1
46 |
47 | fs(k) = czero
48 | b = 0.d0
49 | ome = (k-1)*dom
50 | om2 = -alpha*(ome - om0)/om0*(ome - om0)/om0
51 |
52 | if (abs(om2) <= 40.d0) then
53 | b = exp(om2)
54 | fs(k) = a(k)*b
55 | endif
56 |
57 | enddo
58 |
59 |
60 | return
61 |
62 |
63 | end subroutine ftfilt
64 |
--------------------------------------------------------------------------------
/ANCC/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for ANCC
2 |
3 |
4 | ############################################################################################################
5 | # Option to be set
6 | ############################################################################################################
7 | # Select your compiler
8 | MPIFC=mpiifort # MPI Fortran compiler binding with ifort [recommended]
9 | #MPIFC=mpiifx # MPI Fortran compiler binding with ifx [recommended]
10 | #MPIFC=mpifort # It may bounds to the Intel compiler or to the GNU compiler. Don't fooled by its name.
11 | # You should check it using mpifort --version
12 | #MPIFC=mpif90 # MPI Fortran compiler bound to gfortran or intel
13 | # You should check it using mpif90 --version
14 | # It binds to the GNU compiler if the above command outputs GNU Fortran (GCC)
15 | # It binds to the Intel compiler if the above command outputs ifort (IFORT)
16 | #MPIFC=pgf90 # PGI Fortran compiler with -Mmpi=mpich2
17 | ############################################################################################################
18 |
19 |
20 |
21 | SUBDIRS = \
22 | ANCC \
23 | TF_PWS \
24 | AFTAN \
25 | $(EMPTY_MACRO)
26 |
27 | SUBDIRS := $(addprefix ./src/,$(SUBDIRS))
28 |
29 |
30 | all: config build clean
31 |
32 | config:
33 | @./config.guess $(MPIFC)
34 |
35 | build:
36 | $(call create_bindir)
37 | $(call COMPILE,$(SUBDIRS),$@)
38 |
39 | clean:
40 | $(call COMPILE,$(SUBDIRS),$@)
41 |
42 | cleanall: clean
43 | $(call COMPILE,$(SUBDIRS),$@)
44 |
45 |
46 | define create_bindir:
47 | include ./config.h
48 | ifeq ($(wildcard $(INST_DIR)),)
49 | @mkdir -p $(DIST_DIR)
50 | endif
51 | endef
52 | define COMMAND
53 | $(MAKE) -C $(1) $(2)
54 | endef
55 | define COMPILE
56 | $(foreach dir, $(1), $(call COMMAND,$(dir),$(2));)
57 | endef
58 |
--------------------------------------------------------------------------------
/ANCC/src/AFTAN/trigger.f90:
--------------------------------------------------------------------------------
1 | ! This file is part of ANCC.
2 | !
3 | ! AFTAN is free software: you can redistribute it and/or modify
4 | ! it under the terms of the GNU General Public License as published by
5 | ! the Free Software Foundation, either version 3 of the License, or
6 | ! (at your option) any later version.
7 | !
8 | ! AFTAN is distributed in the hope that it will be useful,
9 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | ! GNU General Public License for more details.
12 | !
13 | ! You should have received a copy of the GNU General Public License
14 | ! along with this program. If not, see .
15 | !
16 | !
17 | !
18 | ! - -----------------------------------------------------------
19 | ! test dispersion curve for jumps
20 | ! - -----------------------------------------------------------
21 | subroutine trigger(grvel, om, nf, tresh, trig, ftrig, ier)
22 |
23 | implicit none
24 |
25 | integer(4), intent(in) :: nf
26 |
27 | real(8), intent(in) :: tresh
28 |
29 | real(8), intent(in) :: grvel(nf), om(nf)
30 |
31 |
32 | integer(4), intent(out) :: ier
33 |
34 | real(8), intent(out) :: trig(nf), ftrig(nf)
35 |
36 |
37 | integer(4) i
38 |
39 | real(8) hh1, hh2, hh3, r
40 |
41 |
42 | ier = 0
43 | ftrig(1) = 0.d0
44 | ftrig(nf) = 0.d0
45 | trig(1) = 0.d0
46 | trig(nf) = 0.d0
47 |
48 |
49 | do i = 1, nf-2, 1
50 |
51 | trig(i+1) = 0.d0
52 | hh1 = om(i+1) - om(i)
53 | hh2 = om(i+2) - om(i+1)
54 | hh3 = hh1 + hh2
55 |
56 | r = 25.d0*(grvel(i)/hh1 - (1.d0/hh1 + 1.d0/hh2)*grvel(i+1) + grvel(i+2)/hh2)*hh3
57 |
58 | ftrig(i+1) = r
59 |
60 | if (abs(r) > tresh) then
61 | trig(i+1) = sign(1.d0, r)
62 | ier = 1
63 | endif
64 |
65 | enddo
66 |
67 |
68 | return
69 |
70 |
71 | end subroutine trigger
72 |
--------------------------------------------------------------------------------
/ANCC/src/AFTAN/fmax.f90:
--------------------------------------------------------------------------------
1 | ! This file is part of ANCC.
2 | !
3 | ! AFTAN is free software: you can redistribute it and/or modify
4 | ! it under the terms of the GNU General Public License as published by
5 | ! the Free Software Foundation, either version 3 of the License, or
6 | ! (at your option) any later version.
7 | !
8 | ! AFTAN is distributed in the hope that it will be useful,
9 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | ! GNU General Public License for more details.
12 | !
13 | ! You should have received a copy of the GNU General Public License
14 | ! along with this program. If not, see .
15 | !
16 | !
17 | !
18 | !----------------------------------------------------------------------
19 | ! parabolic interpolation of signal amplitude and phase,
20 | ! finding phase derivative
21 | !----------------------------------------------------------------------
22 | subroutine fmax(am1, am2, am3, ph1, ph2, ph3, PIover4, om, dt, t, dph, tm, ph)
23 |
24 | implicit none
25 |
26 | real(8), intent(in) :: om, dt
27 | real(8), intent(in) :: am1, am2, am3
28 | real(8), intent(in) :: ph1, ph2, ph3
29 |
30 | real(8), intent(in) :: PIover4
31 |
32 |
33 | real(8), intent(out) :: t, dph, tm, ph
34 |
35 |
36 | integer(4) k
37 |
38 | real(8), parameter :: twoPI = 8.d0*datan(1.d0)
39 |
40 | real(8) a1, a2, a3, dd
41 |
42 |
43 |
44 | dd = am1 + am3 - 2.d0*am2
45 |
46 | t = 0.d0
47 | if (0.d0 /= dd) then
48 | t = 0.5d0*(am1 - am3)/dd
49 | endif
50 |
51 | ! phase derivative
52 | a1 = ph1
53 | a2 = ph2
54 | a3 = ph3
55 |
56 |
57 | ! check for 2*pi phase jump
58 | k = nint((a2 - a1 - om*dt)/twoPI)
59 | a2 = a2 - k*twoPI
60 | k = nint((a3 - a2 - om*dt)/twoPI)
61 | a3 = a3 - k*twoPI
62 |
63 |
64 | ! interpolation
65 | dph = t*(a1 + a3 - 2.d0*a2) + 0.5d0*(a3 - a1)
66 | tm = 0.5d0*t*t*(am1 + am3 - 2.d0*am2) + 0.5d0*t*(am3 - am1) + am2
67 | ph = 0.5d0*t*t*(a1 + a3 - 2.d0*a2) + 0.5d0*t*(a3 - a1) + a2 + 0.125d0*twoPI*PIover4
68 |
69 |
70 | return
71 |
72 |
73 | end subroutine fmax
74 |
--------------------------------------------------------------------------------
/ANCC/src/AFTAN/pred_cur.f90:
--------------------------------------------------------------------------------
1 | ! This file is part of ANCC.
2 | !
3 | ! AFTAN is free software: you can redistribute it and/or modify
4 | ! it under the terms of the GNU General Public License as published by
5 | ! the Free Software Foundation, either version 3 of the License, or
6 | ! (at your option) any later version.
7 | !
8 | ! AFTAN is distributed in the hope that it will be useful,
9 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | ! GNU General Public License for more details.
12 | !
13 | ! You should have received a copy of the GNU General Public License
14 | ! along with this program. If not, see .
15 | !
16 | !
17 | !
18 | !--------------------------------------------------------------
19 | ! create phase prediction curve by group velocity
20 | !--------------------------------------------------------------
21 | subroutine pred_cur(ip, delta, om0, npred, pred, om1, Gt0)
22 |
23 | use spline_m
24 |
25 | implicit none
26 |
27 | integer(4), intent(in) :: ip, npred
28 |
29 | real(8), intent(in) :: delta, om0
30 |
31 | real(8), intent(in) :: pred(npred,2)
32 |
33 |
34 | real(8), intent(out) :: om1, Gt0
35 |
36 |
37 | integer(4) i, ier
38 |
39 | real(8), parameter :: PI = 4.d0*datan(1.d0)
40 |
41 | real(8) s, ss
42 |
43 | real(8), dimension(:), allocatable :: x, y
44 |
45 |
46 | allocate(x(1:npred), y(1:npred), stat=ier)
47 |
48 |
49 |
50 | ! transfer prediction curve (T,vel) ==> (omrga,t)
51 | do i = 1, npred, 1
52 | x(i) = 2.d0*PI/pred(npred-i+1,1)
53 | y(i) = delta/pred(npred-i+1,2)
54 | enddo
55 |
56 | ! get velocity for low integral boundary
57 | call mspline(ip, npred, x, y, 0, 0.d0, 0, 0.d0)
58 | call msplder(ip, om0, Gt0, s, ss, ier)
59 | call free_mspline()
60 |
61 |
62 | ! construct spline for ph filter
63 | do i = 1, npred, 1
64 | y(i) = y(i) - Gt0
65 | enddo
66 |
67 | call mspline(ip+1, npred, x, y, 0, 0.d0, 0, 0.d0)
68 |
69 |
70 | om1 = om0
71 |
72 |
73 | deallocate(x, y)
74 |
75 |
76 | return
77 |
78 |
79 | end subroutine pred_cur
80 |
--------------------------------------------------------------------------------
/ANCC/src/AFTAN/tapers.f90:
--------------------------------------------------------------------------------
1 | ! This file is part of ANCC.
2 | !
3 | ! AFTAN is free software: you can redistribute it and/or modify
4 | ! it under the terms of the GNU General Public License as published by
5 | ! the Free Software Foundation, either version 3 of the License, or
6 | ! (at your option) any later version.
7 | !
8 | ! AFTAN is distributed in the hope that it will be useful,
9 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | ! GNU General Public License for more details.
12 | !
13 | ! You should have received a copy of the GNU General Public License
14 | ! along with this program. If not, see .
15 | !
16 | !
17 | !
18 | !--------------------------------------------------------------
19 | ! spectra tapering procedure
20 | !--------------------------------------------------------------
21 | subroutine tapers(omb, ome, dom, alpha, ns, omstart, inds, inde, omdom, ampdom)
22 |
23 | implicit none
24 |
25 | integer(4), intent(in) :: ns
26 |
27 | real(8), intent(in) :: omb, ome, dom, alpha
28 |
29 |
30 | integer(4), intent(out) :: inds, inde
31 |
32 | real(8), intent(out) :: omstart
33 |
34 | real(8), intent(out) :: ampdom(ns), omdom(ns)
35 |
36 |
37 | integer(4) i, om1, om2, om3, om4
38 |
39 | real(8), parameter :: PI = 4.d0*datan(1.d0)
40 |
41 | real(8) om2d, om3d, wd, tresh
42 |
43 |
44 |
45 | tresh = 0.5d0
46 | ampdom(1:ns) = 0.d0
47 |
48 | om2d = omb/dom
49 | wd = max(16.d0, om2d*sqrt(tresh/alpha))
50 | om1 = nint(max(1.d0, om2d-0.5d0*wd))
51 | om2 = nint(min(real(ns), om1+wd))
52 | do i = om1, om2, 1
53 | ampdom(i) = 0.5d0*(1.d0 - cos(PI*(i-om1)/(om2-om1)))
54 | enddo
55 |
56 |
57 | om3d = ome/dom
58 | wd = max(16.d0, om3d*sqrt(tresh/alpha))
59 | om4 = nint(min(real(ns), om3d+0.5d0*wd))
60 | om3 = nint(max(1.d0, om4-wd))
61 | do i = om3, om4, 1
62 | ampdom(i) = 0.5d0*(1.d0 + cos(PI*(i-om3)/(om4-om3)))
63 | enddo
64 |
65 |
66 | ampdom(om2:om3) = 1.d0
67 |
68 |
69 | do i = 1, ns, 1
70 | omdom(i) = (i-1)*dom
71 | enddo
72 |
73 |
74 | omstart = omb
75 |
76 | inds = om1
77 | inde = om4
78 |
79 |
80 | return
81 |
82 |
83 | end subroutine tapers
84 |
--------------------------------------------------------------------------------
/ANCC/src/AFTAN/aftan.h:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of ANCC.
3 |
4 | AFTAN is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 3 of the License, or
7 | (at your option) any later version.
8 |
9 | AFTAN is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License
15 | along with this program. If not, see .
16 |
17 | */
18 | #ifndef AFTAN_H
19 | #define AFTAN_H 1
20 |
21 | /* Finction prorotypes */
22 |
23 |
24 | void aftanipg_(double *PIover4, int *n, double *seis, double *t0, double *dt,
25 | double *delta, double *vmin, double *vmax, double *tmin, double *tmax,
26 | double *tresh, double *ffact, double *perc, int *npoints,
27 | double *taperl, int *nfin, double *snr, double *fmatch,
28 | int *npred, double **pred,
29 | int *nprpv, double *prpvper, double *prpvvel,
30 | int *nfout1, double **arr1, int *nfout2, double *arr2,
31 | double *tamp, int *nrow, int *ncol, double **ampo, int *ierr);
32 |
33 | void aftanpg_(double *PIover4, int *n, double *seis, double *t0, double *dt,
34 | double *delta, double *vmin, double *vmax, double *tmin, double *tmax,
35 | double *tresh, double *ffact, double *perc, int *npoints,
36 | double *taperl, int *nfin, double *snr,
37 | int *nprpv, double *prpvper, double *prpvvel,
38 | int *nfout1, double **arr1, int *nfout2, double *arr2,
39 | double *tamp, int *nrow, int *ncol, double **ampo, int *ierr);
40 |
41 | /*void printres_(double *dt, double *delta, int *nfout1, double **arr1,
42 | * int *nfout2, double **arr2, double *tamp, int *nrow, int *ncol,
43 | * double **ampo, int *ierr, char *name, char *pref);*/
44 | void printres_(double *dt, double *delta, int *nfout1, double *arr1,
45 | int *nfout2, double *arr2, double *tamp, int *nrow, int *ncol,
46 | double *ampo, int *ierr, char *name, char *pref);
47 |
48 |
49 | void readhead_(int *sac, char *name, int *n, int *ierr);
50 |
51 | void readdata_(int *sac, char *name, double *dt, double *delta,
52 | double *t0, float *seis, int *ierr);
53 |
54 | void swapn(unsigned char *b, int N, int nn);
55 |
56 |
57 | #endif /* !AFTAN_H */
58 |
--------------------------------------------------------------------------------
/ANCC/src/AFTAN/fftw3.f:
--------------------------------------------------------------------------------
1 | INTEGER FFTW_R2HC
2 | PARAMETER (FFTW_R2HC=0)
3 | INTEGER FFTW_HC2R
4 | PARAMETER (FFTW_HC2R=1)
5 | INTEGER FFTW_DHT
6 | PARAMETER (FFTW_DHT=2)
7 | INTEGER FFTW_REDFT00
8 | PARAMETER (FFTW_REDFT00=3)
9 | INTEGER FFTW_REDFT01
10 | PARAMETER (FFTW_REDFT01=4)
11 | INTEGER FFTW_REDFT10
12 | PARAMETER (FFTW_REDFT10=5)
13 | INTEGER FFTW_REDFT11
14 | PARAMETER (FFTW_REDFT11=6)
15 | INTEGER FFTW_RODFT00
16 | PARAMETER (FFTW_RODFT00=7)
17 | INTEGER FFTW_RODFT01
18 | PARAMETER (FFTW_RODFT01=8)
19 | INTEGER FFTW_RODFT10
20 | PARAMETER (FFTW_RODFT10=9)
21 | INTEGER FFTW_RODFT11
22 | PARAMETER (FFTW_RODFT11=10)
23 | INTEGER FFTW_FORWARD
24 | PARAMETER (FFTW_FORWARD=-1)
25 | INTEGER FFTW_BACKWARD
26 | PARAMETER (FFTW_BACKWARD=+1)
27 | INTEGER FFTW_MEASURE
28 | PARAMETER (FFTW_MEASURE=0)
29 | INTEGER FFTW_DESTROY_INPUT
30 | PARAMETER (FFTW_DESTROY_INPUT=1)
31 | INTEGER FFTW_UNALIGNED
32 | PARAMETER (FFTW_UNALIGNED=2)
33 | INTEGER FFTW_CONSERVE_MEMORY
34 | PARAMETER (FFTW_CONSERVE_MEMORY=4)
35 | INTEGER FFTW_EXHAUSTIVE
36 | PARAMETER (FFTW_EXHAUSTIVE=8)
37 | INTEGER FFTW_PRESERVE_INPUT
38 | PARAMETER (FFTW_PRESERVE_INPUT=16)
39 | INTEGER FFTW_PATIENT
40 | PARAMETER (FFTW_PATIENT=32)
41 | INTEGER FFTW_ESTIMATE
42 | PARAMETER (FFTW_ESTIMATE=64)
43 | INTEGER FFTW_WISDOM_ONLY
44 | PARAMETER (FFTW_WISDOM_ONLY=2097152)
45 | INTEGER FFTW_ESTIMATE_PATIENT
46 | PARAMETER (FFTW_ESTIMATE_PATIENT=128)
47 | INTEGER FFTW_BELIEVE_PCOST
48 | PARAMETER (FFTW_BELIEVE_PCOST=256)
49 | INTEGER FFTW_NO_DFT_R2HC
50 | PARAMETER (FFTW_NO_DFT_R2HC=512)
51 | INTEGER FFTW_NO_NONTHREADED
52 | PARAMETER (FFTW_NO_NONTHREADED=1024)
53 | INTEGER FFTW_NO_BUFFERING
54 | PARAMETER (FFTW_NO_BUFFERING=2048)
55 | INTEGER FFTW_NO_INDIRECT_OP
56 | PARAMETER (FFTW_NO_INDIRECT_OP=4096)
57 | INTEGER FFTW_ALLOW_LARGE_GENERIC
58 | PARAMETER (FFTW_ALLOW_LARGE_GENERIC=8192)
59 | INTEGER FFTW_NO_RANK_SPLITS
60 | PARAMETER (FFTW_NO_RANK_SPLITS=16384)
61 | INTEGER FFTW_NO_VRANK_SPLITS
62 | PARAMETER (FFTW_NO_VRANK_SPLITS=32768)
63 | INTEGER FFTW_NO_VRECURSE
64 | PARAMETER (FFTW_NO_VRECURSE=65536)
65 | INTEGER FFTW_NO_SIMD
66 | PARAMETER (FFTW_NO_SIMD=131072)
67 | INTEGER FFTW_NO_SLOW
68 | PARAMETER (FFTW_NO_SLOW=262144)
69 | INTEGER FFTW_NO_FIXED_RADIX_LARGE_N
70 | PARAMETER (FFTW_NO_FIXED_RADIX_LARGE_N=524288)
71 | INTEGER FFTW_ALLOW_PRUNING
72 | PARAMETER (FFTW_ALLOW_PRUNING=1048576)
73 |
--------------------------------------------------------------------------------
/ANCC/src/ANCC/fftw3.f:
--------------------------------------------------------------------------------
1 | INTEGER FFTW_R2HC
2 | PARAMETER (FFTW_R2HC=0)
3 | INTEGER FFTW_HC2R
4 | PARAMETER (FFTW_HC2R=1)
5 | INTEGER FFTW_DHT
6 | PARAMETER (FFTW_DHT=2)
7 | INTEGER FFTW_REDFT00
8 | PARAMETER (FFTW_REDFT00=3)
9 | INTEGER FFTW_REDFT01
10 | PARAMETER (FFTW_REDFT01=4)
11 | INTEGER FFTW_REDFT10
12 | PARAMETER (FFTW_REDFT10=5)
13 | INTEGER FFTW_REDFT11
14 | PARAMETER (FFTW_REDFT11=6)
15 | INTEGER FFTW_RODFT00
16 | PARAMETER (FFTW_RODFT00=7)
17 | INTEGER FFTW_RODFT01
18 | PARAMETER (FFTW_RODFT01=8)
19 | INTEGER FFTW_RODFT10
20 | PARAMETER (FFTW_RODFT10=9)
21 | INTEGER FFTW_RODFT11
22 | PARAMETER (FFTW_RODFT11=10)
23 | INTEGER FFTW_FORWARD
24 | PARAMETER (FFTW_FORWARD=-1)
25 | INTEGER FFTW_BACKWARD
26 | PARAMETER (FFTW_BACKWARD=+1)
27 | INTEGER FFTW_MEASURE
28 | PARAMETER (FFTW_MEASURE=0)
29 | INTEGER FFTW_DESTROY_INPUT
30 | PARAMETER (FFTW_DESTROY_INPUT=1)
31 | INTEGER FFTW_UNALIGNED
32 | PARAMETER (FFTW_UNALIGNED=2)
33 | INTEGER FFTW_CONSERVE_MEMORY
34 | PARAMETER (FFTW_CONSERVE_MEMORY=4)
35 | INTEGER FFTW_EXHAUSTIVE
36 | PARAMETER (FFTW_EXHAUSTIVE=8)
37 | INTEGER FFTW_PRESERVE_INPUT
38 | PARAMETER (FFTW_PRESERVE_INPUT=16)
39 | INTEGER FFTW_PATIENT
40 | PARAMETER (FFTW_PATIENT=32)
41 | INTEGER FFTW_ESTIMATE
42 | PARAMETER (FFTW_ESTIMATE=64)
43 | INTEGER FFTW_WISDOM_ONLY
44 | PARAMETER (FFTW_WISDOM_ONLY=2097152)
45 | INTEGER FFTW_ESTIMATE_PATIENT
46 | PARAMETER (FFTW_ESTIMATE_PATIENT=128)
47 | INTEGER FFTW_BELIEVE_PCOST
48 | PARAMETER (FFTW_BELIEVE_PCOST=256)
49 | INTEGER FFTW_NO_DFT_R2HC
50 | PARAMETER (FFTW_NO_DFT_R2HC=512)
51 | INTEGER FFTW_NO_NONTHREADED
52 | PARAMETER (FFTW_NO_NONTHREADED=1024)
53 | INTEGER FFTW_NO_BUFFERING
54 | PARAMETER (FFTW_NO_BUFFERING=2048)
55 | INTEGER FFTW_NO_INDIRECT_OP
56 | PARAMETER (FFTW_NO_INDIRECT_OP=4096)
57 | INTEGER FFTW_ALLOW_LARGE_GENERIC
58 | PARAMETER (FFTW_ALLOW_LARGE_GENERIC=8192)
59 | INTEGER FFTW_NO_RANK_SPLITS
60 | PARAMETER (FFTW_NO_RANK_SPLITS=16384)
61 | INTEGER FFTW_NO_VRANK_SPLITS
62 | PARAMETER (FFTW_NO_VRANK_SPLITS=32768)
63 | INTEGER FFTW_NO_VRECURSE
64 | PARAMETER (FFTW_NO_VRECURSE=65536)
65 | INTEGER FFTW_NO_SIMD
66 | PARAMETER (FFTW_NO_SIMD=131072)
67 | INTEGER FFTW_NO_SLOW
68 | PARAMETER (FFTW_NO_SLOW=262144)
69 | INTEGER FFTW_NO_FIXED_RADIX_LARGE_N
70 | PARAMETER (FFTW_NO_FIXED_RADIX_LARGE_N=524288)
71 | INTEGER FFTW_ALLOW_PRUNING
72 | PARAMETER (FFTW_ALLOW_PRUNING=1048576)
73 |
--------------------------------------------------------------------------------
/ANCC/src/AFTAN/phtovel.f90:
--------------------------------------------------------------------------------
1 | ! This file is part of ANCC.
2 | !
3 | ! AFTAN is free software: you can redistribute it and/or modify
4 | ! it under the terms of the GNU General Public License as published by
5 | ! the Free Software Foundation, either version 3 of the License, or
6 | ! (at your option) any later version.
7 | !
8 | ! AFTAN is distributed in the hope that it will be useful,
9 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | ! GNU General Public License for more details.
12 | !
13 | ! You should have received a copy of the GNU General Public License
14 | ! along with this program. If not, see .
15 | !
16 | !
17 | !
18 | !-----------------------------------------------------------------
19 | ! convert phase to phase velocity
20 | !-----------------------------------------------------------------
21 | subroutine phtovel(delta, ip, nf, per, U, pha, npr, prper, prvel, n, V)
22 |
23 | !
24 | ! delta - distance, km
25 | ! n - # of points in per
26 | ! per - apparent periods
27 | ! U - group velocity
28 | ! pha - phase
29 | ! npr - # of points in prper
30 | ! prper - pedicted periods
31 | ! prvel - pedicted phase velocity
32 | ! V - observed phase velocity
33 |
34 | use spline_m
35 |
36 |
37 | implicit none
38 |
39 | integer(4), intent(in) :: ip, n, nf, npr
40 |
41 | real(8), intent(in) :: delta
42 |
43 | real(8), intent(in) :: per(nf), U(nf), pha(nf)
44 | real(8), intent(in) :: prper(npr), prvel(npr)
45 |
46 |
47 | real(8), intent(out) :: V(n)
48 |
49 |
50 | integer(4) i, k, m, ier
51 |
52 | real(8) Vpred, phpred, s, ss
53 |
54 | real(8), parameter :: PI = 4.d0*datan(1.d0)
55 |
56 | real(8), dimension(:), allocatable :: om, sU, t
57 |
58 |
59 |
60 | allocate(om(1:n), sU(1:n), t(1:n), stat = ier)
61 |
62 |
63 | Vpred = 0.d0
64 | do i = 1, n, 1
65 | om(i) = 2.d0*PI/per(i)
66 | sU(i) = 1.d0/U(i)
67 | t(i) = delta*sU(i)
68 | V(i) = 0.d0
69 | enddo
70 |
71 |
72 | ! find velocity for the largest period by spline interpolation
73 | ! with not a knot boundary conditions
74 | call mspline(ip+2, npr, prper, prvel, 0, 0.d0, 0, 0.d0)
75 | call msplder(ip+2, per(n), Vpred, s, ss, ier)
76 | call free_mspline()
77 |
78 |
79 | phpred = om(n)*(t(n) - delta/Vpred)
80 | k = nint(0.5d0*(phpred - pha(n))/PI)
81 | V(n) = delta/(t(n) - (pha(n) + 2.d0*k*PI)/om(n))
82 |
83 | do m = n-1, 1, -1
84 |
85 | Vpred = 1.d0/((0.5d0*(sU(m) + sU(m+1))*(om(m) - om(m+1)) + om(m+1)/V(m+1))/om(m))
86 | phpred = om(m)*(t(m) - delta/Vpred)
87 | k = nint(0.5d0*(phpred - pha(m))/PI)
88 | V(m) = delta/(t(m) - (pha(m) + 2.d0*k*PI)/om(m))
89 |
90 | enddo
91 |
92 |
93 | deallocate(om, sU, t)
94 |
95 |
96 | return
97 |
98 |
99 | end subroutine phtovel
100 |
--------------------------------------------------------------------------------
/ANCC/src/AFTAN/taper.f90:
--------------------------------------------------------------------------------
1 | ! This file is part of ANCC.
2 | !
3 | ! AFTAN is free software: you can redistribute it and/or modify
4 | ! it under the terms of the GNU General Public License as published by
5 | ! the Free Software Foundation, either version 3 of the License, or
6 | ! (at your option) any later version.
7 | !
8 | ! AFTAN is distributed in the hope that it will be useful,
9 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | ! GNU General Public License for more details.
12 | !
13 | ! You should have received a copy of the GNU General Public License
14 | ! along with this program. If not, see .
15 | !
16 | !
17 | !
18 | !----------------------------------------------------------
19 | ! tapering both end of input seismogram
20 | !----------------------------------------------------------
21 | module taper_m
22 |
23 |
24 | implicit none
25 |
26 |
27 | contains
28 |
29 |
30 | subroutine taper(nb, ne, n, seis, ntapb, ntape, ns, ss)
31 |
32 | implicit none
33 |
34 | integer(4), intent(in) :: nb, ne, n
35 | integer(4), intent(in) :: ntapb, ntape
36 |
37 | real(4), intent(in) :: seis(n)
38 |
39 |
40 | integer(4), intent(out) :: ns
41 |
42 | complex(8), dimension(:), allocatable, intent(out) :: ss
43 |
44 |
45 | integer(4) k, ncorr, ier
46 |
47 | real(8), parameter :: PI = 4.d0*datan(1.d0)
48 |
49 | real(8) omb, ome, sums, c, r
50 |
51 | real(8), dimension(:), allocatable :: s
52 |
53 |
54 |
55 | omb = PI/dble(ntapb)
56 | ome = PI/dble(ntape)
57 | ncorr = ne + ntape
58 |
59 |
60 | ! make copy seis to s
61 | allocate(s(1:ncorr), stat=ier)
62 | s = 0.d0
63 | s(1:min(n,ncorr)) = dble(seis(1:min(n,ncorr)))
64 | if ((nb-ntapb-1) > 0) then
65 | s(1:nb-ntapb-1) = 0.d0
66 | endif
67 |
68 | sums = 0.d0
69 | ! left end of the signal
70 | do k = nb, nb-ntapb, -1
71 | r = 0.5d0*(1.d0 + cos(omb*(nb - k)))
72 | sums = sums + 2.d0*r
73 | s(k) = s(k)*r
74 | enddo
75 | ! right end of the signal
76 | do k = ne, ne+ntape, 1
77 | s(k) = 0.5d0*(1.d0 + cos(ome*(ne - k)))*s(k)
78 | enddo
79 | sums = sums + ne - nb - 1
80 | c = 0.0
81 | do k = 1, ncorr, 1
82 | c = c + s(k)
83 | enddo
84 | c = -c/sums
85 |
86 | ! left end of the signal
87 | do k = nb, nb-ntapb, -1
88 | r = 0.5d0*(1.d0 + cos(omb*(nb - k)))
89 | s(k) = s(k) + r*c
90 | enddo
91 |
92 | ! right end of the signal
93 | do k = ne, ne+ntape, 1
94 | r = 0.5d0*(1.d0 + cos(ome*(ne - k)))
95 | s(k) = s(k) + r*c
96 | enddo
97 |
98 | ! middle of the signal
99 | s(nb+1:ne-1) = s(nb+1:ne-1) + c
100 |
101 |
102 | ! determine the power of FFT
103 | !ns = 2**(min(max(int(dlog(dble(ncorr))/dlog(2.d0)) + 1, 12), 16))
104 | ns = 2**ceiling(dlog(dble(ncorr))/dlog(2.d0))
105 | !if (ns > ncorr) then
106 | ! s(ncorr+1:ns) = 0.0
107 | !endif
108 |
109 |
110 | ! convert to complex
111 | allocate(ss(1:ns), stat=ier)
112 | ss = dcmplx(0.d0,0.d0)
113 | do k = 1, ncorr, 1
114 | ss(k) = cmplx(s(k), 0.d0)
115 | enddo
116 |
117 |
118 | deallocate(s)
119 |
120 |
121 | return
122 |
123 |
124 | end subroutine taper
125 |
126 |
127 | end module taper_m
128 |
--------------------------------------------------------------------------------
/scripts/stainfo.lst:
--------------------------------------------------------------------------------
1 | knetwk kstnm stla stlo stel
2 | NCISP6 NE00 39.9900 124.3070 44
3 | NCISP6 NE01 40.0650 124.2200 95
4 | NCISP6 NE02 40.1390 124.1330 196
5 | NCISP6 NE03 40.2130 124.0450 149
6 | NCISP6 NE04 40.2880 123.9580 126
7 | NCISP6 NE05 40.3620 123.8700 121
8 | NCISP6 NE06 40.4360 123.7820 192
9 | NCISP6 NE07 40.5110 123.6940 369
10 | NCISP6 NE08 40.5850 123.6050 193
11 | NCISP6 NE09 40.6590 123.5170 191
12 | NCISP6 NE10 40.7330 123.4280 285
13 | NCISP6 NE11 40.8070 123.3390 282
14 | NCISP6 NE12 40.8800 123.2500 293
15 | NCISP6 NE14 41.0280 123.0710 209
16 | NCISP6 NE15 41.1010 122.9810 108
17 | NCISP6 NE16 41.2120 122.8460 16
18 | NCISP6 NE17 41.3220 122.7110 15
19 | NCISP6 NE18 41.4320 122.5750 12
20 | NCISP6 NE19 41.5420 122.4380 18
21 | NCISP6 NE20 41.6510 122.3020 22
22 | NCISP6 NE21 41.7610 122.1640 33
23 | NCISP6 NE22 41.8700 122.0260 89
24 | NCISP6 NE23 41.9790 121.8880 570
25 | NCISP6 NE24 42.0880 121.7490 238
26 | NCISP6 NE25 42.1970 121.6100 393
27 | NCISP6 NE26 42.3060 121.4700 464
28 | NCISP6 NE27 42.4140 121.3300 338
29 | NCISP6 NE28 42.5230 121.1900 388
30 | NCISP6 NE29 42.6310 121.0480 427
31 | NCISP6 NE30 42.7390 120.9070 380
32 | NCISP6 NE31 42.8460 120.7650 371
33 | NCISP6 NE32 42.9540 120.6220 359
34 | NCISP6 NE33 43.0620 120.4790 361
35 | NCISP6 NE34 43.1690 120.3350 333
36 | NCISP6 NE35 43.2760 120.1910 360
37 | NCISP6 NE36 43.3830 120.0460 379
38 | NCISP6 NE37 43.4900 119.9010 391
39 | NCISP6 NE38 43.5960 119.7560 404
40 | NCISP6 NE39 43.7020 119.6090 464
41 | NCISP6 NE40 43.8090 119.4630 575
42 | NCISP6 NE41 43.9150 119.3150 527
43 | NCISP6 NE42 44.0200 119.1680 685
44 | NCISP6 NE43 44.1260 119.0190 727
45 | NCISP6 NE44 44.2310 118.8710 835
46 | NCISP6 NE45 44.3370 118.7210 1060
47 | NCISP6 NE46 44.4420 118.5710 1252
48 | NCISP6 NE47 44.5460 118.4210 1184
49 | NCISP6 NE48 44.6510 118.2700 1166
50 | NCISP6 NE49 44.7550 118.1180 1070
51 | NCISP6 NE50 44.8600 117.9660 968
52 | NCISP6 NE51 44.9640 117.8140 946
53 | NCISP6 NE52 45.0670 117.6610 1029
54 | NCISP6 NE53 45.1710 117.5070 960
55 | NCISP6 NE54 45.2740 117.3530 847
56 | NCISP6 NE55 45.3780 117.1980 836
57 | NCISP6 NE56 45.4810 117.0420 945
58 | NCISP6 NE57 45.5830 116.8860 879
59 | NCISP6 NE58 45.6860 116.7300 1130
60 | NCISP6 NE59 45.7880 116.5730 1047
61 | NCISP6 NE60 45.8900 116.4150 962
62 |
--------------------------------------------------------------------------------
/ANCC/guess.flags:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | function guess_flags() {
4 |
5 | MPIFC=$1
6 | if [[ `type $MPIFC 2>/dev/null` == "" ]]; then
7 | echo "Cannot found $MPIFC in your system !"
8 | return 0
9 | fi
10 | if [[ `$MPIFC --version | grep ifx` != "" ]]; then
11 | CC=icx
12 | FC=ifx
13 | COMPILER=INTEL
14 | elif [[ `$MPIFC --version | grep ifort` != "" ]]; then
15 | CC=icc
16 | FC=ifort
17 | COMPILER=INTEL
18 | elif [[ `$MPIFC --version | grep GNU` != "" ]]; then
19 | CC=gcc
20 | FC=gfortran
21 | COMPILER=GNU
22 | elif [[ `$MPIFC --version | grep pgf` != "" ]]; then
23 | CC=pgcc
24 | FC=pgf90
25 | COMPILER=PGI
26 | fi
27 | if [[ $COMPILER == "" ]]; then
28 | echo "Error: Unknown compilers to configure config.h !"
29 | return 0
30 | fi
31 |
32 |
33 | if [[ "$COMPILER" == "GNU" ]]; then
34 | echo "Build ANCC using the GNU compilers"
35 | CFLAGS="-O3 -Ofast -g -funroll-loops -malign-double -ffast-math -mtune=native -I./"
36 | FFLAGS="-O3 -Ofast -cpp -g -ffree-line-length-200 -funroll-loops -malign-double -ffast-math -mtune=native"
37 | echo "# Build ANCC using the $COMPILER compiler" > config.h
38 | echo "" >> config.h
39 | echo "# Install directory " >> config.h
40 | echo "INST_DIR = ~/bin" >> config.h
41 | echo "" >> config.h
42 | echo "############################################" >> config.h
43 | echo "# GNU Compilers " >> config.h
44 | echo "############################################" >> config.h
45 | echo "" >> config.h
46 | echo "CC = $CC" >> config.h
47 | echo "FC = $FC" >> config.h
48 | echo "MPIFC = $MPIFC" >> config.h
49 | echo "CFLAGS = $CFLAGS" >> config.h
50 | echo "FFLAGS = $FFLAGS" >> config.h
51 | elif [[ "$COMPILER" == "INTEL" ]]; then
52 | echo "Build ANCC using the Intel compilers"
53 | CFLAGS="-O3 -xHost -fma -axAVX -I./"
54 | FFLAGS="-O3 -xHost -unroll -ftz -fma -fpp -fpe0 -assume buffered_io -assume byterecl -align sequence -diag-disable 6477 -implicitnone -gen-interfaces -mcmodel=large -shared-intel -arch AVX"
55 | echo "# Build ANCC using the $COMPILER compiler" > config.h
56 | echo "" >> config.h
57 | echo "# Install directory " >> config.h
58 | echo "INST_DIR = ~/bin" >> config.h
59 | echo "" >> config.h
60 | echo "############################################" >> config.h
61 | echo "# GNU Compilers " >> config.h
62 | echo "############################################" >> config.h
63 | echo "" >> config.h
64 | echo "CC = $CC" >> config.h
65 | echo "FC = $FC" >> config.h
66 | echo "MPIFC = $MPIFC" >> config.h
67 | echo "CFLAGS = $CFLAGS" >> config.h
68 | echo "FFLAGS = $FFLAGS" >> config.h
69 | elif [[ "$COMPILER" == "PGI" ]]; then
70 | echo "Build ANCC using the PGI compilers"
71 | CFLAGS="-O3 -fast -m64 -Mpreprocess -Mnobounds -Mautoinline -Mcache_align -Mfma -Mprefetch -Munroll -Mdaz -mcmodel=medium -Mflushz -Mavx -I./"
72 | FFLAGS="-O3 -fast -m64 -Mpreprocess -Mnobounds -Mautoinline -Mcache_align -Mfma -Mprefetch -Munroll -Mdaz -mcmodel=medium -Mmpi=mpich2 -Mflushz -Mavx"
73 | echo "# Build ANCC using the $COMPILER compiler" > config.h
74 | echo "" >> config.h
75 | echo "# Install directory " >> config.h
76 | echo "INST_DIR = ~/bin" >> config.h
77 | echo "" >> config.h
78 | echo "############################################" >> config.h
79 | echo "# GNU Compilers " >> config.h
80 | echo "############################################" >> config.h
81 | echo "" >> config.h
82 | echo "CC = $CC" >> config.h
83 | echo "FC = $FC" >> config.h
84 | echo "MPIFC = $MPIFC" >> config.h
85 | echo "CFLAGS = $CFLAGS" >> config.h
86 | echo "FFLAGS = $FFLAGS" >> config.h
87 | else
88 | echo "Error: Unknown compilers to configure config.h !"
89 | return 0
90 | fi
91 |
92 | return 1
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/ANCC/README:
--------------------------------------------------------------------------------
1 | In default, the intel compiler (such as ifort/mpiifort or ifx/mpiifx) is recommended. If you use a gnu compiler, you can comment flags for the intel compiler
2 | and uncomments those for the gnu compiler in the Makefile.
3 |
4 | This program includes three parts, i.e. AFTAN (original author, University of Colorado Boulder), ANCC (original author [v2.0], Xingli Fan), TF_PWS (original author, Guoliang Li).
5 | The first part implements time-frequency analysis to extract dispersion curves for ambient noise tomography.
6 | The second part computes the cross-correlation function with MPI parallel computing.
7 | The third part implements a phase-weighted stack of cross-correlation.
8 |
9 | After v3.0, all parts are single precision, which leads to a significant performance improvement.
10 | Any goto syntaxes are removed. All arrays are dynamically allocated based on the length of data instead of 32768 in the original version.
11 | In this version, a lot of errors have been corrected.
12 |
13 | In the original version, all FFT operations are directly applied to time-domain signals. Because FFT requires a periodic signal,
14 | thus it will lead to some spurious oscillations at zero lag. A cosine taper is applied before FFT in the time domain, which can suppress
15 | non-physical zero-arrival spurious oscillations. Many unnecessary file copy and movement operations existed.
16 | In addition, the length of the cross-correlation of two signals with the length of M and N is M+N-1. However, the original version allocates the same length arrays
17 | for cross-correlation and signal itself, it will lead to potential aliasing in truncated frequency points.
18 | After v4.0, different lengths of arrays for cross-correlation and signal are adopted.
19 | All unnecessary file copy and movement are avoided, and a slight performance improvement is obtained.
20 |
21 | In the original version, a master process sends and receives task information, while other slave processors do the real computation.
22 | However, this is completely unnecessary. After redesigning the framework, the master/slave mode is removed. All processors can do real computation.
23 | Thus, any message-passing parts are avoided. It leads to a significant efficiency improvement.
24 | After v5.0, master/slave mode is removed. Some constants are moved to a module and initialized. Many subroutines are optimized.
25 | And some related operations are merged, thus many unnecessary file I/O are avoided.
26 |
27 | Although master/slave mode has been removed in v5.0, however, database-constructing part is still serial. It usually takes tens of hours. It significantly lowers efficiency.
28 | After 6.0, the database-constructing part is also parallelized. The database struct is redesigned. As a result, the access order of the array is the same as the storage order
29 | in computer memory. Further performance is obtained.
30 |
31 | Now the computation for multiple components (such as ZZ, ZN, ZE, NZ, NN, NE, EZ, EN, EE) is ready.
32 |
33 |
34 | In version 7.0, data overlap is allowed.
35 |
36 |
37 |
38 | # Change Log
39 | · 21th Mar. 2021: Calculation of auto-correlation functions is supported.
40 |
41 | · 13th Jul. 2022: Outputing prestack cross-correlation functions is supported.
42 |
43 | · 31th Aug. 2023: Redesigned Makefile. The config.h used in the old versions can be automake by two bash scripts, you just need to select the MPIFC in the Makefile.
44 | Now, it supports Intel, GNU, and PGI Compilers. If you want to modify the guess.flags or anything else to adapt it to other compilers or systems, let me know so that we can make your modifications available to others.
45 | Fix some errors in ./src/TF_PWS/st.c
46 |
47 | · 12th Nov. 2023: Redesigned database structs to save memory and improve MPI communications.
48 |
49 | · 7th Nov. 2024: Fix many errors in AFTAN.
50 |
--------------------------------------------------------------------------------
/scripts/reftek2sac_clean.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: UTF-8 -*-
3 |
4 |
5 | '''
6 | reftek2sac
7 |
8 | This program converts files from REFTEK to SAC format using the ObsPy
9 |
10 | Date: 22/10/2020
11 | Author: Youshan Liu
12 | Affiliation: Institute of Geology and Geophysics, Chinese Academy of Sciences
13 |
14 |
15 | directory structure:
16 | ./top folder/station and stage folder/day folder/Reftek UnitID number/stream/reftek files
17 |
18 | for example:
19 | ./DATA_Raw/NE00_2007_276_2008_005/2007276/9F78/1
20 |
21 |
22 |
23 | Reftek 130 Disk Directory Structure
24 |
25 | Year
26 | | Day of year
27 | | |
28 | v v
29 | __ _
30 | | || |
31 | \2003032
32 | \2003033
33 |
34 | Unit ID number
35 | |
36 | v
37 | __
38 | | |
39 | \90F0
40 |
41 | Datastream
42 | |
43 | v
44 | \0
45 | \1
46 | \2
47 |
48 | '''
49 |
50 |
51 | import os
52 | import re
53 | from obspy import read
54 | from obspy import UTCDateTime
55 | from obspy.io.sac import SACTrace
56 |
57 |
58 |
59 | ##############################################################
60 | ##############################################################
61 | ##############################################################
62 | # some options to be set
63 |
64 |
65 | # dryrun just for debug
66 | # dryrun = True => just print some directory information not to write sac files
67 | # dryrun = False => do the actual files conversion
68 | dryrun = True
69 |
70 | # directory of the reftek data
71 | data_path = './DATA_1'
72 |
73 |
74 | ##############################################################
75 | ##############################################################
76 | ##############################################################
77 | def reftek2sac():
78 |
79 | sac_suffix = '.SAC'
80 |
81 | len_topdir = len(input_path) + 1
82 |
83 | stage_folders_list = os.listdir(input_path)
84 |
85 | # convert reftek to sac
86 | for station_stage_folder in stage_folders_list:
87 |
88 | station_stage_path = input_path + '/' + station_stage_folder + '/'
89 | print('Entering directory ' + station_stage_path[len_topdir:-1])
90 | #print('\n')
91 |
92 | if (not os.path.exists(station_stage_path)):
93 | continue
94 |
95 | day_folders_list = os.listdir(station_stage_path)
96 |
97 | #print(day_folders_list)
98 | #return
99 |
100 | for day_folder in day_folders_list:
101 |
102 | day_path = station_stage_path + day_folder + '/'
103 | print('Entering directory ' + day_path[len_topdir:-1])
104 | #print('\n')
105 |
106 | if (not os.path.exists(day_path)):
107 | continue
108 |
109 | # remove all sac files
110 | #print(day_path)
111 | os.system("rm -rf " + day_path + "*" + sac_suffix)
112 | continue
113 |
114 | print('Leaving directory ' + day_path[len_topdir:-1])
115 | #print('\n')
116 |
117 | del day_folders_list
118 | print('Leaving directory ' + station_stage_path[len_topdir:-1])
119 | #print('\n')
120 |
121 | del stage_folders_list
122 |
123 | return
124 |
125 |
126 |
127 | if __name__ == '__main__':
128 |
129 | print('\n')
130 | print('reftek2sac_clean: ')
131 | print('This program convert files from reftek to sac format using the ObsPy (serial version)')
132 | print('Youshan Liu at Institute of Geology and Geophysics, Chinese Academy of Sciences')
133 | print('Welcome to send any bugs and suggestions to ysliu@mail.iggcas.ac.cn')
134 | print('\n')
135 |
136 | starttime = UTCDateTime()
137 |
138 | # get current path
139 | #current_path = os.getcwd()
140 |
141 | # convert reftek file to sac format
142 | reftek2sac()
143 |
144 | endtime = UTCDateTime()
145 |
146 | elapsed_time = (endtime - starttime)
147 |
148 | print('\n')
149 | print('Start time : %s' % starttime)
150 | print('End time : %s' % endtime)
151 | print('Elapsed time : %f hours' % (elapsed_time / 3600.0))
152 |
153 |
154 |
155 |
--------------------------------------------------------------------------------
/scripts/reftek2sac_p_clean.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: UTF-8 -*-
3 |
4 |
5 | '''
6 | reftek2sac
7 |
8 | This program converts files from REFTEK to SAC format using the ObsPy
9 |
10 | Date: 22/10/2020
11 | Author: Youshan Liu
12 | Affiliation: Institute of Geology and Geophysics, Chinese Academy of Sciences
13 |
14 |
15 | directory structure:
16 | ./top folder/station and stage folder/day folder/Reftek UnitID number/stream/reftek files
17 |
18 | for example:
19 | ./DATA_Raw/NE00_2007_276_2008_005/2007276/9F78/1
20 |
21 |
22 |
23 | Reftek 130 Disk Directory Structure
24 |
25 | Year
26 | | Day of year
27 | | |
28 | v v
29 | __ _
30 | | || |
31 | \2003032
32 | \2003033
33 |
34 | Unit ID number
35 | |
36 | v
37 | __
38 | | |
39 | \90F0
40 |
41 | Datastream
42 | |
43 | v
44 | \0
45 | \1
46 | \2
47 |
48 | '''
49 |
50 |
51 |
52 |
53 | import os
54 | import re
55 | from obspy import read
56 | from obspy import UTCDateTime
57 | from obspy.io.sac import SACTrace
58 | from multiprocessing.pool import ThreadPool
59 |
60 |
61 |
62 | ##############################################################
63 | ##############################################################
64 | ##############################################################
65 | # some options to be set
66 |
67 |
68 | # dryrun just for debug
69 | # dryrun = True => just print some directory information not to write sac files
70 | # dryrun = False => do the actual files conversion
71 | dryrun = False
72 |
73 | # directory of the reftek data
74 | input_path = './DATA_4'
75 |
76 |
77 | ##############################################################
78 | ##############################################################
79 | ##############################################################
80 | def convert_daily(day_folder):
81 |
82 | day_path = station_stage_path + day_folder + '/'
83 | print('Entering directory ' + day_path[len_topdir:-1])
84 | #print('\n')
85 |
86 | os.system("rm -rf " + day_path + "*" + sac_suffix)
87 |
88 | print('Leaving directory ' + day_path[len_topdir:-1])
89 | #print('\n')
90 |
91 | return
92 |
93 |
94 |
95 | def reftek2sac():
96 |
97 | global len_topdir, station_stage_path, sac_suffix
98 |
99 | len_topdir = len(input_path) + 1
100 |
101 | stage_folders_list = os.listdir(input_path)
102 |
103 |
104 | sac_suffix = '.SAC'
105 |
106 | # convert reftek to sac
107 | for station_stage_folder in stage_folders_list:
108 |
109 | station_stage_path = input_path + '/' + station_stage_folder + '/'
110 | print('Entering directory ' + station_stage_path[len_topdir:-1])
111 | #print('\n')
112 |
113 | if (not os.path.isdir(station_stage_path)):
114 | continue
115 |
116 | day_folders_list = os.listdir(station_stage_path)
117 |
118 | pool = ThreadPool()
119 | pool.map(convert_daily, day_folders_list)
120 | pool.close()
121 | pool.join()
122 |
123 | del day_folders_list
124 | print('Leaving directory ' + station_stage_path[len_topdir:-1])
125 | #print('\n')
126 |
127 | del stage_folders_list
128 |
129 | return
130 |
131 |
132 |
133 | if __name__ == '__main__':
134 |
135 | print('\n')
136 | print('reftek2sac_clean: ')
137 | print('This program convert files from reftek to sac format using the ObsPy (parallel version)')
138 | print('Youshan Liu at Institute of Geology and Geophysics, Chinese Academy of Sciences')
139 | print('Welcome to send any bugs and suggestions to ysliu@mail.iggcas.ac.cn')
140 | print('\n')
141 |
142 | starttime = UTCDateTime()
143 |
144 | # absolution path
145 | #current_path = os.getcwd()
146 |
147 | # convert reftek file to sac format
148 | reftek2sac()
149 |
150 | endtime = UTCDateTime()
151 |
152 | elapsed_time = (endtime - starttime)
153 |
154 | print('\n')
155 | print('Start time : %s' % starttime)
156 | print('End time : %s' % endtime)
157 | print('Elapsed time : %f hours' % (elapsed_time / 3600.0))
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/ANCC/src/ANCC/math.f90:
--------------------------------------------------------------------------------
1 | ! This file is part of ANCC.
2 | !
3 | ! ANCC is free software: you can redistribute it and/or modify
4 | ! it under the terms of the GNU General Public License as published by
5 | ! the Free Software Foundation, either version 3 of the License, or
6 | ! (at your option) any later version.
7 | !
8 | ! ANCC is distributed in the hope that it will be useful,
9 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | ! GNU General Public License for more details.
12 | !
13 | ! You should have received a copy of the GNU General Public License
14 | ! along with this program. If not, see .
15 | !
16 | !
17 | module math_m
18 |
19 | use db_m
20 |
21 |
22 | implicit none
23 |
24 |
25 |
26 | contains
27 |
28 | ! ***************************************************************
29 | ! This program is downloaded from http://fcode.cn/guide-96-1.html
30 | ! After invoke this subroutine, random_number can produce different
31 | ! random numbers in the range of [0 1]. Without using this subroutine,
32 | ! random_number will produce the same random numbers every time.
33 | ! ***************************************************************
34 | subroutine init_random_seed()
35 |
36 |
37 | #ifdef __INTEL_COMPILER
38 | use IFPORT
39 | #endif
40 |
41 |
42 | implicit none
43 |
44 |
45 | integer ised, i, pid
46 |
47 | integer(DBL) t
48 |
49 | integer, allocatable, dimension(:) :: sed
50 |
51 |
52 | call random_seed(size = ised) ! Get the size of the seed
53 |
54 |
55 | allocate(sed(ised)) ! Distribute the seed
56 | call system_clock(t) ! Get the time
57 | pid = getpid() ! Get the id of the processor
58 | t = ieor(t, int(pid, kind(t))) ! XOR operation
59 |
60 | do i = 1, ised, 1
61 | sed(i) = lcg(t) ! LCG operation
62 | end do
63 |
64 |
65 | call random_seed(put = sed) ! Set the seed value
66 |
67 |
68 | end subroutine init_random_seed
69 |
70 | ! ***************************************************************
71 | ! Linear congruential generator
72 | ! ***************************************************************
73 | function lcg(s)
74 |
75 | integer(DBL), intent(inout) :: s
76 |
77 |
78 | integer lcg
79 |
80 |
81 | if (0 == s) then
82 |
83 | s = 104729
84 |
85 | else
86 |
87 | s = mod(s, 4294967296_DBL)
88 |
89 | end if
90 |
91 | s = mod(s * 279470273_DBL, 4294967291_DBL)
92 | lcg = int(mod(s, int(huge(0), DBL)), kind(0))
93 |
94 |
95 | return
96 |
97 |
98 | end function lcg
99 |
100 |
101 | ! ***************************************************************
102 | ! ***************************************************************
103 | subroutine matrix_mean_std(A, skip_value, nout, mean, std)
104 |
105 | implicit none
106 |
107 | real(SGL), intent(in) :: skip_value
108 |
109 | real(SGL), dimension(:,:), intent(in) :: A
110 |
111 | integer, intent(out) :: nout
112 |
113 | real(SGL), dimension(:), allocatable, intent(out) :: mean, std
114 |
115 |
116 | integer i, j, ier
117 | integer n, nrow, ncol
118 |
119 | real(SGL) rn, rsum1, rsum2
120 |
121 |
122 | nrow = size(A,1)
123 | ncol = size(A,2)
124 |
125 | nout = nrow
126 |
127 | allocate(mean(1:nrow), std(1:nrow), stat=ier)
128 | std = 0.0
129 | mean = 0.0
130 | do i = 1, nrow, 1
131 |
132 | n = 0
133 |
134 | rsum1 = 0.0
135 | rsum2 = 0.0
136 | do j = 1, ncol, 1
137 | if (abs(A(i,j)-skip_value) > epsilon(A(i,j))) then
138 | rsum1 = rsum1 + A(i,j)
139 | rsum2 = rsum2 + A(i,j)*A(i,j)
140 | n = n + 1
141 | end if
142 | end do
143 |
144 | rn = real(n)
145 | if (n >= 1) then
146 | mean(i) = rsum1 / rn
147 | end if
148 |
149 | if (n >= 2) then
150 | std(i) = sqrt(abs(rn*rsum2 - rsum1*rsum1)/(rn*(n-1)))
151 | end if
152 |
153 | end do
154 |
155 |
156 | end subroutine matrix_mean_std
157 |
158 |
159 | end module math_m
160 |
--------------------------------------------------------------------------------
/ANCC/src/ANCC/db_m.f90:
--------------------------------------------------------------------------------
1 | ! This file is part of ANCC.
2 | !
3 | ! ANCC is free software: you can redistribute it and/or modify
4 | ! it under the terms of the GNU General Public License as published by
5 | ! the Free Software Foundation, either version 3 of the License, or
6 | ! (at your option) any later version.
7 | !
8 | ! ANCC is distributed in the hope that it will be useful,
9 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | ! GNU General Public License for more details.
12 | !
13 | ! You should have received a copy of the GNU General Public License
14 | ! along with this program. If not, see .
15 | !
16 | !
17 | module db_m
18 |
19 |
20 | implicit none
21 |
22 |
23 | ! ***********************************************************************************************
24 | ! ********************************* VARIABLE DEFINITION SECTION *********************************
25 | ! ***********************************************************************************************
26 |
27 | ! some constants
28 | integer, parameter :: SGL = SELECTED_real_KIND(5,20)
29 | integer, parameter :: DBL = SELECTED_real_KIND(13,100)
30 | integer, parameter :: TIMEMAX = 10000000 ! TIMEMAX: maximum time length of the SAC file
31 | real(SGL), parameter :: HUGEVAL = huge(0.0)
32 | real(SGL), parameter :: TINYVAL = tiny(0.0)
33 | complex(SGL), parameter :: ci = cmplx(0.0, 1.0)
34 | complex(SGL), parameter :: czero = cmplx(0.0, 0.0)
35 |
36 |
37 | ! size and rank of MPI_COMM_WORLD
38 | integer :: nprocs = 1
39 | integer :: myrank = 0
40 |
41 |
42 | ! taper parameters
43 | integer, parameter :: ntaper_min = 10
44 | real, parameter :: taper_min = 1.0
45 |
46 | integer :: Nlen = 0, ntaper = 0
47 |
48 |
49 | ! some logical variables
50 | logical is_specwhitening
51 | logical is_stack, is_pws
52 | logical is_only_cf, is_ac
53 | logical is_verbose, is_bootstrap
54 | logical is_overwrite_data, is_save_record
55 | logical is_onebit, is_running_time_average
56 | logical is_bandpass_earthquake, is_suppress_notch
57 |
58 |
59 | ! ***********************************************************************************************
60 | ! *********************************** type DEFINITION SECTION ***********************************
61 | ! ***********************************************************************************************
62 | type station
63 | character(len=8) :: staname = '' ! staname: station name (e.g. MONP)
64 | character(len=17) :: ns_name = '' ! ns_name: network.station name (e.g. AZ.MONP)
65 | real(SGL) :: lat, lon ! lat, lon: latitude and longitude of the station
66 | end type station
67 |
68 | type event
69 | character(len=128) :: evtpath = '' ! evtpath: event path (e.g. path/20150401_000000)
70 | integer :: yy, mm, dd, h, m, jday ! yy, mm, dd, h, m, jday: year, month, day, hour, minute, julian day
71 | real(DBL) :: s = 0.d0 ! ss: second in decimal form
72 | real(DBL) :: t0 = -1.d0 ! t0: epoch time of the event (e.g. 123456789)
73 | end type event
74 |
75 | type record
76 | character(len=192) :: sacfile = '' ! sacname: SAC path and filename (e.g. path/20150401_000000/AZ.MONP.BHZ.SAC)
77 | real(DBL) :: t0 = -1.d0 ! t0: epoch time of the first data point
78 | end type record
79 |
80 | type sac_db
81 | type(event), allocatable, dimension(:) :: ev ! ev: EVENT struct array
82 | type(station), allocatable, dimension(:) :: st ! st: STATION struct array
83 | type(record), allocatable, dimension(:,:) :: rec ! rec: record struct array
84 | integer :: nev, nst ! nev, nst: number of events and stations
85 | integer :: npts = 0 ! npts: number of data points (should be default to 0)
86 | real(DBL) :: dt = 0.d0 ! dt: data sampling interval
87 | end type sac_db
88 |
89 |
90 | end module db_m
91 |
--------------------------------------------------------------------------------
/run /input.dat:
--------------------------------------------------------------------------------
1 | ##############################################################################
2 | # INPUT PARAMETERS FOR AMBIENT NOISE CROSS-CORRELATION
3 | ##############################################################################
4 | BHZ # channel name
5 | 120.0 80.0 0.5 0.25 # frequency limits (used in removal of instrument response and bandpass filter)
6 | 10.0 86380.0 # tBegin, tLen (used in data cut for each event)
7 | 1 # power of cosine tapering function
8 | Y 100 N 10 0.5 # whether use running-absolute-mean time average temporal normalization, half-window width, whether bandpass filter earthquake, period bands
9 | N # whether use one-bit temporal normalization
10 | Y 20 # whether apply spectral whitening, half-window width in spectral whitening
11 | N 0.5 # whether suppressing the notch at 26s and the retaining factor
12 | 100.0 # lag time (in second) for the cross-correlation
13 | N 1 # whether output phase weighted stacking (pws) results, pws weight
14 |
15 |
16 | ##############################################################################
17 | # INPUT PARAMETERS FOR BOOTSTRAP ANALYSIS
18 | ##############################################################################
19 | N 100 # whether doing the bootstrap, number of repeating times
20 | 2_2 # a_b-type of dispersion (a=[1-normal; 2-phase matched filtering], b=[1-raw; 2-clean])
21 |
22 |
23 | ##############################################################################
24 | # INPUT PARAMETERS FOR AUTOMATIC FREQUENCY-TIME ANALYSIS
25 | ##############################################################################
26 | -1.0 # PIover4 (phase_shift = PI/4*PIover4)
27 | 1.5 5.0 # vmin, vmax - minimum and maximum group velocity (for tapering the signal window)
28 | 3.0 45.0 # tmin, tmax - minimum and maximum period for the phase velocity measurement
29 | Y 1 # whether limiting the maximum period (nLambda*period*ref_velocity < delta), nLambda
30 | N # whether output all the preliminary results
31 | 10.0 # tresh-jump detection factor (used in trigger subroutine, if (abs(r) > tresh)
32 | 1.0 1.0 # alpha values in the narrow-band gaussian filters (alpha = 20*ffact*sqrt(delta/1000))
33 | 1.0 # taperl-factor for the left-end seismogram tapering (ntapb = nint(taperl*tmax/dt))
34 | 0.2 # fsnr-not used (for future extension)
35 | 1.0 # fmatch-factor for the length of phase matching window
36 |
37 |
38 | ##############################################################################
39 | # INPUT PARAMETERS FOR OUTPUT AND CONTROL FLOW SETTINGS
40 | ##############################################################################
41 | Y # whether output the SAC file record and cross-correlation record
42 | Y # whether verbose all the processing details
43 | Y # whether only compute auto- or cross-correlation functions, otherwise, it computes correlation function and does dispersion analysis
44 | N # whether overwrite SAC files
45 | Y # whether stack auto- or cross-correlation function
46 | N # whether compute auto-correlation function
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | 
3 | 
4 | 
5 | 
6 | 
7 | 
8 | 
9 | 
10 | 
11 | # ANCC
12 | Some scripts and programs for ambient noise tomography, such as computing cross-correlation, auto-correlation (with parallel computing), and extracting dispersion curves.
13 | It can also output prestack cross-correlation functions.
14 |
15 | 1. Convert the REFTEK file format (or other file formats) to the SAC file format (scripts)
16 |
17 | reftek2sac.py -> file convertor with the folder structure, such as /root/stage_and_station_name/day/
18 |
19 | reftek2sac_p.py -> parallel processing of reftek2sac.py
20 |
21 | reftek2sac2.py -> file convertor with the folder structure, such as /root/stage/station_name/day/
22 |
23 | reftek2sac2_p.py -> a parallel processing of reftek2sac2.py
24 |
25 | Actually, it is easily modified to convert other file formats by using the flexibility of ObsPy's read function, i.e. change the FORMAT parameter in the read of the ObsPy.
26 | A file format should be given, it will improve the performance.
27 |
28 | 2. Cut daily data into predefined-segment data (scripts)
29 |
30 | This program first merges daily data then cut it into predefined segments. Simultaneously, it resamples data at each natural sampling point.
31 |
32 | cutdata.py -> cut daily data into predefined-segment data with the folder structure, such as /root/stage_and_station_name/day/
33 |
34 | cutdata_p.py -> parallel processing of cutdata.py
35 |
36 | cutdata2.py -> cut daily data into predefined-segment data with the folder structure, such as /root/stage/station_name/day/
37 |
38 | cutdata2_p.py -> parallel processing of cutdata2.py
39 |
40 | 3. Auto- or cross-correlation and frequency-time analysis (Ambient Noise Auto- or Cross-Correlation)
41 |
42 | It includes the AFTAN to extract the dispersion curve.
43 |
44 | 4. Generate instrument response automatically (makePZfiles)
45 |
46 | In the makePZfiles folder, you can generate instrument response polezero files automatically using resp2pz.py or makePZs.py,
47 | once fill an Excel sheet based on your project log. The former can take responses of sensor and DAS into consideration,
48 | it then merges them into one PZ file. While the latter only takes the response of the sensor into consideration, then genertes
49 | corresponding PZ files automatically.
50 |
51 |
52 | # Prerequisites
53 | The MPICH/OpenMPI is required. There are many MPI release versions. Usually, MPICH is recommended.
54 | The number of processes that can be used by the former (MPICH) is twice the number of physical
55 | cores, while the number of processes that can be used by the latter (OpenMPI) is equal to the
56 | number of physical cores.
57 | The FFTW3, SAC, and MPI (MPICH2/OpenMPI) softwares are required by the ANCC.
58 | The ObsPy is required by the scripts.
59 | The xlrd is required by the makePZs.py and resp2pz.py.
60 |
61 |
62 |
63 | # LICENSE
64 | ANCC is free software: you can redistribute it and/or modify
65 | it under the terms of the GNU General Public License as published by
66 | the Free Software Foundation, either version 3 of the License, or
67 | (at your option) any later version.
68 |
69 | ANCC is distributed in the hope that it will be useful,
70 | but WITHOUT ANY WARRANTY; without even the implied warranty of
71 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
72 | GNU General Public License for more details.
73 |
74 | You should have received a copy of the GNU General Public License
75 | along with this program. If not, see .
76 |
--------------------------------------------------------------------------------
/ANCC/src/TF_PWS/sacrw.c:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of ANCC.
3 | TF_PWS is free software: you can redistribute it and/or modify
4 | it under the terms of the GNU General Public License as published by
5 | the Free Software Foundation, either version 3 of the License, or
6 | (at your option) any later version.
7 | TF_PWS is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | GNU General Public License for more details.
11 | You should have received a copy of the GNU General Public License
12 | along with this program. If not, see .
13 | */
14 |
15 | #define MAIN
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include "mysac.h"
22 |
23 |
24 | #define PI 3.141592653589793
25 | #define deg2rad PI/180.0
26 | #define R 6371.0
27 | #define TINYVAL 1.e-308
28 |
29 |
30 | float geodist(float evla, float evlo, float stla, float stlo);
31 | //void geodist(SACHead *shd);
32 |
33 |
34 | void read_sac(char *fname, float *wf, SACHead *shd, long Nmax)
35 | {
36 |
37 | FILE *fsac;
38 |
39 | fsac = fopen(fname, "rb");
40 |
41 | if (!fsac)
42 | {
43 | printf("The %s does not exist !\n", fname);
44 | exit(0);
45 | }
46 |
47 | if (!shd) shd = &SAC_HEADER;
48 | fread(shd, sizeof(SACHead), 1, fsac);
49 | if (shd->npts > Nmax)
50 | {
51 | shd->npts = Nmax;
52 | }
53 |
54 | fread(wf, sizeof(float), (int)(shd->npts), fsac);
55 |
56 | fclose(fsac);
57 |
58 | //return shd;
59 |
60 | }
61 |
62 |
63 | void write_sac(char *fname, float *wf, SACHead *shd)
64 | {
65 |
66 | int i, n;
67 |
68 | FILE *fsac;
69 |
70 | fsac = fopen(fname, "wb");
71 |
72 | if ((fsac = fopen(fname, "wb")) == NULL)
73 | {
74 | printf("Could not open SAC file to write \n");
75 | exit(1);
76 | }
77 |
78 | if (!shd)
79 | {
80 | shd = &SAC_HEADER;
81 | }
82 |
83 |
84 | shd->iftype = (long)ITIME;
85 | shd->leven = (long)TRUE;
86 |
87 | shd->lovrok = (long)TRUE;
88 | shd->internal4 = 6L;
89 |
90 |
91 |
92 | shd->depmin = wf[0];
93 | shd->depmax = wf[0];
94 |
95 | for (i = 0; i < shd->npts; i++)
96 | {
97 | if (shd->depmin > wf[i]) shd->depmin = wf[i];
98 | if (shd->depmax < wf[i]) shd->depmax = wf[i];
99 | }
100 |
101 | // compute distance
102 | //geodist(shd);
103 | shd->dist = geodist(shd->evla, shd->evlo, shd->stla, shd->stlo);
104 |
105 |
106 | fwrite(shd, sizeof(SACHead), 1, fsac);
107 |
108 | n = fwrite(wf, sizeof(float), (int)(shd->npts), fsac);
109 | if (n != shd->npts)
110 | {
111 | printf("Error occur when writing the SAC ! ");
112 | printf("n:%d shd -> npts:%d \n", n, (int)(shd->npts));
113 | }
114 |
115 | fclose(fsac);
116 |
117 | }
118 |
119 |
120 | float geodist(float evlaf, float evlof, float stlaf, float stlof)
121 | {
122 |
123 | double stla, stlo, evla, evlo, c, theta;
124 |
125 | evla = evlaf * deg2rad;
126 | evlo = evlof * deg2rad;
127 | stla = stlaf * deg2rad;
128 | stlo = stlof * deg2rad;
129 |
130 | c = sin(stla) * sin(evla) + cos(stla) * cos(evla) * cos(stlo - evlo);
131 |
132 | if (fabs(c - 1.0) < TINYVAL)
133 | {
134 | theta = 0.0;
135 | }
136 | else if (fabs(c + 1.0) < TINYVAL)
137 | {
138 | theta = PI;
139 | }
140 | else
141 | {
142 | theta = acos(c);
143 | }
144 |
145 | return (float)(R * theta);
146 |
147 | }
148 |
149 |
150 |
151 | /*void geodist(SACHead *shd)
152 | {
153 |
154 | double stla, stlo, evla, evlo, c, theta;
155 |
156 | evla = shd->evla * deg2rad;
157 | evlo = shd->evlo * deg2rad;
158 | stla = shd->stla * deg2rad;
159 | stlo = shd->stlo * deg2rad;
160 |
161 | c = sin(stla) * sin(evla) + cos(stla) * cos(evla) * cos(stlo - evlo);
162 |
163 | if (abs(c - 1.0) < TINYVAL)
164 | {
165 | theta = 0.0;
166 | }
167 | else if (abs(c + 1.0) < TINYVAL)
168 | {
169 | theta = PI;
170 | }
171 | else
172 | {
173 | theta = acos(c);
174 | }
175 |
176 | shd->dist = (float)(R * theta);
177 |
178 | }*/
179 |
--------------------------------------------------------------------------------
/scripts/reftek2sac2_p_clean.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: UTF-8 -*-
3 |
4 |
5 | '''
6 | reftek2sac
7 |
8 | This program converts files from REFTEK to SAC format using the ObsPy
9 |
10 | Date: 22/10/2020
11 | Author: Youshan Liu
12 | Affiliation: Institute of Geology and Geophysics, Chinese Academy of Sciences
13 |
14 |
15 | directory structure:
16 | ./top folder/period folder/station folder/day folder/Reftek UnitID number/stream/reftek files
17 |
18 | for example:
19 | ./DATA_Raw/2007_276_2008_005/NE00/2007276/9F78/1
20 |
21 |
22 |
23 | Reftek 130 Disk Directory Structure
24 |
25 | Year
26 | | Day of year
27 | | |
28 | v v
29 | __ _
30 | | || |
31 | \2003032
32 | \2003033
33 |
34 | Unit ID number
35 | |
36 | v
37 | __
38 | | |
39 | \90F0
40 |
41 | Datastream
42 | |
43 | v
44 | \0
45 | \1
46 | \2
47 |
48 | '''
49 |
50 |
51 |
52 |
53 | import os
54 | import re
55 | from obspy import read
56 | from obspy import UTCDateTime
57 | from obspy.io.sac import SACTrace
58 | from multiprocessing.pool import ThreadPool
59 |
60 |
61 | ##############################################################
62 | ##############################################################
63 | ##############################################################
64 | # some options to be set
65 |
66 |
67 | # dryrun just for debug
68 | # dryrun = True => just print some directory information not to write sac files
69 | # dryrun = False => do the actual files conversion
70 | dryrun = False
71 |
72 | # directory of the reftek data
73 | input_path = './DATA_Raw'
74 | #input_path = './Removed_data'
75 |
76 |
77 | ##############################################################
78 | ##############################################################
79 | ##############################################################
80 | def convert_daily(day_folder):
81 |
82 | day_path = station_path + day_folder + '/'
83 | print('Entering directory ' + day_path[len_topdir:-1])
84 | #print('\n')
85 |
86 | os.system("rm -rf " + day_path + "*" + sac_suffix)
87 |
88 | print('Leaving directory ' + day_path[len_topdir:-1])
89 | #print('\n')
90 |
91 | return
92 |
93 |
94 |
95 | def reftek2sac():
96 |
97 | global len_topdir, station_path, sac_suffix
98 |
99 | len_topdir = len(input_path) + 1
100 |
101 | stage_folders_list = os.listdir(input_path)
102 |
103 |
104 | sac_suffix = '.SAC'
105 |
106 | # convert reftek to sac
107 | for stage_folder in stage_folders_list:
108 |
109 | stage_path = input_path + '/' + stage_folder + '/'
110 | print('Entering directory ' + stage_path[len_topdir:-1])
111 | #print('\n')
112 |
113 | if (not os.path.isdir(stage_path)):
114 | continue
115 |
116 | station_folder_list = os.listdir(stage_path)
117 |
118 | for station_folder in station_folder_list:
119 |
120 | station_path = stage_path + station_folder + '/'
121 | print('Entering directory ' + station_path[len_topdir:-1])
122 | #print('\n')
123 |
124 | if (not os.path.isdir(station_path)):
125 | continue
126 |
127 | day_folders_list = os.listdir(station_path)
128 |
129 | pool = ThreadPool()
130 | pool.map(convert_daily, day_folders_list)
131 | pool.close()
132 | pool.join()
133 |
134 | del day_folders_list
135 | print('Leaving directory ' + station_path[len_topdir:-1])
136 | #print('\n')
137 |
138 | del station_folder_list
139 | print('Leaving directory ' + stage_path[len_topdir:-1])
140 | #print('\n')
141 |
142 | del stage_folders_list
143 |
144 | return
145 |
146 |
147 |
148 | if __name__ == '__main__':
149 |
150 | print('\n')
151 | print('reftek2sac_clean: ')
152 | print('This program convert files from reftek to sac format using the ObsPy (parallel version)')
153 | print('Youshan Liu at Institute of Geology and Geophysics, Chinese Academy of Sciences')
154 | print('Welcome to send any bugs and suggestions to ysliu@mail.iggcas.ac.cn')
155 | print('\n')
156 |
157 | starttime = UTCDateTime()
158 |
159 | # absolution path
160 | #current_path = os.getcwd()
161 |
162 | # convert reftek file to sac format
163 | reftek2sac()
164 |
165 | endtime = UTCDateTime()
166 |
167 | elapsed_time = (endtime - starttime)
168 |
169 | print('\n')
170 | print('Start time : %s' % starttime)
171 | print('End time : %s' % endtime)
172 | print('Elapsed time : %f hours' % (elapsed_time / 3600.0))
173 |
174 |
175 |
176 |
--------------------------------------------------------------------------------
/ANCC/src/ANCC/date_time.f90:
--------------------------------------------------------------------------------
1 | ! This file is part of ANCC.
2 | !
3 | ! ANCC is free software: you can redistribute it and/or modify
4 | ! it under the terms of the GNU General Public License as published by
5 | ! the Free Software Foundation, either version 3 of the License, or
6 | ! (at your option) any later version.
7 | !
8 | ! ANCC is distributed in the hope that it will be useful,
9 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | ! GNU General Public License for more details.
12 | !
13 | ! You should have received a copy of the GNU General Public License
14 | ! along with this program. If not, see .
15 | !
16 | !
17 | module date_time_m
18 |
19 | use db_m
20 |
21 |
22 |
23 | implicit none
24 |
25 |
26 |
27 | contains
28 |
29 |
30 | ! ====================================================================
31 | ! Convert the date to julian day
32 | ! year: year [input]
33 | ! month: month [input]
34 | ! day: day [input]
35 | ! date2jday: converted julian day [output]
36 | ! ====================================================================
37 | integer function date2jday(year, month, day)
38 |
39 | implicit none
40 |
41 | integer, intent(in) :: year, month, day
42 |
43 | integer :: i, leap_year
44 |
45 |
46 | if (mod(year, 400) == 0) then
47 | leap_year = 1
48 | else if (mod(year, 100) == 0) then
49 | leap_year = 0
50 | else if (mod(year, 4) == 0) then
51 | leap_year = 1
52 | else
53 | leap_year = 0
54 | end if
55 |
56 |
57 | date2jday = day
58 |
59 | do i = 1, month-1, 1
60 |
61 | select case (i)
62 | case (1,3,5,7,8,10,12)
63 | date2jday = date2jday + 31
64 | case (4,6,9,11)
65 | date2jday = date2jday + 30
66 | case (2)
67 | date2jday = date2jday + 28 + leap_year
68 | end select
69 |
70 | end do
71 |
72 |
73 | end function date2jday
74 |
75 |
76 | ! ====================================================================
77 | ! Convert datetime to timestamp since 1970-01-01T00:00:000000Z in seconds
78 | ! year: year [input]
79 | ! jday: julian day [input]
80 | ! hour: hour [input]
81 | ! min: minute [input]
82 | ! sec: second [input]
83 | ! datetime2timestamp: timestamp in seconds [output]
84 | ! ====================================================================
85 | real(DBL) function datetime2timestamp(year, jday, hour, minute, sec)
86 |
87 | implicit none
88 |
89 | integer, intent(in) :: year, jday, hour, minute
90 | real(DBL), intent(in) :: sec
91 |
92 | integer(8) yeardiff, vis
93 |
94 |
95 | yeardiff = year - 1970
96 | vis = (yeardiff+1)/4 + (yeardiff+369)/400 - (yeardiff+69)/100
97 | datetime2timestamp = (365*yeardiff + vis + jday - 1)*86400.d0 + (hour*60 + minute)*60.d0 + sec
98 |
99 |
100 | end function datetime2timestamp
101 |
102 |
103 | ! ====================================================================
104 | ! Convert timestamp to datetime
105 | ! t: timestamp since 1970-01-01T00:00:000000Z in seconds [input]
106 | ! year: year [output]
107 | ! jday: julian day [output]
108 | ! hour: hour [output]
109 | ! min: minute [output]
110 | ! sec: second [output]
111 | ! ====================================================================
112 | subroutine timestamp2datetime(t, year, jday, hour, minute, sec)
113 |
114 | implicit none
115 |
116 | real(DBL), intent(in) :: t
117 |
118 | integer, intent(out) :: year, jday, hour, minute
119 | real(DBL), intent(out) :: sec
120 |
121 |
122 | integer(8) idate, itime, irest, iysupp, idsupp
123 | real(DBL) fsec
124 |
125 |
126 | idate = int(t/86400.d0)
127 | iysupp = idate/365
128 | idsupp = iysupp*365 + (iysupp+1)/4 + (iysupp+369)/400 - (iysupp+69)/100
129 | if (idate < idsupp) iysupp = iysupp - 1
130 | idsupp = iysupp*365 + (iysupp+1)/4 + (iysupp+369)/400 - (iysupp+69)/100
131 |
132 |
133 | ! extract year
134 | year = int(1970 + iysupp, kind=4)
135 | ! extract jday
136 | jday = int(idate - idsupp + 1, kind=4)
137 | ! time part
138 | fsec = t - idate*86400.d0
139 | irest = int(fsec)
140 | fsec = fsec - irest
141 | itime = irest
142 | irest = itime/60
143 | ! extract second
144 | sec = int(itime - irest*60 + fsec, kind=4)
145 | itime = irest
146 | irest = itime/60
147 | ! extract minute
148 | minute = int(itime - irest*60, kind=4)
149 | ! extract hour
150 | hour = int(irest, kind=4)
151 |
152 |
153 | end subroutine timestamp2datetime
154 |
155 |
156 | end module date_time_m
157 |
--------------------------------------------------------------------------------
/ANCC/src/ANCC/bindata_io.f90:
--------------------------------------------------------------------------------
1 | ! This file is part of ANCC.
2 | !
3 | ! ANCC is free software: you can redistribute it and/or modify
4 | ! it under the terms of the GNU General Public License as published by
5 | ! the Free Software Foundation, either version 3 of the License, or
6 | ! (at your option) any later version.
7 | !
8 | ! ANCC is distributed in the hope that it will be useful,
9 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | ! GNU General Public License for more details.
12 | !
13 | ! You should have received a copy of the GNU General Public License
14 | ! along with this program. If not, see .
15 | !
16 | !
17 | module bindata_io_m
18 |
19 | use db_m
20 | use sac_io_m
21 |
22 |
23 | implicit none
24 |
25 |
26 |
27 | contains
28 |
29 |
30 |
31 | ! ====================================================================
32 | ! write complex data into a local binary file
33 | ! filename: file name of the bianary file [input]
34 | ! n: number of points of the data [input]
35 | ! comdata: complex data array [input]
36 | ! ier: status indicator [output]
37 | ! ====================================================================
38 | subroutine write_bindata(filename, n, comdata, ier)
39 |
40 | implicit none
41 |
42 | integer, intent(in) :: n
43 |
44 | character(len=*), intent(in) :: filename
45 |
46 | complex(SGL), dimension(:), intent(in) :: comdata
47 |
48 |
49 | integer, intent(out) :: ier
50 |
51 |
52 | integer iunit
53 |
54 |
55 |
56 | iunit = 11 + nprocs + myrank
57 |
58 | open(unit=iunit, file=filename, status='replace', action='write', &
59 | iostat=ier, access='stream', form='unformatted')
60 |
61 | if (0 /= ier) then
62 | write(*,"(A,A)") "Error: Cannot open: ", trim(adjustl(filename))
63 | call flush(6)
64 | return
65 | end if
66 |
67 | write(iunit) n
68 | write(iunit) comdata(1:n)
69 |
70 | close(unit=iunit)
71 |
72 |
73 | end subroutine write_bindata
74 |
75 |
76 | ! ====================================================================
77 | ! read complex data from a local binary file
78 | ! filename: file name of the bianary file [input]
79 | ! n: number of points to be read [output]
80 | ! comdata: complex data array [output]
81 | ! ier: status indicator [output]
82 | ! ====================================================================
83 | subroutine read_bindata(filename, n, comdata, ier)
84 |
85 | implicit none
86 |
87 | character(len=*), intent(in) :: filename
88 |
89 |
90 | integer, intent(out) :: n, ier
91 |
92 | complex(SGL), allocatable, dimension(:), intent(out) :: comdata
93 |
94 |
95 | integer iunit
96 |
97 |
98 |
99 | iunit = 11 + myrank
100 |
101 |
102 | open(unit=iunit, file=filename, status='old', action='read', &
103 | iostat=ier, access='stream', form='unformatted')
104 |
105 | if (0 /= ier) then
106 | !write(*,*) trim(adjustl(filename))
107 | write(*,"(A,A)") "Error: Cannot read: ", trim(adjustl(filename))
108 | call flush(6)
109 | return
110 | end if
111 |
112 | read(iunit) n
113 |
114 | allocate(comdata(n), stat=ier)
115 |
116 | read(iunit) comdata
117 |
118 | close(unit=iunit)
119 |
120 |
121 | end subroutine read_bindata
122 |
123 |
124 | ! ====================================================================
125 | ! Convert cross-correlation from sac format to ascii format
126 | ! in order to generate input files for Huajian Yao' code
127 | ! filename: file name of the cross-correlation file in sac format [input]
128 | ! ====================================================================
129 | subroutine sac2asc(filename)
130 |
131 | implicit none
132 |
133 | character(len=*), intent(in) :: filename
134 |
135 |
136 | integer iunit
137 | integer k, n, n0, ier
138 |
139 | logical is_existing
140 |
141 | real dt, stlo, stla, evlo, evla
142 |
143 | type(sachead) shd
144 |
145 | character(len=512) infile, outfile
146 |
147 | real, allocatable, dimension(:) :: sacdata
148 |
149 |
150 |
151 | iunit = 11 + nprocs + myrank
152 |
153 |
154 |
155 | inquire(file=filename, exist=is_existing)
156 | if (.not.(is_existing)) return
157 |
158 |
159 | call sacio_readsac(filename, shd, sacdata, ier)
160 |
161 |
162 | n = shd%npts
163 | dt = shd%delta
164 | stlo = shd%stlo
165 | stla = shd%stla
166 | evlo = shd%evlo
167 | evla = shd%evla
168 |
169 | n0 = n/2 + 1
170 |
171 |
172 | infile = trim(adjustl(filename))
173 | outfile = trim(adjustl(infile(1:len_trim(infile)-4)))//'.dat'
174 |
175 |
176 | open(unit=iunit, file=trim(adjustl(outfile)), action='write', &
177 | status='replace', iostat=ier)
178 |
179 | if (0 /= ier) then
180 | write(*,"(A,A)") "Error: Cannot open: ", trim(adjustl(outfile))
181 | call flush(6)
182 | return
183 | end if
184 |
185 | write(iunit,"(F15.5,5x,F15.5,11x,F15.5)") evlo, evla, dt
186 | write(iunit,"(F15.5,5x,F15.5,11x,F15.5)") stlo, stla, dt
187 |
188 | do k = 1, n0, 1
189 | write(iunit,"(F15.5,4x,2ES25.10)") (k-1)*dt, sacdata(n0+k-1), sacdata(n0-k+1)
190 | end do
191 |
192 | close(unit=iunit)
193 |
194 |
195 | end subroutine sac2asc
196 |
197 |
198 |
199 | end module bindata_io_m
200 |
--------------------------------------------------------------------------------
/ANCC/src/AFTAN/tgauss.f90:
--------------------------------------------------------------------------------
1 | ! This file is part of ANCC.
2 | !
3 | ! AFTAN is free software: you can redistribute it and/or modify
4 | ! it under the terms of the GNU General Public License as published by
5 | ! the Free Software Foundation, either version 3 of the License, or
6 | ! (at your option) any later version.
7 | !
8 | ! AFTAN is distributed in the hope that it will be useful,
9 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | ! GNU General Public License for more details.
12 | !
13 | ! You should have received a copy of the GNU General Public License
14 | ! along with this program. If not, see .
15 | !
16 | !
17 | !
18 | !-------------------------------------------------------------
19 | ! taper phase matched signal
20 | !-------------------------------------------------------------
21 | subroutine tgauss(fsnr, gt0, dw, dt, n, fmatch, seis, ss)
22 |
23 | implicit none
24 |
25 | integer(4), intent(in) :: n
26 |
27 | real(8), intent(in) :: fsnr, gt0, dw, dt, fmatch
28 |
29 | complex(8), intent(in) :: seis(n)
30 |
31 |
32 | complex(8), intent(out) :: ss(n)
33 |
34 |
35 | integer(4) i, ii, ism, nn, nnn
36 | integer(4) nnl, nnnl, nnr, nnnr
37 | integer(4) nc, nleft, nright, ier
38 |
39 | real(8) freq, zero, dl, dr
40 | real(8) sm, smw, tresh, tre, coef
41 |
42 | complex(8), parameter :: czero = cmplx(0.d0,0.d0)
43 |
44 | integer(4), dimension(:), allocatable :: left, right
45 |
46 | real(8), dimension(:), allocatable :: smax, vleft, vright
47 |
48 | allocate(left(1:n), right(1:n), stat=ier)
49 | allocate(smax(1:n), vleft(1:n), vright(1:n), stat=ier)
50 |
51 |
52 |
53 | ism = 1
54 |
55 | zero = 0.d0
56 | nc = nint(gt0/dt) + 1
57 |
58 |
59 | ! find global max, sm, and index ism
60 | sm = 0.d0
61 | do i = 1, n, 1
62 | smw = abs(seis(i))
63 | if (smw >= sm) then
64 | sm = smw
65 | ism = i
66 | endif
67 | smax(i) = smw
68 | ss(i) = seis(i)
69 | enddo
70 | coef = fsnr*sm
71 |
72 |
73 | ! find some local minima,# < 100 from left and right side of central max ism
74 |
75 | ! left side
76 | nleft = 0
77 | do i = ism-1, 2, -1
78 |
79 | dl = smax(i) - smax(i-1)
80 | dr = smax(i+1) - smax(i)
81 |
82 | if (((dl < zero) .and. (dr >= zero)) .or. &
83 | ((dl <= zero) .and. (dr > zero))) then
84 | nleft = nleft + 1
85 | left(nleft) = i
86 | vleft(nleft) = smax(i)
87 | endif
88 |
89 | enddo
90 |
91 |
92 | ! right side
93 | nright = 0
94 | do i = ism+1, n-1, 1
95 |
96 | dl = smax(i) - smax(i-1)
97 | dr = smax(i+1) - smax(i)
98 |
99 | if (((dl < zero) .and. (dr >= zero)) .or. &
100 | ((dl <= zero) .and. (dr > zero))) then
101 | nright = nright + 1
102 | right(nright) = i
103 | vright(nright) = smax(i)
104 | endif
105 |
106 | enddo
107 |
108 |
109 | ! left side, apply cutting
110 | ii = 0
111 | nnl = 0
112 | nnnl = 0
113 | if (0 /= nleft) then
114 | do i = 1, nleft, 1
115 | if (abs(ism - left(i))*dt > 5.d0) then
116 | if (vleft(i) < coef) then
117 | nnnl = left(i)
118 | ii = i
119 | exit
120 | endif
121 | endif
122 | enddo
123 | end if
124 | if (0 /= nnnl) then
125 | if (ii /= nleft) then
126 | nnl = left(ii + 1)
127 | else
128 | nnl = 1
129 | endif
130 | endif
131 |
132 |
133 | ! right side, apply cutting
134 | ii = 0
135 | nnr = 0
136 | nnnr = 0
137 | if (0 /= nright) then
138 | do i = 1, nright, 1
139 | if (abs(ism - right(i))*dt > 5.d0) then
140 | if (vright(i) < coef) then
141 | nnr = right(i)
142 | ii = i
143 | exit
144 | endif
145 | endif
146 | enddo
147 | end if
148 | if (0 /= nnr) then
149 | if (ii /= nright) then
150 | nnnr = right(ii+1)
151 | else
152 | nnnr = n
153 | endif
154 | endif
155 |
156 |
157 | ! ---
158 | if ((0 /= nnnr) .and. (0 /= nnnl)) then
159 | nn = max(abs(ism-nnnl), abs(ism-nnr))
160 | nnn = max(abs(nnnl-nnl), abs(nnnr-nnr))
161 | nnnl = ism - nn
162 | nnl = nnnl - nnn
163 | nnr = ism + nn
164 | nnnr = nnr + nnn
165 | endif
166 |
167 | ! setup cutting point for gaussian
168 | tresh = log(sm) - 24.d0
169 | if (((0 /= nnl) .and. (0 /= nnnl))) then
170 | ! expand left end by factor fmatch
171 | nnl = nint((nnl-ism)*fmatch) + ism
172 | nnnl = nint((nnnl-ism)*fmatch) + ism
173 | nnl = max(1, nnl)
174 | nnnl = max(1, nnnl)
175 | freq = (nnnl - nnl) + 1
176 | do i = 1, nnnl, 1
177 | tre = -0.5d0*(i-nnnl)/freq*(i-nnnl)/freq
178 | if (tre > tresh) then
179 | ss(i) = ss(i)*exp(tre)
180 | else
181 | ss(i) = czero
182 | endif
183 | enddo
184 | end if
185 |
186 |
187 | if (((0 /= nnr) .and. (0 /= nnnr))) then
188 | ! expand right end by factor fmatch
189 | nnr = nint((nnr - ism)*fmatch) + ism
190 | nnnr = nint((nnnr - ism)*fmatch) + ism
191 | nnr = min(n, nnr)
192 | nnnr = min(n, nnnr)
193 | freq = (nnnr - nnr) + 1
194 | do i = nnr, n, 1
195 | tre = -0.5d0*(i-nnr)/freq*(i-nnr)/freq
196 | if (tre > tresh) then
197 | ss(i) = ss(i)*exp(tre)
198 | else
199 | ss(i) = czero
200 | endif
201 | enddo
202 | end if
203 |
204 |
205 | deallocate(left, right)
206 | deallocate(smax, vleft, vright)
207 |
208 |
209 | return
210 |
211 |
212 | end subroutine tgauss
213 |
--------------------------------------------------------------------------------
/ANCC/src/TF_PWS/mysac.h:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of ANCC.
3 | TF_PWS is free software: you can redistribute it and/or modify
4 | it under the terms of the GNU General Public License as published by
5 | the Free Software Foundation, either version 3 of the License, or
6 | (at your option) any later version.
7 | TF_PWS is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | GNU General Public License for more details.
11 | You should have received a copy of the GNU General Public License
12 | along with this program. If not, see .
13 | */
14 |
15 | #ifndef MYSAC
16 | #define MYSAC
17 |
18 | typedef struct sac {
19 | float delta, depmin, depmax, scale, odelta;
20 | float b, e, o, a, internal1;
21 | float t0, t1, t2, t3, t4;
22 | float t5, t6, t7, t8, t9;
23 | float f, resp0, resp1, resp2, resp3;
24 | float resp4, resp5, resp6, resp7, resp8;
25 | float resp9, stla, stlo, stel, stdp;
26 | float evla, evlo, evel, evdp, unused1;
27 | float user0, user1, user2, user3, user4;
28 | float user5, user6, user7, user8, user9;
29 | float dist, az, baz, gcarc, internal2;
30 | float internal3, depmen, cmpaz, cmpinc, unused2;
31 | float unused3, unused4, unused5, unused6, unused7;
32 | float unused8, unused9, unused10, unused11, unused12;
33 | int nzyear, nzjday, nzhour, nzmin, nzsec;
34 | int nzmsec, internal4, internal5, internal6, npts;
35 | int internal7, internal8, unused13, unused14, unused15;
36 | int iftype, idep, iztype, unused16, iinst;
37 | int istreg, ievreg, ievtyp, iqual, isynth;
38 | int unused17, unused18, unused19, unused20, unused21;
39 | int unused22, unused23, unused24, unused25, unused26;
40 | int leven, lpspol, lovrok, lcalda, unused27;
41 | char kstnm[8], kevnm[16];
42 | char khole[8], ko[8], ka[8];
43 | char kt0[8], kt1[8], kt2[8];
44 | char kt3[8], kt4[8], kt5[8];
45 | char kt6[8], kt7[8], kt8[8];
46 | char kt9[8], kf[8], kuser0[8];
47 | char kuser1[8], kuser2[8], kcmpnm[8];
48 | char knetwk[8], kdatrd[8], kinst[8];
49 | } SACHead;
50 |
51 | #ifndef MAIN
52 | extern SACHead SAC_HEADER;
53 | #else
54 | SACHead SAC_HEADER;
55 | #endif
56 |
57 | static SACHead sac_null = {
58 | -12345., -12345., -12345., -12345., -12345.,
59 | -12345., -12345., -12345., -12345., -12345.,
60 | -12345., -12345., -12345., -12345., -12345.,
61 | -12345., -12345., -12345., -12345., -12345.,
62 | -12345., -12345., -12345., -12345., -12345.,
63 | -12345., -12345., -12345., -12345., -12345.,
64 | -12345., -12345., -12345., -12345., -12345.,
65 | -12345., -12345., -12345., -12345., -12345.,
66 | -12345., -12345., -12345., -12345., -12345.,
67 | -12345., -12345., -12345., -12345., -12345.,
68 | -12345., -12345., -12345., -12345., -12345.,
69 | -12345., -12345., -12345., -12345., -12345.,
70 | -12345., -12345., -12345., -12345., -12345.,
71 | -12345., -12345., -12345., -12345., -12345.,
72 | -12345, -12345, -12345, -12345, -12345,
73 | -12345, -12345, -12345, -12345, -12345,
74 | -12345, -12345, -12345, -12345, -12345,
75 | -12345, -12345, -12345, -12345, -12345,
76 | -12345, -12345, -12345, -12345, -12345,
77 | -12345, -12345, -12345, -12345, -12345,
78 | -12345, -12345, -12345, -12345, -12345,
79 | -12345, -12345, -12345, -12345, -12345,
80 | { '-','1','2','3','4','5',' ',' ' },
81 | { '-','1','2','3','4','5',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ' },
82 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
83 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
84 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
85 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
86 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
87 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
88 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
89 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
90 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
91 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
92 | { '-','1','2','3','4','5',' ',' ' }
93 | };
94 |
95 | /* defines for logical data types */
96 | #define TRUE 1
97 | #define FALSE 0
98 |
99 | /* defines for enumerated data types */
100 | #define IREAL 0
101 | #define ITIME 1
102 | #define IRLIM 2
103 | #define IAMPH 3
104 | #define IXY 4
105 | #define IUNKN 5
106 | #define IDISP 6
107 | #define IVEL 7
108 | #define IACC 8
109 | #define IB 9
110 | #define IDAY 10
111 | #define IO 11
112 | #define IA 12
113 | #define IT0 13
114 | #define IT1 14
115 | #define IT2 15
116 | #define IT3 16
117 | #define IT4 17
118 | #define IT5 18
119 | #define IT6 19
120 | #define IT7 20
121 | #define IT8 21
122 | #define IT9 22
123 | #define IRADNV 23
124 | #define ITANNV 24
125 | #define IRADEV 25
126 | #define ITANEV 26
127 | #define INORTH 27
128 | #define IEAST 28
129 | #define IHORZA 29
130 | #define IDOWN 30
131 | #define IUP 31
132 | #define ILLLBB 32
133 | #define IWWSN1 33
134 | #define IWWSN2 34
135 | #define IHGLP 35
136 | #define ISRO 36
137 | #define INUCL 37
138 | #define IPREN 38
139 | #define IPOSTN 39
140 | #define IQUAKE 40
141 | #define IPREQ 41
142 | #define IPOSTQ 42
143 | #define ICHEM 43
144 | #define IOTHER 44
145 | #define IGOOD 45
146 | #define IGLCH 46
147 | #define IDROP 47
148 | #define ILOWSN 48
149 | #define IRLDTA 49
150 | #define IVOLTS 50
151 | #define INIV51 51
152 | #define INIV52 52
153 | #define INIV53 53
154 | #define INIV54 54
155 | #define INIV55 55
156 | #define INIV56 56
157 | #define INIV57 57
158 | #define INIV58 58
159 | #define INIV59 59
160 | #define INIV60 60
161 |
162 | #define FCS "%15.7f%15.7f%15.7f%15.7f%15.7f\n"
163 | #define ICS "%10d%10d%10d%10d%10d\n"
164 | #define CCS1 "%-8.8s%-8.8s%-8.8s\n"
165 | #define CCS2 "%-8.8s%-16.16s\n"
166 |
167 |
168 | void read_sac (char *fname, float *sig, SACHead *shd, long nmax);
169 | void write_sac(char *fname, float *sig, SACHead *shd);
170 |
171 | #endif
172 |
--------------------------------------------------------------------------------
/ANCC/src/ANCC/string.f90:
--------------------------------------------------------------------------------
1 | ! This file is part of ANCC.
2 | !
3 | ! ANCC is free software: you can redistribute it and/or modify
4 | ! it under the terms of the GNU General Public License as published by
5 | ! the Free Software Foundation, either version 3 of the License, or
6 | ! (at your option) any later version.
7 | !
8 | ! ANCC is distributed in the hope that it will be useful,
9 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | ! GNU General Public License for more details.
12 | !
13 | ! You should have received a copy of the GNU General Public License
14 | ! along with this program. If not, see .
15 | !
16 | !
17 | module string_m
18 |
19 |
20 | implicit none
21 |
22 |
23 | contains
24 |
25 |
26 | ! =============================================================================
27 | ! Delete spaces within one string
28 | ! str: input and output string [input and output]
29 | ! =============================================================================
30 | subroutine delspace(str)
31 |
32 | implicit none
33 |
34 | character(len=*), intent(inout) :: str
35 |
36 |
37 | integer nstr
38 |
39 | character(len=512) :: str_tmp, str_result
40 |
41 |
42 | str_result = ''
43 |
44 | do
45 | str = trim(adjustl(str))
46 | if (str == '') exit
47 | read(str, *) str_tmp
48 | nstr = len_trim(str_tmp)
49 | str(1:nstr) = ''
50 | str_result = trim(str_result) // trim(str_tmp)
51 | end do
52 |
53 | str = str_result
54 |
55 |
56 | end subroutine delspace
57 |
58 |
59 | ! =============================================================================
60 | ! Split a string by the given delimiter(s)
61 | ! InStr: input string [input]
62 | ! delimiter: string containing the delimiter(s) (e.g. '/.') [input]
63 | ! OutStr: output string array (allocatable) [output]
64 | ! n: number of output string array [output]
65 | ! =============================================================================
66 | subroutine split_string(InStr, delimiter, nout, OutStr)
67 |
68 | implicit none
69 |
70 | character(len=*), intent(in) :: InStr, delimiter
71 |
72 | integer, intent(out) :: nout
73 | character(len=*), allocatable, dimension(:), intent(out) :: OutStr
74 |
75 |
76 | integer i, j, istart, n
77 | integer nstr, ndelim, ncount
78 |
79 |
80 | n = 1
81 | istart = 1
82 |
83 | nstr = len_trim(InStr)
84 | ndelim = len_trim(delimiter)
85 |
86 | ! Count how many segements the input string has
87 | do i = 1, nstr, 1
88 | do j = 1, ndelim, 1
89 | if (InStr(i:i) == delimiter(j:j)) then
90 | n = n + 1
91 | end if
92 | end do
93 | end do
94 |
95 |
96 | allocate(OutStr(n))
97 |
98 | ! Split the input string
99 | ncount = 0
100 | do i = 1, nstr, 1
101 | do j = 1, ndelim, 1
102 |
103 | if (InStr(i:i) == delimiter(j:j)) then
104 | if (i == 1) then ! the first element of the string is the delimiter
105 | OutStr(1) = ''
106 | ncount = ncount + 1
107 | istart = 2
108 | else
109 | ncount = ncount + 1
110 | OutStr(ncount) = trim(adjustl(InStr(istart:i-1)))
111 | istart = i+1
112 | end if
113 | end if
114 |
115 | end do
116 | end do
117 |
118 |
119 | nout = n
120 | if (n > 1) then
121 | if (istart <= nstr) then
122 | OutStr(n) = InStr(istart:nstr)
123 | else ! the last element of the string is the delimiter
124 | OutStr(n) = ''
125 | end if
126 | else ! no spliting occured
127 | OutStr(1) = InStr
128 | end if
129 |
130 |
131 | end subroutine split_string
132 |
133 |
134 | ! =============================================================================
135 | ! Convert a float point number to a string with leading zeros
136 | ! value: input floating point number [input]
137 | ! m: width of the integer part [input]
138 | ! n: width of the decimal part [input]
139 | ! padzero: output formatted string [output]
140 | ! =============================================================================
141 | function padzero(numeric, m, n)
142 |
143 | implicit none
144 |
145 | real, intent(in) :: numeric
146 | integer, intent(in) :: m, n
147 |
148 | character(len=m+n+2) :: padzero
149 |
150 |
151 | character(len=32) str_tmp1, str_tmp2
152 | character(len=256) str_tmp
153 |
154 |
155 |
156 | if (numeric >= 0.0) then
157 | write(str_tmp1, "(I0, A1, I0)") m, '.', m
158 | write(str_tmp2, "(I0, A1, I0)") 0, '.', n
159 | write(str_tmp,"('(A1,', 'I', A, ',F', A, ')')") trim(adjustl(str_tmp1)), trim(adjustl(str_tmp2))
160 | write(padzero,trim(adjustl(str_tmp))) '+', abs(int(numeric)), abs(numeric-int(numeric))
161 | else
162 | write(str_tmp1, "(I0, A1, I0)") m, '.', m
163 | write(str_tmp2, "(I0, A1, I0)") 0, '.', n
164 | write(str_tmp,"('(A1,', 'I', A, ',F', A, ')')") trim(adjustl(str_tmp1)), trim(adjustl(str_tmp2))
165 | write(padzero,trim(adjustl(str_tmp))) '-', abs(int(numeric)), abs(numeric-int(numeric))
166 | end if
167 |
168 |
169 | return
170 |
171 |
172 | end function padzero
173 |
174 |
175 |
176 | function tolower(string) result(tolower_result)
177 |
178 | implicit none
179 |
180 | character(len=*), intent(in) :: string
181 | character(len=len(string)) :: tolower_result
182 |
183 |
184 | integer i, ii
185 |
186 | do i = 1, len(string), 1
187 |
188 | ii = iachar(string(i:i))
189 |
190 | select case (ii)
191 | case (65:90)
192 | tolower_result(i:i) = achar(ii+32)
193 | case default
194 | tolower_result(i:i) = string(i:i)
195 | end select
196 |
197 | end do
198 |
199 | end function tolower
200 |
201 |
202 |
203 |
204 | function toupper(string) result(toupper_result)
205 |
206 | implicit none
207 |
208 | character(len=*), intent(in) :: string
209 | character(len=len(string)) :: toupper_result
210 |
211 |
212 | integer i, ii
213 |
214 | do i = 1, len(string), 1
215 |
216 | ii = iachar(string(i:i))
217 |
218 | select case (ii)
219 | case (97:122)
220 | toupper_result(i:i)=achar(ii-32)
221 | case default
222 | toupper_result(i:i)=string(i:i)
223 | end select
224 |
225 | end do
226 |
227 | end function toupper
228 |
229 |
230 | end module string_m
231 |
--------------------------------------------------------------------------------
/ANCC/src/AFTAN/AFTAN.f90:
--------------------------------------------------------------------------------
1 | ! This file is part of ANCC.
2 | !
3 | ! AFTAN is free software: you can redistribute it and/or modify
4 | ! it under the terms of the GNU General Public License as published by
5 | ! the Free Software Foundation, either version 3 of the License, or
6 | ! (at your option) any later version.
7 | !
8 | ! AFTAN is distributed in the hope that it will be useful,
9 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | ! GNU General Public License for more details.
12 | !
13 | ! You should have received a copy of the GNU General Public License
14 | ! along with this program. If not, see .
15 | !
16 | !
17 | !
18 | !* The sample of test driver for FTAN with phase match filter for
19 | !* subroutines aftanpg and aftanipg
20 | !
21 | program AFTAN
22 |
23 | use dispio_m
24 | use aftanpg_m
25 | use aftanipg_m
26 |
27 | implicit none
28 |
29 | integer(4) i, k, sac, nargc, iargc
30 | integer(4) n, npoints, nfin, nfout1, nfout2
31 | integer(4) nrow, ncol, npred, nprpv, ier, ioer
32 |
33 | real(8) t0, dt, tresh, ffact1, ffact2
34 | real(8) perc, taperl, fmatch, delta, tamp
35 | real(8) vmin, vmax, tmin, tmax, snr, lambda
36 | real(8) tmin_read, tmax_read
37 |
38 | real(8) PIover4
39 |
40 | real(8) x(1), y(1)
41 |
42 | real(4), dimension(:), allocatable :: seis
43 |
44 | real(8), dimension(:), allocatable :: prpvper, prpvvel
45 | real(8), dimension(:,:), allocatable :: ampo, arr1, arr2, pred
46 |
47 | character(1) isPerCut, isOutput, isVerbose
48 |
49 | character(256) filename, parfile, outfile
50 |
51 |
52 |
53 | sac = 1
54 |
55 | !--- input command line arguments treatment
56 | nargc = iargc()
57 | if (1 /= nargc) then
58 | write(*,*) "Usage: AFTAN parameter_file \n"
59 | stop
60 | endif
61 |
62 |
63 | ! read input.dat
64 | open(unit=99, file='input.dat', status='old')
65 |
66 | do k = 1, 25, 1
67 | read(99,"(A)")
68 | end do
69 | read(99,*) PIover4
70 | read(99,*) vmin, vmax
71 | read(99,*) tmin_read, tmax_read
72 | read(99,*) isPerCut, lambda
73 | read(99,*) isOutput
74 | if (tmin_read < 1) then
75 | isOutput = 'Y'
76 | end if
77 | read(99,*) tresh
78 | read(99,*) ffact1, ffact2
79 | read(99,*) taperl
80 | read(99,*) snr
81 | read(99,*) fmatch
82 | do k = 1, 6, 1
83 | read(99,"(A)")
84 | end do
85 | read(99,*) isVerbose
86 |
87 | close(unit=99)
88 |
89 |
90 |
91 | ! read ref1Dmod.dat
92 | open(11, file='ref1Dmod.dat', status='old', iostat=ier)
93 |
94 | if (0 /= ier) then
95 | write(*,*)'Error: No phase velocity reference file!'
96 | stop
97 | end if
98 |
99 | nprpv = 0
100 | do
101 | read(11, *, iostat=ioer) x(1), y(1)
102 | if (0 /= ioer) exit
103 | nprpv = nprpv + 1
104 | end do
105 |
106 | rewind(11)
107 |
108 | allocate(prpvper(1:nprpv), prpvvel(1:nprpv), stat=ier)
109 | do k = 1, nprpv, 1
110 | read(11, *) prpvper(k), prpvvel(k)
111 | end do
112 |
113 | close(11)
114 |
115 |
116 |
117 | call getarg(1, parfile)
118 | open(10, file=trim(adjustl(parfile)), status='old')
119 |
120 |
121 | do
122 |
123 | read(10, '(A)', iostat=ioer) filename
124 | if (0 /= ioer) exit
125 |
126 |
127 | filename = trim(adjustl(filename))
128 | outfile = trim(adjustl(filename(1:len_trim(filename)-4)))
129 |
130 |
131 | tmin = tmin_read
132 | tmax = tmax_read
133 | if ((isVerbose == 'Y') .or. (isVerbose == 'y')) then
134 | write(*,'(A, A)') 'AFTAN: ', trim(adjustl(filename))
135 | end if
136 |
137 | !
138 | ! read SAC or ascii data
139 | !
140 |
141 | call readhead(sac, filename, n, ier)
142 | allocate(seis(1:n), stat=ier)
143 | call readdata(sac, filename, dt, delta, t0, seis, ier)
144 |
145 | if ((isPerCut == 'Y') .or. (isPerCut == 'y')) then
146 |
147 | do k = 1, 100, 1
148 |
149 | x(1) = k
150 | call linear_interpo(prpvper(1:nprpv), prpvvel(1:nprpv), x, y, ier)
151 |
152 | if ((lambda*x(1)*y(1) > delta) .and. ((k+3) < tmax)) then
153 | tmax = k + 3
154 | exit
155 | end if
156 |
157 | end do
158 |
159 | end if
160 |
161 |
162 | nfin = 64
163 | npoints = 5
164 | perc = 50.0
165 |
166 |
167 | !--- FTAN with phase match filter. First Iteration.
168 | call aftanpg(PIover4, n, seis, t0, dt, delta, vmin, vmax, tmin, tmax, &
169 | tresh, ffact1, perc, npoints, taperl, nfin, nprpv, prpvper, &
170 | prpvvel, nfout1, arr1, nfout2, arr2, tamp, nrow, ncol, ampo, ier)
171 |
172 | if ((isOutput == 'Y') .or. (isOutput == 'y')) then
173 | call printres(dt, delta, nfout1, arr1, nfout2, arr2, &
174 | tamp, nrow, ncol, ampo, ier, outfile, "_1")
175 | end if
176 |
177 | if (tmin >= 1) then
178 | call write_data(arr1, nfout1, arr2, nfout2, trim(adjustl(outfile))//'_1')
179 | endif
180 | if (allocated(ampo)) then
181 | deallocate(ampo)
182 | end if
183 | if (allocated(arr1)) then
184 | deallocate(arr1)
185 | end if
186 |
187 |
188 | if (0 == nfout2) then
189 | cycle
190 | end if
191 |
192 |
193 | !--- Make prediction based on the first iteration
194 | npred = nfout2
195 | tmin = arr2(2,1)
196 | tmax = arr2(2,nfout2)
197 | allocate(pred(1:nfout2,1:2))
198 | do i = 1, nfout2, 1
199 | pred(i,1) = arr2(2,i)
200 | pred(i,2) = arr2(3,i)
201 | enddo
202 | if (allocated(arr2)) then
203 | deallocate(arr2)
204 | end if
205 |
206 |
207 |
208 | !--- FTAN with phase matching filter. Second Iteration.
209 | call aftanipg(PIover4, n, seis, t0, dt, delta, vmin, vmax, tmin, tmax, tresh, &
210 | ffact2, perc, npoints, taperl, nfin, snr, fmatch, npred, pred, nprpv, &
211 | prpvper, prpvvel, nfout1, arr1, nfout2, arr2, tamp, nrow, ncol, ampo, ier)
212 |
213 | if ((isOutput == 'Y') .or. (isOutput == 'y')) then
214 | call printres(dt, delta, nfout1, arr1, nfout2, arr2, &
215 | tamp, nrow, ncol, ampo, ier, outfile, "_2")
216 | end if
217 |
218 |
219 | if (tmin >= 1) then
220 | call write_data(arr1, nfout1, arr2, nfout2, trim(adjustl(outfile))//'_2')
221 | end if
222 |
223 |
224 | deallocate(seis)
225 | if (allocated(arr1)) then
226 | deallocate(arr1)
227 | end if
228 | if (allocated(arr2)) then
229 | deallocate(arr2)
230 | end if
231 | if (allocated(ampo)) then
232 | deallocate(ampo)
233 | end if
234 | if (allocated(pred)) then
235 | deallocate(pred)
236 | end if
237 |
238 | end do
239 |
240 |
241 | close(10)
242 |
243 |
244 | deallocate(prpvper, prpvvel)
245 |
246 |
247 | end program AFTAN
248 |
249 |
--------------------------------------------------------------------------------
/ANCC/src/AFTAN/cucss2sac.h:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of ANCC.
3 |
4 | AFTAN is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 3 of the License, or
7 | (at your option) any later version.
8 |
9 | AFTAN is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License
15 | along with this program. If not, see .
16 |
17 | */
18 | /*
19 | ***************************************************************************
20 | * Header for readdata_ function.
21 | ***************************************************************************
22 | */
23 | #define abs(X) ((X) >= 0.0 ? (X) : -(X))
24 | #ifndef MYSAC
25 | #define MYSAC
26 | /* Preselected filds from CSS relations which are needed for SAC header */
27 | /* Part of .origin structure */
28 | typedef struct ORIGIN
29 | {
30 | double time;
31 | int jdate;
32 | float lat;
33 | float lon;
34 | float depth;
35 | } Origin;
36 |
37 | /* Part of .site structure */
38 | typedef struct SITE
39 | {
40 | char sta[8];
41 | int ondate;
42 | int offdate;
43 | float lat;
44 | float lon;
45 | float depth;
46 | } Site;
47 |
48 | /* Part of .wfdisc structure */
49 | typedef struct WFDISC
50 | {
51 | char sta[8];
52 | char chan[8];
53 | double time;
54 | double endtime;
55 | int jdate;
56 | int nsamp;
57 | float samprate;
58 | int foff;
59 | char datatype[4];
60 | char dir[100];
61 | char file[100];
62 | } Wfdisc;
63 |
64 | /* The SAC header, binary version */
65 | typedef struct sac
66 | {
67 | float delta, depmin, depmax, scale, odelta;
68 | float b, e, o, a, internal1;
69 | float t0, t1, t2, t3, t4;
70 | float t5, t6, t7, t8, t9;
71 | float f, resp0, resp1, resp2, resp3;
72 | float resp4, resp5, resp6, resp7, resp8;
73 | float resp9, stla, stlo, stel, stdp;
74 | float evla, evlo, evel, evdp, unused1;
75 | float user0, user1, user2, user3, user4;
76 | float user5, user6, user7, user8, user9;
77 | float dist, az, baz, gcarc, internal2;
78 | float internal3, depmen, cmpaz, cmpinc, unused2;
79 | float unused3, unused4, unused5, unused6, unused7;
80 | float unused8, unused9, unused10, unused11, unused12;
81 | int nzyear, nzjday, nzhour, nzmin, nzsec;
82 | int nzmsec, internal4, internal5, internal6, npts;
83 | int internal7, internal8, unused13, unused14, unused15;
84 | int iftype, idep, iztype, unused16, iinst;
85 | int istreg, ievreg, ievtyp, iqual, isynth;
86 | int unused17, unused18, unused19, unused20, unused21;
87 | int unused22, unused23, unused24, unused25, unused26;
88 | int leven, lpspol, lovrok, lcalda, unused27;
89 | char kstnm[8], kevnm[16];
90 | char khole[8], ko[8], ka[8];
91 | char kt0[8], kt1[8], kt2[8];
92 | char kt3[8], kt4[8], kt5[8];
93 | char kt6[8], kt7[8], kt8[8];
94 | char kt9[8], kf[8], kuser0[8];
95 | char kuser1[8], kuser2[8], kcmpnm[8];
96 | char knetwk[8], kdatrd[8], kinst[8];
97 | } SAC_HD;
98 |
99 | /* Default values of the SAC header */
100 | /* static SAC_HD sac_null = {
101 | -12345., -12345., -12345., -12345., -12345.,
102 | -12345., -12345., -12345., -12345., -12345.,
103 | -12345., -12345., -12345., -12345., -12345.,
104 | -12345., -12345., -12345., -12345., -12345.,
105 | -12345., -12345., -12345., -12345., -12345.,
106 | -12345., -12345., -12345., -12345., -12345.,
107 | -12345., -12345., -12345., -12345., -12345.,
108 | -12345., -12345., -12345., -12345., -12345.,
109 | -12345., -12345., -12345., -12345., -12345.,
110 | -12345., -12345., -12345., -12345., -12345.,
111 | -12345., -12345., -12345., -12345., -12345.,
112 | -12345., -12345., -12345., -12345., -12345.,
113 | -12345., -12345., -12345., -12345., -12345.,
114 | -12345., -12345., -12345., -12345., -12345.,
115 | -12345, -12345, -12345, -12345, -12345,
116 | -12345, -12345, -12345, -12345, -12345,
117 | -12345, -12345, -12345, -12345, -12345,
118 | -12345, -12345, -12345, -12345, -12345,
119 | -12345, -12345, -12345, -12345, -12345,
120 | -12345, -12345, -12345, -12345, -12345,
121 | -12345, -12345, -12345, -12345, -12345,
122 | -12345, -12345, -12345, -12345, -12345,
123 | { '-','1','2','3','4','5',' ',' ' },
124 | { '-','1','2','3','4','5',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ' },
125 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
126 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
127 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
128 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
129 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
130 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
131 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
132 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
133 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
134 | { '-','1','2','3','4','5',' ',' ' }, { '-','1','2','3','4','5',' ',' ' },
135 | { '-','1','2','3','4','5',' ',' ' }
136 | }; */
137 |
138 | /* defines for logical data types */
139 | #define TRUE 1
140 | #define FALSE 0
141 |
142 | /* defines for enumerated data types */
143 | #define IREAL 0
144 | #define ITIME 1
145 | #define IRLIM 2
146 | #define IAMPH 3
147 | #define IXY 4
148 | #define IUNKN 5
149 | #define IDISP 6
150 | #define IVEL 7
151 | #define IACC 8
152 | #define IB 9
153 | #define IDAY 10
154 | #define IO 11
155 | #define IA 12
156 | #define IT0 13
157 | #define IT1 14
158 | #define IT2 15
159 | #define IT3 16
160 | #define IT4 17
161 | #define IT5 18
162 | #define IT6 19
163 | #define IT7 20
164 | #define IT8 21
165 | #define IT9 22
166 | #define IRADNV 23
167 | #define ITANNV 24
168 | #define IRADEV 25
169 | #define ITANEV 26
170 | #define INORTH 27
171 | #define IEAST 28
172 | #define IHORZA 29
173 | #define IDOWN 30
174 | #define IUP 31
175 | #define ILLLBB 32
176 | #define IWWSN1 33
177 | #define IWWSN2 34
178 | #define IHGLP 35
179 | #define ISRO 36
180 | #define INUCL 37
181 | #define IPREN 38
182 | #define IPOSTN 39
183 | #define IQUAKE 40
184 | #define IPREQ 41
185 | #define IPOSTQ 42
186 | #define ICHEM 43
187 | #define IOTHER 44
188 | #define IGOOD 45
189 | #define IGLCH 46
190 | #define IDROP 47
191 | #define ILOWSN 48
192 | #define IRLDTA 49
193 | #define IVOLTS 50
194 | #define INIV51 51
195 | #define INIV52 52
196 | #define INIV53 53
197 | #define INIV54 54
198 | #define INIV55 55
199 | #define INIV56 56
200 | #define INIV57 57
201 | #define INIV58 58
202 | #define INIV59 59
203 | #define INIV60 60
204 |
205 | #define FCS "%15.7f%15.7f%15.7f%15.7f%15.7f\n"
206 | #define ICS "%10d%10d%10d%10d%10d\n"
207 | #define CCS1 "%-8.8s%-8.8s%-8.8s\n"
208 | #define CCS2 "%-8.8s%-16.16s\n"
209 |
210 | /* Finction prototypes */
211 | SAC_HD *read_sac(char *fname, float *sig, SAC_HD *SHD, int nmax);
212 | void write_sac(char *fname, float *sig, SAC_HD *SHD);
213 | void write_asc(char *fname, int ihed, char *dtype, double wtime, double otime, float *sig, SAC_HD *SHD);
214 | void e2h(double t, int *year, int *doy, int *hour, int *miin, double *sec);
215 | void endian(char *cind);
216 | void swapn(unsigned char *b, int N, int n);
217 |
218 | #endif
219 |
--------------------------------------------------------------------------------
/ANCC/src/AFTAN/dispio.f90:
--------------------------------------------------------------------------------
1 | ! This file is part of ANCC.
2 | !
3 | ! AFTAN is free software: you can redistribute it and/or modify
4 | ! it under the terms of the GNU General Public License as published by
5 | ! the Free Software Foundation, either version 3 of the License, or
6 | ! (at your option) any later version.
7 | !
8 | ! AFTAN is distributed in the hope that it will be useful,
9 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | ! GNU General Public License for more details.
12 | !
13 | ! You should have received a copy of the GNU General Public License
14 | ! along with this program. If not, see .
15 | !
16 | !
17 | !
18 | module dispio_m
19 |
20 | implicit none
21 |
22 | integer, parameter :: SGL = SELECTED_REAL_KIND(5,20)
23 | integer, parameter :: DBL = SELECTED_REAL_KIND(13,100)
24 |
25 |
26 | contains
27 |
28 |
29 | ! ==============================================================
30 | ! write the dispersion results after linear interpolation.
31 | ! array1: raw measurement matrix [input]
32 | ! nfout1: # of raw measurements (# of columns) [input]
33 | ! array2: clean measurement matrix [input]
34 | ! nfout2: # of clean measurements (# of columns) [input]
35 | ! filename: output file name [input]
36 | ! ==============================================================
37 | subroutine write_data(array1, nfout1, array2, nfout2, filename)
38 |
39 | implicit none
40 |
41 | integer, intent(in) :: nfout1, nfout2
42 |
43 | character(len=*), intent(in) :: filename
44 |
45 | real(DBL), dimension(8,nfout1), intent(in) :: array1
46 | real(DBL), dimension(7,nfout2), intent(in) :: array2
47 |
48 |
49 | integer lowPeriod, highPeriod, n, i, ier
50 |
51 | real(DBL), allocatable, dimension(:) :: x, y, z, snr
52 |
53 |
54 |
55 | lowPeriod = nint(minval(array1(2,1:nfout1)))
56 | highPeriod = nint(maxval(array1(2,1:nfout1)))
57 | n = highPeriod - lowPeriod + 1
58 |
59 |
60 | allocate(x(n), y(n), z(n), snr(n))
61 |
62 | do i = 1, n, 1
63 | x(i) = lowPeriod + i - 1
64 | end do
65 |
66 | call linear_interpo(array1(2,1:nfout1), array1(3,1:nfout1), x, y, ier)
67 | call linear_interpo(array1(2,1:nfout1), array1(4,1:nfout1), x, z, ier)
68 | call linear_interpo(array1(2,1:nfout1), array1(7,1:nfout1), x, snr, ier)
69 |
70 | open(unit=33, file=trim(adjustl(filename))//'_1.dat', status='replace', action='write')
71 | do i = 1, n, 1
72 | write(33, "(I5,2F10.4,F12.4)") int(x(i)), y(i), z(i), snr(i)
73 | !write(33, *) x(i), y(i), z(i), snr(i)
74 | end do
75 | close(unit=33)
76 |
77 | deallocate(x, y, z, snr)
78 |
79 |
80 | if (0 == nfout2) return
81 | ! ==============================================================
82 | lowPeriod = nint(minval(array2(2,1:nfout2)))
83 | highPeriod = nint(maxval(array2(2,1:nfout2)))
84 | n = highPeriod - lowPeriod + 1
85 |
86 | allocate(x(n), y(n), z(n), snr(n))
87 |
88 | do i = 1, n
89 | x(i) = lowPeriod + i - 1
90 | end do
91 |
92 | call linear_interpo(array2(2,1:nfout2), array2(3,1:nfout2), x, y, ier)
93 | call linear_interpo(array2(2,1:nfout2), array2(4,1:nfout2), x, z, ier)
94 | call linear_interpo(array2(2,1:nfout2), array2(6,1:nfout2), x, snr, ier)
95 |
96 | open(unit=33, file=trim(adjustl(filename))//'_2.dat', status='replace', action='write')
97 | do i = 1, n, 1
98 | write(33, "(I5,2F10.4,F12.4)") int(x(i)), y(i), z(i), snr(i)
99 | !write(33, *) x(i), y(i), z(i), snr(i)
100 | end do
101 | close(unit=33)
102 |
103 |
104 | deallocate(x, y, z, snr)
105 |
106 |
107 | end subroutine write_data
108 |
109 |
110 | ! ==============================================================
111 | ! Sort the array to make sure the array value increases
112 | ! mononically.
113 | ! array_x: x array (e.g., period) [input and output]
114 | ! array_y: y array (e.g., phase velocity) [input and output]
115 | ! ==============================================================
116 | subroutine sort_array_xy(array_x, array_y)
117 |
118 | implicit none
119 |
120 | real(DBL), dimension(:), intent(inout) :: array_x, array_y
121 |
122 |
123 | integer :: n, i, j, ip
124 |
125 | real(DBL) :: temp, ip_x, ip_y
126 |
127 |
128 | n = size(array_x)
129 | do i = 1, n-1, 1
130 |
131 | ip = i
132 | ip_x = array_x(i)
133 | do j = i+1, n, 1
134 | if (array_x(j) < ip_x) then
135 | ip = j
136 | ip_x = array_x(j)
137 | ip_y = array_y(j)
138 | end if
139 | end do
140 |
141 | if (i /= ip) then
142 | temp = array_x(i)
143 | array_x(i) = ip_x
144 | array_x(ip) = temp
145 | temp = array_y(i)
146 | array_y(i) = ip_y
147 | array_y(ip) = temp
148 | end if
149 |
150 | end do
151 |
152 |
153 | end subroutine sort_array_xy
154 |
155 |
156 | ! ************************************************************
157 | ! Check if there are duplicates in the array
158 | ! array: input array [input]
159 | ! ************************************************************
160 | logical function any_near_dupl(array)
161 |
162 | implicit none
163 |
164 | integer :: n, i
165 |
166 | real(DBL), dimension(:), intent(in) :: array
167 |
168 |
169 | any_near_dupl = .false.
170 | n = size(array)
171 | if (1 == n) return
172 |
173 | do i = 1, n-1, 1
174 |
175 | if (array(i) == array(i+1)) then
176 | any_near_dupl = .true.
177 | return
178 | end if
179 |
180 | end do
181 |
182 |
183 | end function any_near_dupl
184 |
185 | ! ************************************************************
186 | ! Find the index of the value which is non-positive in the array.
187 | ! array: input array [input]
188 | ! index: obtained index [output]
189 | ! ************************************************************
190 | subroutine find_max_nonpos(array, idx)
191 |
192 | implicit none
193 |
194 |
195 | real(DBL), dimension(:), intent(in) :: array
196 |
197 | integer, intent(out) :: idx
198 |
199 |
200 | integer :: n, i
201 |
202 | real(DBL) :: max_value
203 |
204 |
205 | idx = 0
206 | max_value = -huge(max_value)
207 |
208 | n = size(array)
209 | do i = 1, n, 1
210 | if ((array(i) <= 0.0) .and. (array(i) > max_value)) then
211 | idx = i
212 | max_value = array(i)
213 | end if
214 | end do
215 | !idx = maxloc((array(1:n) <= 0), 1)
216 |
217 |
218 | end subroutine find_max_nonpos
219 |
220 | ! ************************************************************
221 | ! Linear interpolation
222 | ! x0, y0: input data points [input]
223 | ! x: inquired x values [input]
224 | ! y: computed y values [output]
225 | ! ier: status indicator [output]
226 | ! ************************************************************
227 | subroutine linear_interpo(x0, y0, x, y, ier)
228 |
229 | implicit none
230 |
231 | real(DBL), dimension(:), intent(in) :: x0, y0, x
232 |
233 | integer, intent(out) :: ier
234 |
235 | real(DBL), dimension(:), intent(out) :: y
236 |
237 |
238 | integer :: n1, n2, k, idx
239 |
240 | real(DBL) :: x1, x2, y1, y2
241 |
242 | real(DBL), allocatable, dimension(:) :: x0_c, y0_c
243 |
244 |
245 |
246 | ier = 1
247 | n1 = size(x0)
248 | n2 = size(x)
249 |
250 | allocate(x0_c(n1), y0_c(n1))
251 |
252 | x0_c = x0
253 | y0_c = y0
254 |
255 | call sort_array_xy(x0_c, y0_c)
256 | if (any_near_dupl(x0_c)) then
257 | write(*,"(A)") 'NO duplicates allowed in x0 !'
258 | return
259 | end if
260 |
261 | do k = 1, n2, 1
262 |
263 | call find_max_nonpos(x0_c-x(k), idx)
264 |
265 | if (0 == idx) then
266 | x1 = x0_c(1)
267 | y1 = y0_c(1)
268 | x2 = x0_c(2)
269 | y2 = y0_c(2)
270 | y(k) = (y2-y1)/(x2-x1)*(x(k)-x1)+y1
271 | else if (n1 == idx) then
272 | x1 = x0_c(n1-1)
273 | y1 = y0_c(n1-1)
274 | x2 = x0_c(n1)
275 | y2 = y0_c(n1)
276 | y(k) = (y2-y1)/(x2-x1)*(x(k)-x1)+y1
277 | else
278 | x1 = x0_c(idx)
279 | y1 = y0_c(idx)
280 | x2 = x0_c(idx+1)
281 | y2 = y0_c(idx+1)
282 | y(k) = (y2-y1)/(x2-x1)*(x(k)-x1)+y1
283 | end if
284 |
285 | end do
286 |
287 | deallocate(x0_c, y0_c)
288 |
289 |
290 | ier = 0
291 |
292 |
293 | end subroutine linear_interpo
294 |
295 |
296 | end module dispio_m
297 |
--------------------------------------------------------------------------------
/run /run.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | #=======================================================================================
4 | #=======================================================================================
5 | # This script is the only one that you need to execute to process the seismic ambient
6 | # noise data with parallel computing. It will invoke the , and
7 | # three executables to deal with the input seismic waveforms based on input
8 | # parameters as defined in . Detailed description of each individual parameter
9 | # can be found in . The output of this program is auto- or cross-correlation
10 | # functions or corresponding group and phase velocity dispersion data.
11 | #=======================================================================================
12 | # The PATH of input data folder is given in the variable in the following
13 | # script. The data structure should be */year/month/event/net.sta.cha.SAC
14 | # e.g. DATA/2018/01/20180101_120000/NE.NE01.BHZ.SAC
15 | #=======================================================================================
16 | # Individual or combined full RESP or PZ file(s) should be put in .
17 | #=======================================================================================
18 | # 1-D phase velocity reference model used in AFTAN is given by . It has
19 | # the format of (period, reference phase velocity)
20 | #=======================================================================================
21 | # The PATH of output data folder is given in the variable in the following
22 | # script. The ouptput 'CC_AFTAN' folder contains all the cross-correlation waveforms and
23 | # corresponding dispersion measurements. The output 'FINAL' folder contains all the final
24 | # dispersion data. The output 'BOOTSTRAP' folder contains all the bootstrap data (optional).
25 | #=======================================================================================
26 | # Required auxiliary files and programs:
27 | # SAC
28 | # input.dat
29 | # ref1Dmod.dat
30 | #=======================================================================================
31 | # Notes: The algorithm of this program is modified from Barmin's code (http://ciei.color
32 | # ado.edu/Products/), including the cross-correlation part and the frequency-time
33 | # analysis part. The phase-weighted stacking program is modified from Guoliang Li'
34 | # code (guoleonlee@gmail.com)
35 | # Any bug reports, suggestions or comments related to this program can be directed
36 | # to Xingli Fan via and .
37 | #=======================================================================================
38 | #=======================================================================================
39 |
40 | import os
41 | import re
42 | import glob
43 | import linecache
44 | import multiprocessing
45 | from obspy import UTCDateTime
46 | from multiprocessing.dummy import Pool as ThreadPool
47 |
48 |
49 | ###########################################################
50 | # Please modify the following three PATH varialbles in
51 | # your own case and set the right core numbers for parallel
52 | # processing according to your own computing resource.
53 | ###########################################################
54 |
55 | SACfolder = "../DATA_cut"
56 | PZfolder = "../PZs_all"
57 | tarfolder = "./Results_10Hz"
58 |
59 | nprocs = multiprocessing.cpu_count()
60 |
61 |
62 | ###########################################################
63 | def count_station_num(files_list):
64 | strs = files_list
65 | for i in range(len(files_list)):
66 | try:
67 | strs[i] = files_list[i].split('/')[-1].split('.')[-3]
68 | except:
69 | strs[i] = ''
70 | return len({}.fromkeys(strs).keys())
71 |
72 |
73 | def check_autocorrelation(filename):
74 | try:
75 | line = linecache.getline(filename, 46)
76 | except:
77 | return False
78 | regexp = re.compile(r"[^#]+[\t \w{,3}]+[\t #\w\d-]*")
79 | ans = regexp.search(line)
80 | if (ans is None):
81 | return False
82 | if (ans.group()[0:3].strip().upper() in "YES"):
83 | is_auto_correlation = True
84 | else:
85 | is_auto_correlation = False
86 | return is_auto_correlation
87 |
88 |
89 | is_auto_correlation = check_autocorrelation("input.dat")
90 | ###########################################################
91 | # Reomve empty folder(s) and file(s)
92 | ###########################################################
93 | #os.system('find %s -depth -type "d" -empty -exec rmdir {} \;' %(SACfolder))
94 | #os.system('find %s -name "*" -type f -size 0c | xargs -n 1 rm -f' % (SACfolder))
95 |
96 | ###########################################################
97 | # Retrieve the station and event information.
98 | ###########################################################
99 | os.system('rm -rf stations.tmp events.lst')
100 |
101 |
102 | #awkstr = " | awk '{printf \"%8s %8s %8.4f %8.4f %5.3f\",$2,$3,$4,$5,$6}' >> stations.tmp"
103 | awkstr = " | awk '{printf " + r'"%-8s %-8s %7.4f %8.4f %5.3f\n",$2,$3,$4,$5,$6}' + "' >> stations.tmp"
104 | global month_folder
105 | def scan_segment(segment):
106 | segment_folder = month_folder + '/' + segment
107 | sacfiles = segment_folder + '/*.SAC'
108 | files_list = glob.glob(sacfiles)
109 | if (not(is_auto_correlation) and (count_station_num(files_list) <= 1)):
110 | print("skip %s because of single station folder\n"%(segment_folder))
111 | return
112 | #os.system("saclst knetwk kstnm stla stlo delta f %s | awk '{print $2,$3,$4,$5,$6}' >> stations.tmp"%(sacfiles))
113 | os.system("saclst knetwk kstnm stla stlo delta f %s"%(sacfiles + awkstr))
114 | os.system("ls %s -d >> events.lst"%(segment_folder))
115 |
116 |
117 | for year in os.listdir(SACfolder):
118 | year_folder = SACfolder + '/' + year
119 | for month in os.listdir(year_folder):
120 | month_folder = year_folder + '/' + month
121 | pool = ThreadPool()
122 | pool.map(scan_segment, os.listdir(month_folder))
123 | pool.close()
124 | pool.join()
125 |
126 |
127 | ##awkstr = " | awk '{printf \"%8s %8s %8.4f %8.4f %5.3f\",$2,$3,$4,$5,$6}' >> stations.tmp"
128 | #awkstr = " | awk '{printf " + r'"%-8s %-8s %7.4f %8.4f %5.3f\n",$2,$3,$4,$5,$6}' + "' >> stations.tmp"
129 | #for year in os.listdir(SACfolder):
130 | # year_folder = SACfolder + '/' + year
131 | # for month in os.listdir(year_folder):
132 | # month_folder = year_folder + '/' + month
133 | # for segment in os.listdir(month_folder):
134 | # segment_folder = month_folder + '/' + day
135 | # sacfiles = segment_folder + '/*.SAC'
136 | # files_list = glob.glob(sacfiles)
137 | # if (not(is_auto_correlation) and (count_station_num(files_list) <= 1)):
138 | # print("skip %s because of single station folder\n"%(segment_folder))
139 | # continue
140 | # #os.system("saclst knetwk kstnm stla stlo delta f %s | awk '{print $2,$3,$4,$5,$6}' >> stations.tmp"%(sacfiles))
141 | # os.system("saclst knetwk kstnm stla stlo delta f %s" % (sacfiles + awkstr))
142 | # os.system("ls %s -d >> events.lst"%(segment_folder))
143 |
144 |
145 | os.system("sort stations.tmp | uniq > stations.lst")
146 | os.system("rm -rf stations.tmp")
147 |
148 | ###########################################################
149 | # Return if stations.lst contains duplicate stations
150 | ###########################################################
151 | stations = []
152 | duplicates = []
153 | for line in open('stations.lst', 'r'):
154 | net, sta = line.split()[0:2]
155 | name = net+'.'+sta
156 | if name in stations:
157 | duplicates.append(name)
158 | else:
159 | stations.append(name)
160 |
161 | if len(duplicates) > 0:
162 | print('Error: The following stations have multiple longitude or latitude or sampling rate.\n\
163 | Please check stations.lst for details and correct the corresponding sac \n\
164 | headers before running this program.')
165 | print(duplicates)
166 | exit()
167 |
168 | ###########################################################
169 | # Execute the main program to process the ambient noise data.
170 | ###########################################################
171 | starttime = UTCDateTime()
172 | os.system("mpirun -np %d ANCC %s %s %s"%(nprocs, SACfolder, PZfolder, tarfolder))
173 | endtime = UTCDateTime()
174 |
175 | elapsed_time = endtime - starttime
176 |
177 |
178 | print("\n")
179 | print('Start time : %s' % (starttime + 28800))
180 | print('End time : %s' % (endtime + 28800))
181 | print('Elapsed time : %f hours \n' % (elapsed_time / 3600.0))
182 |
--------------------------------------------------------------------------------
/ANCC/src/AFTAN/misc.c:
--------------------------------------------------------------------------------
1 | /*
2 | This file is part of ANCC.
3 |
4 | AFTAN is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 3 of the License, or
7 | (at your option) any later version.
8 |
9 | AFTAN is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License
15 | along with this program. If not, see .
16 |
17 | */
18 | /*
19 | * Read SAC header and seismogram and make output
20 | */
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | #include "aftan.h"
28 | #include "cucss2sac.h"
29 |
30 |
31 | void readhead_(int *sac, char *name, int *n, int *ierr)
32 | {
33 |
34 | int i, nn, iswap, *nsam;
35 | int i1 = 0, i2 = 0, idelta = 0;
36 |
37 | FILE *fd;
38 | SAC_HD sach; /* the SAC header */
39 |
40 | float dumm, t0, dt;
41 |
42 | float dum[2];
43 |
44 | char *p = 0, ch = 0;
45 |
46 |
47 | *ierr = 0;
48 | for (i = 0; i < 160; i++)
49 | {
50 | if (name[i] == '\0' || name[i] == ' ')
51 | {
52 | p = &name[i];
53 | ch = *p;
54 | break;
55 | }
56 | }
57 | *p = 0;
58 |
59 | iswap = 0;
60 | if ((fd = fopen(name, "r")) == NULL)
61 | {
62 | printf("Can not find file %s.\n", name);
63 | exit(1);
64 | }
65 | *p = ch;
66 |
67 | if (*sac)
68 | {
69 | /* The header */
70 | fread(&sach, sizeof(SAC_HD), 1, fd);
71 | if ((sach.internal4 > 100) || (sach.internal4 < -100))
72 | iswap = 1;
73 | if (iswap)
74 | swapn((unsigned char *)&sach, (int)(sizeof(float)), 158);
75 | dt = sach.delta;
76 | nsam = &sach.npts;
77 | t0 = sach.b;
78 | *n = *nsam;
79 | /* make symmetric cross-correlaton */
80 | nn = (1.0 - t0 / dt) + 0.5;
81 | if ((2 * nn - 1) != *n)
82 | {
83 | /* lag is not consistent with # of samples */
84 | printf("Wrong SAC header n=%d lag=%d\n", *n, (int)(-t0));
85 | *ierr = 1;
86 | return;
87 | }
88 | *n = nn;
89 | }
90 | fclose(fd);
91 |
92 | }
93 |
94 |
95 | void readdata_(int *sac, char *name, double *dt, double *delta,
96 | double *t0, float *seis, int *ierr)
97 | {
98 |
99 | int i, n, nn, iswap, *nsam;
100 | int i1 = 0, i2 = 0, idelta = 0;
101 |
102 | FILE *fd;
103 | SAC_HD sach; /* the SAC header */
104 |
105 | float dumm;
106 | float dum[2];
107 | float *tr;
108 | char *p = 0, ch = 0;
109 |
110 |
111 | *ierr = 0;
112 | for (i = 0; i < 160; i++)
113 | {
114 | if (name[i] == '\0' || name[i] == ' ')
115 | {
116 | p = &name[i];
117 | ch = *p;
118 | break;
119 | }
120 | }
121 | *p = 0;
122 |
123 | iswap = 0;
124 | if ((fd = fopen(name, "r")) == NULL)
125 | {
126 | printf("Can not find file %s.\n", name);
127 | exit(1);
128 | }
129 | *p = ch;
130 |
131 | if (*sac)
132 | {
133 | /* The header */
134 | fread(&sach, sizeof(SAC_HD), 1, fd);
135 | if ((sach.internal4 > 100) || (sach.internal4 < -100))
136 | iswap = 1;
137 | if (iswap)
138 | swapn((unsigned char *)&sach, (int)(sizeof(float)), 158);
139 | *dt = sach.delta;
140 | *delta = sach.dist;
141 | nsam = &sach.npts;
142 | *t0 = sach.b;
143 | /* The body */
144 | tr = (float *)malloc(*nsam * sizeof(float));
145 | fread(tr, sizeof(float), *nsam, fd);
146 | if (iswap)
147 | swapn((unsigned char *)tr, (int)(sizeof(float)), *nsam);
148 | n = *nsam;
149 | /* make symmetric cross-correlaton */
150 | nn = (1.0 - *t0 / *dt) + 0.5;
151 | if ((2 * nn - 1) != n)
152 | {
153 | /* lag is not consistent with # of samples */
154 | printf("Wrong SAC header n=%d lag=%d\n", n, (int)(-*t0));
155 | *ierr = 1;
156 | return;
157 | }
158 | for (i = 0; i < nn; i++)
159 | tr[n-i-1] = 0.50f*(tr[i] + tr[n-i-1]);
160 | for (i = 0; i < nn; i++)
161 | seis[i] = tr[nn-1+i];
162 | seis[0] *= 0.5f;
163 | //*n = nn;
164 | *t0 = 0.0;
165 | free(tr);
166 | }
167 | else
168 | {
169 | /*
170 | * Read test data from ascii file
171 | */
172 | i = 0;
173 | while ((nn = fscanf(fd, "%f %f", &dumm, &seis[i])) == 2)
174 | {
175 | if (i < 2)
176 | dum[i] = dumm;
177 | i++;
178 | }
179 | /* extract delta from file name */
180 | p = strrchr(name, '/');
181 | sscanf(p + 1, "proba_%d_%d_%d.SAC", &i1, &i2, &idelta);
182 | *delta = idelta;
183 | *dt = dum[1] - dum[0];
184 | //n = i;
185 | *t0 = 0.3;
186 | }
187 | fclose(fd);
188 |
189 | }
190 |
191 |
192 |
193 | /*
194 | * print completion result
195 | */
196 | /*void printres_(double *xdt, double *delta, int *xnfout1, double **arr1,
197 | * int *xnfout2, double **arr2, double *xtamp, int *xnrow,
198 | * int *xncol, double **ampo, int *xierr, char *xname, char *xpref)*/
199 | void printres_(double *xdt, double *delta, int *xnfout1, double *arr1,
200 | int *xnfout2, double *arr2, double *xtamp, int *xnrow, int *xncol,
201 | double *ampo, int *xierr, char *xname, char *xpref)
202 | {
203 |
204 | int i, j, k, ip, ierr;
205 | int nfout1, nfout2, nrow, ncol;
206 |
207 | FILE *out;
208 |
209 | float dt, tamp;
210 |
211 |
212 | char *p = 0, ch = 0, name2[160], name[160], pref[5];
213 |
214 |
215 | strncpy(pref, xpref, 2);
216 | pref[2] = '\0';
217 | for (i = 0; i < 160; i++)
218 | {
219 | if (xname[i] == '\0' || xname[i] == ' ')
220 | {
221 | p = &xname[i];
222 | ch = *p;
223 | break;
224 | }
225 | }
226 |
227 | *p = 0;
228 | strcpy(name, xname);
229 | *p = ch;
230 | dt = *xdt;
231 | nfout1 = *xnfout1;
232 | nfout2 = *xnfout2;
233 | tamp = *xtamp;
234 | nrow = *xnrow;
235 | ncol = *xncol;
236 | ierr = *xierr;
237 |
238 | /* write results to hard drive
239 | file ...DISP.0 contains preliminary result */
240 |
241 | strcpy(name2, name);
242 | strcat(name2, pref);
243 | strcat(name2, "_DISP.0");
244 |
245 | if ((out = fopen(name2, "w")) == NULL)
246 | {
247 | printf("Can not open file %s.\n", name2);
248 | exit(1);
249 | }
250 | for (i = 0; i < nfout1; i++)
251 | {
252 | //fprintf(out, "%4d %10.4lf %10.4lf %12.4lf %12.4lf %12.4lf %12.4lf %8.3lf\n",
253 | // i, arr1[i][0], arr1[i][1], arr1[i][2], arr1[i][3],
254 | // arr1[i][4], arr1[i][5], arr1[i][6]);
255 | k = i*8;
256 | fprintf(out, "%4d %10.4lf %10.4lf %12.4lf %12.4lf %12.4lf %12.4lf %8.3lf\n",
257 | i, arr1[k], arr1[k+1], arr1[k+2], arr1[k+3], arr1[k+4], arr1[k+5], arr1[k+6]);
258 | }
259 | fclose(out);
260 |
261 |
262 | /* file ...DISP.1 includes final results */
263 | if (nfout2 != 0)
264 | {
265 | strcpy(name2, name);
266 | strcat(name2, pref);
267 | strcat(name2, "_DISP.1");
268 | if ((out = fopen(name2, "w")) == NULL)
269 | {
270 | printf("Can not open file %s.\n", name2);
271 | exit(1);
272 | }
273 | for (i = 0; i < nfout2; i++)
274 | {
275 | //fprintf(out, "%4d %10.4lf %10.4lf %12.4lf %12.4lf %12.4lf %8.3lf\n",
276 | // i, arr2[i][0], arr2[i][1], arr2[i][2], arr2[i][3],
277 | // arr2[i][4], arr2[i][5]);
278 | k = i*7;
279 | fprintf(out, "%4d %10.4lf %10.4lf %12.4lf %12.4lf %12.4lf %8.3lf\n",
280 | i, arr2[k], arr2[k+1], arr2[k+2], arr2[k+3], arr2[k+4], arr2[k+5]);
281 | }
282 | fclose(out);
283 | }
284 |
285 | /* Output amplitude array into file on hard drive */
286 | strcpy(name2, name);
287 | strcat(name2, pref);
288 | strcat(name2, "_AMP");
289 | if ((out = fopen(name2, "w")) == NULL)
290 | {
291 | printf("Can not open file %s.\n", name2);
292 | exit(1);
293 | }
294 |
295 | fprintf(out, "%5d %5d %10.4lf %12.5lf\n", nrow, ncol, dt, *delta);
296 | for (i = 0; i < nrow; ++i)
297 | {
298 | ip =i*8 + 1;
299 | k = i*ncol;
300 | for (j = 0; j < ncol; ++j)
301 | {
302 | //fprintf(out, "%5d %8.3lf %15.6e\n", arr2[i][0], *delta / (tamp + j * dt), ampo[i][j]);
303 | fprintf(out, "%10.4lf %8.3lf %15.6e\n", arr1[ip], *delta / (tamp + j * dt), ampo[k+j]);
304 | }
305 | }
306 | fclose(out);
307 |
308 | }
309 |
--------------------------------------------------------------------------------
/scripts/cutdata.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: UTF-8 -*-
3 |
4 |
5 | '''
6 | cutdata
7 |
8 | This program cuts daily SAC files into segments using the ObsPy
9 |
10 | Date: 25/10/2020
11 | Author: Youshan Liu
12 | Affiliation: Institute of Geology and Geophysics, Chinese Academy of Sciences
13 |
14 |
15 | input data directory structure:
16 | ./stage folder/station folder/day folder/SAC files
17 |
18 |
19 | After cutting, the files will be save in the following structures:
20 | ./top folder/yyyy/mm/yyyymmdd_hh00000/
21 |
22 | for example:
23 | ./DATA/2007/10/20071003_000000/NCISP6.NE00.BHZ.SAC
24 |
25 |
26 | '''
27 |
28 |
29 |
30 |
31 | import os
32 | import re
33 | import glob
34 | from math import *
35 | import numpy as np
36 | from obspy import read
37 | from obspy import UTCDateTime
38 | from obspy.io.sac import SACTrace
39 | from obspy.core.trace import Trace
40 | from obspy.core.stream import Stream
41 |
42 |
43 |
44 | ##############################################################
45 | ##############################################################
46 | ##############################################################
47 | # some options to be set
48 |
49 |
50 | # dryrun just for debug
51 | # dryrun = True => just print some directory information not to write sac files
52 | # dryrun = False => do the actual files conversion
53 | dryrun = False
54 |
55 | # directory of the data
56 | input_path = './DATA_Raw'
57 | output_path = './DATA_cut'
58 |
59 | # whether save input data
60 | save_input_data = True
61 |
62 |
63 | # segment length
64 | segment_length = 3600*24
65 |
66 |
67 | # component list to be cut
68 | # three-components
69 | #channels = ['HZ', 'HN', 'HE']
70 | # only Z-component
71 | channels = ['HZ']
72 | # only N-component
73 | #channels = ['HN']
74 | # only E-component
75 | #channels = ['HE']
76 |
77 |
78 | # interpolation method: 'lanczos' is highest quality interpolation but expensive, the 'cubic' method may be a good choice
79 | interpolation_method = 'cubic'
80 | # You can have the following options
81 | #
82 | # "lanczos": This offers the highest quality interpolation and should be chosen whenever possible.
83 | # It is only due to legacy reasons that this is not the default method. The one downside it has is that it can be fairly expensive.
84 | # Essentially a fnite support version of sinc resampling (the ideal reconstruction filter).
85 | # For large values of a, it converges towards sinc resampling.
86 | # if interpolation_method is lanczos, a value of 'a' that is the width of window in samples on either side shold be given.
87 | # Values of a >= 20 show good results even for data that has energy close to the Nyquist frequency.
88 | # Please see the https://docs.obspy.org/packages/autogen/obspy.signal.interpolation.lanczos_interpolation.html#obspy.signal.interpolation.lanczos_interpolation for details.
89 | lanczos_winlen = 20 # this parameter is only valid for the 'lanczos' interpolation method
90 | #
91 | # "weighted_average_slopes": This is the interpolation method used by SAC. Refer to weighted_average_slopes() for more details.
92 | #
93 | # "slinear", "quadratic" and "cubic": spline interpolation of first, second or third order.
94 | #
95 | # "linear": Linear interpolation.
96 | #
97 | # "nearest": Nearest neighbour interpolation.
98 |
99 |
100 | # nskip: a parameter is used to skip head and tail samples to check whether a segment data is zeros
101 | if interpolation_method == 'lanczos':
102 | nskip = lanczos_winlen
103 | else:
104 | nskip = 0
105 |
106 |
107 |
108 | day_in_seconds = 24*3600
109 |
110 | ##############################################################
111 |
112 |
113 |
114 | def create_sac_filename(stats):
115 |
116 | network = stats.sac.knetwk
117 | station = stats.sac.kstnm
118 | channel = stats.sac.kcmpnm
119 |
120 | filename = network + '.' + station + \
121 | '.' + channel + sac_suffix
122 |
123 | return filename
124 |
125 |
126 |
127 | def create_sac_path(starttime):
128 |
129 | year = '%4.4d' % starttime.year
130 | month = '%2.2d' % starttime.month
131 | day = '%2.2d' % starttime.day
132 | hh = '%2.2d' % starttime.hour
133 | mm = '%2.2d' % starttime.minute
134 | ss = '%2.2d' % starttime.second
135 |
136 | mydate = year + month + day
137 |
138 | month_folder = mydate + '_' + hh + mm + ss
139 |
140 | sac_path = year + '/' + month + \
141 | '/' + month_folder + '/'
142 |
143 | return sac_path
144 |
145 |
146 |
147 | def date2str(starttime):
148 |
149 | year = '%4.4d' % starttime.year
150 | month = '%2.2d' % starttime.month
151 | day = '%2.2d' % starttime.day
152 |
153 | mydate = year + month + day
154 |
155 | return mydate
156 |
157 |
158 |
159 | def merge_data(hour_files_list):
160 |
161 | st = Stream()
162 | data_len = 0.0
163 | for hour_file in hour_files_list:
164 | try:
165 | # faster for a specific file format
166 | st_tmp = read(hour_file, format='SAC', check_compression=False)
167 | #st_tmp = read(hour_file)
168 | if (not save_input_data):
169 | os.remove(hour_file)
170 | except:
171 | continue
172 | st += st_tmp
173 | data_len += (st_tmp[0].stats.npts-1)*st_tmp[0].stats.delta
174 |
175 |
176 | if (data_len < 0.50*segment_length):
177 | return []
178 |
179 |
180 | st.sort(['starttime'])
181 |
182 | # merge data
183 | if (len(st) > 1):
184 | st.merge(method=1, fill_value=0.0)
185 | #st.merge(method=1, fill_value='interpolate')
186 |
187 |
188 | #for i in range(0,len(st[0])):
189 | # arr = st[0].data[i]
190 | # if (np.ma.is_masked(arr)):
191 | # st[0].data[i] = 0.0
192 |
193 | #if (np.ma.is_masked(st[0].data)):
194 | # continue
195 |
196 |
197 | try:
198 | tr = st[0]
199 | # remove round error
200 | tr.stats.delta = round(tr.stats.delta*1e6)*1.e-6
201 | except:
202 | return
203 |
204 |
205 | stats = tr.stats
206 | dt = stats.delta
207 | df = stats.sampling_rate
208 | npts_daily = int(day_in_seconds*df)
209 |
210 |
211 | starttime = stats.starttime
212 | endtime = stats.endtime
213 | midtime = starttime + 0.50*stats.npts*dt
214 | starttime_daily = UTCDateTime(midtime.year, midtime.month, midtime.day, 0, 0, 0, 0)
215 | endtime_daily = starttime_daily + day_in_seconds - dt
216 |
217 |
218 | # indexes of the starttime and endtime in local temporal axis
219 | ibeg = ceil((max(starttime, starttime_daily) - starttime_daily)*df)
220 | iend = int((min(endtime, endtime_daily) - starttime_daily)*df)
221 |
222 |
223 | if (0 != starttime.microsecond % round(dt*1e6)):
224 | # interpolate to local temporal axis
225 | #tr.interpolate(df, 'cubic', starttime_daily+ibeg*dt, iend-ibeg+1, 0.0)
226 | #tr.interpolate(df, 'lanczos', starttime_daily+ibeg*dt, iend-ibeg+1, 0.0, a=21)
227 | tr.interpolate(df, interpolation_method, starttime_daily+ibeg*dt, iend-ibeg+1, 0.0, a=lanczos_winlen)
228 | else:
229 | tr = tr.slice(starttime_daily+ibeg*dt, starttime_daily+iend*dt)
230 |
231 |
232 | # pad array
233 | data = np.zeros(npts_daily)
234 | data[ibeg:iend+1] = tr.data
235 |
236 |
237 | # replace data
238 | tr.data = data
239 | tr.stats.starttime = starttime_daily
240 |
241 |
242 | del data, st, st_tmp
243 |
244 | return tr
245 |
246 |
247 |
248 | def cutdata_daily(station_stage_path):
249 |
250 | day_folders_list = os.listdir(station_stage_path)
251 |
252 | for day_folder in day_folders_list:
253 |
254 | day_path = station_stage_path + day_folder + '/'
255 | print('Entering directory ' + day_path[len_topdir:-1])
256 | #print('\n')
257 |
258 | if (not os.path.isdir(day_path)):
259 | return
260 |
261 | for C in channels:
262 |
263 | hour_files_list = glob.glob(day_path + '*' + C + '*' + sac_suffix)
264 |
265 | if ([] == hour_files_list):
266 | continue
267 |
268 |
269 | try:
270 | tr = merge_data(hour_files_list)
271 | if ([] == tr):
272 | continue
273 | # remove round error
274 | tr.stats.delta = round(tr.stats.delta*1e6)*1.e-6
275 | dt = tr.stats.delta
276 | df = tr.stats.sampling_rate
277 | starttime_daily = tr.stats.starttime
278 | except:
279 | print('merge data failure')
280 | del hour_files_list
281 | continue
282 |
283 |
284 | # remove invalid data
285 | if ((max(tr.data[nwin:-nwin-1]) - min(tr.data[nskip:-1-nskip])) < 1.e-12):
286 | del tr, hour_files_list
287 | continue
288 |
289 |
290 |
291 | # cut data into segments
292 | nsegments = round(day_in_seconds / segment_length)
293 | #nsegments = int(day_in_seconds / segment_length)
294 |
295 |
296 | ibeg = 0
297 | tbeg = 0.0
298 | for i in range(nsegments):
299 |
300 | tend = min(tbeg + segment_length - dt, day_in_seconds)
301 | iend = int(tend * df)
302 |
303 |
304 | tr_out = tr.copy()
305 | tr_out.data = tr.data[ibeg:iend+1]
306 | starttime = starttime_daily + tbeg
307 | tr_out.stats.starttime = starttime
308 |
309 |
310 | # remove invalid data
311 | if ((max(tr_out.data[nwin:-nwin-1]) - min(tr_out.data[nskip:-1-nskip])) < 1.e-12):
312 | del tr_out
313 | ibeg = iend + 1
314 | tbeg = tend + dt
315 | if ((day_in_seconds - tend) < 0.4*segment_length):
316 | break
317 | else:
318 | continue
319 |
320 |
321 | sac_path = create_sac_path(starttime)
322 | sac_filename = create_sac_filename(tr_out.stats)
323 |
324 | mypath = output_path + '/' + sac_path
325 |
326 | # create the path if it does not exist
327 | if (not os.path.exists(mypath)):
328 | os.makedirs(mypath, exist_ok=True)
329 |
330 |
331 | outfile = mypath + sac_filename
332 |
333 |
334 | # write sac
335 | if (dryrun):
336 |
337 | if (os.path.exists(outfile) and os.path.isfile(outfile)):
338 | os.remove(outfile)
339 |
340 | else:
341 |
342 | sac = SACTrace.from_obspy_trace(tr_out)
343 |
344 |
345 | sac.nzyear = starttime.year
346 | sac.nzjday = starttime.julday
347 | sac.nzhour = starttime.hour
348 | sac.nzmin = starttime.minute
349 | #sac.nzsec = starttime.second
350 | ##sac.nzmsec = int(starttime.microsecond*1.e-3)
351 | #sac.nzmsec = round(starttime.microsecond*1.e-3)
352 | sec = round((starttime.second + starttime.microsecond*1.e-6)*1000)
353 | sac.nzsec = int(sec*0.001)
354 | sac.nzmsec = int(sec - sac.nzsec*1000)
355 | sac.b = 0
356 | #sac.reftime += sac.b
357 | #sac.reftime = starttime
358 |
359 |
360 | sac.write(outfile)
361 |
362 | del sac
363 |
364 |
365 | del tr_out
366 | ibeg = iend + 1
367 | tbeg = tend + dt
368 |
369 |
370 | if ((day_in_seconds - tend) < 0.4*segment_length):
371 | break
372 |
373 |
374 | del tr, hour_files_list
375 | print('%s is done' % date2str(starttime_daily))
376 |
377 | print('Leaving directory ' + day_path[len_topdir:-1])
378 | #print('\n')
379 |
380 | del day_folders_list
381 |
382 | return
383 |
384 |
385 |
386 | def cutdata():
387 |
388 | global len_topdir, sac_suffix
389 |
390 | len_topdir = len(input_path) + 1
391 |
392 | stage_folders_list = os.listdir(input_path)
393 |
394 |
395 | sac_suffix = '.SAC'
396 |
397 | # cut daily sac files into segments
398 | for station_stage_folder in stage_folders_list:
399 |
400 | station_stage_path = input_path + '/' + station_stage_folder + '/'
401 | print('Entering directory ' + station_stage_path[len_topdir:-1])
402 | #print('\n')
403 |
404 | if (not os.path.exists(station_stage_path)):
405 | continue
406 |
407 | cutdata_daily(station_stage_path)
408 |
409 | print('Leaving directory ' + station_stage_path[len_topdir:-1])
410 | #print('\n')
411 |
412 | del stage_folders_list
413 |
414 | return
415 |
416 |
417 |
418 | if __name__ == '__main__':
419 |
420 | #print('\n')
421 | print('cutdata: ')
422 | print('This program cuts daily data into segments using the ObsPy (serial version)')
423 | print('Youshan Liu at Institute of Geology and Geophysics, Chinese Academy of Sciences')
424 | print('Welcome to send any bugs and suggestions to ysliu@mail.iggcas.ac.cn')
425 | print('\n')
426 |
427 | starttime = UTCDateTime()
428 |
429 | # absolution path
430 | #current_path = os.getcwd()
431 |
432 | # cutdata daily
433 | cutdata()
434 |
435 | endtime = UTCDateTime()
436 |
437 | elapsed_time = (endtime - starttime)
438 |
439 | print('\n')
440 | print('Start time : %s' % starttime)
441 | print('End time : %s' % endtime)
442 | print('Elapsed time : %f hours' % (elapsed_time / 3600.0))
443 |
444 |
445 |
446 |
--------------------------------------------------------------------------------
/scripts/cutdata_p.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: UTF-8 -*-
3 |
4 |
5 | '''
6 | cutdata
7 |
8 | This program cuts daily SAC files into segments using the ObsPy
9 |
10 | Date: 25/10/2020
11 | Author: Youshan Liu
12 | Affiliation: Institute of Geology and Geophysics, Chinese Academy of Sciences
13 |
14 |
15 | input data directory structure:
16 | ./stage folder/station folder/day folder/SAC files
17 |
18 |
19 | After cutting, the files will be save in the following structures:
20 | ./top folder/yyyy/mm/yyyymmdd_hh00000/
21 |
22 | for example:
23 | ./DATA/2007/10/20071003_000000/NCISP6.NE00.BHZ.SAC
24 |
25 |
26 | '''
27 |
28 |
29 |
30 |
31 | import os
32 | import re
33 | import glob
34 | from math import *
35 | import numpy as np
36 | from obspy import read
37 | from obspy import UTCDateTime
38 | from obspy.io.sac import SACTrace
39 | from obspy.core.trace import Trace
40 | from obspy.core.stream import Stream
41 | from multiprocessing.pool import ThreadPool
42 |
43 |
44 |
45 | ##############################################################
46 | ##############################################################
47 | ##############################################################
48 | # some options to be set
49 |
50 |
51 | # dryrun just for debug
52 | # dryrun = True => just print some directory information not to write sac files
53 | # dryrun = False => do the actual files conversion
54 | dryrun = False
55 |
56 | # directory of the data
57 | input_path = './DATA_Raw'
58 | output_path = './DATA_cut'
59 |
60 | # whether save input data
61 | save_input_data = True
62 |
63 |
64 | # segment length
65 | segment_length = 3600*24
66 |
67 |
68 | # component list to be cut
69 | # three-components
70 | #channels = ['HZ', 'HN', 'HE']
71 | # only Z-component
72 | channels = ['HZ']
73 | # only N-component
74 | #channels = ['HN']
75 | # only E-component
76 | #channels = ['HE']
77 |
78 |
79 | # interpolation method: 'lanczos' is highest quality interpolation but expensive, the 'cubic' method may be a good choice
80 | interpolation_method = 'cubic'
81 | # You can have the following options
82 | #
83 | # "lanczos": This offers the highest quality interpolation and should be chosen whenever possible.
84 | # It is only due to legacy reasons that this is not the default method. The one downside it has is that it can be fairly expensive.
85 | # Essentially a fnite support version of sinc resampling (the ideal reconstruction filter).
86 | # For large values of a, it converges towards sinc resampling.
87 | # if interpolation_method is lanczos, a value of 'a' that is the width of window in samples on either side shold be given.
88 | # Values of a >= 20 show good results even for data that has energy close to the Nyquist frequency.
89 | # Please see the https://docs.obspy.org/packages/autogen/obspy.signal.interpolation.lanczos_interpolation.html#obspy.signal.interpolation.lanczos_interpolation for details.
90 | lanczos_winlen = 20 # this parameter is only valid for the 'lanczos' interpolation method
91 | #
92 | # "weighted_average_slopes": This is the interpolation method used by SAC. Refer to weighted_average_slopes() for more details.
93 | #
94 | # "slinear", "quadratic" and "cubic": spline interpolation of first, second or third order.
95 | #
96 | # "linear": Linear interpolation.
97 | #
98 | # "nearest": Nearest neighbour interpolation.
99 |
100 |
101 | # nskip: a parameter is used to skip head and tail samples to check whether a segment data is zeros
102 | if interpolation_method == 'lanczos':
103 | nskip = lanczos_winlen
104 | else:
105 | nskip = 0
106 |
107 |
108 |
109 | day_in_seconds = 24*3600
110 |
111 | ##############################################################
112 |
113 |
114 |
115 | def create_sac_filename(stats):
116 |
117 | network = stats.sac.knetwk
118 | station = stats.sac.kstnm
119 | channel = stats.sac.kcmpnm
120 |
121 | filename = network + '.' + station + \
122 | '.' + channel + sac_suffix
123 |
124 | return filename
125 |
126 |
127 |
128 | def create_sac_path(starttime):
129 |
130 | year = '%4.4d' % starttime.year
131 | month = '%2.2d' % starttime.month
132 | day = '%2.2d' % starttime.day
133 | hh = '%2.2d' % starttime.hour
134 | mm = '%2.2d' % starttime.minute
135 | ss = '%2.2d' % starttime.second
136 |
137 | mydate = year + month + day
138 |
139 | month_folder = mydate + '_' + hh + mm + ss
140 |
141 | sac_path = year + '/' + month + \
142 | '/' + month_folder + '/'
143 |
144 | return sac_path
145 |
146 |
147 |
148 | def date2str(starttime):
149 |
150 | year = '%4.4d' % starttime.year
151 | month = '%2.2d' % starttime.month
152 | day = '%2.2d' % starttime.day
153 |
154 | mydate = year + month + day
155 |
156 | return mydate
157 |
158 |
159 |
160 | def merge_data(hour_files_list):
161 |
162 | #print(hour_files_list)
163 |
164 | st = Stream()
165 | data_len = 0.0
166 | for hour_file in hour_files_list:
167 | try:
168 | # faster for a specific file format
169 | st_tmp = read(hour_file, format='SAC', check_compression=False)
170 | #st_tmp = read(hour_file)
171 | if (not save_input_data):
172 | os.remove(hour_file)
173 | except:
174 | continue
175 | st += st_tmp
176 | data_len += (st_tmp[0].stats.npts-1)*st_tmp[0].stats.delta
177 |
178 |
179 | if (data_len < 0.50*segment_length):
180 | return []
181 |
182 |
183 | st.sort(['starttime'])
184 |
185 | # merge data
186 | if (len(st) > 1):
187 | st.merge(method=1, fill_value=0.0)
188 | #st.merge(method=1, fill_value='interpolate')
189 |
190 |
191 | #for i in range(0,len(st[0])):
192 | # arr = st[0].data[i]
193 | # if (np.ma.is_masked(arr)):
194 | # st[0].data[i] = 0.0
195 |
196 | #if (np.ma.is_masked(st[0].data)):
197 | # continue
198 |
199 |
200 | try:
201 | tr = st[0]
202 | # remove round error
203 | tr.stats.delta = round(tr.stats.delta*1e6)*1.e-6
204 | except:
205 | return
206 |
207 |
208 | stats = tr.stats
209 | dt = stats.delta
210 | df = stats.sampling_rate
211 | npts_daily = int(day_in_seconds*df)
212 |
213 |
214 | starttime = stats.starttime
215 | endtime = stats.endtime
216 | midtime = starttime + 0.50*stats.npts*dt
217 | starttime_daily = UTCDateTime(midtime.year, midtime.month, midtime.day, 0, 0, 0, 0)
218 | endtime_daily = starttime_daily + day_in_seconds - dt
219 |
220 |
221 | # indexes of the starttime and endtime in local temporal axis
222 | ibeg = ceil((max(starttime, starttime_daily) - starttime_daily)*df)
223 | iend = int((min(endtime, endtime_daily) - starttime_daily)*df)
224 |
225 |
226 | if (0 != starttime.microsecond % round(dt*1e6)):
227 | # interpolate to local temporal axis
228 | #tr.interpolate(df, 'cubic', starttime_daily+ibeg*dt, iend-ibeg+1, 0.0)
229 | #tr.interpolate(df, 'lanczos', starttime_daily+ibeg*dt, iend-ibeg+1, 0.0, a=21)
230 | tr.interpolate(df, interpolation_method, starttime_daily+ibeg*dt, iend-ibeg+1, 0.0, a=lanczos_winlen)
231 | else:
232 | tr = tr.slice(starttime_daily+ibeg*dt, starttime_daily+iend*dt)
233 |
234 |
235 | # pad array
236 | data = np.zeros(npts_daily)
237 | data[ibeg:iend+1] = tr.data
238 |
239 |
240 | # replace data
241 | tr.data = data
242 | tr.stats.starttime = starttime_daily
243 |
244 |
245 | del data, st, st_tmp
246 |
247 | return tr
248 |
249 |
250 |
251 | def cutdata_daily(day_folder):
252 |
253 | day_path = station_stage_path + day_folder + '/'
254 | print('Entering directory ' + day_path[len_topdir:-1])
255 | #print('\n')
256 |
257 | if (not os.path.isdir(day_path)):
258 | return
259 |
260 | for C in channels:
261 |
262 | hour_files_list = glob.glob(day_path + '*' + C + '*' + sac_suffix)
263 |
264 | if ([] == hour_files_list):
265 | continue
266 |
267 |
268 | try:
269 | tr = merge_data(hour_files_list)
270 | if ([] == tr):
271 | continue
272 | # remove round error
273 | tr.stats.delta = round(tr.stats.delta*1e6)*1.e-6
274 | dt = tr.stats.delta
275 | df = tr.stats.sampling_rate
276 | starttime_daily = tr.stats.starttime
277 | except:
278 | print('merge data failure')
279 | del hour_files_list
280 | continue
281 |
282 |
283 | # remove invalid data
284 | if ((max(tr.data[nwin:-nwin-1]) - min(tr.data[nskip:-1-nskip])) < 1.e-12):
285 | del tr, hour_files_list
286 | continue
287 |
288 |
289 | # cut data into segments
290 | nsegments = round(day_in_seconds / segment_length)
291 | #nsegments = int(day_in_seconds / segment_length)
292 |
293 |
294 | ibeg = 0
295 | tbeg = 0.0
296 | for i in range(nsegments):
297 |
298 | tend = min(tbeg + segment_length - dt, day_in_seconds)
299 | iend = int(tend * df)
300 |
301 |
302 | tr_out = tr.copy()
303 | tr_out.data = tr.data[ibeg:iend+1]
304 | starttime = starttime_daily + tbeg
305 | tr_out.stats.starttime = starttime
306 |
307 |
308 | # remove invalid data
309 | if ((max(tr_out.data[nwin:-nwin-1]) - min(tr_out.data[nskip:-1-nskip])) < 1.e-12):
310 | del tr_out
311 | ibeg = iend + 1
312 | tbeg = tend + dt
313 | if ((day_in_seconds - tend) < 0.4*segment_length):
314 | break
315 | else:
316 | continue
317 |
318 |
319 | sac_path = create_sac_path(starttime)
320 | sac_filename = create_sac_filename(tr_out.stats)
321 |
322 | mypath = output_path + '/' + sac_path
323 |
324 | # create the path if it does not exist
325 | if (not os.path.exists(mypath)):
326 | os.makedirs(mypath, exist_ok=True)
327 |
328 |
329 | outfile = mypath + sac_filename
330 |
331 |
332 | # write sac
333 | if (dryrun):
334 |
335 | if (os.path.exists(outfile) and os.path.isfile(outfile)):
336 | os.remove(outfile)
337 |
338 | else:
339 |
340 | sac = SACTrace.from_obspy_trace(tr_out)
341 |
342 |
343 | sac.nzyear = starttime.year
344 | sac.nzjday = starttime.julday
345 | sac.nzhour = starttime.hour
346 | sac.nzmin = starttime.minute
347 | #sac.nzsec = starttime.second
348 | ##sac.nzmsec = int(starttime.microsecond*1.e-3)
349 | #sac.nzmsec = round(starttime.microsecond*1.e-3)
350 | sec = round((starttime.second + starttime.microsecond*1.e-6)*1000)
351 | sac.nzsec = int(sec*0.001)
352 | sac.nzmsec = int(sec - sac.nzsec*1000)
353 | sac.b = 0
354 | #sac.reftime += sac.b
355 | #sac.reftime = starttime
356 |
357 |
358 | sac.write(outfile)
359 |
360 | del sac
361 |
362 |
363 | del tr_out
364 | ibeg = iend + 1
365 | tbeg = tend + dt
366 |
367 |
368 | if ((day_in_seconds - tend) < 0.4*segment_length):
369 | break
370 |
371 |
372 | del tr, hour_files_list
373 | print('%s is done' % date2str(starttime_daily))
374 |
375 | print('Leaving directory ' + day_path[len_topdir:-1])
376 | #print('\n')
377 |
378 | return
379 |
380 |
381 |
382 | def cutdata():
383 |
384 | global len_topdir, station_stage_path, sac_suffix
385 |
386 | len_topdir = len(input_path) + 1
387 |
388 | stage_folders_list = os.listdir(input_path)
389 |
390 |
391 | sac_suffix = '.SAC'
392 |
393 | # cut daily sac files into segments
394 | for station_stage_folder in stage_folders_list:
395 |
396 | station_stage_path = input_path + '/' + station_stage_folder + '/'
397 | print('Entering directory ' + station_stage_path[len_topdir:-1])
398 | #print('\n')
399 |
400 | if (not os.path.isdir(station_stage_path)):
401 | continue
402 |
403 | day_folders_list = os.listdir(station_stage_path)
404 |
405 | pool = ThreadPool()
406 | pool.map(cutdata_daily, day_folders_list)
407 | pool.close()
408 | pool.join()
409 |
410 | del day_folders_list
411 | print('Leaving directory ' + station_stage_path[len_topdir:-1])
412 | #print('\n')
413 |
414 | del stage_folders_list
415 |
416 | return
417 |
418 |
419 |
420 | if __name__ == '__main__':
421 |
422 | #print('\n')
423 | print('cutdata: ')
424 | print('This program cuts daily data into segments using the ObsPy (parallel version)')
425 | print('Youshan Liu at Institute of Geology and Geophysics, Chinese Academy of Sciences')
426 | print('Welcome to send any bugs and suggestions to ysliu@mail.iggcas.ac.cn')
427 | print('\n')
428 |
429 | starttime = UTCDateTime()
430 |
431 | # absolution path
432 | #current_path = os.getcwd()
433 |
434 | # cutdata daily
435 | cutdata()
436 |
437 | endtime = UTCDateTime()
438 |
439 | elapsed_time = (endtime - starttime)
440 |
441 | print('\n')
442 | print('Start time : %s' % starttime)
443 | print('End time : %s' % endtime)
444 | print('Elapsed time : %f hours' % (elapsed_time / 3600.0))
445 |
446 |
447 |
448 |
--------------------------------------------------------------------------------
/scripts/cutdata2_p.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: UTF-8 -*-
3 |
4 |
5 | '''
6 | cutdata
7 |
8 | This program cuts daily SAC files into segments using the ObsPy
9 |
10 | Date: 25/10/2020
11 | Author: Youshan Liu
12 | Affiliation: Institute of Geology and Geophysics, Chinese Academy of Sciences
13 |
14 |
15 | input data directory structure:
16 | ./top folder/stage folder/station folder/day folder/SAC files
17 |
18 |
19 | After cutting, the files will be save in the following structures:
20 | ./data folder/yyyy/mm/yyyymmdd_hh00000/
21 |
22 | for example:
23 | ./DATA/2007/10/20071003_000000/NCISP.NE00.BHZ.SAC
24 |
25 |
26 | '''
27 |
28 |
29 |
30 |
31 | import os
32 | import re
33 | import glob
34 | from math import *
35 | import numpy as np
36 | from obspy import read
37 | from obspy import UTCDateTime
38 | from obspy.io.sac import SACTrace
39 | from obspy.core.trace import Trace
40 | from obspy.core.stream import Stream
41 | from multiprocessing.pool import ThreadPool
42 |
43 |
44 |
45 | ##############################################################
46 | ##############################################################
47 | ##############################################################
48 | # some options to be set
49 |
50 |
51 | # dryrun just for debug
52 | # dryrun = True => just print some directory information not to write sac files
53 | # dryrun = False => do the actual files conversion
54 | dryrun = False
55 |
56 | # directory of the data
57 | input_path = './DATA_Raw'
58 | output_path = './DATA_cut'
59 |
60 | # whether save input data
61 | save_input_data = True
62 |
63 |
64 | # segment length
65 | segment_length = 3600*6
66 |
67 |
68 | # component list to be cut
69 | # three-components
70 | #channels = ['HZ', 'HN', 'HE']
71 | # only Z-component
72 | channels = ['HZ']
73 | # only N-component
74 | #channels = ['HN']
75 | # only E-component
76 | #channels = ['HE']
77 |
78 |
79 | # interpolation method: 'lanczos' is highest quality interpolation but expensive, the 'cubic' method may be a good choice
80 | interpolation_method = 'cubic'
81 | # You can have the following options
82 | #
83 | # "lanczos": This offers the highest quality interpolation and should be chosen whenever possible.
84 | # It is only due to legacy reasons that this is not the default method. The one downside it has is that it can be fairly expensive.
85 | # Essentially a fnite support version of sinc resampling (the ideal reconstruction filter).
86 | # For large values of a, it converges towards sinc resampling.
87 | # if interpolation_method is lanczos, a value of 'a' that is the width of window in samples on either side shold be given.
88 | # Values of a >= 20 show good results even for data that has energy close to the Nyquist frequency.
89 | # Please see the https://docs.obspy.org/packages/autogen/obspy.signal.interpolation.lanczos_interpolation.html#obspy.signal.interpolation.lanczos_interpolation for details.
90 | lanczos_winlen = 20 # this parameter is only valid for the 'lanczos' interpolation method
91 | #
92 | # "weighted_average_slopes": This is the interpolation method used by SAC. Refer to weighted_average_slopes() for more details.
93 | #
94 | # "slinear", "quadratic" and "cubic": spline interpolation of first, second or third order.
95 | #
96 | # "linear": Linear interpolation.
97 | #
98 | # "nearest": Nearest neighbour interpolation.
99 |
100 |
101 | # nskip: a parameter is used to skip head and tail samples to check whether a segment data is zeros
102 | if interpolation_method == 'lanczos':
103 | nskip = lanczos_winlen
104 | else:
105 | nskip = 0
106 |
107 |
108 |
109 | day_in_seconds = 24*3600
110 |
111 | ##############################################################
112 |
113 |
114 |
115 | def create_sac_filename(stats):
116 |
117 | network = stats.sac.knetwk
118 | station = stats.sac.kstnm
119 | channel = stats.sac.kcmpnm
120 |
121 | filename = network + '.' + station + \
122 | '.' + channel + sac_suffix
123 |
124 | return filename
125 |
126 |
127 |
128 | def create_sac_path(starttime):
129 |
130 | year = '%4.4d' % starttime.year
131 | month = '%2.2d' % starttime.month
132 | day = '%2.2d' % starttime.day
133 | hh = '%2.2d' % starttime.hour
134 | mm = '%2.2d' % starttime.minute
135 | ss = '%2.2d' % starttime.second
136 |
137 | mydate = year + month + day
138 |
139 | month_folder = mydate + '_' + hh + mm + ss
140 |
141 | sac_path = year + '/' + month + \
142 | '/' + month_folder + '/'
143 |
144 | return sac_path
145 |
146 |
147 |
148 | def date2str(starttime):
149 |
150 | year = '%4.4d' % starttime.year
151 | month = '%2.2d' % starttime.month
152 | day = '%2.2d' % starttime.day
153 |
154 | mydate = year + month + day
155 |
156 | return mydate
157 |
158 |
159 |
160 | def merge_data(hour_files_list):
161 |
162 | st = Stream()
163 | data_len = 0.0
164 | for hour_file in hour_files_list:
165 | try:
166 | # faster for a specific file format
167 | st_tmp = read(hour_file, format='SAC', check_compression=False)
168 | #st_tmp = read(hour_file)
169 | if (not save_input_data):
170 | os.remove(hour_file)
171 | except:
172 | continue
173 | st += st_tmp
174 | data_len += (st_tmp[0].stats.npts-1)*st_tmp[0].stats.delta
175 |
176 |
177 | if (data_len < 0.50*segment_length):
178 | return []
179 |
180 |
181 | st.sort(['starttime'])
182 |
183 | # merge data
184 | if (len(st) > 1):
185 | st.merge(method=1, fill_value=0.0)
186 | #st.merge(method=1, fill_value='interpolate')
187 |
188 |
189 | #for i in range(0,len(st[0])):
190 | # arr = st[0].data[i]
191 | # if (np.ma.is_masked(arr)):
192 | # st[0].data[i] = 0.0
193 |
194 | #if (np.ma.is_masked(st[0].data)):
195 | # continue
196 |
197 |
198 | try:
199 | tr = st[0]
200 | # remove round error
201 | tr.stats.delta = round(tr.stats.delta*1e6)*1.e-6
202 | except:
203 | return
204 |
205 |
206 | stats = tr.stats
207 | dt = stats.delta
208 | df = stats.sampling_rate
209 | npts_daily = int(day_in_seconds*df)
210 |
211 |
212 | starttime = stats.starttime
213 | endtime = stats.endtime
214 | midtime = starttime + 0.50*stats.npts*dt
215 | starttime_daily = UTCDateTime(midtime.year, midtime.month, midtime.day, 0, 0, 0, 0)
216 | endtime_daily = starttime_daily + day_in_seconds - dt
217 |
218 |
219 | # indexes of the starttime and endtime in local temporal axis
220 | ibeg = ceil((max(starttime, starttime_daily) - starttime_daily)*df)
221 | iend = int((min(endtime, endtime_daily) - starttime_daily)*df)
222 |
223 |
224 | if (0 != starttime.microsecond % round(dt*1e6)):
225 | # interpolate to local temporal axis
226 | #tr.interpolate(df, 'cubic', starttime_daily+ibeg*dt, iend-ibeg+1, 0.0)
227 | #tr.interpolate(df, 'lanczos', starttime_daily+ibeg*dt, iend-ibeg+1, 0.0, a=21)
228 | tr.interpolate(df, interpolation_method, starttime_daily+ibeg*dt, iend-ibeg+1, 0.0, a=lanczos_winlen)
229 | else:
230 | tr = tr.slice(starttime_daily+ibeg*dt, starttime_daily+iend*dt)
231 |
232 |
233 | # pad array
234 | data = np.zeros(npts_daily)
235 | data[ibeg:iend+1] = tr.data
236 |
237 |
238 | # replace data
239 | tr.data = data
240 | tr.stats.starttime = starttime_daily
241 |
242 |
243 | del data, st, st_tmp
244 |
245 | return tr
246 |
247 |
248 |
249 | def cutdata_daily(day_folder):
250 |
251 | day_path = station_path + day_folder + '/'
252 | print('Entering directory ' + day_path[len_topdir:-1])
253 | #print('\n')
254 |
255 | if (not os.path.isdir(day_path)):
256 | return
257 |
258 | for C in channels:
259 |
260 | hour_files_list = glob.glob(day_path + '*' + C + '*' + sac_suffix)
261 |
262 | if ([] == hour_files_list):
263 | continue
264 |
265 |
266 | try:
267 | tr = merge_data(hour_files_list)
268 | if ([] == tr):
269 | continue
270 | # remove round error
271 | tr.stats.delta = round(tr.stats.delta*1e6)*1.e-6
272 | dt = tr.stats.delta
273 | df = tr.stats.sampling_rate
274 | starttime_daily = tr.stats.starttime
275 | except:
276 | print('merge data failure')
277 | del hour_files_list
278 | continue
279 |
280 |
281 | # remove invalid data
282 | if ((max(tr.data[nwin:-nwin-1]) - min(tr.data[nskip:-1-nskip])) < 1.e-12):
283 | del tr, hour_files_list
284 | continue
285 |
286 |
287 | # cut data into segments
288 | nsegments = round(day_in_seconds / segment_length)
289 | #nsegments = int(day_in_seconds / segment_length)
290 |
291 |
292 | ibeg = 0
293 | tbeg = 0.0
294 | for i in range(nsegments):
295 |
296 | tend = min(tbeg + segment_length - dt, day_in_seconds)
297 | iend = int(tend * df)
298 |
299 |
300 | tr_out = tr.copy()
301 | tr_out.data = tr.data[ibeg:iend+1]
302 | starttime = starttime_daily + tbeg
303 | tr_out.stats.starttime = starttime
304 |
305 |
306 | # remove invalid data
307 | if ((max(tr_out.data[nwin:-nwin-1]) - min(tr_out.data[nskip:-1-nskip])) < 1.e-12):
308 | del tr_out
309 | ibeg = iend + 1
310 | tbeg = tend + dt
311 | if ((day_in_seconds - tend) < 0.4*segment_length):
312 | break
313 | else:
314 | continue
315 |
316 |
317 | sac_path = create_sac_path(starttime)
318 | sac_filename = create_sac_filename(tr_out.stats)
319 |
320 | mypath = output_path + '/' + sac_path
321 |
322 | # create the path if it does not exist
323 | if (not os.path.exists(mypath)):
324 | os.makedirs(mypath, exist_ok=True)
325 |
326 |
327 | outfile = mypath + sac_filename
328 |
329 |
330 | # write sac
331 | if (dryrun):
332 |
333 | if (os.path.exists(outfile) and os.path.isfile(outfile)):
334 | os.remove(outfile)
335 |
336 | else:
337 |
338 | sac = SACTrace.from_obspy_trace(tr_out)
339 |
340 |
341 | sac.nzyear = starttime.year
342 | sac.nzjday = starttime.julday
343 | sac.nzhour = starttime.hour
344 | sac.nzmin = starttime.minute
345 | #sac.nzsec = starttime.second
346 | ##sac.nzmsec = int(starttime.microsecond*1.e-3)
347 | #sac.nzmsec = round(starttime.microsecond*1.e-3)
348 | sec = round((starttime.second + starttime.microsecond*1.e-6)*1000)
349 | sac.nzsec = int(sec*0.001)
350 | sac.nzmsec = int(sec - sac.nzsec*1000)
351 | sac.b = 0
352 | #sac.reftime += sac.b
353 | #sac.reftime = starttime
354 |
355 |
356 | sac.write(outfile)
357 |
358 | del sac
359 |
360 |
361 | del tr_out
362 | ibeg = iend + 1
363 | tbeg = tend + dt
364 |
365 |
366 | if ((day_in_seconds - tend) < 0.4*segment_length):
367 | break
368 |
369 |
370 | del tr, hour_files_list
371 | print('%s is done' % date2str(starttime_daily))
372 |
373 | print('Leaving directory ' + day_path[len_topdir:-1])
374 | #print('\n')
375 |
376 | return
377 |
378 |
379 |
380 | def cutdata():
381 |
382 | global len_topdir, station_path, sac_suffix
383 |
384 | len_topdir = len(input_path) + 1
385 |
386 | stage_folders_list = os.listdir(input_path)
387 |
388 |
389 | sac_suffix = '.SAC'
390 |
391 | # convert reftek to sac
392 | for stage_folder in stage_folders_list:
393 |
394 | stage_path = input_path + '/' + stage_folder + '/'
395 | print('Entering directory ' + stage_path[len_topdir:-1])
396 | #print('\n')
397 |
398 | if (not os.path.isdir(stage_path)):
399 | continue
400 |
401 | station_folder_list = os.listdir(stage_path)
402 |
403 | for station_folder in station_folder_list:
404 |
405 | station_path = stage_path + station_folder + '/'
406 | print('Entering directory ' + station_path[len_topdir:-1])
407 | #print('\n')
408 |
409 | if (not os.path.isdir(station_path)):
410 | continue
411 |
412 | day_folders_list = os.listdir(station_path)
413 |
414 | pool = ThreadPool()
415 | pool.map(cutdata_daily, day_folders_list)
416 | pool.close()
417 | pool.join()
418 |
419 | del day_folders_list
420 | print('Leaving directory ' + station_path[len_topdir:-1])
421 | #print('\n')
422 |
423 | del station_folder_list
424 | print('Leaving directory ' + stage_path[len_topdir:-1])
425 | #print('\n')
426 |
427 | del stage_folders_list
428 |
429 | return
430 |
431 |
432 |
433 | if __name__ == '__main__':
434 |
435 | #print('\n')
436 | print('cutdata: ')
437 | print('This program cuts daily data into segments using the ObsPy (parallel version)')
438 | print('Youshan Liu at Institute of Geology and Geophysics, Chinese Academy of Sciences')
439 | print('Welcome to send any bugs and suggestions to ysliu@mail.iggcas.ac.cn')
440 | print('\n')
441 |
442 | starttime = UTCDateTime()
443 |
444 | # absolution path
445 | #current_path = os.getcwd()
446 |
447 | # cutdata daily
448 | cutdata()
449 |
450 | endtime = UTCDateTime()
451 |
452 | elapsed_time = (endtime - starttime)
453 |
454 | print('\n')
455 | print('Start time : %s' % starttime)
456 | print('End time : %s' % endtime)
457 | print('Elapsed time : %f hours' % (elapsed_time / 3600.0))
458 |
459 |
460 |
461 |
--------------------------------------------------------------------------------
/scripts/cutdata2.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: UTF-8 -*-
3 |
4 |
5 | '''
6 | cutdata
7 |
8 | This program cuts daily SAC files into segments using the ObsPy
9 |
10 | Date: 25/10/2020
11 | Author: Youshan Liu
12 | Affiliation: Institute of Geology and Geophysics, Chinese Academy of Sciences
13 |
14 |
15 | input data directory structure:
16 | ./top folder/stage folder/station folder/day folder/SAC files
17 |
18 |
19 | After cutting, the files will be save in the following structures:
20 | ./data folder/yyyy/mm/yyyymmdd_hh00000/
21 |
22 | for example:
23 | ./DATA/2007/10/20071003_000000/NCISP.NE00.BHZ.SAC
24 |
25 |
26 | '''
27 |
28 |
29 |
30 |
31 | import os
32 | import re
33 | import glob
34 | from math import *
35 | import numpy as np
36 | from obspy import read
37 | from obspy import UTCDateTime
38 | from obspy.io.sac import SACTrace
39 | from obspy.core.trace import Trace
40 | from obspy.core.stream import Stream
41 |
42 |
43 |
44 | ##############################################################
45 | ##############################################################
46 | ##############################################################
47 | # some options to be set
48 |
49 |
50 | # dryrun just for debug
51 | # dryrun = True => just print some directory information not to write sac files
52 | # dryrun = False => do the actual files conversion
53 | dryrun = False
54 |
55 | # directory of the data
56 | input_path = './DATA_Raw'
57 | output_folder = './DATA_cut'
58 |
59 | # whether save input data
60 | save_input_data = True
61 |
62 |
63 | # segment length
64 | segment_length = 3600*24
65 |
66 |
67 | # component list to be cut
68 | # three-components
69 | #channels = ['HZ', 'HN', 'HE']
70 | # only Z-component
71 | channels = ['HZ']
72 | # only N-component
73 | #channels = ['HN']
74 | # only E-component
75 | #channels = ['HE']
76 |
77 |
78 |
79 | npts_skip = 2*nwin# interpolation method: 'lanczos' is highest quality interpolation but expensive, the 'cubic' method may be a good choice
80 | interpolation_method = 'cubic'
81 | # You can have the following options
82 | #
83 | # "lanczos": This offers the highest quality interpolation and should be chosen whenever possible.
84 | # It is only due to legacy reasons that this is not the default method. The one downside it has is that it can be fairly expensive.
85 | # Essentially a fnite support version of sinc resampling (the ideal reconstruction filter).
86 | # For large values of a, it converges towards sinc resampling.
87 | # if interpolation_method is lanczos, a value of 'a' that is the width of window in samples on either side shold be given.
88 | # Values of a >= 20 show good results even for data that has energy close to the Nyquist frequency.
89 | # Please see the https://docs.obspy.org/packages/autogen/obspy.signal.interpolation.lanczos_interpolation.html#obspy.signal.interpolation.lanczos_interpolation for details.
90 | lanczos_winlen = 20 # this parameter is only valid for the 'lanczos' interpolation method
91 | #
92 | # "weighted_average_slopes": This is the interpolation method used by SAC. Refer to weighted_average_slopes() for more details.
93 | #
94 | # "slinear", "quadratic" and "cubic": spline interpolation of first, second or third order.
95 | #
96 | # "linear": Linear interpolation.
97 | #
98 | # "nearest": Nearest neighbour interpolation.
99 |
100 |
101 | # nskip: a parameter is used to skip head and tail samples to check whether a segment data is zeros
102 | if interpolation_method == 'lanczos':
103 | nskip = lanczos_winlen
104 | else:
105 | nskip = 0
106 |
107 |
108 |
109 | day_in_seconds = 24*3600
110 |
111 | ##############################################################
112 |
113 |
114 |
115 | def create_sac_filename(stats):
116 |
117 | network = stats.sac.knetwk
118 | station = stats.sac.kstnm
119 | channel = stats.sac.kcmpnm
120 |
121 | filename = network + '.' + station + \
122 | '.' + channel + sac_suffix
123 |
124 | return filename
125 |
126 |
127 |
128 | def create_sac_path(starttime):
129 |
130 | year = '%4.4d' % starttime.year
131 | month = '%2.2d' % starttime.month
132 | day = '%2.2d' % starttime.day
133 | hh = '%2.2d' % starttime.hour
134 | mm = '%2.2d' % starttime.minute
135 | ss = '%2.2d' % starttime.second
136 |
137 | mydate = year + month + day
138 |
139 | month_folder = mydate + '_' + hh + mm + ss
140 |
141 | sac_path = year + '/' + month + \
142 | '/' + month_folder + '/'
143 |
144 | return sac_path
145 |
146 |
147 |
148 | def date2str(starttime):
149 |
150 | year = '%4.4d' % starttime.year
151 | month = '%2.2d' % starttime.month
152 | day = '%2.2d' % starttime.day
153 |
154 | mydate = year + month + day
155 |
156 | return mydate
157 |
158 |
159 |
160 | def merge_data(hour_files_list):
161 |
162 | st = Stream()
163 | data_len = 0.0
164 | for hour_file in hour_files_list:
165 | try:
166 | # faster for a specific file format
167 | st_tmp = read(hour_file, format='SAC', check_compression=False)
168 | #st_tmp = read(hour_file)
169 | if (not save_input_data):
170 | os.remove(hour_file)
171 | except:
172 | continue
173 | st += st_tmp
174 | data_len += (st_tmp[0].stats.npts-1)*st_tmp[0].stats.delta
175 |
176 |
177 | if (data_len < 0.50*segment_length):
178 | return []
179 |
180 |
181 | st.sort(['starttime'])
182 |
183 | # merge data
184 | if (len(st) > 1):
185 | st.merge(method=1, fill_value=0.0)
186 | #st.merge(method=1, fill_value='interpolate')
187 |
188 |
189 | #for i in range(0,len(st[0])):
190 | # arr = st[0].data[i]
191 | # if (np.ma.is_masked(arr)):
192 | # st[0].data[i] = 0.0
193 |
194 | #if (np.ma.is_masked(st[0].data)):
195 | # continue
196 |
197 |
198 | try:
199 | tr = st[0]
200 | # remove round error
201 | tr.stats.delta = round(tr.stats.delta*1e6)*1.e-6
202 | except:
203 | return
204 |
205 |
206 | stats = tr.stats
207 | dt = stats.delta
208 | df = stats.sampling_rate
209 | npts_daily = int(day_in_seconds*df)
210 |
211 |
212 | starttime = stats.starttime
213 | endtime = stats.endtime
214 | midtime = starttime + 0.50*stats.npts*dt
215 | starttime_daily = UTCDateTime(midtime.year, midtime.month, midtime.day, 0, 0, 0, 0)
216 | endtime_daily = starttime_daily + day_in_seconds - dt
217 |
218 |
219 | # indexes of the starttime and endtime in local temporal axis
220 | ibeg = ceil((max(starttime, starttime_daily) - starttime_daily)*df)
221 | iend = int((min(endtime, endtime_daily) - starttime_daily)*df)
222 |
223 |
224 | if (0 != starttime.microsecond % round(dt*1e6)):
225 | # interpolate to local temporal axis
226 | #tr.interpolate(df, 'cubic', starttime_daily+ibeg*dt, iend-ibeg+1, 0.0)
227 | #tr.interpolate(df, 'lanczos', starttime_daily+ibeg*dt, iend-ibeg+1, 0.0, a=21)
228 | tr.interpolate(df, interpolation_method, starttime_daily+ibeg*dt, iend-ibeg+1, 0.0, a=lanczos_winlen)
229 | else:
230 | tr = tr.slice(starttime_daily+ibeg*dt, starttime_daily+iend*dt)
231 |
232 |
233 | # pad array
234 | data = np.zeros(npts_daily)
235 | data[ibeg:iend+1] = tr.data
236 |
237 |
238 | # replace data
239 | tr.data = data
240 | tr.stats.starttime = starttime_daily
241 |
242 |
243 | del data, st, st_tmp
244 |
245 | return tr
246 |
247 |
248 |
249 | def cutdata_daily(station_path):
250 |
251 | day_folders_list = os.listdir(station_path)
252 |
253 | for day_folder in day_folders_list:
254 |
255 | day_path = station_path + day_folder + '/'
256 | print('Entering directory ' + day_path[len_topdir:-1])
257 | #print('\n')
258 |
259 | if (not os.path.isdir(day_path)):
260 | return
261 |
262 | for C in channels:
263 |
264 | hour_files_list = glob.glob(day_path + '*' + C + '*' + sac_suffix)
265 |
266 | if ([] == hour_files_list):
267 | continue
268 |
269 |
270 | try:
271 | tr = merge_data(hour_files_list)
272 | if ([] == tr):
273 | continue
274 | # remove round error
275 | tr.stats.delta = round(tr.stats.delta*1e6)*1.e-6
276 | dt = tr.stats.delta
277 | df = tr.stats.sampling_rate
278 | starttime_daily = tr.stats.starttime
279 | except:
280 | print('merge data failure')
281 | del hour_files_list
282 | continue
283 |
284 |
285 | # remove invalid data
286 | if ((max(tr.data[nwin:-nwin-1]) - min(tr.data[nskip:-1-nskip])) < 1.e-12):
287 | del tr, hour_files_list
288 | continue
289 |
290 |
291 | # cut data into segments
292 | nsegments = round(day_in_seconds / segment_length)
293 | #nsegments = int(day_in_seconds / segment_length)
294 |
295 |
296 | ibeg = 0
297 | tbeg = 0.0
298 | for i in range(nsegments):
299 |
300 | tend = min(tbeg + segment_length - dt, day_in_seconds)
301 | iend = int(tend * df)
302 |
303 |
304 | tr_out = tr.copy()
305 | tr_out.data = tr.data[ibeg:iend+1]
306 | starttime = starttime_daily + tbeg
307 | tr_out.stats.starttime = starttime
308 |
309 |
310 | # remove invalid data
311 | if ((max(tr_out.data[nwin:-nwin-1]) - min(tr_out.data[nskip:-1-nskip])) < 1.e-12):
312 | del tr_out
313 | ibeg = iend + 1
314 | tbeg = tend + dt
315 | if ((day_in_seconds - tend) < 0.4*segment_length):
316 | break
317 | else:
318 | continue
319 |
320 |
321 | sac_path = create_sac_path(starttime)
322 | sac_filename = create_sac_filename(tr_out.stats)
323 |
324 | mypath = output_path + '/' + sac_path
325 |
326 | # create the path if it does not exist
327 | if (not os.path.exists(mypath)):
328 | os.makedirs(mypath, exist_ok=True)
329 |
330 |
331 | outfile = mypath + sac_filename
332 |
333 |
334 | # write sac
335 | if (dryrun):
336 |
337 | if (os.path.exists(outfile) and os.path.isfile(outfile)):
338 | os.remove(outfile)
339 |
340 | else:
341 |
342 | sac = SACTrace.from_obspy_trace(tr_out)
343 |
344 |
345 | sac.nzyear = starttime.year
346 | sac.nzjday = starttime.julday
347 | sac.nzhour = starttime.hour
348 | sac.nzmin = starttime.minute
349 | #sac.nzsec = starttime.second
350 | ##sac.nzmsec = int(starttime.microsecond*1.e-3)
351 | #sac.nzmsec = round(starttime.microsecond*1.e-3)
352 | sec = round((starttime.second + starttime.microsecond*1.e-6)*1000)
353 | sac.nzsec = int(sec*0.001)
354 | sac.nzmsec = int(sec - sac.nzsec*1000)
355 | sac.b = 0
356 | #sac.reftime += sac.b
357 | #sac.reftime = starttime
358 |
359 |
360 | sac.write(outfile)
361 |
362 | del sac
363 |
364 |
365 | del tr_out
366 | ibeg = iend + 1
367 | tbeg = tend + dt
368 |
369 |
370 | if ((day_in_seconds - tend) < 0.4*segment_length):
371 | break
372 |
373 |
374 | del tr, hour_files_list
375 | print('%s is done' % date2str(starttime_daily))
376 |
377 | print('Leaving directory ' + day_path[len_topdir:-1])
378 | #print('\n')
379 |
380 | del day_folders_list
381 |
382 | return
383 |
384 |
385 |
386 | def cutdata():
387 |
388 | global len_topdir, sac_suffix
389 |
390 | len_topdir = len(input_path) + 1
391 |
392 | stage_folders_list = os.listdir(input_path)
393 |
394 |
395 | sac_suffix = '.SAC'
396 |
397 | # cut daily sac files into segments
398 | for stage_folder in stage_folders_list:
399 |
400 | stage_path = input_path + '/' + stage_folder + '/'
401 | print('Entering directory ' + stage_path[len_topdir:-1])
402 | #print('\n')
403 |
404 | if (not os.path.exists(stage_path)):
405 | continue
406 |
407 | station_folder_list = os.listdir(stage_path)
408 |
409 | for station_folder in station_folder_list:
410 |
411 | station_path = stage_path + station_folder + '/'
412 | print('Entering directory ' + station_path[len_topdir:-1])
413 | #print('\n')
414 |
415 | if (not os.path.exists(station_path)):
416 | continue
417 |
418 | cutdata_daily(station_path)
419 |
420 | print('Leaving directory ' + station_path[len_topdir:-1])
421 | #print('\n')
422 |
423 | del station_folder_list
424 | print('Leaving directory ' + stage_path[len_topdir:-1])
425 | #print('\n')
426 |
427 | del stage_folders_list
428 |
429 | return
430 |
431 |
432 |
433 | if __name__ == '__main__':
434 |
435 | #print('\n')
436 | print('cutdata: ')
437 | print('This program cuts daily data into segments using the ObsPy (serial version)')
438 | print('Youshan Liu at Institute of Geology and Geophysics, Chinese Academy of Sciences')
439 | print('Welcome to send any bugs and suggestions to ysliu@mail.iggcas.ac.cn')
440 | print('\n')
441 |
442 | starttime = UTCDateTime()
443 |
444 | # absolution path
445 | #current_path = os.getcwd()
446 |
447 | # cutdata daily
448 | cutdata()
449 |
450 | endtime = UTCDateTime()
451 |
452 | elapsed_time = (endtime - starttime)
453 |
454 | print('\n')
455 | print('Start time : %s' % starttime)
456 | print('End time : %s' % endtime)
457 | print('Elapsed time : %f hours' % (elapsed_time / 3600.0))
458 |
459 |
460 |
461 |
--------------------------------------------------------------------------------
/scripts/reftek2sac.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: UTF-8 -*-
3 |
4 | '''
5 | reftek2sac
6 |
7 | This program converts files from REFTEK to SAC format using the ObsPy
8 |
9 | Date: 22/10/2020
10 | Author: Youshan Liu
11 | Affiliation: Institute of Geology and Geophysics, Chinese Academy of Sciences
12 |
13 |
14 | directory structure:
15 | ./top folder/station and stage folder/day folder/Reftek UnitID number/stream/reftek files
16 |
17 | for example:
18 | ./DATA_Raw/NE00_2007_276_2008_005/2007276/9F78/1
19 |
20 |
21 |
22 | Reftek 130 Disk Directory Structure
23 |
24 | Year
25 | | Day of year
26 | | |
27 | v v
28 | __ _
29 | | || |
30 | \2003032
31 | \2003033
32 |
33 | Unit ID number
34 | |
35 | v
36 | __
37 | | |
38 | \90F0
39 |
40 | Datastream
41 | |
42 | v
43 | \0
44 | \1
45 | \2
46 |
47 | '''
48 |
49 |
50 |
51 |
52 | import os
53 | import re
54 | from math import *
55 | from obspy import read
56 | from obspy import UTCDateTime
57 | from obspy.io.sac import SACTrace
58 |
59 |
60 |
61 | ##############################################################
62 | ##############################################################
63 | ##############################################################
64 | # some options to be set
65 |
66 |
67 | # dryrun just for debug
68 | # dryrun = True => just print some directory information not to write sac files
69 | # dryrun = False => do the actual files conversion
70 | dryrun = False
71 |
72 | # directory of the reftek data
73 | input_path = './DATA_Raw'
74 |
75 | # station information file
76 | station_list = './NEsta.lst'
77 |
78 |
79 | # orientation list to be converted
80 | # only Z-orientation
81 | #orientations = ['0']
82 | # only N-orientation
83 | #orientations = ['1']
84 | # only E-orientation
85 | #orientations = ['2']
86 | # three-orientations
87 | orientations = ['0', '1', '2']
88 |
89 | ##############################################################
90 | # preprocess options
91 |
92 | # whether remove mean value or not
93 | is_demean = True
94 |
95 | # whethet remove linear and nonlinear trends or not
96 | is_detrend = True
97 | is_denonlinear = False
98 |
99 | # whether apply bandpass filter or not
100 | is_bandpass = False
101 | is_zerophase = True
102 | flow = 1.0/50.0
103 | fhigh = 5.0
104 |
105 | # whether downsampling seismograms
106 | is_decimate = True
107 | # the downsampling frequency
108 | downsampling_rate = 10.0
109 |
110 | ##############################################################
111 |
112 | # component codes, it consists of band code, instrument code, orientation code
113 | component_codes = ['BHZ', 'BHN', 'BHE']
114 |
115 |
116 | ##############################################################
117 | ##############################################################
118 | ##############################################################
119 | # read station list
120 | def read_station_list(filename):
121 |
122 | class Station:
123 | def __init__(self):
124 | self.stnm = []
125 | self.stla = []
126 | self.stlo = []
127 | self.stel = []
128 | self.netwk = []
129 |
130 |
131 | try:
132 | with open(filename, 'r') as f:
133 | lines = f.readlines()
134 | except:
135 | raise Exception('Cannot open file %s !' % filename)
136 | sta = Station()
137 | netwk, stnm, stla, stlo, stel = None, None, None, None, None
138 | for line in lines[1:]:
139 | try:
140 | line_splited = line.split()
141 | if ([] == line_splited):
142 | continue
143 | netwk, stnm, stla, stlo, stel = line_splited
144 | except:
145 | raise Exception('Format error in %s !' % filename)
146 | sta.stnm.append(stnm)
147 | sta.netwk.append(netwk)
148 | sta.stla.append(float(stla))
149 | sta.stlo.append(float(stlo))
150 | sta.stel.append(float(stel))
151 |
152 | del lines
153 |
154 | return sta
155 |
156 |
157 |
158 | def create_sac_filename(stats):
159 |
160 | starttime = stats.starttime
161 | yyyy = '%4.4d' % starttime.year
162 | ddd = '%3.3d' % starttime.julday
163 | hh = '%2.2d' % starttime.hour
164 | mm = '%2.2d' % starttime.minute
165 | ss = '%2.2d' % starttime.second
166 | fff = '%3.3d' % (0.001*starttime.microsecond)
167 |
168 | sac_filename = yyyy + '.' + ddd + '.' + hh + '.' + \
169 | mm + '.' + ss + '.' + fff + '.' + \
170 | stats.network + '.' + stats.station + '.' + \
171 | stats.channel + sac_suffix
172 |
173 | return sac_filename
174 |
175 |
176 |
177 | def findstr(str_src, str_target):
178 |
179 | '''
180 | findstr(str_src, str_target)
181 | find the index of a substring in a string
182 | str_src -> source string
183 | str_target -> substring
184 | '''
185 |
186 | n_src = len(str_src)
187 | n_target = len(str_target)
188 | i = 0
189 | ipos = []
190 | while str_target in str_src[i:]:
191 | idx = str_src.index(str_target, i, n_src)
192 | ipos.append(idx)
193 | i = (idx + n_target)
194 |
195 | return ipos
196 |
197 |
198 |
199 | def convert_hourly(hour_files_path, day_path):
200 |
201 | hour_files_list = os.listdir(hour_files_path)
202 |
203 | idx = findstr(hour_files_path, '/')
204 |
205 |
206 | ipos = -1
207 | station_name = hour_files_path[idx[-5]+1:idx[-4]]
208 | for j in range(len(sta.stnm)):
209 | res = findstr(station_name, sta.stnm[j])
210 | #res = findstr(hour_files_path[len_topdir:-1], sta.stnm[j])
211 | if ([] != res):
212 | ipos = j
213 | break
214 | if (-1 == ipos):
215 | print("Error: station folder %s does not include the name of this station or this station is missing in the stainfo.lst" % station_name)
216 | return
217 |
218 |
219 | for hour_file in hour_files_list:
220 |
221 | #if ('EE' != hour_file[-4:-2]):
222 | # continue
223 |
224 | # if this file is not a reftek format
225 | is_sacfile = False
226 | starts = [each.start() for each in re.finditer(sac_suffix, hour_file.upper())]
227 | ends = [start+len(sac_suffix) - 1 for start in starts]
228 | span = [(start, end) for start,end in zip(starts, ends)]
229 | is_sacfile = is_sacfile and (len(span) >= 1)
230 |
231 | if (is_sacfile):
232 | continue
233 |
234 |
235 | try:
236 | has_dot_in_filename = hour_file.index('.')
237 | except:
238 | has_dot_in_filename = False
239 | if (has_dot_in_filename):
240 | continue
241 |
242 |
243 | infile = hour_files_path + hour_file
244 | try:
245 | # faster for specific file format
246 | st = read(infile, format='REFTEK130', check_compression=False, component_codes=component_codes)
247 | #st = read(infile, format='REFTEK130', check_compression=False, component_codes=['0', '1', '2'])
248 | #st = read(infile, component_codes=['0', '1', '2'])
249 | #st = read(infile, component_codes=['Z', 'N', 'E'])
250 | # cancel out the sort in obspy
251 | #st.sort(reverse=True)
252 | except:
253 | continue
254 |
255 |
256 | if (len(st) > 3):
257 | st.sort(['starttime'])
258 | if ((st[nstream-1].stats.endtime - st[0].stats.starttime) > 129600):
259 | continue
260 | st.merge(method=1, fill_value=0)
261 | st.sort()
262 |
263 |
264 |
265 | for i in range(len(st)):
266 |
267 | try:
268 | tr = st[i]
269 | # remove round error
270 | tr.stats.delta = round(tr.stats.delta*1e6)*1.e-6
271 | except:
272 | continue
273 |
274 | if (tr.stats.channel[-1] not in orientations):
275 | continue
276 |
277 |
278 |
279 | #starttime = tr.stats.starttime
280 | #endtime = tr.stats.endtime
281 | #min2hour = int((starttime.hour + (starttime.second + starttime.microsecond*1.e-6)/60.0 + 40)/60.0)
282 | #if (0 == min2hour):
283 | # #dtinus = 1e6 / downsampling_rate
284 | # #microsecond = ceil(microsecond / dtinus) * dtinus
285 | # #starttime_first = starttime
286 | # #starttime_first = UTCDateTime(starttime.year, starttime.month, starttime.day, starttime.hour, starttime.minute, starttime.second, microsecond, strict=False)
287 | # sec = round(starttime.second*1e6 + starttime.microsecond)
288 | # #sec = ceil(sec / dtinus) * dtinus
289 | # second = int(sec * 1.e-6)
290 | # microsecond = int(sec - second*1e6)
291 | # starttime_first = UTCDateTime(starttime.year, starttime.month, starttime.day, starttime.hour, starttime.minute, second, microsecond, strict=False)
292 | #else:
293 | # starttime_first = UTCDateTime(starttime.year, starttime.month, starttime.day, starttime.hour + min2hour, 0, 0, 0)
294 | # starttime_first = UTCDateTime(starttime.year, starttime.month, starttime.day, starttime.hour, 0, 0, 0) + 3600
295 | #if ((starttime.minute + (starttime.second + starttime.microsecond*1.e-6)/60.0) > 40.0):
296 | # endtime_last = endtime
297 | #else:
298 | # endtime_last = UTCDateTime(endtime.year, endtime.month, endtime.day, endtime.hour, 0, 0, 0)
299 | #if (starttime_first < endtime_last):
300 | # tr = tr.slice(starttime=starttime_first, endtime=endtime_last, nearest_sample=False)
301 | #else:
302 | # del tr
303 | # continue
304 |
305 |
306 | # some preprocesses
307 | if (is_demean):
308 | tr.detrend(type='demean')
309 | if (is_detrend):
310 | tr.detrend(type='linear')
311 | #if (is_denonlinear):
312 | # #tr.detrend('polynomial', order=3)
313 | # tr.detrend('spline', order=3, dspline=5)
314 |
315 |
316 | # bandpass
317 | if (is_bandpass):
318 | tr.filter('bandpass', freqmin=flow, freqmax=fhigh, corners=3, zerophase=is_zerophase)
319 |
320 |
321 | # downsampling
322 | if (is_decimate):
323 | df = tr.stats.sampling_rate
324 | if (downsampling_rate > df):
325 | print("Error: downsampling sampling rate cannot large than original sampling rate !")
326 | continue
327 | decimate_factor = int(df / downsampling_rate)
328 | if (abs(df - (decimate_factor*downsampling_rate)) > 0.0):
329 | print("Error: decimate factor can only be integer !")
330 | continue
331 | if (decimate_factor > 1):
332 | # Nyquist frequency of downsampling rate
333 | freq_lowpass = 0.5 * downsampling_rate
334 | #freq_lowpass = 0.5 * tr.stats.sampling_rate / decimate_factor
335 | if (not(is_bandpass and (fhigh <= freq_lowpass))):
336 | tr.filter('lowpass', freq=freq_lowpass, corners=3, zerophase=True)
337 | tr.decimate(factor=decimate_factor, strict_length=False, no_filter=True)
338 |
339 |
340 | # get the index of station name in station list
341 | #station_name = tr.stats.station
342 | #res = [sta.stnm.index(x) for x in sta.stnm if x.upper() == station_name.upper()]
343 | #if ([] != res):
344 | # # first find station name in reftek head.
345 | # # if the field "station" in reftek header is NULL, then try extract station name from folder name
346 | # try:
347 | # ipos = res[0]
348 | # except:
349 | # raise Exception('Error: station %s is not in the station list' % station_name)
350 | #else:
351 | # #print("Warning: station field in reftek header is NULL")
352 | # # try to extract station name based on folder name
353 | # ipos = -1
354 | # for j in range(len(sta.stnm)):
355 | # res = findstr(hour_files_path[idx[-5]+1:idx[-4]], sta.stnm[j])
356 | # if ([] != res):
357 | # ipos = j
358 | # break
359 | # if (-1 == ipos):
360 | # print("Error: station %s is not in the station list or field 'station' in reftek header is NULL" % station_name)
361 | # return
362 |
363 |
364 | station = sta.stnm[ipos]
365 | network = sta.netwk[ipos]
366 | tr.stats.network = network
367 | tr.stats.station = station
368 | starttime = tr.stats.starttime
369 |
370 | sac_filename = create_sac_filename(tr.stats)
371 |
372 | outfile = day_path + sac_filename
373 |
374 |
375 | if (dryrun):
376 |
377 | if (os.path.exists(outfile) and os.path.isfile(outfile)):
378 | os.remove(outfile)
379 |
380 | else:
381 |
382 | sac = SACTrace.from_obspy_trace(tr)
383 |
384 |
385 | # write stla, stlo, stel into sac header
386 | sac.stla = sta.stla[ipos]
387 | sac.stlo = sta.stlo[ipos]
388 | sac.stel = sta.stel[ipos]
389 | # write station name
390 | sac.kstnm = station
391 | # write network name
392 | sac.knetwk = network
393 |
394 |
395 | sac.nzyear = starttime.year
396 | sac.nzjday = starttime.julday
397 | sac.nzhour = starttime.hour
398 | sac.nzmin = starttime.minute
399 | #sac.nzsec = starttime.second
400 | ##sac.nzmsec = int(starttime.microsecond*1.e-3)
401 | #sac.nzmsec = round(starttime.microsecond*1.e-3)
402 | sec = round((starttime.second + starttime.microsecond*1.e-6)*1000)
403 | sac.nzsec = int(sec*0.001)
404 | sac.nzmsec = int(sec - sac.nzsec*1000)
405 | sac.b = 0
406 | #sac.reftime += sac.b
407 | ##sac.reftime = starttime
408 |
409 |
410 |
411 | # write sac
412 | sac.write(outfile)
413 | #tr.write(outfile, format='sac')
414 |
415 | del sac
416 |
417 | del tr
418 |
419 | del st
420 | print('%s is done' % hour_file)
421 |
422 | del hour_files_list
423 |
424 | return
425 |
426 |
427 |
428 | def convert_daily(station_stage_path):
429 |
430 | day_folders_list = os.listdir(station_stage_path)
431 |
432 | for day_folder in day_folders_list:
433 |
434 | day_path = station_stage_path + day_folder + '/'
435 | print('Entering directory ' + day_path[len_topdir:-1])
436 | #print('\n')
437 |
438 | if (not os.path.exists(day_path)):
439 | continue
440 |
441 | UnitID_folders_list = os.listdir(day_path)
442 |
443 | for UnitID in UnitID_folders_list:
444 |
445 | UnitID_path = day_path + UnitID + '/'
446 |
447 | if (not os.path.isdir(UnitID_path)):
448 | continue
449 |
450 | print('Entering directory ' + UnitID_path[len_topdir:-1])
451 | #print('\n')
452 |
453 | hour_files_path = UnitID_path + '1/'
454 |
455 | if (not os.path.exists(hour_files_path)):
456 | continue
457 |
458 | print('Entering directory ' + hour_files_path[len_topdir:-1])
459 | #print('\n')
460 |
461 | convert_hourly(hour_files_path, day_path)
462 |
463 | print('Leaving directory ' + hour_files_path[len_topdir:-1])
464 | #print('\n')
465 |
466 | print('Leaving directory ' + UnitID_path[len_topdir:-1])
467 | #print('\n')
468 |
469 | del UnitID_folders_list
470 | print('Leaving directory ' + day_path[len_topdir:-1])
471 | #print('\n')
472 |
473 | del day_folders_list
474 |
475 | return
476 |
477 |
478 |
479 | def reftek2sac():
480 |
481 | global len_topdir, sac_suffix
482 |
483 | len_topdir = len(input_path) + 1
484 |
485 | stage_folders_list = os.listdir(input_path)
486 |
487 |
488 | sac_suffix = '.SAC'
489 |
490 | # convert reftek to sac
491 | for station_stage_folder in stage_folders_list:
492 |
493 | station_stage_path = input_path + '/' + station_stage_folder + '/'
494 | print('Entering directory ' + station_stage_path[len_topdir:-1])
495 | #print('\n')
496 |
497 | if (not os.path.exists(station_stage_path)):
498 | continue
499 |
500 | convert_daily(station_stage_path)
501 |
502 | print('Leaving directory ' + station_stage_path[len_topdir:-1])
503 | #print('\n')
504 |
505 | del stage_folders_list
506 |
507 | return
508 |
509 |
510 |
511 | if __name__ == '__main__':
512 |
513 | #print('\n')
514 | print('reftek2sac: ')
515 | print('This program converts files from reftek to sac format using the ObsPy (serial version)')
516 | print('Youshan Liu at Institute of Geology and Geophysics, Chinese Academy of Sciences')
517 | print('Welcome to send any bugs and suggestions to ysliu@mail.iggcas.ac.cn')
518 | print('\n')
519 |
520 | starttime = UTCDateTime()
521 |
522 | # absolution path
523 | #current_path = os.getcwd()
524 |
525 | # read station information
526 | sta = read_station_list(current_path + '/' + station_list)
527 |
528 | # convert reftek file to sac format
529 | reftek2sac()
530 |
531 | endtime = UTCDateTime()
532 |
533 | elapsed_time = (endtime - starttime)
534 |
535 | print('\n')
536 | print('Start time : %s' % starttime)
537 | print('End time : %s' % endtime)
538 | print('Elapsed time : %f hours' % (elapsed_time / 3600.0))
539 |
540 |
541 |
542 |
--------------------------------------------------------------------------------
/scripts/reftek2sac_p.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: UTF-8 -*-
3 |
4 |
5 | '''
6 | reftek2sac
7 |
8 | This program converts files from REFTEK to SAC format using the ObsPy
9 |
10 | Date: 22/10/2020
11 | Author: Youshan Liu
12 | Affiliation: Institute of Geology and Geophysics, Chinese Academy of Sciences
13 |
14 |
15 | directory structure:
16 | ./top folder/station and stage folder/day folder/Reftek UnitID number/stream/reftek files
17 |
18 | for example:
19 | ./DATA_Raw/NE00_2007_276_2008_005/2007276/9F78/1
20 |
21 |
22 |
23 | Reftek 130 Disk Directory Structure
24 |
25 | Year
26 | | Day of year
27 | | |
28 | v v
29 | __ _
30 | | || |
31 | \2003032
32 | \2003033
33 |
34 | Unit ID number
35 | |
36 | v
37 | __
38 | | |
39 | \90F0
40 |
41 | Datastream
42 | |
43 | v
44 | \0
45 | \1
46 | \2
47 |
48 | '''
49 |
50 |
51 |
52 |
53 | import os
54 | import re
55 | from math import *
56 | from obspy import read
57 | from obspy import UTCDateTime
58 | from obspy.io.sac import SACTrace
59 | from multiprocessing.pool import ThreadPool
60 |
61 |
62 |
63 | ##############################################################
64 | ##############################################################
65 | ##############################################################
66 | # some options to be set
67 |
68 |
69 | # dryrun just for debug
70 | # dryrun = True => just print some directory information not to write sac files
71 | # dryrun = False => do the actual files conversion
72 | dryrun = False
73 |
74 | # directory of the reftek data
75 | input_path = './DATA_1'
76 |
77 | # station information file
78 | station_list = './NEsta.lst'
79 |
80 |
81 | # orientation list to be converted
82 | # only Z-orientation
83 | #orientations = ['0']
84 | # only N-orientation
85 | #orientations = ['1']
86 | # only E-orientation
87 | #orientations = ['2']
88 | # three-orientations
89 | orientations = ['0', '1', '2']
90 |
91 | ##############################################################
92 | # preprocess options
93 |
94 | # whether remove mean value or not
95 | is_demean = True
96 |
97 | # whethet remove linear and nonlinear trends or not
98 | is_detrend = True
99 | is_denonlinear = False
100 |
101 | # whether apply bandpass filter or not
102 | is_bandpass = False
103 | is_zerophase = True
104 | flow = 1.0/50.0
105 | fhigh = 5.0
106 |
107 | # whether downsampling seismograms
108 | is_decimate = True
109 | # the downsampling frequency
110 | downsampling_rate = 10.0
111 |
112 | ##############################################################
113 |
114 | # component codes, it consists of band code, instrument code, orientation code
115 | component_codes = ['BHZ', 'BHN', 'BHE']
116 |
117 |
118 | ##############################################################
119 | ##############################################################
120 | ##############################################################
121 | # read station list
122 | def read_station_list(filename):
123 |
124 | class Station:
125 | def __init__(self):
126 | self.stnm = []
127 | self.stla = []
128 | self.stlo = []
129 | self.stel = []
130 | self.netwk = []
131 |
132 |
133 | try:
134 | with open(filename, 'r') as f:
135 | lines = f.readlines()
136 | except:
137 | raise Exception('Cannot open file %s !' % filename)
138 | sta = Station()
139 | netwk, stnm, stla, stlo, stel = None, None, None, None, None
140 | for line in lines[1:]:
141 | try:
142 | line_splited = line.split()
143 | if ([] == line_splited):
144 | continue
145 | netwk, stnm, stla, stlo, stel = line_splited
146 | except:
147 | raise Exception('Format error in %s !' % filename)
148 | sta.stnm.append(stnm)
149 | sta.netwk.append(netwk)
150 | sta.stla.append(float(stla))
151 | sta.stlo.append(float(stlo))
152 | sta.stel.append(float(stel))
153 |
154 | del lines
155 |
156 | return sta
157 |
158 |
159 |
160 | def create_sac_filename(stats):
161 |
162 | starttime = stats.starttime
163 | yyyy = '%4.4d' % starttime.year
164 | ddd = '%3.3d' % starttime.julday
165 | hh = '%2.2d' % starttime.hour
166 | mm = '%2.2d' % starttime.minute
167 | ss = '%2.2d' % starttime.second
168 | fff = '%3.3d' % (0.001*starttime.microsecond)
169 |
170 | sac_filename = yyyy + '.' + ddd + '.' + hh + '.' + \
171 | mm + '.' + ss + '.' + fff + '.' + \
172 | stats.network + '.' + stats.station + '.' + \
173 | stats.channel + sac_suffix
174 |
175 | return sac_filename
176 |
177 |
178 |
179 | def findstr(str_src, str_target):
180 |
181 | '''
182 | findstr(str_src, str_target)
183 | find the index of a substring in a string
184 | str_src -> source string
185 | str_target -> substring
186 | '''
187 |
188 | n_src = len(str_src)
189 | n_target = len(str_target)
190 | i = 0
191 | ipos = []
192 | while str_target in str_src[i:]:
193 | idx = str_src.index(str_target, i, n_src)
194 | ipos.append(idx)
195 | i = (idx + n_target)
196 |
197 | return ipos
198 |
199 |
200 |
201 | def convert_files(hour_files_path, day_path):
202 |
203 | hour_files_list = os.listdir(hour_files_path)
204 |
205 | idx = findstr(hour_files_path, '/')
206 |
207 |
208 | ipos = -1
209 | station_name = hour_files_path[idx[-5]+1:idx[-4]]
210 | for j in range(len(sta.stnm)):
211 | res = findstr(station_name, sta.stnm[j])
212 | #res = findstr(hour_files_path[len_topdir:-1], sta.stnm[j])
213 | if ([] != res):
214 | ipos = j
215 | break
216 | if (-1 == ipos):
217 | print("Error: station folder %s does not include the name of this station or this station is missing in the stainfo.lst" % station_name)
218 | return
219 |
220 |
221 | for hour_file in hour_files_list:
222 |
223 | #if ('EE' != hour_file[-4:-2]):
224 | # continue
225 |
226 | # if this file is not a reftek format
227 | is_sacfile = False
228 | starts = [each.start() for each in re.finditer(sac_suffix, hour_file.upper())]
229 | ends = [start+len(sac_suffix) - 1 for start in starts]
230 | span = [(start, end) for start,end in zip(starts, ends)]
231 | is_sacfile = is_sacfile and (len(span) >= 1)
232 |
233 | if (is_sacfile):
234 | continue
235 |
236 |
237 | try:
238 | has_dot_in_filename = hour_file.index('.')
239 | except:
240 | has_dot_in_filename = False
241 | if (has_dot_in_filename):
242 | continue
243 |
244 |
245 | infile = hour_files_path + hour_file
246 | try:
247 | # faster for specific file format
248 | st = read(infile, format='REFTEK130', check_compression=False, component_codes=component_codes)
249 | #st = read(infile, format='REFTEK130', check_compression=False, component_codes=['0', '1', '2'])
250 | #st = read(infile, component_codes=['0', '1', '2'])
251 | #st = read(infile, component_codes=['Z', 'N', 'E'])
252 | # cancel out the sort in obspy
253 | #st.sort(reverse=True)
254 | except:
255 | continue
256 |
257 |
258 | if (len(st) > 3):
259 | st.sort(['starttime'])
260 | if ((st[nstream-1].stats.endtime - st[0].stats.starttime) > 129600):
261 | continue
262 | st.merge(method=1, fill_value=0)
263 | st.sort()
264 |
265 |
266 |
267 | for i in range(len(st)):
268 |
269 | try:
270 | tr = st[i]
271 | # remove round error
272 | tr.stats.delta = round(tr.stats.delta*1e6)*1.e-6
273 | except:
274 | continue
275 |
276 | if (tr.stats.channel[-1] not in orientations):
277 | continue
278 |
279 |
280 |
281 | #starttime = tr.stats.starttime
282 | #endtime = tr.stats.endtime
283 | #min2hour = int((starttime.hour + (starttime.second + starttime.microsecond*1.e-6)/60.0 + 40)/60.0)
284 | #if (0 == min2hour):
285 | # #dtinus = 1e6 / downsampling_rate
286 | # #microsecond = ceil(microsecond / dtinus) * dtinus
287 | # #starttime_first = starttime
288 | # #starttime_first = UTCDateTime(starttime.year, starttime.month, starttime.day, starttime.hour, starttime.minute, starttime.second, microsecond, strict=False)
289 | # sec = round(starttime.second*1e6 + starttime.microsecond)
290 | # #sec = ceil(sec / dtinus) * dtinus
291 | # second = int(sec * 1.e-6)
292 | # microsecond = int(sec - second*1e6)
293 | # starttime_first = UTCDateTime(starttime.year, starttime.month, starttime.day, starttime.hour, starttime.minute, second, microsecond, strict=False)
294 | #else:
295 | # starttime_first = UTCDateTime(starttime.year, starttime.month, starttime.day, starttime.hour + min2hour, 0, 0, 0)
296 | # starttime_first = UTCDateTime(starttime.year, starttime.month, starttime.day, starttime.hour, 0, 0, 0) + 3600
297 | #if ((starttime.minute + (starttime.second + starttime.microsecond*1.e-6)/60.0) > 40.0):
298 | # endtime_last = endtime
299 | #else:
300 | # endtime_last = UTCDateTime(endtime.year, endtime.month, endtime.day, endtime.hour, 0, 0, 0)
301 | #if (starttime_first < endtime_last):
302 | # tr = tr.slice(starttime=starttime_first, endtime=endtime_last, nearest_sample=False)
303 | #else:
304 | # del tr
305 | # continue
306 |
307 |
308 |
309 |
310 | # some preprocesses
311 | if (is_demean):
312 | tr.detrend(type='demean')
313 | if (is_detrend):
314 | tr.detrend(type='linear')
315 | #if (is_denonlinear):
316 | # #tr.detrend('polynomial', order=3)
317 | # tr.detrend('spline', order=3, dspline=5)
318 |
319 |
320 | # bandpass
321 | if (is_bandpass):
322 | tr.filter('bandpass', freqmin=flow, freqmax=fhigh, corners=3, zerophase=is_zerophase)
323 |
324 |
325 | # downsampling
326 | if (is_decimate):
327 | df = tr.stats.sampling_rate
328 | if (downsampling_rate > df):
329 | print("Error: downsampling sampling rate cannot large than original sampling rate !")
330 | continue
331 | decimate_factor = int(df / downsampling_rate)
332 | if (abs(df - (decimate_factor*downsampling_rate)) > 0.0):
333 | print("Error: decimate factor can only be integer !")
334 | continue
335 | if (decimate_factor > 1):
336 | # N*-iyquist frequency of downsampling rate
337 | freq_lowpass = 0.5 * downsampling_rate
338 | #freq_lowpass = 0.5 * tr.stats.sampling_rate / decimate_factor
339 | if (not(is_bandpass and (fhigh <= freq_lowpass))):
340 | tr.filter('lowpass', freq=freq_lowpass, corners=3, zerophase=True)
341 | tr.decimate(factor=decimate_factor, strict_length=False, no_filter=True)
342 |
343 |
344 | # get the index of station name in station list
345 | #station_name = tr.stats.station
346 | #res = [sta.stnm.index(x) for x in sta.stnm if x.upper() == station_name.upper()]
347 | #if ([] != res):
348 | # # first find station name in reftek head.
349 | # # if the field "station" in reftek header is NULL, then try extract station name from folder name
350 | # try:
351 | # ipos = res[0]
352 | # except:
353 | # raise Exception('Error: station %s is not in the station list' % station_name)
354 | #else:
355 | # #print("Warning: station field in reftek header is NULL")
356 | # # try to extract station name based on folder name
357 | # ipos = -1
358 | # for j in range(len(sta.stnm)):
359 | # res = findstr(hour_files_path[idx[-5]+1:idx[-4]], sta.stnm[j])
360 | # if ([] != res):
361 | # ipos = j
362 | # break
363 | # if (-1 == ipos):
364 | # print("Error: station %s is not in the station list or field 'station' in reftek header is NULL" % station_name)
365 | # return
366 |
367 |
368 | station = sta.stnm[ipos]
369 | network = sta.netwk[ipos]
370 | tr.stats.network = network
371 | tr.stats.station = station
372 | starttime = tr.stats.starttime
373 |
374 | sac_filename = create_sac_filename(tr.stats)
375 |
376 | outfile = day_path + sac_filename
377 |
378 |
379 | if (dryrun):
380 |
381 | if (os.path.exists(outfile) and os.path.isfile(outfile)):
382 | os.remove(outfile)
383 |
384 | else:
385 |
386 | sac = SACTrace.from_obspy_trace(tr)
387 |
388 |
389 | # write stla, stlo, stel into sac header
390 | sac.stla = sta.stla[ipos]
391 | sac.stlo = sta.stlo[ipos]
392 | sac.stel = sta.stel[ipos]
393 | # write station name
394 | sac.kstnm = station
395 | # write network name
396 | sac.knetwk = network
397 |
398 |
399 | sac.nzyear = starttime.year
400 | sac.nzjday = starttime.julday
401 | sac.nzhour = starttime.hour
402 | sac.nzmin = starttime.minute
403 | #sac.nzsec = starttime.second
404 | ##sac.nzmsec = int(starttime.microsecond*1.e-3)
405 | #sac.nzmsec = round(starttime.microsecond*1.e-3)
406 | sec = round((starttime.second + starttime.microsecond*1.e-6)*1000)
407 | sac.nzsec = int(sec*0.001)
408 | sac.nzmsec = int(sec - sac.nzsec*1000)
409 | sac.b = 0
410 | #sac.reftime += sac.b
411 | ##sac.reftime = starttime
412 |
413 |
414 |
415 | # write sac
416 | sac.write(outfile)
417 | #tr.write(outfile, format='sac')
418 |
419 | del sac
420 |
421 | del tr
422 |
423 | del st
424 | print('%s is done' % hour_file)
425 |
426 | del hour_files_list
427 |
428 | return
429 |
430 |
431 |
432 | def convert_daily(day_folder):
433 |
434 | day_path = station_stage_path + day_folder + '/'
435 | print('Entering directory ' + day_path[len_topdir:-1])
436 | #print('\n')
437 |
438 | if (not os.path.isdir(day_path)):
439 | return
440 |
441 | UnitID_folders_list = os.listdir(day_path)
442 |
443 | for UnitID in UnitID_folders_list:
444 |
445 | UnitID_path = day_path + UnitID + '/'
446 |
447 | if (not os.path.isdir(UnitID_path)):
448 | continue
449 |
450 | print('Entering directory ' + UnitID_path[len_topdir:-1])
451 | #print('\n')
452 |
453 | hour_files_path = UnitID_path + '1/'
454 |
455 | if (not os.path.exists(hour_files_path)):
456 | continue
457 |
458 | print('Entering directory ' + hour_files_path[len_topdir:-1])
459 | #print('\n')
460 |
461 | convert_files(hour_files_path, day_path)
462 |
463 | print('Leaving directory ' + hour_files_path[len_topdir:-1])
464 | #print('\n')
465 |
466 | print('Leaving directory ' + UnitID_path[len_topdir:-1])
467 | #print('\n')
468 |
469 | del UnitID_folders_list
470 | print('Leaving directory ' + day_path[len_topdir:-1])
471 | #print('\n')
472 |
473 | return
474 |
475 |
476 |
477 | def reftek2sac():
478 |
479 | global len_topdir, station_stage_path, sac_suffix
480 |
481 | len_topdir = len(input_path) + 1
482 |
483 | stage_folders_list = os.listdir(input_path)
484 |
485 |
486 | sac_suffix = '.SAC'
487 |
488 | # convert reftek to sac
489 | for station_stage_folder in stage_folders_list:
490 |
491 | station_stage_path = input_path + '/' + station_stage_folder + '/'
492 | print('Entering directory ' + station_stage_path[len_topdir:-1])
493 | #print('\n')
494 |
495 | if (not os.path.isdir(station_stage_path)):
496 | continue
497 |
498 | day_folders_list = os.listdir(station_stage_path)
499 |
500 | pool = ThreadPool()
501 | pool.map(convert_daily, day_folders_list)
502 | pool.close()
503 | pool.join()
504 |
505 | del day_folders_list
506 | print('Leaving directory ' + station_stage_path[len_topdir:-1])
507 | #print('\n')
508 |
509 | del stage_folders_list
510 |
511 | return
512 |
513 |
514 |
515 | if __name__ == '__main__':
516 |
517 | #print('\n')
518 | print('reftek2sac: ')
519 | print('This program converts files from reftek to sac format using the ObsPy (parallel version)')
520 | print('Youshan Liu at Institute of Geology and Geophysics, Chinese Academy of Sciences')
521 | print('Welcome to send any bugs and suggestions to ysliu@mail.iggcas.ac.cn')
522 | print('\n')
523 |
524 | starttime = UTCDateTime()
525 |
526 | # absolution path
527 | #current_path = os.getcwd()
528 |
529 | # read station information
530 | sta = read_station_list(current_path + '/' + station_list)
531 |
532 | # convert reftek file to sac format
533 | reftek2sac()
534 |
535 | endtime = UTCDateTime()
536 |
537 | elapsed_time = (endtime - starttime)
538 |
539 | print('\n')
540 | print('Start time : %s' % starttime)
541 | print('End time : %s' % endtime)
542 | print('Elapsed time : %f hours' % (elapsed_time / 3600.0))
543 |
544 |
545 |
546 |
--------------------------------------------------------------------------------