├── 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 | ![Lanuguage](https://img.shields.io/badge/-Fortran-734f96?logo=fortran) 2 | ![Python](https://img.shields.io/badge/-Python3-3776AB?style=flat&logo=python&logoColor=white) 3 | ![Version](https://img.shields.io/static/v1?label=version&message=6.6&color=blue) 4 | ![Downloads](https://img.shields.io/github/downloads/YoushanLiu/ANCC/total) 5 | ![Commits](https://img.shields.io/github/commit-activity/m/YoushanLiu/ANCC) 6 | ![Size](https://img.shields.io/github/languages/code-size/YoushanLiu/ANCC) 7 | ![RepoSize](https://img.shields.io/github/repo-size/YoushanLiu/ANCC) 8 | ![License](https://img.shields.io/github/license/YoushanLiu/ANCC) 9 | ![Stars](https://img.shields.io/github/stars/YoushanLiu/ANCC) 10 | ![Forks](https://img.shields.io/github/forks/YoushanLiu/ANCC) 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 | --------------------------------------------------------------------------------