@register_array_xcorr('<STR_LIT>', is_default=True)<EOL>def fftw_normxcorr(templates, stream, pads, threaded=False, *args, **kwargs):
utilslib = _load_cdll('<STR_LIT>')<EOL>argtypes = [<EOL>np.ctypeslib.ndpointer(dtype=np.float32, ndim=<NUM_LIT:1>,<EOL>flags=native_str('<STR_LIT>')),<EOL>ctypes.c_long, ctypes.c_long,<EOL>np.ctypeslib.ndpointer(dtype=np.float32, ndim=<NUM_LIT:1>,<EOL>flags=native_str('<STR_LIT>')),<EOL>ctypes.c_long,<EOL>np.ctypeslib.ndpointer(dtype=np.float32,<EOL>flags=native_str('<STR_LIT>')),<EOL>ctypes.c_long,<EOL>np.ctypeslib.ndpointer(dtype=np.intc,<EOL>flags=native_str('<STR_LIT>')),<EOL>np.ctypeslib.ndpointer(dtype=np.intc,<EOL>flags=native_str('<STR_LIT>')),<EOL>np.ctypeslib.ndpointer(dtype=np.intc,<EOL>flags=native_str('<STR_LIT>'))]<EOL>restype = ctypes.c_int<EOL>if threaded:<EOL><INDENT>func = utilslib.normxcorr_fftw_threaded<EOL><DEDENT>else:<EOL><INDENT>func = utilslib.normxcorr_fftw<EOL><DEDENT>func.argtypes = argtypes<EOL>func.restype = restype<EOL>used_chans = ~np.isnan(templates).any(axis=<NUM_LIT:1>)<EOL>template_length = templates.shape[<NUM_LIT:1>]<EOL>stream_length = len(stream)<EOL>n_templates = templates.shape[<NUM_LIT:0>]<EOL>fftshape = next_fast_len(template_length + stream_length - <NUM_LIT:1>)<EOL>norm = ((templates - templates.mean(axis=-<NUM_LIT:1>, keepdims=True)) / (<EOL>templates.std(axis=-<NUM_LIT:1>, keepdims=True) * template_length))<EOL>norm = np.nan_to_num(norm)<EOL>ccc = np.zeros((n_templates, stream_length - template_length + <NUM_LIT:1>),<EOL>np.float32)<EOL>used_chans_np = np.ascontiguousarray(used_chans, dtype=np.intc)<EOL>pads_np = np.ascontiguousarray(pads, dtype=np.intc)<EOL>variance_warning = np.ascontiguousarray([<NUM_LIT:0>], dtype=np.intc)<EOL>if not np.all(stream == <NUM_LIT:0>) and np.var(stream) < <NUM_LIT>:<EOL><INDENT>stream *= <NUM_LIT><EOL>warnings.warn("<STR_LIT>"<EOL>"<STR_LIT>")<EOL><DEDENT>ret = func(<EOL>np.ascontiguousarray(norm.flatten(order='<STR_LIT:C>'), np.float32),<EOL>template_length, n_templates,<EOL>np.ascontiguousarray(stream, np.float32), stream_length,<EOL>np.ascontiguousarray(ccc, np.float32), fftshape,<EOL>used_chans_np, pads_np, variance_warning)<EOL>if ret < <NUM_LIT:0>:<EOL><INDENT>raise MemoryError()<EOL><DEDENT>elif ret not in [<NUM_LIT:0>, <NUM_LIT>]:<EOL><INDENT>print('<STR_LIT>')<EOL>print('<STR_LIT>' % (ccc.max(), ccc.argmax()))<EOL>print('<STR_LIT>' % (ccc.min(), ccc.argmin()))<EOL>raise CorrelationError("<STR_LIT>")<EOL><DEDENT>elif ret == <NUM_LIT>:<EOL><INDENT>warnings.warn("<STR_LIT>"<EOL>"<STR_LIT>")<EOL><DEDENT>if variance_warning[<NUM_LIT:0>] and variance_warning[<NUM_LIT:0>] > template_length:<EOL><INDENT>warnings.warn(<EOL>"<STR_LIT>".format(<EOL>variance_warning[<NUM_LIT:0>]))<EOL><DEDENT>return ccc, used_chans<EOL>
Normalised cross-correlation using the fftw library.

Internally this function used double precision numbers, which is definitely
required for seismic data. Cross-correlations are computed as the
inverse fft of the dot product of the ffts of the stream and the reversed,
normalised, templates.  The cross-correlation is then normalised using the
running mean and standard deviation (not using the N-1 correction) of the
stream and the sums of the normalised templates.

This python function wraps the C-library written by C. Chamberlain for this
purpose.

:param templates: 2D Array of templates
:type templates: np.ndarray
:param stream: 1D array of continuous data
:type stream: np.ndarray
:param pads: List of ints of pad lengths in the same order as templates
:type pads: list
:param threaded:
    Whether to use the threaded routine or not - note openMP and python
    multiprocessing don't seem to play nice for this.
:type threaded: bool

:return: np.ndarray of cross-correlations
:return: np.ndarray channels used