Beispiel #1
0
def Amp_pick_sfile(sfile, datapath, respdir, chans=['Z'], var_wintype=True, \
                   winlen=0.9, pre_pick=0.2, pre_filt=True, lowcut=1.0,\
                   highcut=20.0, corners=4):
    """
    Function to read information from a SEISAN s-file, load the data and the
    picks, cut the data for the channels given around the S-window, simulate
    a Wood Anderson seismometer, then pick the maximum peak-to-trough
    amplitude.

    Output will be put into a mag_calc.out file which will be in full S-file
    format and can be copied to a REA database.

    :type sfile: String
    :type datapath: String
    :param datapath: Path to the waveform files - usually the path to the WAV directory
    :type respdir: String
    :param respdir: Path to the response information directory
    :type chans: List of strings
    :param chans: List of the channels to pick on, defaults to ['Z'] - should
                just be the orientations, e.g. Z,1,2,N,E
    :type var_wintype: Bool
    :param var_wintype: If True, the winlen will be
                    multiplied by the P-S time if both P and S picks are
                    available, otherwise it will be multiplied by the hypocentral
                    distance*0.34 - dervided using a p-s ratio of 1.68 and
                    S-velocity of 1.5km/s to give a large window, defaults to True
    :type winlen: Float
    :param winlen: Length of window, see above parameter, if var_wintype is False
                    Then this will be in seconds, otherwise it is the multiplier
                    to the p-s time, defaults to 0.5
    :type pre_pick: Float
    :param pre_pick: Time before the s-pick to start the cut window, defaults
                    to 0.2
    :type pre_filt: Bool
    :param pre_filt: To apply a pre-filter or not, defaults to True
    :type lowcut: Float
    :param lowcut: Lowcut in Hz for the pre-filter, defaults to 1.0
    :type highcut: Float
    :param highcut: Highcut in Hz for the pre-filter, defaults to 20.0
    :type corners: Int
    :param corners: Number of corners to use in the pre-filter
    """
    # Hardwire a p-s multiplier of hypocentral distance based on p-s ratio of
    # 1.68 and an S-velocity 0f 1.5km/s, deliberately chosen to be quite slow
    ps_multiplier=0.34
    from eqcorrscan.utils import Sfile_util
    from obspy import read
    from scipy.signal import iirfilter
    from obspy.signal.invsim import paz2AmpValueOfFreqResp
    import warnings
    # First we need to work out what stations have what picks
    picks=Sfile_util.readpicks(sfile)
    # Convert these picks into a lists
    stations=[] # List of stations
    channels=[] # List of channels
    picktimes=[] # List of pick times
    picktypes=[] # List of pick types
    distances=[] # List of hypocentral distances
    picks_out=[]
    for pick in picks:
        if pick.phase in ['P','S']:
            picks_out.append(pick) # Need to be able to remove this if there
                                   # isn't data for a station!
            stations.append(pick.station)
            channels.append(pick.channel)
            picktimes.append(pick.time)
            picktypes.append(pick.phase)
            distances.append(pick.distance)
    # Read in waveforms
    stream=read(datapath+'/'+Sfile_util.readwavename(sfile)[0])
    if len(Sfile_util.readwavename(sfile)) > 1:
        for wavfile in Sfile_util.readwavename(sfile):
            stream+=read(datapath+'/'+wavfile)
    stream.merge() # merge the data, just in case!
    # For each station cut the window
    uniq_stas=list(set(stations))
    for sta in uniq_stas:
        for chan in chans:
            print 'Working on '+sta+' '+chan
            tr=stream.select(station=sta, channel='*'+chan)
            if not tr:
                # Remove picks from file
                # picks_out=[picks_out[i] for i in xrange(len(picks))\
                           # if picks_out[i].station+picks_out[i].channel != \
                           # sta+chan]
            	warnings.warn('There is no station and channel match in the wavefile!')
                break
            else:
                tr=tr[0]
            # Apply the pre-filter
            if pre_filt:
                try:
                    tr.detrend('simple')
                except:
                    dummy=tr.split()
                    dummy.detrend('simple')
                    tr=dummy.merge()[0]
                tr.filter('bandpass',freqmin=lowcut, freqmax=highcut,\
                             corners=corners)
            sta_picks=[i for i in xrange(len(stations)) \
                           if stations[i]==sta]
            hypo_dist=picks[sta_picks[0]].distance
            CAZ=picks[sta_picks[0]].CAZ
            if var_wintype:
                if 'S' in [picktypes[i] for i in sta_picks] and\
                   'P' in [picktypes[i] for i in sta_picks]:
                    # If there is an S-pick we can use this :D
                    S_pick=[picktimes[i] for i in sta_picks \
                            if picktypes[i]=='S']
                    S_pick=min(S_pick)
                    P_pick=[picktimes[i] for i in sta_picks \
                            if picktypes[i]=='P']
                    P_pick=min(P_pick)
                    try:
                    	tr.trim(starttime=S_pick-pre_pick, \
                               endtime=S_pick+(S_pick-P_pick)*winlen)
                    except:
                    	break
                elif 'S' in [picktypes[i] for i in sta_picks]:
                    S_pick=[picktimes[i] for i in sta_picks \
                            if picktypes[i]=='S']
                    S_pick=min(S_pick)
                    P_modelled=S_pick-hypo_dist*ps_multiplier
                    try:
                    	tr.trim(starttime=S_pick-pre_pick,\
                            endtime=S_pick+(S_pick-P_modelled)*winlen)
                    except:
                    	break
                else:
                    # In this case we only have a P pick
                    P_pick=[picktimes[i] for i in sta_picks \
                            if picktypes[i]=='P']
                    P_pick=min(P_pick)
                    S_modelled=P_pick+hypo_dist*ps_multiplier
                    try:
                    	tr.trim(starttime=S_modelled-pre_pick,\
                        	    endtime=S_modelled+(S_modelled-P_pick)*winlen)
                    except:
                    	break
                # Work out the window length based on p-s time or distance
            elif 'S' in [picktypes[i] for i in sta_picks]:
                # If the window is fixed we still need to find the start time,
                # which can be based either on the S-pick (this elif), or
                # on the hypocentral distance and the P-pick

                # Take the minimum S-pick time if more than one S-pick is available
                S_pick=[picktimes[i] for i in sta_picks \
                           if picktypes[i]=='S']
                S_pick=min(S_pick)
                try:
                	tr.trim(starttime=S_pick-pre_pick, endtime=S_pick+winlen)
                except:
                	break
            else:
                # In this case, there is no S-pick and the window length is fixed
                # We need to calculate an expected S_pick based on the hypocentral
                # distance, this will be quite hand-wavey as we are not using
                # any kind of velocity model.
                P_pick=[picktimes[i] for i in sta_picks \
                           if picktypes[i]=='P']
                P_pick=min(P_pick)
                hypo_dist=[distances[i] for i in sta_picks\
                           if picktypes[i]=='P'][0]
                S_modelled=P_pick+hypo_dist*ps_multiplier
                try:
                	tr.trim(starttime=S_modelled-pre_pick,\
                    	       endtime=S_modelled+winlen)
                except:
        	       break
            # Find the response information
            resp_info=_find_resp(tr.stats.station, tr.stats.channel,\
                           tr.stats.network, tr.stats.starttime, tr.stats.delta,\
                                 respdir)
            PAZ=[]
            seedresp=[]
            if resp_info and 'gain' in resp_info:
                PAZ=resp_info
            elif resp_info:
                seedresp=resp_info
            # Simulate a Wood Anderson Seismograph
            if PAZ and len(tr.data) > 10: # Set ten data points to be the minimum to pass
                tr=_sim_WA(tr, PAZ, None, 10)
            elif seedresp and len(tr.data) > 10:
                tr=_sim_WA(tr, None, seedresp, 10)
            elif len(tr.data) > 10:
                warnings.warn('No PAZ for '+tr.stats.station+' '+\
                                 tr.stats.channel+' at time: '+\
                                 str(tr.stats.starttime))
                continue
            if len(tr.data) <= 10:
                # Should remove the P and S picks if len(tr.data)==0
                warnings.warn('No data found for: '+tr.stats.station)
                # print 'No data in miniseed file for '+tr.stats.station+\
                              # ' removing picks'
                # picks_out=[picks_out[i] for i in xrange(len(picks_out))\
                           # if i not in sta_picks]
            	break
            # Get the amplitude
            amplitude, period, delay= _max_p2t(tr.data, tr.stats.delta)
            if amplitude==0.0:
                break
            print 'Amplitude picked: '+str(amplitude)
            # Note, amplitude should be in meters at the moment!
            # Remove the pre-filter response
            if pre_filt:
                # Generate poles and zeros for the filter we used earlier - this
                # is how the filter is designed in the convenience methods of
                # filtering in obspy.
                z, p, k=iirfilter(corners, [lowcut/(0.5*tr.stats.sampling_rate),\
                                            highcut/(0.5*tr.stats.sampling_rate)],\
                                  btype='band', ftype='butter', output='zpk')
                filt_paz={'poles': list(p),
                          'zeros': list(z),
                          'gain': k,
                          'sensitivity':  1.0}
                amplitude /= (paz2AmpValueOfFreqResp(filt_paz, 1/period) * \
                              filt_paz['sensitivity'])
            # Convert amplitude to mm
            if PAZ: # Divide by Gain to get to nm (returns pm? 10^-12)
                # amplitude *=PAZ['gain']
                amplitude /= 1000
            if seedresp: # Seedresp method returns mm
                amplitude *= 1000000
            # Write out the half amplitude, approximately the peak amplitude as
            # used directly in magnitude calculations
            # Page 343 of Seisan manual:
            #   Amplitude (Zero-Peak) in units of nm, nm/s, nm/s^2 or counts
            amplitude *= 0.5
            # Generate a PICK type object for this pick
            picks_out.append(Sfile_util.PICK(station=tr.stats.station,
                                         channel=tr.stats.channel,
                                         impulsivity=' ',
                                         phase='IAML',
                                         weight='', polarity=' ',
                                         time=tr.stats.starttime+delay,
                                         coda=999, amplitude=amplitude,
                                         peri=period, azimuth=float('NaN'),
                                         velocity=float('NaN'), AIN=999, SNR='',
                                         azimuthres=999, timeres=float('NaN'),
                                         finalweight=999, distance=hypo_dist,
                                         CAZ=CAZ))
    # Copy the header from the sfile to a new local S-file
    fin=open(sfile,'r')
    fout=open('mag_calc.out','w')
    for line in fin:
        if not line[79]=='7':
            fout.write(line)
        else:
            fout.write(line)
            break
    fin.close()
    fout.close()
    # Write picks out to new s-file
    for pick in picks_out:
        print pick
    Sfile_util.populateSfile('mag_calc.out',picks_out)
    return picks
