Presentation on theme: "MATLAB SAC. MATLAB SAC Data Format and Header Each signal or seismogram is stored in a separate binary or alphanumeric data file. Each data file contains."— Presentation transcript:
3Data Format and HeaderEach signal or seismogram is stored in a separate binary or alphanumeric data file.Each data file contains a header that describes the contents of that file.
4TimeThe SAC header contains a reference or zero time, stored as six integers (NZYEAR, NZJDAY, NZHOUR, NZMIN, NZSEC, NZMSEC), but normally printed in an equivalent alphanumeric format (KZDATE and KZTIME).%sacSAC> r GRAT.EHZ.NMSAC> lh #list headerFILE: GRAT.EHZ.NM – 1 #this is a partial headerNPTS =B = e+00E = e+03IFTYPE = TIME SERIES FILEDELTA = e-02KZDATE = APR 06 (097), 2008KZTIME = 02:59:59.320
5Event and Station Info SAC header can store station and event info FILE: WMQ.BHZ.D :KSTNM = WMQSTLA = e+01STLO = e+01STEL = e+02 (m)EVLA = e+00EVLO = e+01EVDP = e+01
6Once the event and station information are store, the program automatically calculates and stores distance, azimuth, backazimuth, and great circle arc lengthDIST = e+03 (km)AZ = e+02 (degrees)BAZ = e+02 (degrees)GCARC = e+01 (degrees)
8Matlab function: sac.mfunction [head1, head2, head3, data]=sac(filename)% Read one single SAC format file%head1 (float matrix), head2 (int matrix), and head3 (char matrix).% head3 here is integer matrix, to show it under ASCII, just char(head3).fid=fopen(filename, 'rb','b');status=fseek(fid,0,'bof');head1=fread(fid, [5, 14], 'float32');head2=fread(fid, [5, 8], 'int32');head3=fread(fid, [24, 8], 'char');head1=head1'; head2=head2'; head3=head3';data=fread(fid, npts, 'float32');
9Matlab function: loadsac.m function [data,npts,delta,b,dist,az,baz,gcarc] = … loadsac(sacfilename) [head1, head2, head3, data]= … sac(sacfilename); delta = head1(1); npts=head2(2,5); b = head1(2,1); dist= head1(11,1); az = head1(11,2); baz = head1(11,3); gcarc=head1(11,4);As currently written, you modifythe output of loadsac to get the header values you are interested in …. Needs to be generalized, and other similar sac readers exist
10Coding and Flow Charts Longer codes may require a roadmap (much like your research projects!)Today’s lecture will focus on understanding Chuck’s matlab script for polarization analysis using 3 component recordings of body and/or surface waves.html
11GOAL: solve for polarization using 3 component seismic data Starting data: 3 component single station SAC formatted dataResult: Identify the azimuth(s) of the primary wave(s) recorded in the dataHow to we get from A to B?
12Principal Component Analysis Principal component analysis (PCA) is a vector space transform often used to reduce multidimensional data sets to lower dimensions for analysis.
13PCA involves the calculation of the eigenvalue decomposition of a data covariance matrix or singular value decomposition of a data matrix, usually after mean centering the data for each attribute.Its operation can be thought of as revealing the internal structure of the data in a way which best explains the variance in the data.
14What we are looking for: New set of axes (basis) that maximizes the correlation of HT(Z) with R, and minimizes the correlations between both HT(Z) and R with T.We are not using the full power of PCA, since we already have some model for the result of the analysis (and have therefore preprocessed the data by taking the Hilbert transform of the z component).
15What is the idea?Seismic waves are polarizedP wave longitudinal (V and R)S wave transverse with SH and SV polarizations (T, V and R)Rayleigh waves (V and R)Love waves (T).
16GOAL: Solve for polarization load SAC dataremove meanplot waveformsfilter waveforms to highlight waves of interestplot filtered waveformsData Preparationprincipal component analysis using 3-component datanote, this technique requires zero-mean dataMain Codeplot azimuths of eigenvectorsplot azimuths exceeding 50% of maximum valueResults
17Step 1: Data Preparation Load SAC data3 files (Z,E,N)…. suggests using a subroutineProvide station nameRemove the meanPlot waveforms vs timeFilter waveformsDesign a filter; allow flexible input of corner infoWork on 3 files…suggests a subroutinePlot filtered waveforms
18Create function ‘polarize’ function polarize(station,twin,hilb,flp,fhi)% Program to read in 3 component waveform data% Create the covariance matrix for a moving time window% Find the principal components and infer polarization% Written by CL Langston on somedate% input:% station = station name for sacfile prefix% twin = window size in secs% hilb=1 to preform hilbert transform, 0 to not% flp = low frequency corner frequency of a 2nd order butterworth% filter used to filter the data, if 0, then no filtering% fhi = hi frequency corner frequency of the filter
19Loading SAC data Many matlab scripts exist to read in sac data. Chuck provides one .m file called readsac.m onlineCurrently this is sensitive to byte order format and requires that you provide the npts and delta of the input sac data…It is not as flexible as it could beAmplitude data is a row vectorI have one loadsac.m that uses a subroutine ‘sac’not sensitive to byte orderreturns the data, npts, delta, and begin point of the SAC filedata is a column vectormay be stolen from /home/hdeshon/Bolivia/matlab
20%use input variable station to construct the filenames ename=strcat(station,'.BHE.SAC'); nname=strcat(station,'.BHN.SAC'); zname=strcat(station,'.BHZ.SAC'); [e,npts1,delt1,b] = loadsac(ename); [n,npts2,delt2,b] = loadsac(nname); [z,npts3,delt3,b] = loadsac(zname);
21if npts1~=npts2 && npts1~=npts3 %requires data be same length exit; elsenpts=npts1;delt=delt1;ttot=(npts-1)*delt; %total time in secsfor i=1:nptst(1,i)=i*delt; %create row vector of times rather than pointsendHow would we vectorized this?t=linspace(1,npts,npts);t=t*delt;
22Removing the data meanWe need to remove the mean of the data for principal component analysis (PCA).We also need to transpose the column vector data into row vectors.e=dmean(e’); % remove the mean from eachn=dmean(n’); % and transpose the dataz=dmean(z’);
23subroutine: dmean function [a]=dmean(b) % [a]=dmean(b) % Remove the mean from a row vectorm=mean(b);a=b-m;return;
24For this example, the data is actually a synthetically derived set of surface waves using a function Chuck wrote called testchirps. Real data would not look this clean.
25Rayleigh R and Z related by Hilbert X-form 90° phase shift, blue trace is Hilbert Transformed to green trace,then overlays red trace
26Hilbert Transformif hilb ==1; % hilbert transform the vertical componentzh=hilbert(z); % to make Rayleigh wave in phase on vert and horzz=-imag(zh); % if presentelse;end;
29Plot the data% plot the raw data f1=figure('name','DATA SEISMOGRAMS'); subplot(3,1,1); plot(t,e); xlabel('time sec'); ylabel(strcat('EW Comp at ',station)); subplot(3,1,2); plot(t,n); ylabel(strcat('NS Comp at ',station)); subplot(3,1,3); plot(t,z); ylabel(strcat('Z comp at ',station));Love WaveRayleigh WaveRayleigh Wave
30Filtering Filtering is a two part project in Matlab Design the filterApply the filterThere is a filter design GUI you can use to design the perfect filter called fdatoolOr you can design filters using pre-built filter types (Butterworth, Bessel, etc.)
31function [d]=bandpass(c,flp,fhi,npts,delt) % bandpass a time series with a 2nd order butterworth filter% c = input time series% flp = lowpass corner frequency of filter% fhi = highpass corner frequency% npts = samples in data% delt = sampling interval of datan=2; % 2nd order butterworth filterfnq=1/(2*delt); % Nyquist frequencyWn=[flp/fnq fhi/fnq]; % non-dimensionalize the corner frequencies[b,a]=butter(n,Wn); % butterworth bandpass non-dimensional frequencyd=filtfilt(b,a,c); % apply the filter: use zero phase filter (p=2)return;
32Filter & plot the filtered data % filter the data e1=bandpass(e,flp,fhi,npts,delt); n1=bandpass(n,flp,fhi,npts,delt); z1=bandpass(z,flp,fhi,npts,delt); e=e1; n=n1; z=z1; % plot the filtered data f2=figure('name','FILTERED SEISMOGRAMS'); subplot(3,1,1); plot(t,e1); …… removed for clarity
33GOAL: Solve for polarization Recognize that incoming seismic phases should represent the principal components, or the strongest signal, on the 3 component dataThe principal components, in turn, are equal to the eigenvectors of the covariance matrix of the 3 component matrix. This can be derived using PCA techniquesEigenvectors/values represent a spatial transformation which maximizes covariance between the 3 components, and they contain information on the azimuth from which the primary signal is derivedSince multiple phases may be present, we would prefer to look at short time windows of the 3 component data, or in other words, perform PCA on a running window through the continuous waveformsMain Codeplot azimuths of eigenvectorsplot azimuths exceeding 50% of maximum valueResults
34Step 2: Main Code Create a running window Create a matrix of the 3 component data in the windowCalculate the correlation matrixFind the eigenvectors and eigenvaluesReorder the eigenvectors/eigenvaluesCalculate the azimuth for each eigenvalue
35Moving window using loops % Moving window loopnpts1=fix(ttot/delt) + 1; % total number of samples to analyzenwin=fix(twin/delt) + 1; % number of samples in a time windownpshift=fix(twin/(2*delt))+1; % number of samples to shift overkfin=fix((npts1-nwin)/(npshift+1))+1; % number of time windows consideredmxde1=0.;mxde2=0.;mxde3=0.;npts1nwinnpshift
36for k=1:kfin;nwinst=(k-1)*(npshift-1)+1; % start of time windownwinfn=nwinst+nwin-1; % end of time window…….. missing code to be supplied latert2(k)=delt*(nwinst-1); % assign time for this window to the window startend;k=1k=3…k=kfink=2
39Missing code from inside our loop a=csigm(e,n,z,nwinst,nwinfn); % signal matrix c=a'*a; % covariance matrix [v1,d1]=eig(c); % eigenvalue/eigenvectors [v,d]=order(v1,d1); % put eigenvalues & eigenvectors in ascending order % azimuth for each of the 3 eigenvalues ang1(k)=atan2(v(1,1),v(2,1)) * 180/pi; ang2(k)=atan2(v(1,2),v(2,2)) * 180/pi; ang3(k)=atan2(v(1,3),v(2,3)) * 180/pi; % incidence angle of the 3 eigenvalues vang1(k)=acos(abs(v(3,1)))* 180/pi; %angle from the vertical vang2(k)=acos(abs(v(3,2)))* 180/pi; vang3(k)=acos(abs(v(3,3)))* 180/pi;
40Still in loop de1(k)=d(1); de2(k)=d(2); de3(k)=d(3); mxde1=max(mxde1,de1(k)); % find the maximum valuesmxde2=max(mxde2,de2(k));mxde3=max(mxde3,de3(k));
41f3=figure('name','Eigenvalues and Inferred Azimuth'); Outside of Loop againf3=figure('name','Eigenvalues and Inferred Azimuth');subplot(3,1,1); plot(t2,de1,'-or',t2,de2,'-dg',t2,de3,'-+b');xlabel('time sec');ylabel('eigenvalues');subplot(3,1,2); plot(t2,ang1,'-or',t2,ang2,'-dg',t2,ang3,'-+b');ylabel('Azimuth ');subplot(3,1,3); plot(t2,vang1,'-or',t2,vang2,'-dg',t2,vang3,'-+b');ylabel('incidence angle ');
46Vectorization of polarization code 2 Bonus Points:Vectorization of polarization codeIf we take a short time period we can think of each component as a vector of n terms.If we take the dot product of each vector with itself and with the other two components we can find the “angle” between them.
47We can also make these dot products by making a 3xn array using each seismogram as a row. Multiplying this array with its transpose results in a 3x3 matrix with the various dot products in the elements of the matrix.
48Now find the eigenvectors and eigenvalues of this matrix. From the eigenvectors we can make a rotation matrix that will rotate our matrix to a diagonal matrix.The off diagonal elements are now all zero and from the geometric interpretation of the dot product this means that the two vectors used to make that dot product are perpendicular.
49So we can rotate the original horizontal components into a new set of seismograms rotated to the principal directions defined by the eigenvectors.The dot products of the off diagonal terms will now be zero, indicating the vectors are perpendicular.