def template_grid(stations, nodes, travel_times, phase, PS_ratio=<NUM_LIT>,<EOL>samp_rate=<NUM_LIT:100>, flength=False, phaseout='<STR_LIT:all>'):
if phase not in ['<STR_LIT:S>', '<STR_LIT:P>']:<EOL><INDENT>raise IOError('<STR_LIT>')<EOL><DEDENT>templates = []<EOL>for i, node in enumerate(nodes):<EOL><INDENT>st = []  <EOL>for j, station in enumerate(stations):<EOL><INDENT>tr = Trace()<EOL>tr.stats.sampling_rate = samp_rate<EOL>tr.stats.station = station<EOL>tr.stats.channel = '<STR_LIT>'<EOL>tt = travel_times[j][i]<EOL>if phase == '<STR_LIT:P>':<EOL><INDENT>SP_time = (tt * PS_ratio) - tt<EOL>if phaseout == '<STR_LIT:S>':<EOL><INDENT>tr.stats.starttime += tt + SP_time<EOL><DEDENT>else:<EOL><INDENT>tr.stats.starttime += tt<EOL><DEDENT><DEDENT>elif phase == '<STR_LIT:S>':<EOL><INDENT>SP_time = tt - (tt / PS_ratio)<EOL>if phaseout == '<STR_LIT:S>':<EOL><INDENT>tr.stats.starttime += tt<EOL><DEDENT>else:<EOL><INDENT>tr.stats.starttime += tt - SP_time<EOL><DEDENT><DEDENT>if flength and SP_time * samp_rate < flength - <NUM_LIT:11>and phaseout == '<STR_LIT:all>':<EOL><INDENT>tr.data = seis_sim(sp=int(SP_time * samp_rate), amp_ratio=<NUM_LIT>,<EOL>flength=flength, phaseout=phaseout)<EOL>st.append(tr)<EOL><DEDENT>elif flength and phaseout == '<STR_LIT:all>':<EOL><INDENT>warnings.warn('<STR_LIT>' +<EOL>'<STR_LIT>' + station)<EOL><DEDENT>elif phaseout == '<STR_LIT:all>':<EOL><INDENT>tr.data = seis_sim(sp=int(SP_time * samp_rate), amp_ratio=<NUM_LIT>,<EOL>flength=flength, phaseout=phaseout)<EOL>st.append(tr)<EOL><DEDENT>elif phaseout in ['<STR_LIT:P>', '<STR_LIT:S>']:<EOL><INDENT>tr.data = seis_sim(sp=int(SP_time * samp_rate), amp_ratio=<NUM_LIT>,<EOL>flength=flength, phaseout=phaseout)<EOL>st.append(tr)<EOL><DEDENT>elif phaseout == '<STR_LIT>':<EOL><INDENT>for _phaseout in ['<STR_LIT:P>', '<STR_LIT:S>']:<EOL><INDENT>_tr = tr.copy()<EOL>_tr.data = seis_sim(sp=int(SP_time * samp_rate),<EOL>amp_ratio=<NUM_LIT>, flength=flength,<EOL>phaseout=_phaseout)<EOL>if _phaseout == '<STR_LIT:P>':<EOL><INDENT>_tr.stats.channel = '<STR_LIT>'<EOL>_tr.stats.starttime = _tr.stats.starttime - SP_time<EOL><DEDENT>elif _phaseout == '<STR_LIT:S>':<EOL><INDENT>_tr.stats.channel = '<STR_LIT>'<EOL><DEDENT>st.append(_tr)<EOL><DEDENT><DEDENT><DEDENT>templates.append(Stream(st))<EOL><DEDENT>return templates<EOL>
Generate a group of synthetic seismograms for a grid of sources.

Used to simulate phase arrivals from a grid of known sources in a
three-dimensional model.  Lags must be known and supplied, these can be
generated from the bright_lights function: read_tt, and resampled to fit
the desired grid dimensions and spacing using other functions therein.
These synthetic seismograms are very simple models of seismograms using
the seis_sim function herein. These approximate body-wave P and S first
arrivals as spikes convolved with damped sine waves.

:type stations: list
:param stations: List of the station names
:type nodes: list
:param nodes: List of node locations in (lon,lat,depth)
:type travel_times: numpy.ndarray
:param travel_times: Array of travel times where travel_times[i][:] \
    refers to the travel times for station=stations[i], and \
    travel_times[i][j] refers to stations[i] for nodes[j]
:type phase: str
:param phase: Can be either 'P' or 'S'
:type PS_ratio: float
:param PS_ratio: P/S velocity ratio, defaults to 1.68
:type samp_rate: float
:param samp_rate: Desired sample rate in Hz, defaults to 100.0
:type flength: int
:param flength: Length of template in samples, defaults to False
:type phaseout: str
:param phaseout: Either 'S', 'P', 'all' or 'both', determines which \
    phases to clip around.  'all' Encompasses both phases in one channel, \
    but will return nothing if the flength is not long enough, 'both' \
    will return two channels for each stations, one SYN_Z with the \
    synthetic P-phase, and one SYN_H with the synthetic S-phase.

:returns: List of :class:`obspy.core.stream.Stream`