Beispiel #2
0
def lag_calc(detections, detect_data, templates, shift_len=0.2, min_cc=0.4):
    """
    Overseer function to take a list of detection objects, cut the data for
    them to lengths of the same length of the template + shift_len on
    either side. This will then write out SEISAN s-file for the detections
    with pick times based on the lag-times found at the maximum correlation,
    providing that correlation is above the min_cc.

    :type detections: List of DETECTION
    :param detections: List of DETECTION objects
    :type detect_data: obspy.Stream
    :param detect_data: All the data needed to cut from - can be a gappy Stream
    :type templates: List of tuple of String, obspy.Stream
    :param templates: List of the templates used as tuples of template name, template
    :type shift_len: float
    :param shift_len: Shift length allowed for the pick in seconds, will be
                    plus/minus this amount - default=0.2
    :type min_cc: float
    :param min_cc: Minimum cross-correlation value to be considered a pick,
                    default=0.4
    """
    from eqcorrscan.utils import Sfile_util
    from obspy import Stream
    # First work out the delays for each template
    delays = []  # List of tuples
    for template in templates:
        temp_delays = []
        for tr in tempate[1]:
            temp_delays.append((tr.stats.station, tr.stats.channel,\
                    tr.stats.starttime-template.sort['starttime'][0].stats.starttime))
        delays.append((template[0], temp_delays))
    detect_streams = []
    for detection in detections:
        detect_stream = []
        for tr in detect_data:
            tr_copy = tr.copy()
            template = [
                t for t in templates if t[0] == detection.template_name
            ][0]
            template = template.select(station=tr.stats.station,
                                       channel=tr.stats.channel)
            if template:
                template_len = len(template[0])
            else:
                continue  # If there is no template-data match then skip the rest
                # of the trace loop.
            delay = [
                delay for delay in delays
                if delay[0] == detection.template_name
            ][0]
            delay=[d for d in delay if d[0]==tr.stats.station and \
                    d[1]==tr.stats.channel][0]
            detect_stream.append(tr_copy.trim(starttime=detection.detect_time-\
                        shift_len+delay, endtime=detection.detect_time+delay+\
                        shift_len+template_len))
        detect_streams.append((detection.template_name, Stream(detect_stream)))
        # Tuple of template name and data stream
    # Segregate detections by template
    lags = []
    for template in templates:
        template_detections=[detect[1] for detect in detect_streams\
                if detect[0]==template[0]]
        lags.append(day_loop(template_detections, template[1]))

    # Write out the lags!
    for event in lags:
        # I think I have an old version of Sfile_util here
        sfilename = Sfile_util.blanksfile(wavefile, 'L', 'PYTH', 'out', True)
        picks = []
        for pick in event:
            picks.append(Sfile_util.PICK())
        Sfile_util.populateSfile(sfilename, picks)
Beispiel #3
0
def lag_calc(detections, detect_data, templates, shift_len=0.2, min_cc=0.4):
    """
    Overseer function to take a list of detection objects, cut the data for
    them to lengths of the same length of the template + shift_len on
    either side. This will then write out SEISAN s-file for the detections
    with pick times based on the lag-times found at the maximum correlation,
    providing that correlation is above the min_cc.

    :type detections: List of DETECTION
    :param detections: List of DETECTION objects
    :type detect_data: obspy.Stream
    :param detect_data: All the data needed to cut from - can be a gappy Stream
    :type templates: List of tuple of String, obspy.Stream
    :param templates: List of the templates used as tuples of template name, template
    :type shift_len: float
    :param shift_len: Shift length allowed for the pick in seconds, will be
                    plus/minus this amount - default=0.2
    :type min_cc: float
    :param min_cc: Minimum cross-correlation value to be considered a pick,
                    default=0.4
    """
    from eqcorrscan.utils import Sfile_util
    from obspy import Stream
    # First work out the delays for each template
    delays=[] # List of tuples
    for template in templates:
        temp_delays=[]
        for tr in tempate[1]:
            temp_delays.append((tr.stats.station, tr.stats.channel,\
                    tr.stats.starttime-template.sort['starttime'][0].stats.starttime))
        delays.append((template[0], temp_delays))
    detect_streams=[]
    for detection in detections:
        detect_stream=[]
        for tr in detect_data:
            tr_copy=tr.copy()
            template=[t for t in templates if t[0]==detection.template_name][0]
            template=template.select(station=tr.stats.station,
                            channel=tr.stats.channel)
            if template:
                template_len=len(template[0])
            else:
                continue # If there is no template-data match then skip the rest
                         # of the trace loop.
            delay=[delay for delay in delays if delay[0]==detection.template_name][0]
            delay=[d for d in delay if d[0]==tr.stats.station and \
                    d[1]==tr.stats.channel][0]
            detect_stream.append(tr_copy.trim(starttime=detection.detect_time-\
                        shift_len+delay, endtime=detection.detect_time+delay+\
                        shift_len+template_len))
        detect_streams.append((detection.template_name, Stream(detect_stream)))
        # Tuple of template name and data stream
    # Segregate detections by template
    lags=[]
    for template in templates:
        template_detections=[detect[1] for detect in detect_streams\
                if detect[0]==template[0]]
        lags.append(day_loop(template_detections, template[1]))

    # Write out the lags!
    for event in lags:
        # I think I have an old version of Sfile_util here
        sfilename=Sfile_util.blanksfile(wavefile, 'L', 'PYTH', 'out', True)
        picks=[]
        for pick in event:
            picks.append(Sfile_util.PICK())
        Sfile_util.populateSfile(sfilename, picks)
Beispiel #4
0
def Amp_pick_sfile(sfile, datapath, respdir, chans=['Z'], var_wintype=True, \
                   winlen=0.9, pre_pick=0.2, pre_filt=True, lowcut=1.0,\
                   highcut=20.0, corners=4):
    """
    Function to read information from a SEISAN s-file, load the data and the
    picks, cut the data for the channels given around the S-window, simulate
    a Wood Anderson seismometer, then pick the maximum peak-to-trough
    amplitude.

    Output will be put into a mag_calc.out file which will be in full S-file
    format and can be copied to a REA database.

    :type sfile: String
    :type datapath: String
    :param datapath: Path to the waveform files - usually the path to the WAV directory
    :type respdir: String
    :param respdir: Path to the response information directory
    :type chans: List of strings
    :param chans: List of the channels to pick on, defaults to ['Z'] - should
                just be the orientations, e.g. Z,1,2,N,E
    :type var_wintype: Bool
    :param var_wintype: If True, the winlen will be
                    multiplied by the P-S time if both P and S picks are
                    available, otherwise it will be multiplied by the hypocentral
                    distance*0.34 - dervided using a p-s ratio of 1.68 and
                    S-velocity of 1.5km/s to give a large window, defaults to True
    :type winlen: Float
    :param winlen: Length of window, see above parameter, if var_wintype is False
                    Then this will be in seconds, otherwise it is the multiplier
                    to the p-s time, defaults to 0.5
    :type pre_pick: Float
    :param pre_pick: Time before the s-pick to start the cut window, defaults
                    to 0.2
    :type pre_filt: Bool
    :param pre_filt: To apply a pre-filter or not, defaults to True
    :type lowcut: Float
    :param lowcut: Lowcut in Hz for the pre-filter, defaults to 1.0
    :type highcut: Float
    :param highcut: Highcut in Hz for the pre-filter, defaults to 20.0
    :type corners: Int
    :param corners: Number of corners to use in the pre-filter
    """
    # Hardwire a p-s multiplier of hypocentral distance based on p-s ratio of
    # 1.68 and an S-velocity 0f 1.5km/s, deliberately chosen to be quite slow
    ps_multiplier = 0.34
    from eqcorrscan.utils import Sfile_util
    from obspy import read
    from scipy.signal import iirfilter
    from obspy.signal.invsim import paz2AmpValueOfFreqResp
    import warnings
    # First we need to work out what stations have what picks
    picks = Sfile_util.readpicks(sfile)
    # Convert these picks into a lists
    stations = []  # List of stations
    channels = []  # List of channels
    picktimes = []  # List of pick times
    picktypes = []  # List of pick types
    distances = []  # List of hypocentral distances
    picks_out = []
    for pick in picks:
        if pick.phase in ['P', 'S']:
            picks_out.append(pick)  # Need to be able to remove this if there
            # isn't data for a station!
            stations.append(pick.station)
            channels.append(pick.channel)
            picktimes.append(pick.time)
            picktypes.append(pick.phase)
            distances.append(pick.distance)
    # Read in waveforms
    stream = read(datapath + '/' + Sfile_util.readwavename(sfile)[0])
    if len(Sfile_util.readwavename(sfile)) > 1:
        for wavfile in Sfile_util.readwavename(sfile):
            stream += read(datapath + '/' + wavfile)
    stream.merge()  # merge the data, just in case!
    # For each station cut the window
    uniq_stas = list(set(stations))
    for sta in uniq_stas:
        for chan in chans:
            print 'Working on ' + sta + ' ' + chan
            tr = stream.select(station=sta, channel='*' + chan)
            if not tr:
                # Remove picks from file
                # picks_out=[picks_out[i] for i in xrange(len(picks))\
                # if picks_out[i].station+picks_out[i].channel != \
                # sta+chan]
                warnings.warn(
                    'There is no station and channel match in the wavefile!')
                break
            else:
                tr = tr[0]
            # Apply the pre-filter
            if pre_filt:
                try:
                    tr.detrend('simple')
                except:
                    dummy = tr.split()
                    dummy.detrend('simple')
                    tr = dummy.merge()[0]
                tr.filter('bandpass',freqmin=lowcut, freqmax=highcut,\
                             corners=corners)
            sta_picks=[i for i in xrange(len(stations)) \
                           if stations[i]==sta]
            hypo_dist = picks[sta_picks[0]].distance
            CAZ = picks[sta_picks[0]].CAZ
            if var_wintype:
                if 'S' in [picktypes[i] for i in sta_picks] and\
                   'P' in [picktypes[i] for i in sta_picks]:
                    # If there is an S-pick we can use this :D
                    S_pick=[picktimes[i] for i in sta_picks \
                            if picktypes[i]=='S']
                    S_pick = min(S_pick)
                    P_pick=[picktimes[i] for i in sta_picks \
                            if picktypes[i]=='P']
                    P_pick = min(P_pick)
                    try:
                        tr.trim(starttime=S_pick-pre_pick, \
                                  endtime=S_pick+(S_pick-P_pick)*winlen)
                    except:
                        break
                elif 'S' in [picktypes[i] for i in sta_picks]:
                    S_pick=[picktimes[i] for i in sta_picks \
                            if picktypes[i]=='S']
                    S_pick = min(S_pick)
                    P_modelled = S_pick - hypo_dist * ps_multiplier
                    try:
                        tr.trim(starttime=S_pick-pre_pick,\
                               endtime=S_pick+(S_pick-P_modelled)*winlen)
                    except:
                        break
                else:
                    # In this case we only have a P pick
                    P_pick=[picktimes[i] for i in sta_picks \
                            if picktypes[i]=='P']
                    P_pick = min(P_pick)
                    S_modelled = P_pick + hypo_dist * ps_multiplier
                    try:
                        tr.trim(starttime=S_modelled-pre_pick,\
                                endtime=S_modelled+(S_modelled-P_pick)*winlen)
                    except:
                        break
                # Work out the window length based on p-s time or distance
            elif 'S' in [picktypes[i] for i in sta_picks]:
                # If the window is fixed we still need to find the start time,
                # which can be based either on the S-pick (this elif), or
                # on the hypocentral distance and the P-pick

                # Take the minimum S-pick time if more than one S-pick is available
                S_pick=[picktimes[i] for i in sta_picks \
                           if picktypes[i]=='S']
                S_pick = min(S_pick)
                try:
                    tr.trim(starttime=S_pick - pre_pick,
                            endtime=S_pick + winlen)
                except:
                    break
            else:
                # In this case, there is no S-pick and the window length is fixed
                # We need to calculate an expected S_pick based on the hypocentral
                # distance, this will be quite hand-wavey as we are not using
                # any kind of velocity model.
                P_pick=[picktimes[i] for i in sta_picks \
                           if picktypes[i]=='P']
                P_pick = min(P_pick)
                hypo_dist=[distances[i] for i in sta_picks\
                           if picktypes[i]=='P'][0]
                S_modelled = P_pick + hypo_dist * ps_multiplier
                try:
                    tr.trim(starttime=S_modelled-pre_pick,\
                               endtime=S_modelled+winlen)
                except:
                    break
            # Find the response information
            resp_info=_find_resp(tr.stats.station, tr.stats.channel,\
                           tr.stats.network, tr.stats.starttime, tr.stats.delta,\
                                 respdir)
            PAZ = []
            seedresp = []
            if resp_info and 'gain' in resp_info:
                PAZ = resp_info
            elif resp_info:
                seedresp = resp_info
            # Simulate a Wood Anderson Seismograph
            if PAZ and len(
                    tr.data
            ) > 10:  # Set ten data points to be the minimum to pass
                tr = _sim_WA(tr, PAZ, None, 10)
            elif seedresp and len(tr.data) > 10:
                tr = _sim_WA(tr, None, seedresp, 10)
            elif len(tr.data) > 10:
                warnings.warn('No PAZ for '+tr.stats.station+' '+\
                                 tr.stats.channel+' at time: '+\
                                 str(tr.stats.starttime))
                continue
            if len(tr.data) <= 10:
                # Should remove the P and S picks if len(tr.data)==0
                warnings.warn('No data found for: ' + tr.stats.station)
                # print 'No data in miniseed file for '+tr.stats.station+\
                # ' removing picks'
                # picks_out=[picks_out[i] for i in xrange(len(picks_out))\
                # if i not in sta_picks]
                break
            # Get the amplitude
            amplitude, period, delay = _max_p2t(tr.data, tr.stats.delta)
            if amplitude == 0.0:
                break
            print 'Amplitude picked: ' + str(amplitude)
            # Note, amplitude should be in meters at the moment!
            # Remove the pre-filter response
            if pre_filt:
                # Generate poles and zeros for the filter we used earlier - this
                # is how the filter is designed in the convenience methods of
                # filtering in obspy.
                z, p, k=iirfilter(corners, [lowcut/(0.5*tr.stats.sampling_rate),\
                                            highcut/(0.5*tr.stats.sampling_rate)],\
                                  btype='band', ftype='butter', output='zpk')
                filt_paz = {
                    'poles': list(p),
                    'zeros': list(z),
                    'gain': k,
                    'sensitivity': 1.0
                }
                amplitude /= (paz2AmpValueOfFreqResp(filt_paz, 1/period) * \
                              filt_paz['sensitivity'])
            # Convert amplitude to mm
            if PAZ:  # Divide by Gain to get to nm (returns pm? 10^-12)
                # amplitude *=PAZ['gain']
                amplitude /= 1000
            if seedresp:  # Seedresp method returns mm
                amplitude *= 1000000
            # Write out the half amplitude, approximately the peak amplitude as
            # used directly in magnitude calculations
            # Page 343 of Seisan manual:
            #   Amplitude (Zero-Peak) in units of nm, nm/s, nm/s^2 or counts
            amplitude *= 0.5
            # Generate a PICK type object for this pick
            picks_out.append(
                Sfile_util.PICK(station=tr.stats.station,
                                channel=tr.stats.channel,
                                impulsivity=' ',
                                phase='IAML',
                                weight='',
                                polarity=' ',
                                time=tr.stats.starttime + delay,
                                coda=999,
                                amplitude=amplitude,
                                peri=period,
                                azimuth=float('NaN'),
                                velocity=float('NaN'),
                                AIN=999,
                                SNR='',
                                azimuthres=999,
                                timeres=float('NaN'),
                                finalweight=999,
                                distance=hypo_dist,
                                CAZ=CAZ))
    # Copy the header from the sfile to a new local S-file
    fin = open(sfile, 'r')
    fout = open('mag_calc.out', 'w')
    for line in fin:
        if not line[79] == '7':
            fout.write(line)
        else:
            fout.write(line)
            break
    fin.close()
    fout.close()
    # Write picks out to new s-file
    for pick in picks_out:
        print pick
    Sfile_util.populateSfile('mag_calc.out', picks_out)
    return picks