From a4989289e9feede15d35e356cc91fcb0a0ab9ffd Mon Sep 17 00:00:00 2001 From: Vincent Dumont Date: Sat, 25 Mar 2017 12:03:57 -0700 Subject: [PATCH] update readme --- LICENSE | 21 + README.md | 35 + README.org | 9 - docs/.buildinfo | 4 - docs/.nojekyll | 0 docs/_images/jupyter1.png | Bin 130991 -> 0 bytes docs/_images/jupyter2.png | Bin 136660 -> 0 bytes docs/_images/overview.png | Bin 135118 -> 0 bytes docs/_modules/gdas/epower.html | 701 -- docs/_modules/index.html | 64 - docs/_sources/backup/backup.rst.txt | 1406 --- docs/_sources/backup/excess_power.rst.txt | 697 -- docs/_sources/calculate_psd.rst.txt | 54 - .../calculate_spectral_correlation.rst.txt | 25 - .../_sources/check_filtering_settings.rst.txt | 50 - .../compute_channel_renormalization.rst.txt | 23 - docs/_sources/construct_tiles.rst.txt | 33 - docs/_sources/create_filter_bank.rst.txt | 52 - docs/_sources/create_tf_plane.rst.txt | 47 - docs/_sources/create_xml.rst.txt | 56 - docs/_sources/example.rst.txt | 41 - docs/_sources/excess_power.rst.txt | 47 - docs/_sources/explore_duration.rst.txt | 54 - .../gdas.epower.calculate_psd.rst.txt | 6 - ...wer.calculate_spectral_correlation.rst.txt | 6 - ...as.epower.check_filtering_settings.rst.txt | 6 - ...er.compute_channel_renormalization.rst.txt | 6 - .../gdas.epower.create_filter_bank.rst.txt | 6 - .../gdas.epower.excess_power.rst.txt | 6 - docs/_sources/identify_block.rst.txt | 25 - docs/_sources/index.rst.txt | 68 - docs/_sources/initialization.rst.txt | 41 - docs/_sources/installation.rst.txt | 57 - docs/_sources/server.rst.txt | 20 - docs/_static/ajax-loader.gif | Bin 673 -> 0 bytes docs/_static/alert_info_32.png | Bin 1128 -> 0 bytes docs/_static/alert_warning_32.png | Bin 944 -> 0 bytes docs/_static/basic.css | 632 - docs/_static/bg-page.png | Bin 82 -> 0 bytes docs/_static/bullet_orange.png | Bin 165 -> 0 bytes docs/_static/comment-bright.png | Bin 756 -> 0 bytes docs/_static/comment-close.png | Bin 829 -> 0 bytes docs/_static/comment.png | Bin 641 -> 0 bytes docs/_static/doctools.js | 287 - docs/_static/down-pressed.png | Bin 222 -> 0 bytes docs/_static/down.png | Bin 202 -> 0 bytes docs/_static/file.png | Bin 286 -> 0 bytes docs/_static/haiku.css | 376 - docs/_static/jquery-3.1.0.js | 10074 ---------------- docs/_static/jquery.js | 4 - docs/_static/minus.png | Bin 90 -> 0 bytes docs/_static/plus.png | Bin 90 -> 0 bytes docs/_static/pygments.css | 65 - docs/_static/searchtools.js | 758 -- docs/_static/underscore-1.3.1.js | 999 -- docs/_static/underscore.js | 31 - docs/_static/up-pressed.png | Bin 214 -> 0 bytes docs/_static/up.png | Bin 203 -> 0 bytes docs/_static/websupport.js | 808 -- docs/backup/backup.html | 1138 -- docs/backup/excess_power.html | 413 - docs/calculate_psd.html | 125 - docs/calculate_spectral_correlation.html | 102 - docs/check_filtering_settings.html | 123 - docs/compute_channel_renormalization.html | 100 - docs/construct_tiles.html | 104 - docs/create_filter_bank.html | 124 - docs/create_tf_plane.html | 120 - docs/create_xml.html | 122 - docs/example.html | 113 - docs/excess_power.html | 127 - docs/explore_duration.html | 125 - docs/generated/gdas.epower.calculate_psd.html | 111 - ...epower.calculate_spectral_correlation.html | 84 - .../gdas.epower.check_filtering_settings.html | 110 - ...power.compute_channel_renormalization.html | 81 - .../gdas.epower.create_filter_bank.html | 98 - docs/generated/gdas.epower.excess_power.html | 133 - docs/genindex.html | 97 - docs/identify_block.html | 96 - docs/index.html | 132 - docs/initialization.html | 114 - docs/installation.html | 123 - docs/objects.inv | Bin 983 -> 0 bytes docs/search.html | 92 - docs/searchindex.js | 1 - docs/server.html | 88 - scripts/gdas_test | 2 +- sphinx/calculate_psd.rst | 13 - sphinx/calculate_spectral_correlation.rst | 10 - sphinx/check_filtering_settings.rst | 13 - sphinx/compute_channel_renormalization.rst | 10 - sphinx/create_filter_bank.rst | 11 - sphinx/excess_power.rst | 13 - 94 files changed, 57 insertions(+), 21911 deletions(-) create mode 100644 LICENSE create mode 100644 README.md delete mode 100644 README.org delete mode 100644 docs/.buildinfo delete mode 100644 docs/.nojekyll delete mode 100644 docs/_images/jupyter1.png delete mode 100644 docs/_images/jupyter2.png delete mode 100644 docs/_images/overview.png delete mode 100644 docs/_modules/gdas/epower.html delete mode 100644 docs/_modules/index.html delete mode 100644 docs/_sources/backup/backup.rst.txt delete mode 100644 docs/_sources/backup/excess_power.rst.txt delete mode 100644 docs/_sources/calculate_psd.rst.txt delete mode 100644 docs/_sources/calculate_spectral_correlation.rst.txt delete mode 100644 docs/_sources/check_filtering_settings.rst.txt delete mode 100644 docs/_sources/compute_channel_renormalization.rst.txt delete mode 100644 docs/_sources/construct_tiles.rst.txt delete mode 100644 docs/_sources/create_filter_bank.rst.txt delete mode 100644 docs/_sources/create_tf_plane.rst.txt delete mode 100644 docs/_sources/create_xml.rst.txt delete mode 100644 docs/_sources/example.rst.txt delete mode 100644 docs/_sources/excess_power.rst.txt delete mode 100644 docs/_sources/explore_duration.rst.txt delete mode 100644 docs/_sources/generated/gdas.epower.calculate_psd.rst.txt delete mode 100644 docs/_sources/generated/gdas.epower.calculate_spectral_correlation.rst.txt delete mode 100644 docs/_sources/generated/gdas.epower.check_filtering_settings.rst.txt delete mode 100644 docs/_sources/generated/gdas.epower.compute_channel_renormalization.rst.txt delete mode 100644 docs/_sources/generated/gdas.epower.create_filter_bank.rst.txt delete mode 100644 docs/_sources/generated/gdas.epower.excess_power.rst.txt delete mode 100644 docs/_sources/identify_block.rst.txt delete mode 100644 docs/_sources/index.rst.txt delete mode 100644 docs/_sources/initialization.rst.txt delete mode 100644 docs/_sources/installation.rst.txt delete mode 100644 docs/_sources/server.rst.txt delete mode 100644 docs/_static/ajax-loader.gif delete mode 100644 docs/_static/alert_info_32.png delete mode 100644 docs/_static/alert_warning_32.png delete mode 100644 docs/_static/basic.css delete mode 100644 docs/_static/bg-page.png delete mode 100644 docs/_static/bullet_orange.png delete mode 100644 docs/_static/comment-bright.png delete mode 100644 docs/_static/comment-close.png delete mode 100644 docs/_static/comment.png delete mode 100644 docs/_static/doctools.js delete mode 100644 docs/_static/down-pressed.png delete mode 100644 docs/_static/down.png delete mode 100644 docs/_static/file.png delete mode 100644 docs/_static/haiku.css delete mode 100644 docs/_static/jquery-3.1.0.js delete mode 100644 docs/_static/jquery.js delete mode 100644 docs/_static/minus.png delete mode 100644 docs/_static/plus.png delete mode 100644 docs/_static/pygments.css delete mode 100644 docs/_static/searchtools.js delete mode 100644 docs/_static/underscore-1.3.1.js delete mode 100644 docs/_static/underscore.js delete mode 100644 docs/_static/up-pressed.png delete mode 100644 docs/_static/up.png delete mode 100644 docs/_static/websupport.js delete mode 100644 docs/backup/backup.html delete mode 100644 docs/backup/excess_power.html delete mode 100644 docs/calculate_psd.html delete mode 100644 docs/calculate_spectral_correlation.html delete mode 100644 docs/check_filtering_settings.html delete mode 100644 docs/compute_channel_renormalization.html delete mode 100644 docs/construct_tiles.html delete mode 100644 docs/create_filter_bank.html delete mode 100644 docs/create_tf_plane.html delete mode 100644 docs/create_xml.html delete mode 100644 docs/example.html delete mode 100644 docs/excess_power.html delete mode 100644 docs/explore_duration.html delete mode 100644 docs/generated/gdas.epower.calculate_psd.html delete mode 100644 docs/generated/gdas.epower.calculate_spectral_correlation.html delete mode 100644 docs/generated/gdas.epower.check_filtering_settings.html delete mode 100644 docs/generated/gdas.epower.compute_channel_renormalization.html delete mode 100644 docs/generated/gdas.epower.create_filter_bank.html delete mode 100644 docs/generated/gdas.epower.excess_power.html delete mode 100644 docs/genindex.html delete mode 100644 docs/identify_block.html delete mode 100644 docs/index.html delete mode 100644 docs/initialization.html delete mode 100644 docs/installation.html delete mode 100644 docs/objects.inv delete mode 100644 docs/search.html delete mode 100644 docs/searchindex.js delete mode 100644 docs/server.html diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0ecc8ae --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016-2017 The GNOME Collaboration + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f9ed050 --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +# GNOME Data Analysis Software + +[![License MIT](https://img.shields.io/badge/License-MIT-blue.svg)](http://opensource.org/licenses/MIT) +[![PyPI version](https://badge.fury.io/py/gdas.svg)](https://badge.fury.io/py/gdas) + +## Installation & Documentation + +The program is available through [pip](https://pypi.python.org/pypi/pip). +A full description of the software is provided at the following link: + + https://gnome-physics.github.io/gdas + +## License + +(The MIT License) + +Copyright (c) 2016-2017 The GNOME Collaboration + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.org b/README.org deleted file mode 100644 index 64ab89f..0000000 --- a/README.org +++ /dev/null @@ -1,9 +0,0 @@ -#+TITLE: README -#+AUTHOR: Vincent Dumont -#+EMAIL: vincentdumont11@gmail.com - -A full documentation of the software is provided at the following link: - - https://gnome-physics.github.io/gdas - -Feel free to [[mailto:vincentdumont11@gmail.com][email me]] if you have any questions. diff --git a/docs/.buildinfo b/docs/.buildinfo deleted file mode 100644 index c17c206..0000000 --- a/docs/.buildinfo +++ /dev/null @@ -1,4 +0,0 @@ -# Sphinx build info version 1 -# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: a5704f500776dac1385d77f6ad5ed451 -tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/.nojekyll b/docs/.nojekyll deleted file mode 100644 index e69de29..0000000 diff --git a/docs/_images/jupyter1.png b/docs/_images/jupyter1.png deleted file mode 100644 index 5cb4809537c4838403a819367491bdb86088bf6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130991 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�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 z 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]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
  • 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 I2llW32QsOxE&u=k diff --git a/docs/_modules/gdas/epower.html b/docs/_modules/gdas/epower.html deleted file mode 100644 index 814d977..0000000 --- a/docs/_modules/gdas/epower.html +++ /dev/null @@ -1,701 +0,0 @@ - - - - - - - - gdas.epower — gdas 0.3.0 documentation - - - - - - - - - - - - - -

    - -
    - - -

    Source code for gdas.epower

    -import time,math,os,scipy,lal,lalburst
    -from plots                            import *
    -from pycbc                            import psd,types,filter
    -from glue.ligolw                      import lsctables
    -from gwpy.spectrum                    import Spectrum
    -from gwpy.timeseries                  import TimeSeries
    -from scipy.signal                     import fftconvolve
    -from utils                            import *
    -from glue                             import git_version
    -from glue.lal                         import LIGOTimeGPS
    -from glue.ligolw                      import ligolw,utils
    -from glue.ligolw.utils.search_summary import append_search_summary
    -from glue.ligolw.utils.process        import register_to_xmldoc
    -from glue.segments                    import segment
    -
    -
    [docs]def excess_power(ts_data,psd_segment_length,psd_segment_stride,psd_estimation,window_fraction,tile_fap,station,nchans=None,band=None,fmin=0,fmax=None,max_duration=None): - """ - Perform excess-power search analysis on magnetic field data. - This method will produce a bunch of time-frequency plots for every - tile duration and bandwidth analysed as well as a XML file identifying - all the triggers found in the selected data within the user-defined - time range. - - Parameters - ---------- - ts_data : TimeSeries - Time Series from magnetic field data - psd_segment_length : float - Length of each segment in seconds - psd_segment_stride : float - Separation between 2 consecutive segments in seconds - psd_estimation : string - Average method - window_fraction : float - Withening window fraction - tile_fap : float - Tile false alarm probability threshold in Gaussian noise. - nchans : int - Total number of channels - band : float - Tile bandwidth - fmin : float - Lowest frequency of the filter bank. - fmax : float - Highest frequency of the filter bank - """ - #print strain.insert_strain_option_group.__dict__ - #print psd.insert_psd_option_group.__dict__ - sample_rate = ts_data.sample_rate - nchans,band,flow = check_filtering_settings(sample_rate,nchans,band,fmin,fmax) - seg_len,fd_psd,lal_psd = calculate_psd(ts_data,sample_rate,psd_segment_length,psd_segment_stride,psd_estimation) - window, spec_corr = calculate_spectral_correlation(seg_len,'tukey',window_fraction=window_fraction) - filter_bank, fdb = create_filter_bank(fd_psd.delta_f,flow+band/2,band,nchans,fd_psd,spec_corr,fmin,fmax) - # This is necessary to compute the mu^2 normalizations - #white_filter_ip = compute_filter_ips_self(filter_bank, spec_corr, None) - #unwhite_filter_ip = compute_filter_ips_self(filter_bank, spec_corr, lal_psd) - # These two are needed for the unwhitened mean square sum (hrss) - #white_ss_ip = compute_filter_ips_adjacent(filter_bank, spec_corr, None) - #unwhite_ss_ip = compute_filter_ips_adjacent(filter_bank, spec_corr, lal_psd) - tdb = convert_to_time_domain(fdb,sample_rate) - plot_bank(fdb) - plot_filters(tdb,flow,band) - mu_sq_dict = compute_channel_renormalization(filter_bank, spec_corr, nchans) - event_list = lsctables.New(lsctables.SnglBurstTable, - ['start_time','start_time_ns','peak_time','peak_time_ns', - 'duration','bandwidth','central_freq','chisq_dof', - 'confidence','snr','amplitude','channel','ifo', - 'process_id','event_id','search','stop_time','stop_time_ns']) - t_idx_min, t_idx_max = 0, seg_len - os.system('mkdir -p segments/time-frequency') - os.system('mkdir -p segments/time-series') - while t_idx_max <= len(ts_data): - start_time, end_time, tmp_ts_data, fs_data = identify_block(ts_data,fd_psd,window,t_idx_min,t_idx_max) - tf_map = create_tf_plane(fd_psd,nchans,seg_len,filter_bank,band,fs_data) - plot_spectrogram(numpy.abs(tf_map).T,tmp_ts_data.delta_t,band,ts_data.sample_rate,start_time,end_time,fname='segments/time-frequency/%i-%i.png'%(start_time,end_time)) - for nc_sum in range(0, int(math.log(nchans, 2)))[::-1]: # nc_sum additional channel adds - nc_sum = 2**nc_sum - 1 - mu_sq = mu_sq_dict[nc_sum] - max_dof, tiles, us_rate, dt, df = construct_tiles(nc_sum,mu_sq,band,ts_data,tf_map,psd_segment_length,window_fraction,max_duration) - t3 = time.time() - for j in [2**l for l in xrange(0, int(math.log(max_dof, 2)))]: - duration = j / 2.0 / df - dof_tiles = create_tile_duration(j,df,duration,tiles) - plot_spectrogram(dof_tiles.T,dt,df,ts_data.sample_rate,start_time,end_time,fname='segments/%i-%i/tf_%02ichans_%02idof.png'%(start_time,end_time,nc_sum+1,2*j)) - threshold = scipy.stats.chi2.isf(tile_fap, j) - print "|------ Threshold for this level: %f" % threshold - spant, spanf = dof_tiles.shape[1] * dt, dof_tiles.shape[0] * df - print "|------ Processing %.2fx%.2f time-frequency map." % (spant, spanf) - # Since we clip the data, the start time needs to be adjusted accordingly - window_offset_epoch = fs_data.epoch + psd_segment_length * window_fraction / 2 - trigger_list_from_map(dof_tiles, event_list, threshold, window_offset_epoch, filter_bank[0].f0 + band/2, duration, df, df, dt, None) - for event in event_list[::-1]: - if event.amplitude != None: - continue - etime_min_idx = float(event.get_start()) - float(fs_data.epoch) - etime_min_idx = int(etime_min_idx / tmp_ts_data.delta_t) - etime_max_idx = float(event.get_start()) - float(fs_data.epoch) + event.duration - etime_max_idx = int(etime_max_idx / tmp_ts_data.delta_t) - # (band / 2) to account for sin^2 wings from finest filters - flow_idx = int((event.central_freq - event.bandwidth / 2 - (band / 2) - flow) / band) - fhigh_idx = int((event.central_freq + event.bandwidth / 2 + (band / 2) - flow) / band) - # TODO: Check that the undersampling rate is always commensurate - # with the indexing: that is to say that - # mod(etime_min_idx, us_rate) == 0 always - z_j_b = tf_map[flow_idx:fhigh_idx,etime_min_idx:etime_max_idx:us_rate] - event.amplitude = 0 - print "|------ Total number of events: %d" % len(event_list) - t_idx_min += int(seg_len * (1 - window_fraction)) - t_idx_max += int(seg_len * (1 - window_fraction)) - create_xml(ts_data,psd_segment_length,window_fraction,event_list,station)
    - -
    [docs]def check_filtering_settings(sample_rate,channels,tile_bandwidth,fmin,fmax): - """ - Check filtering settings and define the total number of channels - and bandwidth to use for filter bank. - - Parameters - ---------- - sample_rate : float - Sampling rate in Hz of the data retrieved from the metadata - min_frequency : float - Lowest frequency of the filter bank - max_frequency : float - Highest frequency of the filter bank - channels : int - Number of frequency channels to use - tile_bandwidth : float - Bandwidth of the finest filters - - Return - ------ - nchans, band, flow : int, float, float - Number of channels, filter bandwidth, initial frequency offset - """ - # Check if tile maximum frequency is not defined - if fmax is None or fmax>sample_rate/2.: - # Set the tile maximum frequency equal to the Nyquist frequency (i.e. half the sampling rate) - fmax = sample_rate / 2.0 - # Check whether or not tile bandwidth and channel are defined - if tile_bandwidth is None and channels is None: - # Exit program with error message - exit("Either --tile-bandwidth or --channels must be specified to set up time-frequency plane") - else: - # Define as assert statement that tile maximum frequency larger than its minimum frequency - assert fmax >= fmin - # Define spectral band of data - data_band = fmax - fmin - # Check if tile bandwidth or channel is defined - if tile_bandwidth is not None: - # Define number of possible filter bands - band = tile_bandwidth - nchans = channels = int(data_band / tile_bandwidth) - 1 - elif channels is not None: - # Define filter bandwidth - band = tile_bandwidth = data_band / channels - nchans = channels - 1 - assert channels > 1 - # Lowest frequency of the filter bank - flow = fmin - return nchans,band,flow
    - -
    [docs]def calculate_psd(ts_data,sample_rate,psd_segment_length,psd_segment_stride,psd_estimation): - """ - Estimate Power Spectral Density (PSD) - - Parameters - ---------- - ts_data : TimeSeries - Time series of magnetic field data - sample_rate : float - Sampling rate of data - psd_segment_length : float - Length of data segment in seconds - psd_segment_stride : float - Separation between consecutive segments in seconds - psd_estimation : string - Average method to measure PSD from the data - - Return - ------ - seg_len, fd_psd, lal_psd : Segment length in sample unit, PSD results - in 2 different formats. - - Notes - ----- - Need to contact Chris Pankow for more information on the 2 formats. - """ - print "|- Estimating PSD from segments of time %.2f s in length, with %.2f s stride..." % (psd_segment_length, psd_segment_stride) - # Convert time series as array of float - data = ts_data.astype(numpy.float64) - # Average method to measure PSD from the data - avg_method = psd_estimation - # The segment length for PSD estimation in samples - seg_len = int(psd_segment_length * sample_rate) - # The separation between consecutive segments in samples - seg_stride = int(psd_segment_stride * sample_rate) - # Lifted from the psd.from_cli module - fd_psd = psd.welch(data,avg_method=avg_method,seg_len=seg_len,seg_stride=seg_stride) - # Plot the power spectral density - plot_spectrum(fd_psd) - # We need this for the SWIG functions - lal_psd = fd_psd.lal() - return seg_len,fd_psd,lal_psd
    - -
    [docs]def calculate_spectral_correlation(fft_window_len,wtype='hann',window_fraction=None): - """ - Calculate the two point spectral correlation introduced by windowing - the data before transforming to the frequency domain -- valid choices - are 'hann' and 'tukey'. The window_fraction parameter only has meaning - for wtype='tukey'. - """ - print "|- Whitening window and spectral correlation..." - if wtype == 'hann': - window = lal.CreateHannREAL8Window(fft_window_len) - elif wtype == 'tukey': - window = lal.CreateTukeyREAL8Window(fft_window_len, window_fraction) - else: - raise ValueError("Can't handle window type %s" % wtype) - fft_plan = lal.CreateForwardREAL8FFTPlan(len(window.data.data), 1) - window = window.data.data - window_sigma_sq = numpy.mean(window**2) - # Pre scale the window by its root mean squared -- see eqn 11 of EP document - #window /= numpy.sqrt(window_sigma_sq) - return window, lal.REAL8WindowTwoPointSpectralCorrelation(window, fft_plan)
    - -
    [docs]def create_filter_bank(delta_f,flow,band,nchan,psd,spec_corr,fmin=0,fmax=None): - """ - Create filter bank - - Parameters - ---------- - delta_f : float - Bandwidth of each filter - flow : float - Lowest frequency of the filter bank - band : - """ - print "|- Create filter..." - lal_psd = psd.lal() - lal_filters, np_filters = [], [] - for i in range(nchan): - lal_filter = lalburst.CreateExcessPowerFilter(flow + i*band, band, lal_psd, spec_corr) - np_filters.append(Spectrum.from_lal(lal_filter)) - lal_filters.append(lal_filter) - return lal_filters, np_filters
    - -def convert_to_time_domain(fdb,sample_rate): - """ - Convert filter bank from frequency to time domain - - Parameters - ---------- - fdb : list - List of filters from the filter bank in frequency domain - sample_rate : float - Sampling rate of magnetic field data - - Return - ------ - tdb : list - List of filters from the filter bank in time domain - """ - print "|- Convert all the frequency domain to the time domain..." - tdb = [] - for fdt in fdb: - zero_padded = numpy.zeros(int((fdt.f0 / fdt.df).value) + len(fdt)) - st = int((fdt.f0 / fdt.df).value) - zero_padded[st:st+len(fdt)] = numpy.real_if_close(fdt.value) - n_freq = int(sample_rate / 2 / fdt.df.value) * 2 - tdt = numpy.fft.irfft(zero_padded, n_freq) * math.sqrt(sample_rate) - tdt = numpy.roll(tdt, len(tdt)/2) - tdt = TimeSeries(tdt, name="", epoch=fdt.epoch, sample_rate=sample_rate) - tdb.append(tdt) - return tdb - -def identify_block(ts_data,fd_psd,window,t_idx_min,t_idx_max): - """ - Get frequency series of the current block - - Parameters - ---------- - ts_data : TimeSeries - Time series of magnetic field data - fd_psd : - Power Spectrum Density - window : - t_idx_min : float - Index in time series of first data point - t_idx_max : float - Index in time series of last data point - - Return - ------ - start_time : float - Starting time of the block - end_time : float - Ending time of the block - tmp_ts_data : TimeSeries - Time series magnetic data of the block - fs_data : FrequencySeries - Frequency series magnetic data of the block - """ - # Define starting and ending time of the segment in seconds - start_time = ts_data.start_time + t_idx_min/float(ts_data.sample_rate) - end_time = ts_data.start_time + t_idx_max/float(ts_data.sample_rate) - print "|-- Analyzing block %i to %i (%.2f percent)"%(start_time,end_time,100*float(t_idx_max)/len(ts_data)) - # Model a withen time series for the block - tmp_ts_data = types.TimeSeries(ts_data[t_idx_min:t_idx_max]*window,delta_t=1./ts_data.sample_rate,epoch=start_time) - # Save time series in relevant repository - segfolder = 'segments/%i-%i'%(start_time,end_time) - os.system('mkdir -p '+segfolder) - plot_ts(tmp_ts_data,fname='segments/time-series/%i-%i.png'%(start_time,end_time)) - # Convert times series to frequency series - fs_data = tmp_ts_data.to_frequencyseries() - print "|-- Frequency series data has variance: %s" % fs_data.data.std()**2 - # Whitening (FIXME: Whiten the filters, not the data) - fs_data.data /= numpy.sqrt(fd_psd) / numpy.sqrt(2 * fd_psd.delta_f) - print "|-- Whitened frequency series data has variance: %s" % fs_data.data.std()**2 - return start_time, end_time, tmp_ts_data, fs_data - -def create_tf_plane(fd_psd,nchans,seg_len,filter_bank,band,fs_data): - """ - Create time-frequency map - - Parameters - ---------- - fd_psd : array - Power Spectrum Density - """ - print "|-- Create time-frequency plane for current block" - # Return the complex snr, along with its associated normalization of the template, - # matched filtered against the data - #filter.matched_filter_core(types.FrequencySeries(tmp_filter_bank,delta_f=fd_psd.delta_f),fs_data,h_norm=1,psd=fd_psd,low_frequency_cutoff=filter_bank[0].f0,high_frequency_cutoff=filter_bank[0].f0+2*band) - print "|-- Filtering all %d channels..." % nchans - # Initialise 2D zero array - tmp_filter_bank = numpy.zeros(len(fd_psd), dtype=numpy.complex128) - # Initialise 2D zero array for time-frequency map - tf_map = numpy.zeros((nchans, seg_len), dtype=numpy.complex128) - # Loop over all the channels - for i in range(nchans): - # Reset filter bank series - tmp_filter_bank *= 0.0 - # Index of starting frequency - f1 = int(filter_bank[i].f0/fd_psd.delta_f) - # Index of ending frequency - f2 = int((filter_bank[i].f0 + 2*band)/fd_psd.delta_f)+1 - # (FIXME: Why is there a factor of 2 here?) - tmp_filter_bank[f1:f2] = filter_bank[i].data.data * 2 - # Define the template to filter the frequency series with - template = types.FrequencySeries(tmp_filter_bank, delta_f=fd_psd.delta_f, copy=False) - # Create filtered series - filtered_series = filter.matched_filter_core(template,fs_data,h_norm=None,psd=None,low_frequency_cutoff=filter_bank[i].f0,high_frequency_cutoff=filter_bank[i].f0+2*band) - # Include filtered series in the map - tf_map[i,:] = filtered_series[0].numpy() - return tf_map - -def compute_filter_ips_self(lal_filters, spec_corr, psd=None): - """ - Compute a set of inner products of input filters with themselves. If psd - argument is given, the unwhitened filter inner products will be returned. - """ - return numpy.array([lalburst.ExcessPowerFilterInnerProduct(f, f, spec_corr, psd) for f in lal_filters]) - -def compute_filter_ips_adjacent(lal_filters, spec_corr, psd=None): - """ - Compute a set of filter inner products between input adjacent filters. - If psd argument is given, the unwhitened filter inner products will be - returned. The returned array index is the inner product between the - lal_filter of the same index, and its (array) adjacent filter --- assumed - to be the frequency adjacent filter. - """ - return numpy.array([lalburst.ExcessPowerFilterInnerProduct(f1, f2, spec_corr, psd) for f1, f2 in zip(lal_filters[:-1], lal_filters[1:])]) - -
    [docs]def compute_channel_renormalization(filter_bank, spec_corr, nchans): - """ - Compute the renormalization for the base filters up to a given bandwidth. - """ - mu_sq_dict = {} - for nc_sum in range(0, int(math.log(nchans, 2))): - min_band = (len(filter_bank[0].data.data)-1) * filter_bank[0].deltaF / 2 - print "|- Calculation for %d %dHz channels" % (nc_sum+1, min_band) - nc_sum = 2**nc_sum - 1 - mu_sq = (nc_sum+1)*numpy.array([lalburst.ExcessPowerFilterInnerProduct(f, f, spec_corr, None) for f in filter_bank]) - # Uncomment to get all possible frequency renormalizations - #for n in xrange(nc_sum, nchans): # channel position index - for n in xrange(nc_sum, nchans, nc_sum+1): # channel position index - for k in xrange(0, nc_sum): # channel sum index - # FIXME: We've precomputed this, so use it instead - mu_sq[n] += 2*lalburst.ExcessPowerFilterInnerProduct(filter_bank[n-k], filter_bank[n-1-k], spec_corr, None) - #print mu_sq[nc_sum::nc_sum+1] - mu_sq_dict[nc_sum] = mu_sq - return mu_sq_dict
    - -def measure_hrss(z_j_b, uw_ss_ii, uw_ss_ij, w_ss_ij, delta_f, delta_t, filter_len, dof): - """ - Approximation of unwhitened sum of squares signal energy in a given EP tile. - See T1200125 for equation number reference. - - Parameters - ---------- - z_j_b : time frequency map block which the constructed tile covers - uw_ss_ii : unwhitened filter inner products - uw_ss_ij : unwhitened adjacent filter inner products - w_ss_ij : whitened adjacent filter inner products - delta_f : frequency binning of EP filters - delta_t : native time resolution of the time frequency map - filter_len : number of samples in a fitler - dof : degrees of freedom in the tile (twice the time-frequency area) - """ - s_j_b_avg = uw_ss_ii * delta_f / 2 - # unwhitened sum of squares of wide virtual filter - s_j_nb_avg = uw_ss_ii.sum() / 2 + uw_ss_ij.sum() - s_j_nb_avg *= delta_f - s_j_nb_denom = s_j_b_avg.sum() + 2 * 2 / filter_len * \ - numpy.sum(numpy.sqrt(s_j_b_avg[:-1] * s_j_b_avg[1:]) * w_ss_ij) - # eqn. 62 - uw_ups_ratio = s_j_nb_avg / s_j_nb_denom - # eqn. 63 -- approximation of unwhitened signal energy time series - # FIXME: The sum in this equation is over nothing, but indexed by frequency - # I'll make that assumption here too. - s_j_nb = numpy.sum(z_j_b.T * numpy.sqrt(s_j_b_avg), axis=0) - s_j_nb *= numpy.sqrt(uw_ups_ratio / filter_len * 2) - # eqn. 64 -- approximate unwhitened signal energy minus noise contribution - # FIXME: correct axis of summation? - return math.sqrt(numpy.sum(numpy.absolute(s_j_nb)**2) * delta_t - s_j_nb_avg * dof * delta_t) - -def uw_sum_sq(filter1, filter2, spec_corr, psd): - # < s^2_j(f_1, b) > = 1 / 2 / N * \delta_t EPIP{\Theta, \Theta; P} - return lalburst.ExcessPowerFilterInnerProduct(filter1, filter2, spec_corr, psd) - -def measure_hrss_slowly(z_j_b, lal_filters, spec_corr, psd, delta_t, dof): - """ - Approximation of unwhitened sum of squares signal energy in a given EP tile. - See T1200125 for equation number reference. NOTE: This function is deprecated - in favor of measure_hrss, since it requires recomputation of many inner products, - making it particularly slow. - """ - # FIXME: Make sure you sum in time correctly - # Number of finest bands in given tile - nb = len(z_j_b) - # eqn. 56 -- unwhitened mean square of filter with itself - uw_ss_ii = numpy.array([uw_sum_sq(lal_filters[i], lal_filters[i], spec_corr, psd) for i in range(nb)]) - s_j_b_avg = uw_ss_ii * lal_filters[0].deltaF / 2 - # eqn. 57 -- unwhitened mean square of filter with adjacent filter - uw_ss_ij = numpy.array([uw_sum_sq(lal_filters[i], lal_filters[i+1], spec_corr, psd) for i in range(nb-1)]) - # unwhitened sum of squares of wide virtual filter - s_j_nb_avg = uw_ss_ii.sum() / 2 + uw_ss_ij.sum() - s_j_nb_avg *= lal_filters[0].deltaF - # eqn. 61 - w_ss_ij = numpy.array([uw_sum_sq(lal_filters[i], lal_filters[i+1], spec_corr, None) for i in range(nb-1)]) - s_j_nb_denom = s_j_b_avg.sum() + 2 * 2 / len(lal_filters[0].data.data) * \ - (numpy.sqrt(s_j_b_avg[:-1] * s_j_b_avg[1:]) * w_ss_ij).sum() - # eqn. 62 - uw_ups_ratio = s_j_nb_avg / s_j_nb_denom - # eqn. 63 -- approximation of unwhitened signal energy time series - # FIXME: The sum in this equation is over nothing, but indexed by frequency - # I'll make that assumption here too. - s_j_nb = numpy.sum(z_j_b.T * numpy.sqrt(s_j_b_avg), axis=0) - s_j_nb *= numpy.sqrt(uw_ups_ratio / len(lal_filters[0].data.data) * 2) - # eqn. 64 -- approximate unwhitened signal energy minus noise contribution - # FIXME: correct axis of summation? - return math.sqrt((numpy.absolute(s_j_nb)**2).sum() * delta_t - s_j_nb_avg * dof * delta_t) - -def measure_hrss_poorly(tile_energy, sub_psd): - return math.sqrt(tile_energy / numpy.average(1.0 / sub_psd) / 2) - -def trigger_list_from_map(tfmap, event_list, threshold, start_time, start_freq, duration, band, df, dt, psd=None): - - # FIXME: If we don't convert this the calculation takes forever --- - # but we should convert it once and handle deltaF better later - if psd is not None: - npy_psd = psd.numpy() - - start_time = LIGOTimeGPS(float(start_time)) - ndof = 2 * duration * band - - for i, j in zip(*numpy.where(tfmap > threshold)): - event = event_list.RowType() - - # The points are summed forward in time and thus a `summed point' is the - # sum of the previous N points. If this point is above threshold, it - # corresponds to a tile which spans the previous N points. However, the - # 0th point (due to the convolution specifier 'valid') is actually - # already a duration from the start time. All of this means, the + - # duration and the - duration cancels, and the tile 'start' is, by - # definition, the start of the time frequency map if j = 0 - # FIXME: I think this needs a + dt/2 to center the tile properly - event.set_start(start_time + float(j * dt)) - event.set_stop(start_time + float(j * dt) + duration) - event.set_peak(event.get_start() + duration / 2) - event.central_freq = start_freq + i * df + 0.5 * band - - event.duration = duration - event.bandwidth = band - event.chisq_dof = ndof - - event.snr = math.sqrt(tfmap[i,j] / event.chisq_dof - 1) - # FIXME: Magic number 0.62 should be determine empircally - event.confidence = -lal.LogChisqCCDF(event.snr * 0.62, event.chisq_dof * 0.62) - if psd is not None: - # NOTE: I think the pycbc PSDs always start at 0 Hz --- check - psd_idx_min = int((event.central_freq - event.bandwidth / 2) / psd.delta_f) - psd_idx_max = int((event.central_freq + event.bandwidth / 2) / psd.delta_f) - - # FIXME: heuristically this works better with E - D -- it's all - # going away with the better h_rss calculation soon anyway - event.amplitude = measure_hrss_poorly(tfmap[i,j] - event.chisq_dof, npy_psd[psd_idx_min:psd_idx_max]) - else: - event.amplitude = None - - event.process_id = None - event.event_id = event_list.get_next_id() - event_list.append(event) - -def make_tiles(tf_map, nc_sum, mu_sq): - tiles = numpy.zeros(tf_map.shape) - sum_filter = numpy.ones(nc_sum+1) - # Here's the deal: we're going to keep only the valid output and - # it's *always* going to exist in the lowest available indices - for t in xrange(tf_map.shape[1]): - # Sum and drop correlate tiles - # FIXME: don't drop correlated tiles - output = numpy.convolve(tf_map[:,t], sum_filter, 'valid')[::nc_sum+1] - #output = fftconvolve(tf_map[:,t], sum_filter, 'valid')[::nc_sum+1] - tiles[:len(output),t] = numpy.absolute(output) / math.sqrt(2) - return tiles[:len(output)]**2 / mu_sq[nc_sum::nc_sum+1].reshape(-1, 1) - -def make_indp_tiles(tf_map, nc_sum, mu_sq): - """ - Create a time frequency map with resolution of tf_map binning - divided by nc_sum + 1. All tiles will be independent up to - overlap from the original tiling. The mu_sq is applied to the - resulting addition to normalize the outputs to be zero-mean - unit-variance Gaussian variables (if the input is Gaussian). - - Notes - ----- - Optimization plan: If we keep the summed complex TF plane in known - indices, we can save ourselves individual sums at wider frequency - resolutions. - Caveats: - 1. We have to keep track of where we're storing things - 2. We have to do it from the finest resolution (for *all* t0s) - and work our way up - In the end, I think this is a Haar wavelet transform. Look into it. - """ - tiles = tf_map.copy() - # Here's the deal: we're going to keep only the valid output and - # it's *always* going to exist in the lowest available indices - stride = nc_sum + 1 - for i in xrange(tiles.shape[0]/stride): - numpy.absolute(tiles[stride*i:stride*(i+1)].sum(axis=0), tiles[stride*(i+1)-1]) - return tiles[nc_sum::nc_sum+1].real**2 / mu_sq[nc_sum::nc_sum+1].reshape(-1, 1) - -def make_filename(ifo, seg, tag="excesspower", ext="xml.gz"): - if isinstance(ifo, str): - ifostr = ifo - else: - ifostr = "".join(ifo) - st_rnd, end_rnd = int(math.floor(seg[0])), int(math.ceil(seg[1])) - dur = end_rnd - st_rnd - #return "%s-%s-%d-%d.%s" % (ifostr, tag, st_rnd, dur, ext) - return "%s.%s" % (tag, ext) - -def construct_tiles(nc_sum,mu_sq,band,ts_data,tf_map,psd_segment_length,window_fraction,max_duration): - """ - Constructing tile and calculate their energy - """ - # Clip the boundaries to remove window corruption - clip_samples = int(psd_segment_length * window_fraction * ts_data.sample_rate / 2) - print "|--- Constructing tile with %d summed channels..." % (nc_sum+1) - # Current bandwidth of the time-frequency map tiles - df = band * (nc_sum + 1) - # How much each "step" is in the time domain -- under sampling rate - dt = 1.0 / (2 * df) - us_rate = int(round(dt / ts_data.delta_t)) - print "|--- Undersampling rate for this level: %f" % (ts_data.sample_rate/us_rate) - print "|--- Calculating tiles..." - if clip_samples > 0: # because [0:-0] does not give the full array - tiles = make_indp_tiles(tf_map[:,clip_samples:-clip_samples:us_rate], nc_sum, mu_sq) - else: - tiles = make_indp_tiles(tf_map[:,::us_rate], nc_sum, mu_sq) - print "|--- TF-plane is %dx%s samples" % tiles.shape - print "|--- Tile energy mean %f, var %f" % (numpy.mean(tiles), numpy.var(tiles)) - if max_duration is not None: - max_dof = 2 * max_duration * (band * (nc_sum+1)) - else: - max_dof = 32 - assert max_dof >= 2 - return max_dof, tiles, us_rate, dt, df - -def create_tile_duration(j,df,duration,tiles): - # Duration is fixed by the NDOF and bandwidth - duration = j / 2.0 / df - print "|----- Explore signal duration of %f s..." % duration - print "|----- Summing DOF = %d ..." % (2*j) - tlen = tiles.shape[1] - 2*j + 1 + 1 - dof_tiles = numpy.zeros((tiles.shape[0], tlen)) - sum_filter = numpy.array([1,0] * (j-1) + [1]) - for f in range(tiles.shape[0]): - # Sum and drop correlate tiles - dof_tiles[f] = fftconvolve(tiles[f], sum_filter, 'valid') - print "|----- Summed tile energy mean: %f, var %f" % (numpy.mean(dof_tiles), numpy.var(dof_tiles)) - return dof_tiles - -def create_xml(ts_data,psd_segment_length,window_fraction,event_list,station,setname="MagneticFields"): - __program__ = 'pyburst_excesspower' - start_time = LIGOTimeGPS(int(ts_data.start_time)) - end_time = LIGOTimeGPS(int(ts_data.end_time)) - inseg = segment(start_time,end_time) - xmldoc = ligolw.Document() - xmldoc.appendChild(ligolw.LIGO_LW()) - ifo = 'H1'#channel_name.split(":")[0] - straindict = psd.insert_psd_option_group.__dict__ - proc_row = register_to_xmldoc(xmldoc, __program__,straindict, ifos=[ifo],version=git_version.id, cvs_repository=git_version.branch, cvs_entry_time=git_version.date) - outseg = determine_output_segment(inseg, psd_segment_length, ts_data.sample_rate, window_fraction) - ss = append_search_summary(xmldoc, proc_row, ifos=(station,), inseg=inseg, outseg=outseg) - for sb in event_list: - sb.process_id = proc_row.process_id - sb.search = proc_row.program - sb.ifo, sb.channel = station, setname - xmldoc.childNodes[0].appendChild(event_list) - fname = make_filename(station, inseg) - utils.write_filename(xmldoc, fname, gz=fname.endswith("gz")) - -def determine_output_segment(inseg, dt_stride, sample_rate, window_fraction=0.0): - """ - Given an input data stretch segment inseg, a data block stride dt_stride, the data sample rate, and an optional window_fraction, return the amount of data that can be processed without corruption effects from the window. - If window_fration is set to 0 (default), assume no windowing. - """ - # Amount to overlap successive blocks so as not to lose data - window_overlap_samples = window_fraction * sample_rate - outseg = inseg.contract(window_fraction * dt_stride / 2) - # With a given dt_stride, we cannot process the remainder of this data - remainder = math.fmod(abs(outseg), dt_stride * (1 - window_fraction)) - # ...so make an accounting of it - outseg = segment(outseg[0], outseg[1] - remainder) - return outseg -
    - -
    - - - - - \ No newline at end of file diff --git a/docs/_modules/index.html b/docs/_modules/index.html deleted file mode 100644 index 408a090..0000000 --- a/docs/_modules/index.html +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - Overview: module code — gdas 0.3.0 documentation - - - - - - - - - - - - - - - -
    - - -

    All modules for which code is available

    - - -
    - - - - - \ No newline at end of file diff --git a/docs/_sources/backup/backup.rst.txt b/docs/_sources/backup/backup.rst.txt deleted file mode 100644 index 85ce8b7..0000000 --- a/docs/_sources/backup/backup.rst.txt +++ /dev/null @@ -1,1406 +0,0 @@ -GNOME Data Analysis Software -============================ - -* :ref:`test2` - - .. _test2: - -.. toctree:: - :maxdepth: 2 - :caption: People & By-laws - - test - -.. toctree:: - :maxdepth: 2 - - index.rst - -Introduction -============ - -This package contains functions useful for magnetic field signal processing, with a focus on Excess Power search analysis and application on the data for the GNOME collaboration, see `Pustelny et al. (2013) `_. This documentation details all the available functions and tasks available through this software. Here are some example tasks that can (or will soon to) be handled: - -* Plot usual time series and spectrogram of magnetic field data. -* Perform excess power analysis and plot detected triggers in time-frequency map. -* Create artificial data for testing data analysis. -* Inject fake signal of different bandwidth and durations. -* Cross-correlation of continuous sine wave signals. -* Perform Allan Standard deviation. - -.. raw:: html - - Fork me on GitHub - -Installation -============ - -The program requires the following general packages to run: `Numpy `_, `Matplotlib `_, `Scipy `_ and `Astropy `_. The following LIGO-related packages are also required for full functionality: `Gwpy `_, `PyCBC `_, `Glue `_, `LAL `_, `LALburst `_ and `LALsimulation `_. - -While most of the packages can be installed automatically using `pip `_, some LIGO packages (Glue, LAL, LALburst and LALsimulation) must be installed separately beforehand as they contain several C routines that need specific compilation. However, these packages are already included in a bigger package called `LALsuite `_ which can be installed fairly easily on Debian (Linux) and Mac OS machines. - -LALsuite tools --------------- - -Some useful pages on how to download and install the LIGO software can be found `here `_. - -MacPorts (Mac) -~~~~~~~~~~~~~~ - -For Mac users, the installation is pretty easy, detailed information can be found on `this page `_. You need to have `MacPorts `_ installed. The following commands should suffice to install the LALsuite package on your machine:: - - sudo port install lscsoft-deps - sudo port install glue - sudo port install lalapps - -The first command will install all the dependencies needed for the LIGO software to be installed. The following 2 commands will install the actual packages. - -apt-get (Debian) -~~~~~~~~~~~~~~~~ - -Since the LIGO software is not a default package in the apt package manager system on Debian machine, additional steps will be needed. The first step is to add the following links to the source list located at ``/etc/apt/sources.list``:: - - deb [arch=amd64] http://software.ligo.org/lscsoft/debian jessie contrib - deb-src [arch=amd64] http://software.ligo.org/lscsoft/debian jessie contrib - -Note that the ``[arch=amd64]`` is needed to fix the architecture problem in case it tries to install i386 version on 64-bit Debian. Once the sources have been added, you must first install all the dependencies as follows:: - - apt-get install build-essential automake autoconf libtool devscripts - -The LIGO software can finally be installed using the following command:: - - apt-get install lscsoft-all - -Main Program ------------- - -The best way to install the GNOME software along with the rest of the dependencies is by using `pip`:: - - pip install gdas - -(You may need to put a ``sudo`` in front of this). For this to work -you need to have `pip -`_ installed. This -method allows for easy uninstallation. - -You can also simply download the tarball from the PyPI website, unpack it and then do:: - - python setup.py install - -The latest stable package can be downloaded from PyPI: https://pypi.python.org/pypi/gdas. -The development version can be downloaded from `here `_. - -Multi-user Server -================= - -A GNOME JupyterHub, or multi-user server has been created to allow each member to access the entire available dataset. Member who do not have access to the server but wish to access it should send a request to Dr. Sam Afach. Member who are not part of the GNOME collaboration will not be granted access to the dataset but are free to use our software on their own data. - -The server can be accessed in two ways, either by acceding the `server's webpage `_, or from your terminal through SSH:: - - ssh -X username@budker.uni-mainz.de -p 8022 - -While SSH is very handy for people using UNIX-like operating systems, this can become more complicated for those working on Windows machines. Fortunately, access to a terminal is also possible through the webpage, which means directly from your internet browser! This can be done by clicking on the New tab after login and select Terminal: - -.. figure:: img/jupyter1.png - :width: 70% - :align: center - -You can then use the terminal window to access files and create new Python scripts for your analysis. - -.. figure:: img/jupyter2.png - :width: 70% - :align: center - -Working Example -=============== - -Either on your own computer or on the server, on a Jupyter notebook or on a Python script, the first thing to do is to import the ``gdas`` package that contain all the modules present in the GNOME software. That can be done easily by doing the following:: - - import gdas - -In order to retrieve a specific chunk of data to be analyzed for a particular station, the name of the station along with the start and end dates should be specified:: - - station = 'fribourg01' - start_time = '2016-11-03-04' - end_time = '2016-11-03-04-2' - -where the start and end times should always have at least the year, month and day specified, and with the values separated by a dash symbol. Hour and minute can also be specified. - -If you are not working on the server and the data are located in a different repository than ``/GNOMEDrive/gnome/serverdata/``, a custom path can be defined. For instance:: - - datapath = '/Users/vincent/data/GNOMEDrive/gnome/serverdata/' - -The magnetic field data can then be retrieve as follows:: - - ts_data,ts_list,activity = gdas.magfield(station,start_time,end_time,rep=datapath) - -The ``gdas.magfield`` method will return 3 arrays of data that can then be used to produce different plots:: - - gdas.plot_activity(activity) - gdas.plot_time_series(station,ts_list,seglist=activity) - gdas.plot_asd(station,ts_list) - gdas.plot_whitening(station,ts_list,activity) - -This is a script to do Excess Power analysis:: - - psd_segment_length = 60 - psd_segment_stride = 30 - psd_estimation = 'median-mean' - window_fraction = 0 - tile_fap = 1e-5 - channels = 250 - - gdas.excess_power(ts_data,psd_segment_length,psd_segment_stride,psd_estimation,window_fraction,tile_fap,station,nchans=channels) - gdas.plot_triggers() - -Data extraction -=============== - -Extracting real data --------------------- - -Retrieve metadata -~~~~~~~~~~~~~~~~~ - -The first step is to define some variables related to which data we want to study and their location. The ``os.path.join`` method will join that different paths called as arguments (i.e. in the parenthesis):: - - # Set name of the channel to extract - setname = "MagneticFields" - # Define station name and map - station = "fribourg01" - # Define year, month and day - year,month,day = '2016','11','03' - # Define path to main data repository - path1 = '/Users/vincent/ASTRO/data/GNOMEDrive/gnome/serverdata/' - # Define path to day repository - path2 = "%s/%s/%s/%s/"%(station,year,month,day) - # Define generic hdf5 filenames - path3 = "%s_%s%s%s_*.hdf5"%(station,year,month,day) - # Define full generic path name - fullpath = os.path.join(path1,path2,path3) - -We then use the `glob `_ module to list all the files that satisfy the full path name and loop over each HDF5 file and do the following: - -- Extract its metadata using the `h5py `_ package; -- Calculate the segment in time for which the data corresponds to using the :ref:`file_to_segment ` function; -- Store each filename and metadata on two different dictionary variables ``file_order`` and ``file_order``. - -Finally, we extract the sampling rate from one of the file which will be use later in the analysis. The sampling rate is the same for all the data files:: - - # Initialising dictionary for data - file_order,data_order = {},{} - # Loop over all existing data files - for fname in glob.glob(fullpath): - # Read hdf5 file - hfile = h5py.File(fname, "r") - # Extract segment information from file - segfile = file_to_segment(hfile,setname) - # Associate file in dictionary with association to segment data - file_order[segfile] = fname - data_order[segfile] = hfile - # Retrieve sampling rate from last read file - sample_rate = hfile[setname].attrs["SamplingRate(Hz)"] - -Creating segment lists -~~~~~~~~~~~~~~~~~~~~~~ - -This section will create a continuous list of all the data segments available. We use the following modules in order to create the list properly: - -- The `segmentlist `_ module from the ``glue.segments`` library defines the list of segments. The =coalesce()= method is then used to put all the segments in coalesced state. -- The `DataQualityDict `_ module from the ``gwpy.segments`` library allows to store all the data segments in an ordered dictionary. -- The `DataQualityFlag `_ module from the ``gwpy.segments`` library allows to *record times during which the instrument was operating outside of its nominal condition*. - -The script is as follows:: - - # Generate an ASCII representation of the GPS timestamped segments of time covered by the input data - seglist = segmentlist(data_order.keys()) - # Sort the segment list - seglist.sort() - # Initialise dictionary for segment information - full_seglist = DataQualityDict() - # Save time span for each segment in ASCII file - with open("segments.txt", "w") as fout: - for seg in seglist: - print >>fout, "%10.9f %10.9f" % seg - # FIXME: Active should be masked from the sanity channel - full_seglist[station] = DataQualityFlag(station,active=seglist.coalesce(),known=seglist.coalesce()) - # Define start and end time of entire dataset - start, end = full_seglist[station].active.extent() - -Establishing active times -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Here's the script:: - - # Generate an ASCII representation of the GPS timestamped segments of time covered by the input data - seglist = segmentlist(data_order.keys()) - # Sort the segment list - seglist.sort() - # Import gwpy tools - plot = SegmentPlot() - # Initialize plotting figure - ax = plot.gca() - # Plot all segment in figure - ax.plot(full_seglist) - # Save figure - pyplot.savefig("activity.png",dpi=500) - -Retrieve and concatenate the data. -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Here's the script:: - - # Generate time series for the ensemble of data - data_list = generate_timeseries(file_order,setname) - # Retrieve channel data for all the segments - full_data = numpy.hstack([retrieve_channel_data(data_order[seg],setname) for seg in seglist]) - # Define log base 2 of the total time length of the full data - loglength = math.log(len(full_data)/sample_rate, 2) - # Define zero padding - zpad = math.ceil(loglength) - zpad = int(2**zpad) - len(full_data)/sample_rate - zpad = numpy.zeros(int(zpad*sample_rate / 2.0)) - # Include padding next to the data - full_data = numpy.hstack((zpad, full_data, zpad)) - # Models a time series consisting of uniformly sampled scalar values - ts_data = types.TimeSeries(full_data,delta_t=1/sample_rate,epoch=seglist[0][0]) - # Loop over all the elements in the dictionary - for v in data_order.values(): - # Close the element - v.close() - -Producing fake data -------------------- - -Create simulated time series data -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -It is easy to create fake data, one can use the `numpy.random.normal `_ method from the Numpy library to draw random samples from a normal Gaussian distribution with mean of 0, standard deviation of 1, and a length equal to the sampling rate (``args.sample_rate``) times the length in seconds of individual segments (``args.psd_segment_length``) times the number of segment the user wish to produce. After defining the starting UTC time, one can then create a time series of the data using the `TimeSeries `_ module from the ``gwpy.timeseries`` library.:: - - print "Create fake data..." - start = 1153742437.0 - end = start + args.psd_segment_length * 16 - station = "gaussian-noise" - setname = "MagneticFields" - full_data = numpy.random.normal(0, 1, int(args.sample_rate * args.psd_segment_length * 16)) - ts_data = TimeSeries(full_data, sample_rate=args.sample_rate,epoch=start) - -Produce and plot fake signal -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Here's the script:: - - delta_t = 1.0/args.sample_rate - filter_band = 4 - #q = math.sqrt(2)*f_0/filter_band * 2 - #f_0 = 18 - duration = 0.1 - hrss = 0.0275 - #hp, hx = SimBurstSineGaussian(q * 2, f_0, hrss, 1, 0, data_dt) - hp, hx = SimBurstGaussian(duration, hrss, delta_t) - hp = TimeSeries.from_lal(hp) - hx = TimeSeries.from_lal(hx) - # We rescale the amplitude to hide or expose it in the data a bit better - hp *= 100. - - pyplot.figure() - pyplot.plot(hp.times, hp, 'k-') - pyplot.xlim([-0.5, 0.5]) - pyplot.ylim([-0.1, 0.1]); - pyplot.xlabel('Time (s)') - pyplot.ylabel('Magnitude') - pyplot.savefig('fakesignal.png') - pyplot.close() - -Inject fake signal into artificial data -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Here's the script:: - - random_time = int((start+end)/2.) - st = (random_time-start)*args.sample_rate - len(hp)/2 - en = st + len(hp) - hp.epoch = random_time - ts_data[st:en] += hp - data_list = [ts_data] - ts_data = types.TimeSeries(ts_data.value,delta_t=1.0/args.sample_rate,epoch=start) - -Plotting Data -============= - -Generate a plot of the data time series ---------------------------------------- - -Here's the script:: - - # Include time series element in dictionary - plot = TimeSeriesPlot() - # Create axis in plot - ax = plot.gca() - # Loop over all the time series - for ts in data_list: - # Plot time series for each segment - ax.plot(ts, color='blue') - # Display title - ax.set_title(station) - # Plot activity segments - plot.add_state_segments(SegmentList(full_seglist[station].active),plotargs={'label':'data present','facecolor': 'g','edgecolor': 'k'}) - # Define edges of the x axis - ax.set_xlim(start, end) - # Save figure - plot.savefig('time_series.png',dpi=500) - -Create sound based on the data ------------------------------- - -Here's the script:: - - wout = wave.open("pure_tone.wav", "w") - wout.setnchannels(1) # mono - wout.setsampwidth(4) # 32 bit audio - wout.setframerate(1000) - wout.writeframes(ts[:]) - wout.close() - -Invoking precision issues -------------------------- - -AGG complexity starts to complain with large numbers of points and we somehow invoke precision issues that need to be ameliorated:: - - for d in data_list: - d.x0 = Quantity(int(d.x0.value * 500), d.xunit) - d.dx = Quantity(1, d.xunit) - data_list.coalesce() - for d in data_list: - d.x0 = Quantity(d.x0.value / 500, d.xunit) - d.dx = Quantity(0.002, d.xunit) - -Amplitude Spectral Density (ASD) --------------------------------- - -Here's the script:: - - # Initialize plotting functionality - plot = SpectrumPlot() - # Loop over all the time series - for d in data_list: - # Generate 8 seconds per FFT with 4 second (50%) overlap - spectrum = d.asd(8, 4) - # Create plotting axis - ax = plot.gca() - # Plot square root of the spectrum - ax.plot(numpy.sqrt(spectrum)) - # Set x axis to log scale - ax.set_xscale('log') - # Set y axis to log scale - ax.set_yscale('log') - # Set x axis limits - ax.set_xlim(1e-1, 500) - # Save figure - plot.savefig("asd.png",dpi=500) - -(Un)normalized Spectrograms ---------------------------- - -The first thing to do is to initialise the plotting axis for both figure as well as some display settings specific to spectrogram and which can be loaded using the `SpectrogramPlot() `_ module from the ``gwpy.plotter`` library:: - - plot = SpectrogramPlot() - ax = plot.gca() - white_plot = SpectrogramPlot() - wax = white_plot.gca() - -The spectrogram is then created using the `spectrogram `_ function from the ``gwpy.timeseries.TimeSeries`` package. This will *calculate the average power spectrogram of this TimeSeries using the specified average spectrum method* (default being the Welch's method). We define the 3 following variables that will be used to construct the spectrogram: - -- ``stride``: number of seconds in single PSD (column of spectrogram), default 20; -- ``fftlength``: number of seconds in single FFT, default 6; -- ``overlap``: number of seconds between FFTs, default 3. - -We can then loop over all the time series made from each loaded HDF5 data file, and construct the spectrogram for each time series. The whitening of the spectrogram is then done by normalisation it, which can be performed using the `ratio `_ method from the ``gwpy.spectrogram.Spectrogram`` library. This will calculate the ratio of the created spectrogram against a specific reference, here we chose the reference to be the median of each spectrum in the given spectrogram: - -.. math:: - \sqrt{S(f,t)}/\sqrt{\overline{S(f)}} - -The script is as follows:: - - for ts in data_list: - if (len(ts) * ts.dt).value < stride: - continue - spec = ts.spectrogram(stride, fftlength=fftlength, overlap=overlap) - ax.plot(spec) - wspec = spec.ratio('median') - wax.plot(wspec, vmin=0.1, vmax=100) - -Finally, the plot can be completed by including the activity period below each figure:: - - ax.set_title(station) - ax.set_xlim(seglist[0][0], seglist[-1][1]) - ax.set_ylim(1e-1, 500) - ax.set_yscale('log') - plot.add_colorbar(log=True) - plot.add_state_segments(SegmentList(full_seglist[station].active),plotargs={'label':'data present','facecolor':'g','edgecolor':'k'}) - plot.savefig("spectrogram.png",dpi=500) - - wax.set_title(station) - wax.set_xlim(seglist[0][0], seglist[-1][1]) - wax.set_ylim(1e-1, 500) - wax.set_yscale('log') - white_plot.add_colorbar(log=True) - white_plot.add_state_segments(SegmentList(full_seglist[station].active),plotargs={'label':'data present','facecolor':'g','edgecolor':'k'}) - white_plot.savefig("whitened_spectrogram.png",dpi=500) - -Excess-Power algorithm -====================== - -General overview ----------------- - -The **Excess Power method** is known as the *optimal detection strategy* to search for burst signals for which only the duration and frequency band are known, which is basically the case for GNOME and its search of Axion-Like Particles (ALP). This method was developed and introduced by `Anderson et al. (200) `_ and has been extensively used in the detection of burst sources of gravitational radiation. A more technical documentation was written by `Brady et al. (2007) `_ describing how the algorithm used by the LIGO collaboration works and how the theory is translated into code. - -We present below a step-by-step procedure followed during the Excess Power search analysis. For a better representation of what is happening, the figure at the end shows how the data is being split and analysed to search for multiple signals of different bandwidth and duration in the time-frequency plane. - -- :ref:`Time domain segmentation and PSD estimate ` - - We first estimate the instrument's noise Power Spectral Density (PSD) by splitting the time-series data into multiple overlapping segments. A periodogram for each segment is calculated separately and then averaged, which will reduce the variance of the individual power measurements. The result is a frequency series where samples are separated in frequency space by :math:`\Delta f` equal to the inverse of a segment’s length and with a high end frequency limit equal to the Nyquist limit. The final power spectrum will help reveal the existence, or the absence, of repetitive patterns and correlation structures in a signal process. - -- :ref:`Comb of frequency channels ` - - We then split the PSD frequency series into multiple channels. For each channel, a frequency domain filter is created with a :math:`\Delta f` determined by the PSD and a total extent in Fourier space that is twice the stated bandwidth of a channel. The result is a list of each channel filter's frequency series. - -- :ref:`Creating analysing blocks ` - - The Excess Power method can lead to moderately-large computational requirements, and it has been found that the computational efficiency of this implementation can be improved upon by considering blocks of data that are much longer than the longest signal time duration. The entire time series is therefore split into separate blocks. We use the length of the segments used for PSD estimate to define the duration of each block. For each block, the time series is c0Aonverted into frequency series which is then filtered by the filter bank throughout all the channels. A time-frequency map is finally created which stores all the filtered frequency series from each channel. - -- :ref:`Creating tiles with different bandwidth ` - - We can now construct tiles with different bandwidth by summing multiple channels together. - -- :ref:`Exploring tiles with different duration ` - - For each given tile's bandwidth, one can investigate different tile's duration. This can be done by exploring different number of degrees of freedom, :math:`d`, which can be calculated as follows: :math:`d=2BT` where :math:`B` and :math:`T` are respectively the bandwidth and duration of the tile. Section 2.2.5 of `Brady et al. `_ gives a great description of how to interpret the number of degrees of freedom. Therefore, by changing the :math:`d`, one can explore multiple tile's duration for different bandwidth. - -- :ref:`Define triggering signal ` - - The energy of each tile in the time-frequency space is calculated and compare to a user-defined threshold value. After defining a tile false alarm probability threshold in Gaussian noise and using the number of degrees of freedom for each tile, one can define a energy threshold value above which a burst trigger can be identified by comparing the energy threshold with the tile's energy in the time-frequency map. A tile energy time frequency map plot similar to Figure 5 in `Pustelny et al. (2013) `_ can then be made which plots the outlying tile energies present in the data. - -.. figure:: ./img/overview.png - - Overview of the Excess Power method and difference between segments, channels, tiles and blocks. - -.. _psdestimate: - -Estimate Power Spectral Density (PSD) -------------------------------------- - -The instrument's noise Power Spectral Density (PSD) will be used to whiten the data and help reveal the existence, or the absence, of repetitive patterns and correlation structures in the signal process. It will also determine the total bandwidth spanned by each of the filters that will subsequently be created. The first thing to do before calculating the PSD is to ensure that the time series data is converted into an array of floating values. :: - - # Convert time series as array of float - data = ts_data.astype(numpy.float64) - -The PSD is calculated by splitting up the signal into overlapping segments and scan through each segment to calculate individual periodogram. The periodograms from each segment are then averaged, reducing the variance of the individual power measurements. In order to proceed, we need to define the average method, ``avg_method``, that will be used to measure the PSD from the data. This can be specified with the ``--psd-estimation`` option. :: - - # Average method to measure PSD from the data - avg_method = args.psd_estimation - -One also needs to specify the length of each segment, ``seg_len``, as well as the separation between 2 consecutive segments, ``seg_stride``. Both parameters can be defined in second units with the ``--psd-segment-length`` and ``--psd-segment-stride`` arguments respectively and can then be converted into sample unit. :: - - # The segment length for PSD estimation in samples - seg_len = int(args.psd_segment_length * args.sample_rate) - # The separation between consecutive segments in samples - seg_stride = int(args.psd_segment_stride * args.sample_rate) - -We then use the `Welch's method `_ to perform the power spectral density estimate using the `welch `_ module from the ``pycbc.psd`` library. What this will do is to compute the discrete Fourier transform for each PSD segment to produce invidual periodograms, and then compute the squared magnitude of the result. The individual periodograms are then averaged using the user-defined average method, ``avg_method``, and return the frequency series, ``fd_psd``, which will store the power measurement for each frequency bin. :: - - # Lifted from the psd.from_cli module - fd_psd = psd.welch(data,avg_method=avg_method,seg_len=seg_len,seg_stride=seg_stride) - # Plot the power spectral density - plot_spectrum(fd_psd) - # We need this for the SWIG functions - lal_psd = fd_psd.lal() - -One can display the power measurements, frequency array and frequency between consecutive samples, :math:`\Delta f` in Hertz, by printing the following variables: :: - - print 'Display power measurements of the first 10 frequency bins' - print fd_psd[:10] - print 'Display central frequency of the first 10 bins' - print fd_psd.sample_frequencies[:10] - print 'Display the frequency separation between bins' - print fd_psd.delta_f - -:math:`\Delta f` corresponds to the inverse of a segment's length which is the smallest frequency (i.e. highest period) of detectable signals in each segment. The frequency range spans from 0 to the Nyquist frequency, i.e. half de the sampling rate. - -Checking filtering settings ---------------------------- - -The first thing to check is that the frequency of the high-pass filter (if defined) is below the minimum frequency of the filter bank. Indeed, a high-pass filter will only let pass frequency that are higher than the cutoff frequency (here defined by the ``strain_high_pass`` argument). If the high pass frequency is greater from the minimum frequency in the filter bank, the signal with frequencies lower than the cutoff frequency will get attenuated. :: - - if args.min_frequency < args.strain_high_pass: - print >>sys.stderr, "Warning: strain high pass frequency %f is greater than the tile minimum frequency %f --- this is likely to cause strange output below the bandpass frequency" % (args.strain_high_pass, args.min_frequency) - -In case the maximum frequency in the filter bank is not defined, we set it to be equal to the Nyquist frequency, i.e. half the sampling rate, which makes sense as a larger signal will not be able to get easily identifiable. :: - - if args.max_frequency is None: - args.max_frequency = args.sample_rate / 2.0 - -If the bandwidth of the finest filter (``--tile-bandwidth`` argument, see section :ref:`construct_args ` or the number of frequency channels (=--channels= argument) is not defined but the total spectral band is (``data_band``), one can then determined all the filter settings as follows: :: - - - if args.tile_bandwidth is None and args.channels is None: - # Exit program with error message - exit("Either --tile-bandwidth or --channels must be specified to set up time-frequency plane") - else: - # Define as assert statement that tile maximum frequency larger than its minimum frequency - assert args.max_frequency >= args.min_frequency - # Define spectral band of data - data_band = args.max_frequency - args.min_frequency - # Check if tile bandwidth or channel is defined - if args.tile_bandwidth is not None: - # Define number of possible filter bands - nchans = args.channels = int(data_band / args.tile_bandwidth) - 1 - elif args.channels is not None: - # Define filter bandwidth - band = args.tile_bandwidth = data_band / (args.channels + 1) - assert args.channels > 1 - -The minimum frequency to be explored can be user-defined by using the ``--min-frequency`` option. :: - - # Lowest frequency of the first filter - flow = args.min_frequency - -Whitening window and spectral correlation ------------------------------------------ - -This part determines how much data on either side of the tukey window is to be discarded. Nominally, this means that one will lose ``window_fraction`` * ``args.psd_segment_length`` to corruption from the window, i.e. this is simply discarded. This is tuned to give an integer offset when used with ``args.psd_segment_length`` equal to 8, smaller windows will have fractions of integers, but larger powers of two will still preseve this (probably not a big deal in the end). :: - - window_fraction = 0 - -The two point spectral correlation is then done with the :ref:`calculate_spectral_correlation ` function which will return both the Tukey window applied to the original time series data and the actual two-point spectral correlation function for the whitened frequency series from the applied whitening window. :: - - # Do two point spectral correlation - window, spec_corr = calculate_spectral_correlation(seg_len,'tukey',window_fraction=window_fraction) - window = window.data.data - window_sigma_sq = numpy.mean(window**2) - # Pre scale the window by its root mean squared -- see eqn 11 of EP document - #window /= numpy.sqrt(window_sigma_sq) - -.. _filterbank: - -Computing the filter bank -------------------------- - -The filter bank will create band-pass filters for each channel in the PSD frequency domain. The :ref:`create_filter_bank ` function will san the bandwidth from the central frequency of the first channel (i.e. flow+band/2) to final frequency of the last channel (i.e. band*nchans) in a increment equal to the frequency band. The filter's total extent in Fourier space is actually twice the stated bandwidth (FWHM). :: - - # Define filters - filter_bank, fdb = create_filter_bank(fd_psd.delta_f, flow+band/2, band, nchans, fd_psd, spec_corr) - -This function will returns 2 arrays: the ``filter_bank`` array which is a list of `COMPLEX16FrequencySeries `_ arrays corresponding to each channel's filter, and the =fdb= array which provides the time-series from each filter. The length of each array is equal to the total number of channel (i.e. =nchans=). The filter's data, :math:`\Delta f` value, and first and last frequencies of any channel's filter can be displayed as followed: :: - - # Print data of first channel's filter - print filter_bank[0].data.data - # Print frequency separation between 2 values in the first channel's filter - print filter_bank[0].deltaF - # Print first frequency of the first channel's filter - print filter_bank[0].f0 - # Print last frequency of the first channel's filter (equal to twice the channel's bandwidth) - print filter_bank[0].f0+(len(filter_bank[0].data.data)-1)*filter_bank[0].deltaF - -Further in the analysis, the following filters will used: -1. ``white_filter_ip``: Whitened filter inner products computed with themselves. -2. ``unwhite_filter_ip``: Unwhitened filter inner products computed with themselves. -3. ``white_ss_ip``: Whitened filter inner products computed between input adjacent filters. -4. ``unwhite_ss_ip``: Unwhitened filter inner products computed between input adjacent filters. - -:: - - # This is necessary to compute the mu^2 normalizations - white_filter_ip = compute_filter_ips_self(filter_bank, spec_corr, None) - unwhite_filter_ip = compute_filter_ips_self(filter_bank, spec_corr, lal_psd) - # These two are needed for the unwhitened mean square sum (hrss) - white_ss_ip = compute_filter_ips_adjacent(filter_bank, spec_corr, None) - unwhite_ss_ip = compute_filter_ips_adjacent(filter_bank, spec_corr, lal_psd) - -Normalization of virtual channel --------------------------------- - -The virtual channels will be used during the excesspower analysis to explore different frequency ranges around each PSD segments and look for possible triggers. Each channel is renormalized using the :ref:`compute_channel_renomalization ` internal function. :: - - # Initialise dictionary - mu_sq_dict = {} - # nc_sum additional channel adds - for nc_sum in range(0, int(math.log(nchans, 2))): - min_band = (len(filter_bank[0].data.data)-1) * filter_bank[0].deltaF / 2 - print tprint(t0,t1),"Calculation for %d %d Hz channels" % (nc_sum+1, min_band) - nc_sum = 2**nc_sum - 1 - mu_sq_dict[nc_sum] = compute_channel_renomalization(nc_sum, filter_bank, spec_corr, nchans) - -Initialise event list and determine stride boundaries ------------------------------------------------------ - -First of all, we create a table similar than the one made by the LIGO Scientific Collaboration (LSC) where all the information will be stored. Such table is commonly know as ``lsctables``. A pre-defined LSC table can be constructed using ``New`` function from the `glue.ligolw.lsctables `_ module. We use the ``SnglBurstTable`` function for the type of data to be stored and define all the columns we wish to record. :: - - # Create event list for single burst table - event_list = lsctables.New(lsctables.SnglBurstTable, - ['start_time','start_time_ns','peak_time','peak_time_ns', - 'duration','bandwidth','central_freq','chisq_dof', - 'confidence','snr','amplitude','channel','ifo', - 'process_id','event_id','search','stop_time','stop_time_ns']) - -We also need to determine the indexes of both starting and ending times for the first segment to analyse, respectively ``t_idx_min`` and ``t_idx_max``. The default values are considered to be 0 for the starting index and the segment length in sample unit for the ending time index. Also, if the user defines a different starting time than the one from the loaded data, the offset index in sample unit is determined and added the both starting and ending time indexes. :: - - # Determine boundaries of stride in time domain - t_idx_min, t_idx_max = 0, seg_len - # Check if user requested starting time is defined - if args.analysis_start_time is not None: - # Define the time difference in seconds between data and user requested starting times - t_idx_off = args.analysis_start_time - ts_data.start_time - # Calculate the index of the user requested starting point in the data - t_idx_off = int(t_idx_off * args.sample_rate) - else: - # Define index of the starting point as first value in data - t_idx_off = 0 - # Initialise minimum index values as offset starting index - t_idx_min += t_idx_off - # Initialise maximum index values as offset starting index - t_idx_max += t_idx_off - -Finally, the index for the ending time after all the segments have been analysed can be estimated for the user-defined parameter or is defined as the length of the time series data ``ts_data``. :: - - # Check if user requested end time is defined - if args.analysis_end_time is not None: - # Define the time difference between data and user requested ending times - t_idx_max_off = args.analysis_end_time - ts_data.start_time - # Calculate the index of the user requested starting point in the data - t_idx_max_off = int(t_idx_max_off * args.sample_rate) - else: - # Define index of the ending point as the length of data array - t_idx_max_off = len(ts_data) - -.. _analysingblocks: - -Define analysing blocks ------------------------ - -The first thing we do is to calculate the time series for the segment that is covered (``tmp_ts_data``) and redefined the metadata, especially the time of the first sample in seconds which is defined by the ``epoch`` argument and is different for every segment. After plotting the time series for that segment, the data are then converted into frequency series (``fs_data``) using the `to_frequencyseries `_ module from the ``pycbc.types.timeseries.TimeSeries`` library. Finally, the frequency data are then whitened. :: - - # Loop over each data within the user requested time period - while t_idx_max <= t_idx_max_off: - # Define starting and ending time of the segment in seconds - start_time = ts_data.start_time + t_idx_min/float(args.sample_rate) - end_time = ts_data.start_time + t_idx_max/float(args.sample_rate) - print tprint(t0,t1),"Analyzing block %i to %i (%.2f percent)"%(start_time,end_time,100*float(t_idx_max)/float(idx_max_off)) - # Model a withen time series for the block - tmp_ts_data = types.TimeSeries(ts_data[t_idx_min:t_idx_max]*window, 1.0/args.sample_rate,epoch=start_time) - # Save time series in segment repository - segfolder = 'segments/%i-%i'%(start_time,end_time) - os.system('mkdir -p '+segfolder) - plot_ts(tmp_ts_data,fname='%s/ts.png'%(segfolder)) - # Convert times series to frequency series - fs_data = tmp_ts_data.to_frequencyseries() - print tprint(t0,t1),"Frequency series data has variance: %s" % fs_data.data.std()**2 - # Whitening (FIXME: Whiten the filters, not the data) - fs_data.data /= numpy.sqrt(fd_psd) / numpy.sqrt(2 * fd_psd.delta_f) - print tprint(t0,t1),"Whitened frequency series data has variance: %s" % fs_data.data.std()**2 - -Create time-frequency map for each block ----------------------------------------- - -We initialise a 2D zero array for a time-frequency map (``tf_map``) which will be computed for each frequency-domain filter associated to each PSD segment and where the filtered time-series for each frequency channels will be stored. The number of rows corresponds to the total number of frequency channels which is defined by the ``nchans`` variable. The number of columns corresponds to the segment length in samples (i.e. the number of samples covering one segment) which is defined by the ``seg_len`` variable. :: - - # Initialise 2D zero array for time-frequency map - tf_map = numpy.zeros((nchans, seg_len), dtype=numpy.complex128) - -We also initialise a zero vector for a temporary filter bank (``tmp_filter_bank``) that will store, for a given channel, the filter's values from the original filter bank (``filter_bank``) for that channel only. The length of the temporary filter bank is equal to the length of the PSD frequency series (``fd_psd``). :: - - # Initialise 1D zero array - tmp_filter_bank = numpy.zeros(len(fd_psd), dtype=numpy.complex128) - -We then loop over all the frequency channels. While in the loop, we first re-initialise the temporary filter bank with zero values everywhere along the frequency series. We then determine the first and last frequency of each channel and re-define the values of the filter in that frequency range based on the values from the original channel's filter from the original filter bank. :: - - # Loop over all the channels - print tprint(t0,t1),"Filtering all %d channels..." % nchans - for i in range(nchans): - # Reset filter bank series - tmp_filter_bank *= 0.0 - # Index of starting frequency - f1 = int(filter_bank[i].f0/fd_psd.delta_f) - # Index of ending frequency - f2 = int((filter_bank[i].f0 + 2*band)/fd_psd.delta_f)+1 - # (FIXME: Why is there a factor of 2 here?) - tmp_filter_bank[f1:f2] = filter_bank[i].data.data * 2 - -We then extract the frequency series from the filter bank for that channel, which will be used as a template waveform to filter the actual data from the channel. :: - - # Define the template to filter the frequency series with - template = types.FrequencySeries(tmp_filter_bank, delta_f=fd_psd.delta_f, copy=False) - -Finally, we use the `matched_filter_core `_ module from the ``pycbc.filter.matchedfilter`` library to filter the frequency series from the channel. This will return both a time series containing the complex signal-to-noise matched filtered against the data, and a frequency series containing the correlation vector. :: - - # Create filtered series - filtered_series = filter.matched_filter_core(template,fs_data,h_norm=None,psd=None, - low_frequency_cutoff=filter_bank[i].f0, - high_frequency_cutoff=filter_bank[i].f0+2*band) - -The `matched filter `_ is the optimal linear filter for maximizing the signal to noise ratio (SNR) in the presence of additive stochastic noise. The filtered time series is stored in the time-frequency map and can be used to produce a spectrogram of the segment of data being analysed. :: - - # Include filtered series in the map - tf_map[i,:] = filtered_series[0].numpy() - -The time-frequency map is a 2D array with a length that corresponds to the number of channels and a width equal to the number of sample present in one segment of data, i.e. segment's length in seconds times the the sampling rate. The map can finally be plotted with a :math:`\Delta t` corresponding to the sampling period of the original dataset (i.e. inverse of the original sampling rate), and :math:`\Delta f` is equal to the bandwidth of one channel. :: - - plot_spectrogram(numpy.abs(tf_map).T,tmp_ts_data.delta_t,fd_psd.delta_f,ts_data.sample_rate,start_time,end_time,fname='%s/tf.png'%(segfolder)) - -.. _tilebandwidth: - -Constructing tiles of different bandwidth ------------------------------------------ - -First and foremost, we define a clipping region in the data to be used to remove window corruption, this is non-zero if the ``window_fraction`` variable is set to a non-zero value. :: - - print tprint(t0,t1),"Beginning tile construction..." - # Clip the boundaries to remove window corruption - clip_samples = int(args.psd_segment_length * window_fraction * args.sample_rate / 2) - -In order to perform a multi-resolution search, tiles of many different bandwidths and durations will be scanned. We first need to setup a loop such that the maximum number of additional channel is equal to the base 2 logarithm of the total number of channels. The number of narrow band channels to be summed (``nc_sum``) would therefore be equal to 2 to the power of the current quantity of additional channels. :: - - for nc_sum in range(0, int(math.log(nchans, 2)))[::-1]: # nc_sum additional channel adds - nc_sum = 2**nc_sum - 1 - print tprint(t0,t1,t2),"Summing %d narrow band channels..." % (nc_sum+1) - -The undersampling rate for this tile can be calculated using the channel frequency band and the number of narrow band channels to be summed such that the bandwidth of the tile is equal to ``band * (nc_sum + 1)``. :: - - us_rate = int(round(1.0 / (2 * band*(nc_sum+1) * ts_data.delta_t))) - print >>sys.stderr, "Undersampling rate for this level: %f" % (args.sample_rate/us_rate) - -"Virtual" wide bandwidth channels are constructed by summing the samples from multiple channels, and correcting for the overlap between adjacent channel filters. We then define the normalised channel at the current level and create a time frequency map for this tile using the :ref:`make_indp_tiles ` internal function. In other word, we are constructing multiple sub-tiles for which we can determined the respective energy in the given frequency band. :: - - mu_sq = mu_sq_dict[nc_sum] - sys.stderr.write("\t...calculating tiles...") - if clip_samples > 0: - tiles = make_indp_tiles(tf_map[:,clip_samples:-clip_samples:us_rate], nc_sum, mu_sq) - else: - tiles = make_indp_tiles(tf_map[:,::us_rate], nc_sum, mu_sq) - sys.stderr.write(" TF-plane is %dx%s samples... " % tiles.shape) - print >>sys.stderr, " done" - print "Tile energy mean: %f, var %f" % (numpy.mean(tiles), numpy.var(tiles)) - -.. _tileduration: - -Explore multiple tile durations -------------------------------- - -Now that we create a tile with a specific bandwidth, we can start exploring different durations for the tile. We will start checking if the user manually defined a value for the longest duration tile to compute, which can be done using the ``--max-duration`` argument. If not, the value will be set to 32. :: - - if args.max_duration is not None: - max_dof = 2 * args.max_duration * (band * (nc_sum+1)) - else: - max_dof = 32 - assert max_dof >= 2 - -Since we produce (initially) tiles with 1 degree of freedom, the duration goes as one over twice the bandwidth. :: - - print "\t\t...getting longer durations..." - #for j in [2**l for l in xrange(1, int(math.log(max_dof, 2))+1)]: - for j in [2**l for l in xrange(0, int(math.log(max_dof, 2)))]: - sys.stderr.write("\t\tSumming DOF = %d ..." % (2*j)) - #tlen = tiles.shape[1] - j + 1 - tlen = tiles.shape[1] - 2*j + 1 + 1 - if tlen <= 0: - print >>sys.stderr, " ...not enough samples." - continue - dof_tiles = numpy.zeros((tiles.shape[0], tlen)) - #:sum_filter = numpy.ones(j) - # FIXME: This is the correct filter for 50% overlap - sum_filter = numpy.array([1,0] * (j-1) + [1]) - #sum_filter = numpy.array([1,0] * int(math.log(j, 2)-1) + [1]) - for f in range(tiles.shape[0]): - # Sum and drop correlate tiles - # FIXME: don't drop correlated tiles - #output = numpy.convolve(tiles[f,:], sum_filter, 'valid') - dof_tiles[f] = fftconvolve(tiles[f], sum_filter, 'valid') - print >>sys.stderr, " done" - print "Summed tile energy mean: %f, var %f" % (numpy.mean(dof_tiles), numpy.var(dof_tiles)) - level_tdiff = time.time() - tdiff - print >>sys.stderr, "Done with this resolution, total %f" % level_tdiff - -Finally, the bandwidth and duration of the tile can be defined as followed: :: - - # Current bandwidth of the time-frequency map tiles - current_band = band * (nc_sum + 1) - # How much each "step" is in the frequency domain -- almost - # assuredly the fundamental bandwidth - df = current_band - # How much each "step" is in the time domain -- under sampling rate - # FIXME: THis won't work if the sample rate isn't a power of 2 - dt = 1.0 / 2 / (2 * current_band) * 2 - full_band = 250 - dt = current_band / full_band * ts_data.sample_rate - dt = 1.0/dt - # Duration is fixed by the NDOF and bandwidth - duration = j / 2.0 / current_band - -.. _triggerfinding: - -Trigger finding ---------------- - -In order to find any trigger in the data, we first need to set a false alarm probability threshold in Gaussian noise above which signal will be distinguished from the noise. Such threshold can be determined by using the /inverse survival function/ method from the `scipy.stats.chi2 `_ package. :: - - threshold = scipy.stats.chi2.isf(args.tile_fap, j) - print "Threshold for this level: %f" % threshold - #if numpy.any(dof_tiles > threshold): - #plot_spectrogram(dof_tiles.T) - #import pdb; pdb.set_trace() - -Once the threshold is set, one can then run the :ref:`trigger_list_from_map ` function to quickly find the trigger signal from the ``dof_tiles`` array that :: - - # Since we clip the data, the start time needs to be adjusted accordingly - window_offset_epoch = fs_data.epoch + args.psd_segment_length * window_fraction / 2 - trigger_list_from_map(dof_tiles, event_list, threshold, window_offset_epoch, filter_bank[0].f0 + band/2, duration, current_band, df, dt, None) - for event in event_list[::-1]: - if event.amplitude != None: - continue - etime_min_idx = float(event.get_start()) - float(fs_data.epoch) - etime_min_idx = int(etime_min_idx / tmp_ts_data.delta_t) - etime_max_idx = float(event.get_start()) - float(fs_data.epoch) + event.duration - etime_max_idx = int(etime_max_idx / tmp_ts_data.delta_t) - # (band / 2) to account for sin^2 wings from finest filters - flow_idx = int((event.central_freq - event.bandwidth / 2 - (band / 2) - flow) / band) - fhigh_idx = int((event.central_freq + event.bandwidth / 2 + (band / 2) - flow) / band) - # TODO: Check that the undersampling rate is always commensurate - # with the indexing: that is to say that - # mod(etime_min_idx, us_rate) == 0 always - z_j_b = tf_map[flow_idx:fhigh_idx,etime_min_idx:etime_max_idx:us_rate] - # FIXME: Deal with negative hrss^2 -- e.g. remove the event - try: - event.amplitude = measure_hrss(z_j_b, unwhite_filter_ip[flow_idx:fhigh_idx], unwhite_ss_ip[flow_idx:fhigh_idx-1], white_ss_ip[flow_idx:fhigh_idx-1], fd_psd.delta_f, tmp_ts_data.delta_t, len(filter_bank[0].data.data), event.chisq_dof) - except ValueError: - event.amplitude = 0 - - print "Total number of events: %d" % len(event_list) - -Switch to new block -------------------- - -The following will move the frequency band to the next segment: :: - - tdiff = time.time() - tdiff - print "Done with this block: total %f" % tdiff - - t_idx_min += int(seg_len * (1 - window_fraction)) - t_idx_max += int(seg_len * (1 - window_fraction)) - -Extracting GPS time range -------------------------- - -We use the `LIGOTimeGPS `_ structure from the =glue.lal= package to /store the starting and ending time in the dataset to nanosecond precision and synchronized to the Global Positioning System time reference/. Once both times are defined, the range of value is stored in a semi-open interval using the `segment `_ module from the =glue.segments= package. :: - - # Starting epoch relative to GPS starting epoch - start_time = LIGOTimeGPS(args.analysis_start_time or args.gps_start_time) - # Ending epoch relative to GPS ending epoch - end_time = LIGOTimeGPS(args.analysis_end_time or args.gps_end_time) - # Represent the range of values in the semi-open interval - inseg = segment(start_time,end_time) - -Prepare output file for given time range ----------------------------------------- - -:: - - xmldoc = ligolw.Document() - xmldoc.appendChild(ligolw.LIGO_LW()) - - ifo = args.channel_name.split(":")[0] - proc_row = register_to_xmldoc(xmldoc, __program__, args.__dict__, ifos=[ifo],version=glue.git_version.id, cvs_repository=glue.git_version.branch, cvs_entry_time=glue.git_version.date) - - # Figure out the data we actually analyzed - outseg = determine_output_segment(inseg, args.psd_segment_length, args.sample_rate, window_fraction) - - ss = append_search_summary(xmldoc, proc_row, ifos=(station,), inseg=inseg, outseg=outseg) - - for sb in event_list: - sb.process_id = proc_row.process_id - sb.search = proc_row.program - #sb.ifo, sb.channel = args.channel_name.split(":") - sb.ifo, sb.channel = station, setname - - xmldoc.childNodes[0].appendChild(event_list) - fname = make_filename(station, inseg) - - utils.write_filename(xmldoc, fname, gz=fname.endswith("gz"), verbose=True) - -Plot trigger results --------------------- - -:: - - events = SnglBurstTable.read(fname+'.gz') - #del events[10000:] - plot = events.plot('time', 'central_freq', "duration", "bandwidth", color="snr") - #plot = events.plot('time', 'central_freq', color='snr') - #plot.set_yscale("log") - plot.set_ylim(1e-0, 250) - t0 = 1153742417 - plot.set_xlim(t0 + 0*60, t0 + 1*60) - #plot.set_xlim(t0 + 28, t0 + 32) - pyplot.axvline(t0 + 30, color='r') - cb = plot.add_colorbar(cmap='viridis') - plot.savefig("triggers.png") - -Module Access -============= - -Extract Magnetic Field Data ---------------------------- - -Extract magnetic field data from HDF5 files. - -.. currentmodule:: gdas.retrieve - -.. autosummary:: - :toctree: generated/ - - magfield - file_to_segment - construct_utc_from_metadata - generate_timeseries - create_activity_list - retrieve_data_timeseries - retrieve_channel_data - -Plotting routines ------------------ - -Methods to produce time-frequency plots and others - -.. currentmodule:: gdas.plots - -.. autosummary:: - :toctree: generated/ - - plot_activity - plot_time_series - plot_asd - plot_whitening - plot_ts - plot_spectrum - plot_spectrogram - plot_spectrogram_from_ts - plot_triggers - -Excess Power Search Analysis ----------------------------- - -Main class to do excess-power search analysis - -.. currentmodule:: gdas.epower - -.. autosummary:: - :toctree: generated/ - - excess_power - check_filtering_settings - calculate_psd - calculate_spectral_correlation - create_filter_bank - convert_to_time_domain - identify_block - create_tf_plane - compute_filter_ips_self - compute_filter_ips_adjacent - compute_channel_renormalization - measure_hrss - measure_hrss_slowly - measure_hrss_poorly - trigger_list_from_map - determine_output_segment - make_tiles - make_indp_tiles - make_filename - construct_tiles - create_tile_duration - create_xml - -Utilities ---------- - -Independent routines to do various other things - -.. currentmodule:: gdas.utils - -.. autosummary:: - :toctree: generated/ - - create_sound - - -.. _file_to_segment: - -.. ** Extract segment information -.. -.. The starting and ending UTC times for a specific HDF5 file are determined by using the =Date=, =t0= and =t1= attributes from the metadata. The [[construct_utc_from_metadata][=construct_utc_from_metadata=]] function is then used to calculate the UTC time. Finally, the [[http://software.ligo.org/docs/glue/glue.__segments.segment-class.html][=segment=]] module from the =glue.segments= library is used to represent the range of times in a semi-open interval. -.. -.. #+BEGIN_SRC python -.. def file_to_segment(hfile,segname): -.. # Extract all atributes from the data -.. attrs = hfile[segname].attrs -.. # Define each attribute -.. dstr, t0, t1 = attrs["Date"], attrs["t0"], attrs["t1"] -.. # Construct GPS starting time from data -.. start_utc = construct_utc_from_metadata(dstr, t0) -.. # Construct GPS starting time from data -.. end_utc = construct_utc_from_metadata(dstr, t1) -.. # Represent the range of times in the semi-open interval -.. return segment(start_utc,end_utc) -.. #+END_SRC -.. -.. ** Constructing UTC from metadata -.. <> -.. -.. #+BEGIN_SRC python -.. def construct_utc_from_metadata(datestr, t0str): -.. instr = "%d-%d-%02dT" % tuple(map(int, datestr.split('/'))) -.. instr += t0str -.. t = Time(instr, format='isot', scale='utc') -.. return t.gps -.. #+END_SRC -.. -.. ** Generate time series -.. <> -.. -.. #+BEGIN_SRC python -.. def generate_timeseries(data_list, setname="MagneticFields"): -.. full_data = TimeSeriesList() -.. for seg in sorted(data_list): -.. hfile = h5py.File(data_list[seg], "r") -.. full_data.append(retrieve_data_timeseries(hfile, "MagneticFields")) -.. hfile.close() -.. return full_data -.. #+END_SRC -.. -.. ** Retrieve data time series -.. <> -.. -.. #+BEGIN_SRC python -.. def retrieve_data_timeseries(hfile, setname): -.. dset = hfile[setname] -.. sample_rate = dset.attrs["SamplingRate(Hz)"] -.. gps_epoch = construct_utc_from_metadata(dset.attrs["Date"], dset.attrs["t0"]) -.. data = retrieve_channel_data(hfile, setname) -.. ts_data = TimeSeries(data, sample_rate=sample_rate, epoch=gps_epoch) -.. return ts_data -.. #+END_SRC -.. -.. ** Retrieve channel data -.. <> -.. -.. #+BEGIN_SRC python -.. def retrieve_channel_data(hfile, setname): -.. return hfile[setname][:] -.. #+END_SRC -.. -.. .. _calculate_spectral_correlation: -.. -.. ** Two point spectral correlation -.. -.. For our data, we apply a Tukey window whose flat bit corresponds to =window_fraction= (in percentage) of the segment length (in samples) used for PSD estimation (i.e. =fft_window_len=). This can be done by using the [[http://software.ligo.org/docs/lalsuite/lal/_window_8c_source.html#l00597][=CreateTukeyREAL8Window=]] module from the =lal= library. -.. -.. #+BEGIN_SRC python -.. def calculate_spectral_correlation(fft_window_len, wtype='hann', window_fraction=None): -.. if wtype == 'hann': -.. window = lal.CreateHannREAL8Window(fft_window_len) -.. elif wtype == 'tukey': -.. window = lal.CreateTukeyREAL8Window(fft_window_len, window_fraction) -.. else: -.. raise ValueError("Can't handle window type %s" % wtype) -.. #+END_SRC -.. -.. Once the window is built, a new frequency plan is created which will help performing a [[http://fourier.eng.hmc.edu/e101/lectures/fourier_transform_d/node1.html][forward transform]] on the data. This is done with the [[http://software.ligo.org/docs/lalsuite/lal/group___real_f_f_t__h.html#gac4413752db2d19cbe48742e922670af4][=CreateForwardREAL8FFTPlan=]] module which takes as argument the total number of points in the real data and the measurement level for plan creation (here 1 stands for measuring the best plan). -.. -.. #+BEGIN_SRC python -.. fft_plan = lal.CreateForwardREAL8FFTPlan(len(window.data.data), 1) -.. #+END_SRC -.. -.. We can finally compute and return the two-point spectral correlation function for the whitened frequency series (=fft_plan=) from the window applied to the original time series using the [[http://software.ligo.org/docs/lalsuite/lal/group___time_freq_f_f_t__h.html#ga2bd5c4258eff57cc80103d2ed489e076][=REAL8WindowTwoPointSpectralCorrelation=]] module. -.. -.. #+BEGIN_SRC python -.. return window, lal.REAL8WindowTwoPointSpectralCorrelation(window, fft_plan) -.. #+END_SRC -.. -.. ** Create filter bank -.. <> -.. -.. The construction of a filter bank is fairly simple. For each channel, a frequency domain channel filter function will be created using the [[http://software.ligo.org/docs/lalsuite/lalburst/group___e_p_search__h.html#ga899990cbd45111ba907772650c265ec9][=CreateExcessPowerFilter=]] module from the =lalburst= package. Each channel filter is divided by the square root of the PSD frequency series prior to normalization, which has the effect of de-emphasizing frequency bins with high noise content, and is called "over whitening". The data and metadata are finally stored in the =filter_fseries= and =filter_bank= arrays respectively. Finally, we store on a final array, called =np_filters= the all time-series generated from each filter so that we can plot them afterwards -.. -.. #+BEGIN_SRC python -.. def create_filter_bank(delta_f, flow, band, nchan, psd, spec_corr): -.. lal_psd = psd.lal() -.. lal_filters, np_filters = [],[] -.. for i in range(nchan): -.. lal_filter = lalburst.CreateExcessPowerFilter(flow + i*band, band, lal_psd, spec_corr) -.. np_filters.append(Spectrum.from_lal(lal_filter)) -.. lal_filters.append(lal_filter) -.. return filter_fseries, lal_filters, np_filters -.. #+END_SRC -.. -.. ** Compute filter inner products with themselves -.. <> -.. #+BEGIN_SRC python -.. def compute_filter_ips_self(lal_filters, spec_corr, psd=None): -.. """ -.. Compute a set of inner products of input filters with themselves. If psd -.. argument is given, the unwhitened filter inner products will be returned. -.. """ -.. return numpy.array([lalburst.ExcessPowerFilterInnerProduct(f, f, spec_corr, psd) for f in lal_filters]) -.. #+END_SRC -.. -.. ** Compute filter inner products with adjecant filters -.. <> -.. -.. #+BEGIN_SRC python -.. def compute_filter_ips_adjacent(lal_filters, spec_corr, psd=None): -.. """ -.. Compute a set of filter inner products between input adjacent filters. -.. If psd argument is given, the unwhitened filter inner products will be -.. returned. The returned array index is the inner product between the -.. lal_filter of the same index, and its (array) adjacent filter --- assumed -.. to be the frequency adjacent filter. -.. """ -.. return numpy.array([lalburst.ExcessPowerFilterInnerProduct(f1, f2, spec_corr, psd) for f1, f2 in zip(lal_filters[:-1], lal_filters[1:])]) -.. #+END_SRC -.. -.. .. _compute_channel_renomalization: -.. -.. Compute channel renormalization -.. ------------------------------- -.. -.. Compute the renormalization for the base filters up to a given bandwidth. -.. -.. #+BEGIN_SRC python -.. def compute_channel_renomalization(nc_sum, lal_filters, spec_corr, nchans, verbose=True): -.. mu_sq = (nc_sum+1)*numpy.array([lalburst.ExcessPowerFilterInnerProduct(f, f, spec_corr, None) for f in lal_filters]) -.. # Uncomment to get all possible frequency renormalizations -.. #for n in xrange(nc_sum, nchans): # channel position index -.. for n in xrange(nc_sum, nchans, nc_sum+1): # channel position index -.. for k in xrange(0, nc_sum): # channel sum index -.. # FIXME: We've precomputed this, so use it instead -.. mu_sq[n] += 2*lalburst.ExcessPowerFilterInnerProduct(lal_filters[n-k], lal_filters[n-1-k], spec_corr, None) -.. #print mu_sq[nc_sum::nc_sum+1] -.. return mu_sq -.. #+END_SRC -.. -.. ** Measure root-sum-square strain (hrss) -.. <> -.. -.. #+BEGIN_SRC python -.. def measure_hrss(z_j_b, uw_ss_ii, uw_ss_ij, w_ss_ij, delta_f, delta_t, filter_len, dof): -.. """ -.. Approximation of unwhitened sum of squares signal energy in a given EP tile. -.. See T1200125 for equation number reference. -.. z_j_b - time frequency map block which the constructed tile covers -.. uw_ss_ii - unwhitened filter inner products -.. uw_ss_ij - unwhitened adjacent filter inner products -.. w_ss_ij - whitened adjacent filter inner products -.. delta_f - frequency binning of EP filters -.. delta_t - native time resolution of the time frequency map -.. filter_len - number of samples in a fitler -.. dof - degrees of freedom in the tile (twice the time-frequency area) -.. """ -.. s_j_b_avg = uw_ss_ii * delta_f / 2 -.. # unwhitened sum of squares of wide virtual filter -.. s_j_nb_avg = uw_ss_ii.sum() / 2 + uw_ss_ij.sum() -.. s_j_nb_avg *= delta_f -.. s_j_nb_denom = s_j_b_avg.sum() + 2 * 2 / filter_len * \ -.. numpy.sum(numpy.sqrt(s_j_b_avg[:-1] * s_j_b_avg[1:]) * w_ss_ij) -.. # eqn. 62 -.. uw_ups_ratio = s_j_nb_avg / s_j_nb_denom -.. # eqn. 63 -- approximation of unwhitened signal energy time series -.. # FIXME: The sum in this equation is over nothing, but indexed by frequency -.. # I'll make that assumption here too. -.. s_j_nb = numpy.sum(z_j_b.T * numpy.sqrt(s_j_b_avg), axis=0) -.. s_j_nb *= numpy.sqrt(uw_ups_ratio / filter_len * 2) -.. # eqn. 64 -- approximate unwhitened signal energy minus noise contribution -.. # FIXME: correct axis of summation? -.. return math.sqrt(numpy.sum(numpy.absolute(s_j_nb)**2) * delta_t - s_j_nb_avg * dof * delta_t) -.. #+END_SRC -.. -.. ** Unwhitened inner products filtering -.. <> -.. -.. #+BEGIN_SRC python -.. # < s^2_j(f_1, b) > = 1 / 2 / N * \delta_t EPIP{\Theta, \Theta; P} -.. def uw_sum_sq(filter1, filter2, spec_corr, psd): -.. return lalburst.ExcessPowerFilterInnerProduct(filter1, filter2, spec_corr, psd) -.. #+END_SRC -.. -.. ** Unwhitened sum of squares signal -.. <> -.. -.. #+BEGIN_SRC python -.. def measure_hrss_slowly(z_j_b, lal_filters, spec_corr, psd, delta_t, dof): -.. """ -.. Approximation of unwhitened sum of squares signal energy in a given EP tile. -.. See T1200125 for equation number reference. NOTE: This function is deprecated -.. in favor of measure_hrss, since it requires recomputation of many inner products, -.. making it particularly slow. -.. """ -.. # FIXME: Make sure you sum in time correctly -.. # Number of finest bands in given tile -.. nb = len(z_j_b) -.. # eqn. 56 -- unwhitened mean square of filter with itself -.. uw_ss_ii = numpy.array([uw_sum_sq(lal_filters[i], lal_filters[i], spec_corr, psd) for i in range(nb)]) -.. s_j_b_avg = uw_ss_ii * lal_filters[0].deltaF / 2 -.. # eqn. 57 -- unwhitened mean square of filter with adjacent filter -.. uw_ss_ij = numpy.array([uw_sum_sq(lal_filters[i], lal_filters[i+1], spec_corr, psd) for i in range(nb-1)]) -.. # unwhitened sum of squares of wide virtual filter -.. s_j_nb_avg = uw_ss_ii.sum() / 2 + uw_ss_ij.sum() -.. s_j_nb_avg *= lal_filters[0].deltaF -.. -.. # eqn. 61 -.. w_ss_ij = numpy.array([uw_sum_sq(lal_filters[i], lal_filters[i+1], spec_corr, None) for i in range(nb-1)]) -.. s_j_nb_denom = s_j_b_avg.sum() + 2 * 2 / len(lal_filters[0].data.data) * \ -.. (numpy.sqrt(s_j_b_avg[:-1] * s_j_b_avg[1:]) * w_ss_ij).sum() -.. -.. # eqn. 62 -.. uw_ups_ratio = s_j_nb_avg / s_j_nb_denom -.. -.. # eqn. 63 -- approximation of unwhitened signal energy time series -.. # FIXME: The sum in this equation is over nothing, but indexed by frequency -.. # I'll make that assumption here too. -.. s_j_nb = numpy.sum(z_j_b.T * numpy.sqrt(s_j_b_avg), axis=0) -.. s_j_nb *= numpy.sqrt(uw_ups_ratio / len(lal_filters[0].data.data) * 2) -.. # eqn. 64 -- approximate unwhitened signal energy minus noise contribution -.. # FIXME: correct axis of summation? -.. return math.sqrt((numpy.absolute(s_j_nb)**2).sum() * delta_t - s_j_nb_avg * dof * delta_t) -.. #+END_SRC -.. -.. ** Measure root-mean square strain poorly -.. <> -.. -.. #+BEGIN_SRC python -.. def measure_hrss_poorly(tile_energy, sub_psd): -.. return math.sqrt(tile_energy / numpy.average(1.0 / sub_psd) / 2) -.. #+END_SRC -.. -.. ** List triggers from map -.. <> -.. -.. #+BEGIN_SRC python -.. def trigger_list_from_map(tfmap, event_list, threshold, start_time, start_freq, duration, band, df, dt, psd=None): -.. -.. # FIXME: If we don't convert this the calculation takes forever --- but we should convert it once and handle deltaF better later -.. if psd is not None: -.. npy_psd = psd.numpy() -.. -.. start_time = LIGOTimeGPS(float(start_time)) -.. ndof = 2 * duration * band -.. -.. spanf, spant = tfmap.shape[0] * df, tfmap.shape[1] * dt -.. print "Processing %.2fx%.2f time-frequency map." % (spant, spanf) -.. -.. for i, j in zip(*numpy.where(tfmap > threshold)): -.. event = event_list.RowType() -.. -.. # The points are summed forward in time and thus a `summed point' is the -.. # sum of the previous N points. If this point is above threshold, it -.. # corresponds to a tile which spans the previous N points. However, th -.. # 0th point (due to the convolution specifier 'valid') is actually -.. # already a duration from the start time. All of this means, the + -.. # duration and the - duration cancels, and the tile 'start' is, by -.. # definition, the start of the time frequency map if j = 0 -.. # FIXME: I think this needs a + dt/2 to center the tile properly -.. event.set_start(start_time + float(j * dt)) -.. event.set_stop(start_time + float(j * dt) + duration) -.. event.set_peak(event.get_start() + duration / 2) -.. event.central_freq = start_freq + i * df + 0.5 * band -.. -.. event.duration = duration -.. event.bandwidth = band -.. event.chisq_dof = ndof -.. -.. event.snr = math.sqrt(tfmap[i,j] / event.chisq_dof - 1) -.. # FIXME: Magic number 0.62 should be determine empircally -.. event.confidence = -lal.LogChisqCCDF(event.snr * 0.62, event.chisq_dof * 0.62) -.. if psd is not None: -.. # NOTE: I think the pycbc PSDs always start at 0 Hz --- check -.. psd_idx_min = int((event.central_freq - event.bandwidth / 2) / psd.delta_f) -.. psd_idx_max = int((event.central_freq + event.bandwidth / 2) / psd.delta_f) -.. -.. # FIXME: heuristically this works better with E - D -- it's all -.. # going away with the better h_rss calculation soon anyway -.. event.amplitude = measure_hrss_poorly(tfmap[i,j] - event.chisq_dof, npy_psd[psd_idx_min:psd_idx_max]) -.. else: -.. event.amplitude = None -.. -.. event.process_id = None -.. event.event_id = event_list.get_next_id() -.. event_list.append(event) -.. #+END_SRC -.. -.. ** Determine output segment -.. <> -.. -.. #+BEGIN_SRC python -.. def determine_output_segment(inseg, dt_stride, sample_rate, window_fraction=0.0): -.. """ -.. Given an input data stretch segment inseg, a data block stride dt_stride, the data sample rate, and an optional window_fraction, return the amount of data that can be processed without corruption effects from the window. -.. -.. If window_fration is set to 0 (default), assume no windowing. -.. """ -.. # Amount to overlap successive blocks so as not to lose data -.. window_overlap_samples = window_fraction * sample_rate -.. outseg = inseg.contract(window_fraction * dt_stride / 2) -.. -.. # With a given dt_stride, we cannot process the remainder of this data -.. remainder = math.fmod(abs(outseg), dt_stride * (1 - window_fraction)) -.. # ...so make an accounting of it -.. outseg = segment(outseg[0], outseg[1] - remainder) -.. return outseg -.. #+END_SRC -.. -.. ** Make tiles -.. <> -.. -.. #+BEGIN_SRC python -.. def make_tiles(tf_map, nc_sum, mu_sq): -.. tiles = numpy.zeros(tf_map.shape) -.. sum_filter = numpy.ones(nc_sum+1) -.. # Here's the deal: we're going to keep only the valid output and -.. # it's *always* going to exist in the lowest available indices -.. for t in xrange(tf_map.shape[1]): -.. # Sum and drop correlate tiles -.. # FIXME: don't drop correlated tiles -.. output = numpy.convolve(tf_map[:,t], sum_filter, 'valid')[::nc_sum+1] -.. #output = fftconvolve(tf_map[:,t], sum_filter, 'valid')[::nc_sum+1] -.. tiles[:len(output),t] = numpy.absolute(output) / math.sqrt(2) -.. return tiles[:len(output)]**2 / mu_sq[nc_sum::nc_sum+1].reshape(-1, 1) -.. #+END_SRC -.. -.. ** Create a time frequency map -.. <> -.. -.. In this function, we create a time frequency map with resolution similar than =tf_map= but rescale by a factor of =nc_sum= + 1. All tiles will be independent up to overlap from the original tiling. The =mu_sq= is applied to the resulting addition to normalize the outputs to be zero-mean unit-variance Gaussian variables (if the input is Gaussian). -.. -.. #+BEGIN_SRC python -.. def make_indp_tiles(tf_map, nc_sum, mu_sq): -.. tiles = tf_map.copy() -.. # Here's the deal: we're going to keep only the valid output and -.. # it's *always* going to exist in the lowest available indices -.. stride = nc_sum + 1 -.. for i in xrange(tiles.shape[0]/stride): -.. numpy.absolute(tiles[stride*i:stride*(i+1)].sum(axis=0), tiles[stride*(i+1)-1]) -.. return tiles[nc_sum::nc_sum+1].real**2 / mu_sq[nc_sum::nc_sum+1].reshape(-1, 1) -.. #+END_SRC -.. -.. ** Create output filename -.. <> -.. -.. #+BEGIN_SRC python -.. def make_filename(ifo, seg, tag="excesspower", ext="xml.gz"): -.. if isinstance(ifo, str): -.. ifostr = ifo -.. else: -.. ifostr = "".join(ifo) -.. st_rnd, end_rnd = int(math.floor(seg[0])), int(math.ceil(seg[1])) -.. dur = end_rnd - st_rnd -.. return "%s-%s-%d-%d.%s" % (ifostr, tag, st_rnd, dur, ext) -.. #+END_SRC - diff --git a/docs/_sources/backup/excess_power.rst.txt b/docs/_sources/backup/excess_power.rst.txt deleted file mode 100644 index 8f18ff6..0000000 --- a/docs/_sources/backup/excess_power.rst.txt +++ /dev/null @@ -1,697 +0,0 @@ -.. _analysingblocks: - -Define analysing blocks ------------------------ - -The first thing we do is to calculate the time series for the segment that is covered (``tmp_ts_data``) and redefined the metadata, especially the time of the first sample in seconds which is defined by the ``epoch`` argument and is different for every segment. After plotting the time series for that segment, the data are then converted into frequency series (``fs_data``) using the `to_frequencyseries `_ module from the ``pycbc.types.timeseries.TimeSeries`` library. Finally, the frequency data are then whitened. :: - - # Loop over each data within the user requested time period - while t_idx_max <= t_idx_max_off: - # Define starting and ending time of the segment in seconds - start_time = ts_data.start_time + t_idx_min/float(args.sample_rate) - end_time = ts_data.start_time + t_idx_max/float(args.sample_rate) - print tprint(t0,t1),"Analyzing block %i to %i (%.2f percent)"%(start_time,end_time,100*float(t_idx_max)/float(idx_max_off)) - # Model a withen time series for the block - tmp_ts_data = types.TimeSeries(ts_data[t_idx_min:t_idx_max]*window, 1.0/args.sample_rate,epoch=start_time) - # Save time series in segment repository - segfolder = 'segments/%i-%i'%(start_time,end_time) - os.system('mkdir -p '+segfolder) - plot_ts(tmp_ts_data,fname='%s/ts.png'%(segfolder)) - # Convert times series to frequency series - fs_data = tmp_ts_data.to_frequencyseries() - print tprint(t0,t1),"Frequency series data has variance: %s" % fs_data.data.std()**2 - # Whitening (FIXME: Whiten the filters, not the data) - fs_data.data /= numpy.sqrt(fd_psd) / numpy.sqrt(2 * fd_psd.delta_f) - print tprint(t0,t1),"Whitened frequency series data has variance: %s" % fs_data.data.std()**2 - -Create time-frequency map for each block ----------------------------------------- - -We initialise a 2D zero array for a time-frequency map (``tf_map``) which will be computed for each frequency-domain filter associated to each PSD segment and where the filtered time-series for each frequency channels will be stored. The number of rows corresponds to the total number of frequency channels which is defined by the ``nchans`` variable. The number of columns corresponds to the segment length in samples (i.e. the number of samples covering one segment) which is defined by the ``seg_len`` variable. :: - - # Initialise 2D zero array for time-frequency map - tf_map = numpy.zeros((nchans, seg_len), dtype=numpy.complex128) - -We also initialise a zero vector for a temporary filter bank (``tmp_filter_bank``) that will store, for a given channel, the filter's values from the original filter bank (``filter_bank``) for that channel only. The length of the temporary filter bank is equal to the length of the PSD frequency series (``fd_psd``). :: - - # Initialise 1D zero array - tmp_filter_bank = numpy.zeros(len(fd_psd), dtype=numpy.complex128) - -We then loop over all the frequency channels. While in the loop, we first re-initialise the temporary filter bank with zero values everywhere along the frequency series. We then determine the first and last frequency of each channel and re-define the values of the filter in that frequency range based on the values from the original channel's filter from the original filter bank. :: - - # Loop over all the channels - print tprint(t0,t1),"Filtering all %d channels..." % nchans - for i in range(nchans): - # Reset filter bank series - tmp_filter_bank *= 0.0 - # Index of starting frequency - f1 = int(filter_bank[i].f0/fd_psd.delta_f) - # Index of ending frequency - f2 = int((filter_bank[i].f0 + 2*band)/fd_psd.delta_f)+1 - # (FIXME: Why is there a factor of 2 here?) - tmp_filter_bank[f1:f2] = filter_bank[i].data.data * 2 - -We then extract the frequency series from the filter bank for that channel, which will be used as a template waveform to filter the actual data from the channel. :: - - # Define the template to filter the frequency series with - template = types.FrequencySeries(tmp_filter_bank, delta_f=fd_psd.delta_f, copy=False) - -Finally, we use the `matched_filter_core `_ module from the ``pycbc.filter.matchedfilter`` library to filter the frequency series from the channel. This will return both a time series containing the complex signal-to-noise matched filtered against the data, and a frequency series containing the correlation vector. :: - - # Create filtered series - filtered_series = filter.matched_filter_core(template,fs_data,h_norm=None,psd=None, - low_frequency_cutoff=filter_bank[i].f0, - high_frequency_cutoff=filter_bank[i].f0+2*band) - -The `matched filter `_ is the optimal linear filter for maximizing the signal to noise ratio (SNR) in the presence of additive stochastic noise. The filtered time series is stored in the time-frequency map and can be used to produce a spectrogram of the segment of data being analysed. :: - - # Include filtered series in the map - tf_map[i,:] = filtered_series[0].numpy() - -The time-frequency map is a 2D array with a length that corresponds to the number of channels and a width equal to the number of sample present in one segment of data, i.e. segment's length in seconds times the the sampling rate. The map can finally be plotted with a :math:`\Delta t` corresponding to the sampling period of the original dataset (i.e. inverse of the original sampling rate), and :math:`\Delta f` is equal to the bandwidth of one channel. :: - - plot_spectrogram(numpy.abs(tf_map).T,tmp_ts_data.delta_t,fd_psd.delta_f,ts_data.sample_rate,start_time,end_time,fname='%s/tf.png'%(segfolder)) - -.. _tilebandwidth: - -Constructing tiles of different bandwidth ------------------------------------------ - -First and foremost, we define a clipping region in the data to be used to remove window corruption, this is non-zero if the ``window_fraction`` variable is set to a non-zero value. :: - - print tprint(t0,t1),"Beginning tile construction..." - # Clip the boundaries to remove window corruption - clip_samples = int(args.psd_segment_length * window_fraction * args.sample_rate / 2) - -In order to perform a multi-resolution search, tiles of many different bandwidths and durations will be scanned. We first need to setup a loop such that the maximum number of additional channel is equal to the base 2 logarithm of the total number of channels. The number of narrow band channels to be summed (``nc_sum``) would therefore be equal to 2 to the power of the current quantity of additional channels. :: - - for nc_sum in range(0, int(math.log(nchans, 2)))[::-1]: # nc_sum additional channel adds - nc_sum = 2**nc_sum - 1 - print tprint(t0,t1,t2),"Summing %d narrow band channels..." % (nc_sum+1) - -The undersampling rate for this tile can be calculated using the channel frequency band and the number of narrow band channels to be summed such that the bandwidth of the tile is equal to ``band * (nc_sum + 1)``. :: - - us_rate = int(round(1.0 / (2 * band*(nc_sum+1) * ts_data.delta_t))) - print >>sys.stderr, "Undersampling rate for this level: %f" % (args.sample_rate/us_rate) - -"Virtual" wide bandwidth channels are constructed by summing the samples from multiple channels, and correcting for the overlap between adjacent channel filters. We then define the normalised channel at the current level and create a time frequency map for this tile using the :ref:`make_indp_tiles ` internal function. In other word, we are constructing multiple sub-tiles for which we can determined the respective energy in the given frequency band. :: - - mu_sq = mu_sq_dict[nc_sum] - sys.stderr.write("\t...calculating tiles...") - if clip_samples > 0: - tiles = make_indp_tiles(tf_map[:,clip_samples:-clip_samples:us_rate], nc_sum, mu_sq) - else: - tiles = make_indp_tiles(tf_map[:,::us_rate], nc_sum, mu_sq) - sys.stderr.write(" TF-plane is %dx%s samples... " % tiles.shape) - print >>sys.stderr, " done" - print "Tile energy mean: %f, var %f" % (numpy.mean(tiles), numpy.var(tiles)) - -.. _tileduration: - -Explore multiple tile durations -------------------------------- - -Now that we create a tile with a specific bandwidth, we can start exploring different durations for the tile. We will start checking if the user manually defined a value for the longest duration tile to compute, which can be done using the ``--max-duration`` argument. If not, the value will be set to 32. :: - - if args.max_duration is not None: - max_dof = 2 * args.max_duration * (band * (nc_sum+1)) - else: - max_dof = 32 - assert max_dof >= 2 - -Since we produce (initially) tiles with 1 degree of freedom, the duration goes as one over twice the bandwidth. :: - - print "\t\t...getting longer durations..." - #for j in [2**l for l in xrange(1, int(math.log(max_dof, 2))+1)]: - for j in [2**l for l in xrange(0, int(math.log(max_dof, 2)))]: - sys.stderr.write("\t\tSumming DOF = %d ..." % (2*j)) - #tlen = tiles.shape[1] - j + 1 - tlen = tiles.shape[1] - 2*j + 1 + 1 - if tlen <= 0: - print >>sys.stderr, " ...not enough samples." - continue - dof_tiles = numpy.zeros((tiles.shape[0], tlen)) - #:sum_filter = numpy.ones(j) - # FIXME: This is the correct filter for 50% overlap - sum_filter = numpy.array([1,0] * (j-1) + [1]) - #sum_filter = numpy.array([1,0] * int(math.log(j, 2)-1) + [1]) - for f in range(tiles.shape[0]): - # Sum and drop correlate tiles - # FIXME: don't drop correlated tiles - #output = numpy.convolve(tiles[f,:], sum_filter, 'valid') - dof_tiles[f] = fftconvolve(tiles[f], sum_filter, 'valid') - print >>sys.stderr, " done" - print "Summed tile energy mean: %f, var %f" % (numpy.mean(dof_tiles), numpy.var(dof_tiles)) - level_tdiff = time.time() - tdiff - print >>sys.stderr, "Done with this resolution, total %f" % level_tdiff - -Finally, the bandwidth and duration of the tile can be defined as followed: :: - - # Current bandwidth of the time-frequency map tiles - current_band = band * (nc_sum + 1) - # How much each "step" is in the frequency domain -- almost - # assuredly the fundamental bandwidth - df = current_band - # How much each "step" is in the time domain -- under sampling rate - # FIXME: THis won't work if the sample rate isn't a power of 2 - dt = 1.0 / 2 / (2 * current_band) * 2 - full_band = 250 - dt = current_band / full_band * ts_data.sample_rate - dt = 1.0/dt - # Duration is fixed by the NDOF and bandwidth - duration = j / 2.0 / current_band - -.. _triggerfinding: - -Trigger finding ---------------- - -In order to find any trigger in the data, we first need to set a false alarm probability threshold in Gaussian noise above which signal will be distinguished from the noise. Such threshold can be determined by using the /inverse survival function/ method from the `scipy.stats.chi2 `_ package. :: - - threshold = scipy.stats.chi2.isf(args.tile_fap, j) - print "Threshold for this level: %f" % threshold - #if numpy.any(dof_tiles > threshold): - #plot_spectrogram(dof_tiles.T) - #import pdb; pdb.set_trace() - -Once the threshold is set, one can then run the :ref:`trigger_list_from_map ` function to quickly find the trigger signal from the ``dof_tiles`` array that :: - - # Since we clip the data, the start time needs to be adjusted accordingly - window_offset_epoch = fs_data.epoch + args.psd_segment_length * window_fraction / 2 - trigger_list_from_map(dof_tiles, event_list, threshold, window_offset_epoch, filter_bank[0].f0 + band/2, duration, current_band, df, dt, None) - for event in event_list[::-1]: - if event.amplitude != None: - continue - etime_min_idx = float(event.get_start()) - float(fs_data.epoch) - etime_min_idx = int(etime_min_idx / tmp_ts_data.delta_t) - etime_max_idx = float(event.get_start()) - float(fs_data.epoch) + event.duration - etime_max_idx = int(etime_max_idx / tmp_ts_data.delta_t) - # (band / 2) to account for sin^2 wings from finest filters - flow_idx = int((event.central_freq - event.bandwidth / 2 - (band / 2) - flow) / band) - fhigh_idx = int((event.central_freq + event.bandwidth / 2 + (band / 2) - flow) / band) - # TODO: Check that the undersampling rate is always commensurate - # with the indexing: that is to say that - # mod(etime_min_idx, us_rate) == 0 always - z_j_b = tf_map[flow_idx:fhigh_idx,etime_min_idx:etime_max_idx:us_rate] - # FIXME: Deal with negative hrss^2 -- e.g. remove the event - try: - event.amplitude = measure_hrss(z_j_b, unwhite_filter_ip[flow_idx:fhigh_idx], unwhite_ss_ip[flow_idx:fhigh_idx-1], white_ss_ip[flow_idx:fhigh_idx-1], fd_psd.delta_f, tmp_ts_data.delta_t, len(filter_bank[0].data.data), event.chisq_dof) - except ValueError: - event.amplitude = 0 - - print "Total number of events: %d" % len(event_list) - -Switch to new block -------------------- - -The following will move the frequency band to the next segment: :: - - tdiff = time.time() - tdiff - print "Done with this block: total %f" % tdiff - - t_idx_min += int(seg_len * (1 - window_fraction)) - t_idx_max += int(seg_len * (1 - window_fraction)) - -Extracting GPS time range -------------------------- - -We use the `LIGOTimeGPS `_ structure from the =glue.lal= package to /store the starting and ending time in the dataset to nanosecond precision and synchronized to the Global Positioning System time reference/. Once both times are defined, the range of value is stored in a semi-open interval using the `segment `_ module from the =glue.segments= package. :: - - # Starting epoch relative to GPS starting epoch - start_time = LIGOTimeGPS(args.analysis_start_time or args.gps_start_time) - # Ending epoch relative to GPS ending epoch - end_time = LIGOTimeGPS(args.analysis_end_time or args.gps_end_time) - # Represent the range of values in the semi-open interval - inseg = segment(start_time,end_time) - -Prepare output file for given time range ----------------------------------------- - -:: - - xmldoc = ligolw.Document() - xmldoc.appendChild(ligolw.LIGO_LW()) - - ifo = args.channel_name.split(":")[0] - proc_row = register_to_xmldoc(xmldoc, __program__, args.__dict__, ifos=[ifo],version=glue.git_version.id, cvs_repository=glue.git_version.branch, cvs_entry_time=glue.git_version.date) - - # Figure out the data we actually analyzed - outseg = determine_output_segment(inseg, args.psd_segment_length, args.sample_rate, window_fraction) - - ss = append_search_summary(xmldoc, proc_row, ifos=(station,), inseg=inseg, outseg=outseg) - - for sb in event_list: - sb.process_id = proc_row.process_id - sb.search = proc_row.program - #sb.ifo, sb.channel = args.channel_name.split(":") - sb.ifo, sb.channel = station, setname - - xmldoc.childNodes[0].appendChild(event_list) - fname = make_filename(station, inseg) - - utils.write_filename(xmldoc, fname, gz=fname.endswith("gz"), verbose=True) - -Plot trigger results --------------------- - -:: - - events = SnglBurstTable.read(fname+'.gz') - #del events[10000:] - plot = events.plot('time', 'central_freq', "duration", "bandwidth", color="snr") - #plot = events.plot('time', 'central_freq', color='snr') - #plot.set_yscale("log") - plot.set_ylim(1e-0, 250) - t0 = 1153742417 - plot.set_xlim(t0 + 0*60, t0 + 1*60) - #plot.set_xlim(t0 + 28, t0 + 32) - pyplot.axvline(t0 + 30, color='r') - cb = plot.add_colorbar(cmap='viridis') - plot.savefig("triggers.png") - -Module Access -============= - -Extract Magnetic Field Data ---------------------------- - -Extract magnetic field data from HDF5 files. - -.. currentmodule:: gdas.retrieve - -.. autosummary:: - :toctree: generated/ - - magfield - file_to_segment - construct_utc_from_metadata - generate_timeseries - create_activity_list - retrieve_data_timeseries - retrieve_channel_data - -Plotting routines ------------------ - -Methods to produce time-frequency plots and others - -.. currentmodule:: gdas.plots - -.. autosummary:: - :toctree: generated/ - - plot_activity - plot_time_series - plot_asd - plot_whitening - plot_ts - plot_spectrum - plot_spectrogram - plot_spectrogram_from_ts - plot_triggers - -Utilities ---------- - -Independent routines to do various other things - -.. currentmodule:: gdas.utils - -.. autosummary:: - :toctree: generated/ - - create_sound - - -.. _file_to_segment: - -.. ** Extract segment information -.. -.. The starting and ending UTC times for a specific HDF5 file are determined by using the =Date=, =t0= and =t1= attributes from the metadata. The [[construct_utc_from_metadata][=construct_utc_from_metadata=]] function is then used to calculate the UTC time. Finally, the [[http://software.ligo.org/docs/glue/glue.__segments.segment-class.html][=segment=]] module from the =glue.segments= library is used to represent the range of times in a semi-open interval. -.. -.. #+BEGIN_SRC python -.. def file_to_segment(hfile,segname): -.. # Extract all atributes from the data -.. attrs = hfile[segname].attrs -.. # Define each attribute -.. dstr, t0, t1 = attrs["Date"], attrs["t0"], attrs["t1"] -.. # Construct GPS starting time from data -.. start_utc = construct_utc_from_metadata(dstr, t0) -.. # Construct GPS starting time from data -.. end_utc = construct_utc_from_metadata(dstr, t1) -.. # Represent the range of times in the semi-open interval -.. return segment(start_utc,end_utc) -.. #+END_SRC -.. -.. ** Constructing UTC from metadata -.. <> -.. -.. #+BEGIN_SRC python -.. def construct_utc_from_metadata(datestr, t0str): -.. instr = "%d-%d-%02dT" % tuple(map(int, datestr.split('/'))) -.. instr += t0str -.. t = Time(instr, format='isot', scale='utc') -.. return t.gps -.. #+END_SRC -.. -.. ** Generate time series -.. <> -.. -.. #+BEGIN_SRC python -.. def generate_timeseries(data_list, setname="MagneticFields"): -.. full_data = TimeSeriesList() -.. for seg in sorted(data_list): -.. hfile = h5py.File(data_list[seg], "r") -.. full_data.append(retrieve_data_timeseries(hfile, "MagneticFields")) -.. hfile.close() -.. return full_data -.. #+END_SRC -.. -.. ** Retrieve data time series -.. <> -.. -.. #+BEGIN_SRC python -.. def retrieve_data_timeseries(hfile, setname): -.. dset = hfile[setname] -.. sample_rate = dset.attrs["SamplingRate(Hz)"] -.. gps_epoch = construct_utc_from_metadata(dset.attrs["Date"], dset.attrs["t0"]) -.. data = retrieve_channel_data(hfile, setname) -.. ts_data = TimeSeries(data, sample_rate=sample_rate, epoch=gps_epoch) -.. return ts_data -.. #+END_SRC -.. -.. ** Retrieve channel data -.. <> -.. -.. #+BEGIN_SRC python -.. def retrieve_channel_data(hfile, setname): -.. return hfile[setname][:] -.. #+END_SRC -.. -.. .. _calculate_spectral_correlation: -.. -.. ** Two point spectral correlation -.. -.. For our data, we apply a Tukey window whose flat bit corresponds to =window_fraction= (in percentage) of the segment length (in samples) used for PSD estimation (i.e. =fft_window_len=). This can be done by using the [[http://software.ligo.org/docs/lalsuite/lal/_window_8c_source.html#l00597][=CreateTukeyREAL8Window=]] module from the =lal= library. -.. -.. #+BEGIN_SRC python -.. def calculate_spectral_correlation(fft_window_len, wtype='hann', window_fraction=None): -.. if wtype == 'hann': -.. window = lal.CreateHannREAL8Window(fft_window_len) -.. elif wtype == 'tukey': -.. window = lal.CreateTukeyREAL8Window(fft_window_len, window_fraction) -.. else: -.. raise ValueError("Can't handle window type %s" % wtype) -.. #+END_SRC -.. -.. Once the window is built, a new frequency plan is created which will help performing a [[http://fourier.eng.hmc.edu/e101/lectures/fourier_transform_d/node1.html][forward transform]] on the data. This is done with the [[http://software.ligo.org/docs/lalsuite/lal/group___real_f_f_t__h.html#gac4413752db2d19cbe48742e922670af4][=CreateForwardREAL8FFTPlan=]] module which takes as argument the total number of points in the real data and the measurement level for plan creation (here 1 stands for measuring the best plan). -.. -.. #+BEGIN_SRC python -.. fft_plan = lal.CreateForwardREAL8FFTPlan(len(window.data.data), 1) -.. #+END_SRC -.. -.. We can finally compute and return the two-point spectral correlation function for the whitened frequency series (=fft_plan=) from the window applied to the original time series using the [[http://software.ligo.org/docs/lalsuite/lal/group___time_freq_f_f_t__h.html#ga2bd5c4258eff57cc80103d2ed489e076][=REAL8WindowTwoPointSpectralCorrelation=]] module. -.. -.. #+BEGIN_SRC python -.. return window, lal.REAL8WindowTwoPointSpectralCorrelation(window, fft_plan) -.. #+END_SRC -.. -.. ** Create filter bank -.. <> -.. -.. The construction of a filter bank is fairly simple. For each channel, a frequency domain channel filter function will be created using the [[http://software.ligo.org/docs/lalsuite/lalburst/group___e_p_search__h.html#ga899990cbd45111ba907772650c265ec9][=CreateExcessPowerFilter=]] module from the =lalburst= package. Each channel filter is divided by the square root of the PSD frequency series prior to normalization, which has the effect of de-emphasizing frequency bins with high noise content, and is called "over whitening". The data and metadata are finally stored in the =filter_fseries= and =filter_bank= arrays respectively. Finally, we store on a final array, called =np_filters= the all time-series generated from each filter so that we can plot them afterwards -.. -.. #+BEGIN_SRC python -.. def create_filter_bank(delta_f, flow, band, nchan, psd, spec_corr): -.. lal_psd = psd.lal() -.. lal_filters, np_filters = [],[] -.. for i in range(nchan): -.. lal_filter = lalburst.CreateExcessPowerFilter(flow + i*band, band, lal_psd, spec_corr) -.. np_filters.append(Spectrum.from_lal(lal_filter)) -.. lal_filters.append(lal_filter) -.. return filter_fseries, lal_filters, np_filters -.. #+END_SRC -.. -.. ** Compute filter inner products with themselves -.. <> -.. #+BEGIN_SRC python -.. def compute_filter_ips_self(lal_filters, spec_corr, psd=None): -.. """ -.. Compute a set of inner products of input filters with themselves. If psd -.. argument is given, the unwhitened filter inner products will be returned. -.. """ -.. return numpy.array([lalburst.ExcessPowerFilterInnerProduct(f, f, spec_corr, psd) for f in lal_filters]) -.. #+END_SRC -.. -.. ** Compute filter inner products with adjecant filters -.. <> -.. -.. #+BEGIN_SRC python -.. def compute_filter_ips_adjacent(lal_filters, spec_corr, psd=None): -.. """ -.. Compute a set of filter inner products between input adjacent filters. -.. If psd argument is given, the unwhitened filter inner products will be -.. returned. The returned array index is the inner product between the -.. lal_filter of the same index, and its (array) adjacent filter --- assumed -.. to be the frequency adjacent filter. -.. """ -.. return numpy.array([lalburst.ExcessPowerFilterInnerProduct(f1, f2, spec_corr, psd) for f1, f2 in zip(lal_filters[:-1], lal_filters[1:])]) -.. #+END_SRC -.. -.. .. _compute_channel_renomalization: -.. -.. Compute channel renormalization -.. ------------------------------- -.. -.. Compute the renormalization for the base filters up to a given bandwidth. -.. -.. #+BEGIN_SRC python -.. def compute_channel_renomalization(nc_sum, lal_filters, spec_corr, nchans, verbose=True): -.. mu_sq = (nc_sum+1)*numpy.array([lalburst.ExcessPowerFilterInnerProduct(f, f, spec_corr, None) for f in lal_filters]) -.. # Uncomment to get all possible frequency renormalizations -.. #for n in xrange(nc_sum, nchans): # channel position index -.. for n in xrange(nc_sum, nchans, nc_sum+1): # channel position index -.. for k in xrange(0, nc_sum): # channel sum index -.. # FIXME: We've precomputed this, so use it instead -.. mu_sq[n] += 2*lalburst.ExcessPowerFilterInnerProduct(lal_filters[n-k], lal_filters[n-1-k], spec_corr, None) -.. #print mu_sq[nc_sum::nc_sum+1] -.. return mu_sq -.. #+END_SRC -.. -.. ** Measure root-sum-square strain (hrss) -.. <> -.. -.. #+BEGIN_SRC python -.. def measure_hrss(z_j_b, uw_ss_ii, uw_ss_ij, w_ss_ij, delta_f, delta_t, filter_len, dof): -.. """ -.. Approximation of unwhitened sum of squares signal energy in a given EP tile. -.. See T1200125 for equation number reference. -.. z_j_b - time frequency map block which the constructed tile covers -.. uw_ss_ii - unwhitened filter inner products -.. uw_ss_ij - unwhitened adjacent filter inner products -.. w_ss_ij - whitened adjacent filter inner products -.. delta_f - frequency binning of EP filters -.. delta_t - native time resolution of the time frequency map -.. filter_len - number of samples in a fitler -.. dof - degrees of freedom in the tile (twice the time-frequency area) -.. """ -.. s_j_b_avg = uw_ss_ii * delta_f / 2 -.. # unwhitened sum of squares of wide virtual filter -.. s_j_nb_avg = uw_ss_ii.sum() / 2 + uw_ss_ij.sum() -.. s_j_nb_avg *= delta_f -.. s_j_nb_denom = s_j_b_avg.sum() + 2 * 2 / filter_len * \ -.. numpy.sum(numpy.sqrt(s_j_b_avg[:-1] * s_j_b_avg[1:]) * w_ss_ij) -.. # eqn. 62 -.. uw_ups_ratio = s_j_nb_avg / s_j_nb_denom -.. # eqn. 63 -- approximation of unwhitened signal energy time series -.. # FIXME: The sum in this equation is over nothing, but indexed by frequency -.. # I'll make that assumption here too. -.. s_j_nb = numpy.sum(z_j_b.T * numpy.sqrt(s_j_b_avg), axis=0) -.. s_j_nb *= numpy.sqrt(uw_ups_ratio / filter_len * 2) -.. # eqn. 64 -- approximate unwhitened signal energy minus noise contribution -.. # FIXME: correct axis of summation? -.. return math.sqrt(numpy.sum(numpy.absolute(s_j_nb)**2) * delta_t - s_j_nb_avg * dof * delta_t) -.. #+END_SRC -.. -.. ** Unwhitened inner products filtering -.. <> -.. -.. #+BEGIN_SRC python -.. # < s^2_j(f_1, b) > = 1 / 2 / N * \delta_t EPIP{\Theta, \Theta; P} -.. def uw_sum_sq(filter1, filter2, spec_corr, psd): -.. return lalburst.ExcessPowerFilterInnerProduct(filter1, filter2, spec_corr, psd) -.. #+END_SRC -.. -.. ** Unwhitened sum of squares signal -.. <> -.. -.. #+BEGIN_SRC python -.. def measure_hrss_slowly(z_j_b, lal_filters, spec_corr, psd, delta_t, dof): -.. """ -.. Approximation of unwhitened sum of squares signal energy in a given EP tile. -.. See T1200125 for equation number reference. NOTE: This function is deprecated -.. in favor of measure_hrss, since it requires recomputation of many inner products, -.. making it particularly slow. -.. """ -.. # FIXME: Make sure you sum in time correctly -.. # Number of finest bands in given tile -.. nb = len(z_j_b) -.. # eqn. 56 -- unwhitened mean square of filter with itself -.. uw_ss_ii = numpy.array([uw_sum_sq(lal_filters[i], lal_filters[i], spec_corr, psd) for i in range(nb)]) -.. s_j_b_avg = uw_ss_ii * lal_filters[0].deltaF / 2 -.. # eqn. 57 -- unwhitened mean square of filter with adjacent filter -.. uw_ss_ij = numpy.array([uw_sum_sq(lal_filters[i], lal_filters[i+1], spec_corr, psd) for i in range(nb-1)]) -.. # unwhitened sum of squares of wide virtual filter -.. s_j_nb_avg = uw_ss_ii.sum() / 2 + uw_ss_ij.sum() -.. s_j_nb_avg *= lal_filters[0].deltaF -.. -.. # eqn. 61 -.. w_ss_ij = numpy.array([uw_sum_sq(lal_filters[i], lal_filters[i+1], spec_corr, None) for i in range(nb-1)]) -.. s_j_nb_denom = s_j_b_avg.sum() + 2 * 2 / len(lal_filters[0].data.data) * \ -.. (numpy.sqrt(s_j_b_avg[:-1] * s_j_b_avg[1:]) * w_ss_ij).sum() -.. -.. # eqn. 62 -.. uw_ups_ratio = s_j_nb_avg / s_j_nb_denom -.. -.. # eqn. 63 -- approximation of unwhitened signal energy time series -.. # FIXME: The sum in this equation is over nothing, but indexed by frequency -.. # I'll make that assumption here too. -.. s_j_nb = numpy.sum(z_j_b.T * numpy.sqrt(s_j_b_avg), axis=0) -.. s_j_nb *= numpy.sqrt(uw_ups_ratio / len(lal_filters[0].data.data) * 2) -.. # eqn. 64 -- approximate unwhitened signal energy minus noise contribution -.. # FIXME: correct axis of summation? -.. return math.sqrt((numpy.absolute(s_j_nb)**2).sum() * delta_t - s_j_nb_avg * dof * delta_t) -.. #+END_SRC -.. -.. ** Measure root-mean square strain poorly -.. <> -.. -.. #+BEGIN_SRC python -.. def measure_hrss_poorly(tile_energy, sub_psd): -.. return math.sqrt(tile_energy / numpy.average(1.0 / sub_psd) / 2) -.. #+END_SRC -.. -.. ** List triggers from map -.. <> -.. -.. #+BEGIN_SRC python -.. def trigger_list_from_map(tfmap, event_list, threshold, start_time, start_freq, duration, band, df, dt, psd=None): -.. -.. # FIXME: If we don't convert this the calculation takes forever --- but we should convert it once and handle deltaF better later -.. if psd is not None: -.. npy_psd = psd.numpy() -.. -.. start_time = LIGOTimeGPS(float(start_time)) -.. ndof = 2 * duration * band -.. -.. spanf, spant = tfmap.shape[0] * df, tfmap.shape[1] * dt -.. print "Processing %.2fx%.2f time-frequency map." % (spant, spanf) -.. -.. for i, j in zip(*numpy.where(tfmap > threshold)): -.. event = event_list.RowType() -.. -.. # The points are summed forward in time and thus a `summed point' is the -.. # sum of the previous N points. If this point is above threshold, it -.. # corresponds to a tile which spans the previous N points. However, th -.. # 0th point (due to the convolution specifier 'valid') is actually -.. # already a duration from the start time. All of this means, the + -.. # duration and the - duration cancels, and the tile 'start' is, by -.. # definition, the start of the time frequency map if j = 0 -.. # FIXME: I think this needs a + dt/2 to center the tile properly -.. event.set_start(start_time + float(j * dt)) -.. event.set_stop(start_time + float(j * dt) + duration) -.. event.set_peak(event.get_start() + duration / 2) -.. event.central_freq = start_freq + i * df + 0.5 * band -.. -.. event.duration = duration -.. event.bandwidth = band -.. event.chisq_dof = ndof -.. -.. event.snr = math.sqrt(tfmap[i,j] / event.chisq_dof - 1) -.. # FIXME: Magic number 0.62 should be determine empircally -.. event.confidence = -lal.LogChisqCCDF(event.snr * 0.62, event.chisq_dof * 0.62) -.. if psd is not None: -.. # NOTE: I think the pycbc PSDs always start at 0 Hz --- check -.. psd_idx_min = int((event.central_freq - event.bandwidth / 2) / psd.delta_f) -.. psd_idx_max = int((event.central_freq + event.bandwidth / 2) / psd.delta_f) -.. -.. # FIXME: heuristically this works better with E - D -- it's all -.. # going away with the better h_rss calculation soon anyway -.. event.amplitude = measure_hrss_poorly(tfmap[i,j] - event.chisq_dof, npy_psd[psd_idx_min:psd_idx_max]) -.. else: -.. event.amplitude = None -.. -.. event.process_id = None -.. event.event_id = event_list.get_next_id() -.. event_list.append(event) -.. #+END_SRC -.. -.. ** Determine output segment -.. <> -.. -.. #+BEGIN_SRC python -.. def determine_output_segment(inseg, dt_stride, sample_rate, window_fraction=0.0): -.. """ -.. Given an input data stretch segment inseg, a data block stride dt_stride, the data sample rate, and an optional window_fraction, return the amount of data that can be processed without corruption effects from the window. -.. -.. If window_fration is set to 0 (default), assume no windowing. -.. """ -.. # Amount to overlap successive blocks so as not to lose data -.. window_overlap_samples = window_fraction * sample_rate -.. outseg = inseg.contract(window_fraction * dt_stride / 2) -.. -.. # With a given dt_stride, we cannot process the remainder of this data -.. remainder = math.fmod(abs(outseg), dt_stride * (1 - window_fraction)) -.. # ...so make an accounting of it -.. outseg = segment(outseg[0], outseg[1] - remainder) -.. return outseg -.. #+END_SRC -.. -.. ** Make tiles -.. <> -.. -.. #+BEGIN_SRC python -.. def make_tiles(tf_map, nc_sum, mu_sq): -.. tiles = numpy.zeros(tf_map.shape) -.. sum_filter = numpy.ones(nc_sum+1) -.. # Here's the deal: we're going to keep only the valid output and -.. # it's *always* going to exist in the lowest available indices -.. for t in xrange(tf_map.shape[1]): -.. # Sum and drop correlate tiles -.. # FIXME: don't drop correlated tiles -.. output = numpy.convolve(tf_map[:,t], sum_filter, 'valid')[::nc_sum+1] -.. #output = fftconvolve(tf_map[:,t], sum_filter, 'valid')[::nc_sum+1] -.. tiles[:len(output),t] = numpy.absolute(output) / math.sqrt(2) -.. return tiles[:len(output)]**2 / mu_sq[nc_sum::nc_sum+1].reshape(-1, 1) -.. #+END_SRC -.. -.. ** Create a time frequency map -.. <> -.. -.. In this function, we create a time frequency map with resolution similar than =tf_map= but rescale by a factor of =nc_sum= + 1. All tiles will be independent up to overlap from the original tiling. The =mu_sq= is applied to the resulting addition to normalize the outputs to be zero-mean unit-variance Gaussian variables (if the input is Gaussian). -.. -.. #+BEGIN_SRC python -.. def make_indp_tiles(tf_map, nc_sum, mu_sq): -.. tiles = tf_map.copy() -.. # Here's the deal: we're going to keep only the valid output and -.. # it's *always* going to exist in the lowest available indices -.. stride = nc_sum + 1 -.. for i in xrange(tiles.shape[0]/stride): -.. numpy.absolute(tiles[stride*i:stride*(i+1)].sum(axis=0), tiles[stride*(i+1)-1]) -.. return tiles[nc_sum::nc_sum+1].real**2 / mu_sq[nc_sum::nc_sum+1].reshape(-1, 1) -.. #+END_SRC -.. -.. ** Create output filename -.. <> -.. -.. #+BEGIN_SRC python -.. def make_filename(ifo, seg, tag="excesspower", ext="xml.gz"): -.. if isinstance(ifo, str): -.. ifostr = ifo -.. else: -.. ifostr = "".join(ifo) -.. st_rnd, end_rnd = int(math.floor(seg[0])), int(math.ceil(seg[1])) -.. dur = end_rnd - st_rnd -.. return "%s-%s-%d-%d.%s" % (ifostr, tag, st_rnd, dur, ext) -.. #+END_SRC - diff --git a/docs/_sources/calculate_psd.rst.txt b/docs/_sources/calculate_psd.rst.txt deleted file mode 100644 index 8055185..0000000 --- a/docs/_sources/calculate_psd.rst.txt +++ /dev/null @@ -1,54 +0,0 @@ -.. _psdestimate: - -Calculate Power Spectral Density (PSD) -====================================== - -The instrument's noise Power Spectral Density (PSD) will be used to whiten the data and help reveal the existence, or the absence, of repetitive patterns and correlation structures in the signal process. It will also determine the total bandwidth spanned by each of the filters that will subsequently be created. The first thing to do before calculating the PSD is to ensure that the time series data is converted into an array of floating values. :: - - # Convert time series as array of float - data = ts_data.astype(numpy.float64) - -The PSD is calculated by splitting up the signal into overlapping segments and scan through each segment to calculate individual periodogram. The periodograms from each segment are then averaged, reducing the variance of the individual power measurements. In order to proceed, we need to define the average method, ``avg_method``, that will be used to measure the PSD from the data. This can be specified with the ``--psd-estimation`` option. :: - - # Average method to measure PSD from the data - avg_method = args.psd_estimation - -One also needs to specify the length of each segment, ``seg_len``, as well as the separation between 2 consecutive segments, ``seg_stride``. Both parameters can be defined in second units with the ``--psd-segment-length`` and ``--psd-segment-stride`` arguments respectively and can then be converted into sample unit. :: - - # The segment length for PSD estimation in samples - seg_len = int(args.psd_segment_length * args.sample_rate) - # The separation between consecutive segments in samples - seg_stride = int(args.psd_segment_stride * args.sample_rate) - -We then use the `Welch's method `_ to perform the power spectral density estimate using the `welch `_ module from the ``pycbc.psd`` library. What this will do is to compute the discrete Fourier transform for each PSD segment to produce invidual periodograms, and then compute the squared magnitude of the result. The individual periodograms are then averaged using the user-defined average method, ``avg_method``, and return the frequency series, ``fd_psd``, which will store the power measurement for each frequency bin. :: - - # Lifted from the psd.from_cli module - fd_psd = psd.welch(data,avg_method=avg_method,seg_len=seg_len,seg_stride=seg_stride) - # Plot the power spectral density - plot_spectrum(fd_psd) - # We need this for the SWIG functions - lal_psd = fd_psd.lal() - -One can display the power measurements, frequency array and frequency between consecutive samples, :math:`\Delta f` in Hertz, by printing the following variables: :: - - print 'Display power measurements of the first 10 frequency bins' - print fd_psd[:10] - print 'Display central frequency of the first 10 bins' - print fd_psd.sample_frequencies[:10] - print 'Display the frequency separation between bins' - print fd_psd.delta_f - -:math:`\Delta f` corresponds to the inverse of a segment's length which is the smallest frequency (i.e. highest period) of detectable signals in each segment. The frequency range spans from 0 to the Nyquist frequency, i.e. half de the sampling rate. - -Code access ------------ - -.. currentmodule:: gdas.epower - -.. autosummary:: - :toctree: generated/ - - calculate_psd - - - diff --git a/docs/_sources/calculate_spectral_correlation.rst.txt b/docs/_sources/calculate_spectral_correlation.rst.txt deleted file mode 100644 index e3df67a..0000000 --- a/docs/_sources/calculate_spectral_correlation.rst.txt +++ /dev/null @@ -1,25 +0,0 @@ -Two point spectral correlation -============================== - -This part determines how much data on either side of the tukey window is to be discarded. Nominally, this means that one will lose ``window_fraction`` * ``args.psd_segment_length`` to corruption from the window, i.e. this is simply discarded. This is tuned to give an integer offset when used with ``args.psd_segment_length`` equal to 8, smaller windows will have fractions of integers, but larger powers of two will still preseve this (probably not a big deal in the end). :: - - window_fraction = 0 - -The two point spectral correlation is then done with the :ref:`calculate_spectral_correlation ` function which will return both the Tukey window applied to the original time series data and the actual two-point spectral correlation function for the whitened frequency series from the applied whitening window. :: - - # Do two point spectral correlation - window, spec_corr = calculate_spectral_correlation(seg_len,'tukey',window_fraction=window_fraction) - window = window.data.data - window_sigma_sq = numpy.mean(window**2) - # Pre scale the window by its root mean squared -- see eqn 11 of EP document - #window /= numpy.sqrt(window_sigma_sq) - -Code access ------------ - -.. currentmodule:: gdas.epower - -.. autosummary:: - :toctree: generated/ - - calculate_spectral_correlation diff --git a/docs/_sources/check_filtering_settings.rst.txt b/docs/_sources/check_filtering_settings.rst.txt deleted file mode 100644 index 43e5357..0000000 --- a/docs/_sources/check_filtering_settings.rst.txt +++ /dev/null @@ -1,50 +0,0 @@ -Checking filtering settings -=========================== - -The first thing to check is that the frequency of the high-pass filter (if defined) is below the minimum frequency of the filter bank. Indeed, a high-pass filter will only let pass frequency that are higher than the cutoff frequency (here defined by the ``strain_high_pass`` argument). If the high pass frequency is greater from the minimum frequency in the filter bank, the signal with frequencies lower than the cutoff frequency will get attenuated. :: - - if args.min_frequency < args.strain_high_pass: - print >>sys.stderr, "Warning: strain high pass frequency %f is greater than the tile minimum frequency %f --- this is likely to cause strange output below the bandpass frequency" % (args.strain_high_pass, args.min_frequency) - -In case the maximum frequency in the filter bank is not defined, we set it to be equal to the Nyquist frequency, i.e. half the sampling rate, which makes sense as a larger signal will not be able to get easily identifiable. :: - - if args.max_frequency is None: - args.max_frequency = args.sample_rate / 2.0 - -If the bandwidth of the finest filter (``--tile-bandwidth`` argument, see section :ref:`construct_args ` or the number of frequency channels (=--channels= argument) is not defined but the total spectral band is (``data_band``), one can then determined all the filter settings as follows: :: - - - if args.tile_bandwidth is None and args.channels is None: - # Exit program with error message - exit("Either --tile-bandwidth or --channels must be specified to set up time-frequency plane") - else: - # Define as assert statement that tile maximum frequency larger than its minimum frequency - assert args.max_frequency >= args.min_frequency - # Define spectral band of data - data_band = args.max_frequency - args.min_frequency - # Check if tile bandwidth or channel is defined - if args.tile_bandwidth is not None: - # Define number of possible filter bands - nchans = args.channels = int(data_band / args.tile_bandwidth) - 1 - elif args.channels is not None: - # Define filter bandwidth - band = args.tile_bandwidth = data_band / (args.channels + 1) - assert args.channels > 1 - -The minimum frequency to be explored can be user-defined by using the ``--min-frequency`` option. :: - - # Lowest frequency of the first filter - flow = args.min_frequency - -Code access ------------ - -.. currentmodule:: gdas.epower - -.. autosummary:: - :toctree: generated/ - - check_filtering_settings - - - diff --git a/docs/_sources/compute_channel_renormalization.rst.txt b/docs/_sources/compute_channel_renormalization.rst.txt deleted file mode 100644 index cc36882..0000000 --- a/docs/_sources/compute_channel_renormalization.rst.txt +++ /dev/null @@ -1,23 +0,0 @@ -Normalization of virtual channel -================================ - -The virtual channels will be used during the excesspower analysis to explore different frequency ranges around each PSD segments and look for possible triggers. Each channel is renormalized using the :ref:`compute_channel_renomalization ` internal function. :: - - # Initialise dictionary - mu_sq_dict = {} - # nc_sum additional channel adds - for nc_sum in range(0, int(math.log(nchans, 2))): - min_band = (len(filter_bank[0].data.data)-1) * filter_bank[0].deltaF / 2 - print tprint(t0,t1),"Calculation for %d %d Hz channels" % (nc_sum+1, min_band) - nc_sum = 2**nc_sum - 1 - mu_sq_dict[nc_sum] = compute_channel_renomalization(nc_sum, filter_bank, spec_corr, nchans) - -Code access ------------ - -.. currentmodule:: gdas.epower - -.. autosummary:: - :toctree: generated/ - - compute_channel_renormalization diff --git a/docs/_sources/construct_tiles.rst.txt b/docs/_sources/construct_tiles.rst.txt deleted file mode 100644 index ec0f619..0000000 --- a/docs/_sources/construct_tiles.rst.txt +++ /dev/null @@ -1,33 +0,0 @@ -.. _tilebandwidth: - -Constructing tiles of different bandwidth -========================================= - -First and foremost, we define a clipping region in the data to be used to remove window corruption, this is non-zero if the ``window_fraction`` variable is set to a non-zero value. :: - - print tprint(t0,t1),"Beginning tile construction..." - # Clip the boundaries to remove window corruption - clip_samples = int(args.psd_segment_length * window_fraction * args.sample_rate / 2) - -In order to perform a multi-resolution search, tiles of many different bandwidths and durations will be scanned. We first need to setup a loop such that the maximum number of additional channel is equal to the base 2 logarithm of the total number of channels. The number of narrow band channels to be summed (``nc_sum``) would therefore be equal to 2 to the power of the current quantity of additional channels. :: - - for nc_sum in range(0, int(math.log(nchans, 2)))[::-1]: # nc_sum additional channel adds - nc_sum = 2**nc_sum - 1 - print tprint(t0,t1,t2),"Summing %d narrow band channels..." % (nc_sum+1) - -The undersampling rate for this tile can be calculated using the channel frequency band and the number of narrow band channels to be summed such that the bandwidth of the tile is equal to ``band * (nc_sum + 1)``. :: - - us_rate = int(round(1.0 / (2 * band*(nc_sum+1) * ts_data.delta_t))) - print >>sys.stderr, "Undersampling rate for this level: %f" % (args.sample_rate/us_rate) - -"Virtual" wide bandwidth channels are constructed by summing the samples from multiple channels, and correcting for the overlap between adjacent channel filters. We then define the normalised channel at the current level and create a time frequency map for this tile using the :ref:`make_indp_tiles ` internal function. In other word, we are constructing multiple sub-tiles for which we can determined the respective energy in the given frequency band. :: - - mu_sq = mu_sq_dict[nc_sum] - sys.stderr.write("\t...calculating tiles...") - if clip_samples > 0: - tiles = make_indp_tiles(tf_map[:,clip_samples:-clip_samples:us_rate], nc_sum, mu_sq) - else: - tiles = make_indp_tiles(tf_map[:,::us_rate], nc_sum, mu_sq) - sys.stderr.write(" TF-plane is %dx%s samples... " % tiles.shape) - print >>sys.stderr, " done" - print "Tile energy mean: %f, var %f" % (numpy.mean(tiles), numpy.var(tiles)) diff --git a/docs/_sources/create_filter_bank.rst.txt b/docs/_sources/create_filter_bank.rst.txt deleted file mode 100644 index 4b18bef..0000000 --- a/docs/_sources/create_filter_bank.rst.txt +++ /dev/null @@ -1,52 +0,0 @@ -.. _filterbank: - -Computing the filter bank -========================= - -The filter bank will create band-pass filters for each channel in the PSD frequency domain. The :ref:`create_filter_bank ` function will san the bandwidth from the central frequency of the first channel (i.e. flow+band/2) to final frequency of the last channel (i.e. band*nchans) in a increment equal to the frequency band. The filter's total extent in Fourier space is actually twice the stated bandwidth (FWHM). :: - - # Define filters - filter_bank, fdb = create_filter_bank(fd_psd.delta_f, flow+band/2, band, nchans, fd_psd, spec_corr) - -This function will returns 2 arrays: the ``filter_bank`` array which is a list of `COMPLEX16FrequencySeries `_ arrays corresponding to each channel's filter, and the =fdb= array which provides the time-series from each filter. The length of each array is equal to the total number of channel (i.e. =nchans=). The filter's data, :math:`\Delta f` value, and first and last frequencies of any channel's filter can be displayed as followed: :: - - # Print data of first channel's filter - print filter_bank[0].data.data - # Print frequency separation between 2 values in the first channel's filter - print filter_bank[0].deltaF - # Print first frequency of the first channel's filter - print filter_bank[0].f0 - # Print last frequency of the first channel's filter (equal to twice the channel's bandwidth) - print filter_bank[0].f0+(len(filter_bank[0].data.data)-1)*filter_bank[0].deltaF - -Further in the analysis, the following filters will used: -1. ``white_filter_ip``: Whitened filter inner products computed with themselves. -2. ``unwhite_filter_ip``: Unwhitened filter inner products computed with themselves. -3. ``white_ss_ip``: Whitened filter inner products computed between input adjacent filters. -4. ``unwhite_ss_ip``: Unwhitened filter inner products computed between input adjacent filters. - -:: - - # This is necessary to compute the mu^2 normalizations - white_filter_ip = compute_filter_ips_self(filter_bank, spec_corr, None) - unwhite_filter_ip = compute_filter_ips_self(filter_bank, spec_corr, lal_psd) - # These two are needed for the unwhitened mean square sum (hrss) - white_ss_ip = compute_filter_ips_adjacent(filter_bank, spec_corr, None) - unwhite_ss_ip = compute_filter_ips_adjacent(filter_bank, spec_corr, lal_psd) - -Some extra plots can also be made :: - - tdb = convert_to_time_domain(fdb,sample_rate) - plot_bank(fdb) - plot_filters(tdb,flow,band) - - -Code access ------------ - -.. currentmodule:: gdas.epower - -.. autosummary:: - :toctree: generated/ - - create_filter_bank diff --git a/docs/_sources/create_tf_plane.rst.txt b/docs/_sources/create_tf_plane.rst.txt deleted file mode 100644 index dd95435..0000000 --- a/docs/_sources/create_tf_plane.rst.txt +++ /dev/null @@ -1,47 +0,0 @@ -Create time-frequency map -========================= - -We initialise a 2D zero array for a time-frequency map (``tf_map``) which will be computed for each frequency-domain filter associated to each PSD segment and where the filtered time-series for each frequency channels will be stored. The number of rows corresponds to the total number of frequency channels which is defined by the ``nchans`` variable. The number of columns corresponds to the segment length in samples (i.e. the number of samples covering one segment) which is defined by the ``seg_len`` variable. :: - - # Initialise 2D zero array for time-frequency map - tf_map = numpy.zeros((nchans, seg_len), dtype=numpy.complex128) - -We also initialise a zero vector for a temporary filter bank (``tmp_filter_bank``) that will store, for a given channel, the filter's values from the original filter bank (``filter_bank``) for that channel only. The length of the temporary filter bank is equal to the length of the PSD frequency series (``fd_psd``). :: - - # Initialise 1D zero array - tmp_filter_bank = numpy.zeros(len(fd_psd), dtype=numpy.complex128) - -We then loop over all the frequency channels. While in the loop, we first re-initialise the temporary filter bank with zero values everywhere along the frequency series. We then determine the first and last frequency of each channel and re-define the values of the filter in that frequency range based on the values from the original channel's filter from the original filter bank. :: - - # Loop over all the channels - print tprint(t0,t1),"Filtering all %d channels..." % nchans - for i in range(nchans): - # Reset filter bank series - tmp_filter_bank *= 0.0 - # Index of starting frequency - f1 = int(filter_bank[i].f0/fd_psd.delta_f) - # Index of ending frequency - f2 = int((filter_bank[i].f0 + 2*band)/fd_psd.delta_f)+1 - # (FIXME: Why is there a factor of 2 here?) - tmp_filter_bank[f1:f2] = filter_bank[i].data.data * 2 - -We then extract the frequency series from the filter bank for that channel, which will be used as a template waveform to filter the actual data from the channel. :: - - # Define the template to filter the frequency series with - template = types.FrequencySeries(tmp_filter_bank, delta_f=fd_psd.delta_f, copy=False) - -Finally, we use the `matched_filter_core `_ module from the ``pycbc.filter.matchedfilter`` library to filter the frequency series from the channel. This will return both a time series containing the complex signal-to-noise matched filtered against the data, and a frequency series containing the correlation vector. :: - - # Create filtered series - filtered_series = filter.matched_filter_core(template,fs_data,h_norm=None,psd=None, - low_frequency_cutoff=filter_bank[i].f0, - high_frequency_cutoff=filter_bank[i].f0+2*band) - -The `matched filter `_ is the optimal linear filter for maximizing the signal to noise ratio (SNR) in the presence of additive stochastic noise. The filtered time series is stored in the time-frequency map and can be used to produce a spectrogram of the segment of data being analysed. :: - - # Include filtered series in the map - tf_map[i,:] = filtered_series[0].numpy() - -The time-frequency map is a 2D array with a length that corresponds to the number of channels and a width equal to the number of sample present in one segment of data, i.e. segment's length in seconds times the the sampling rate. The map can finally be plotted with a :math:`\Delta t` corresponding to the sampling period of the original dataset (i.e. inverse of the original sampling rate), and :math:`\Delta f` is equal to the bandwidth of one channel. :: - - plot_spectrogram(numpy.abs(tf_map).T,tmp_ts_data.delta_t,fd_psd.delta_f,ts_data.sample_rate,start_time,end_time,fname='%s/tf.png'%(segfolder)) diff --git a/docs/_sources/create_xml.rst.txt b/docs/_sources/create_xml.rst.txt deleted file mode 100644 index 53c771e..0000000 --- a/docs/_sources/create_xml.rst.txt +++ /dev/null @@ -1,56 +0,0 @@ -Extracting GPS time range -========================= - -We use the `LIGOTimeGPS `_ structure from the =glue.lal= package to /store the starting and ending time in the dataset to nanosecond precision and synchronized to the Global Positioning System time reference/. Once both times are defined, the range of value is stored in a semi-open interval using the `segment `_ module from the =glue.segments= package. :: - - # Starting epoch relative to GPS starting epoch - start_time = LIGOTimeGPS(args.analysis_start_time or args.gps_start_time) - # Ending epoch relative to GPS ending epoch - end_time = LIGOTimeGPS(args.analysis_end_time or args.gps_end_time) - # Represent the range of values in the semi-open interval - inseg = segment(start_time,end_time) - -Prepare output file for given time range -======================================== - -:: - - xmldoc = ligolw.Document() - xmldoc.appendChild(ligolw.LIGO_LW()) - - ifo = args.channel_name.split(":")[0] - proc_row = register_to_xmldoc(xmldoc, __program__, args.__dict__, ifos=[ifo],version=glue.git_version.id, cvs_repository=glue.git_version.branch, cvs_entry_time=glue.git_version.date) - - # Figure out the data we actually analyzed - outseg = determine_output_segment(inseg, args.psd_segment_length, args.sample_rate, window_fraction) - - ss = append_search_summary(xmldoc, proc_row, ifos=(station,), inseg=inseg, outseg=outseg) - - for sb in event_list: - sb.process_id = proc_row.process_id - sb.search = proc_row.program - #sb.ifo, sb.channel = args.channel_name.split(":") - sb.ifo, sb.channel = station, setname - - xmldoc.childNodes[0].appendChild(event_list) - fname = make_filename(station, inseg) - - utils.write_filename(xmldoc, fname, gz=fname.endswith("gz"), verbose=True) - -Plot trigger results -==================== - -:: - - events = SnglBurstTable.read(fname+'.gz') - #del events[10000:] - plot = events.plot('time', 'central_freq', "duration", "bandwidth", color="snr") - #plot = events.plot('time', 'central_freq', color='snr') - #plot.set_yscale("log") - plot.set_ylim(1e-0, 250) - t0 = 1153742417 - plot.set_xlim(t0 + 0*60, t0 + 1*60) - #plot.set_xlim(t0 + 28, t0 + 32) - pyplot.axvline(t0 + 30, color='r') - cb = plot.add_colorbar(cmap='viridis') - plot.savefig("triggers.png") diff --git a/docs/_sources/example.rst.txt b/docs/_sources/example.rst.txt deleted file mode 100644 index 6677764..0000000 --- a/docs/_sources/example.rst.txt +++ /dev/null @@ -1,41 +0,0 @@ -Working Example -=============== - -Either on your own computer or on the server, on a Jupyter notebook or on a Python script, the first thing to do is to import the ``gdas`` package that contain all the modules present in the GNOME software. That can be done easily by doing the following:: - - import gdas - -In order to retrieve a specific chunk of data to be analyzed for a particular station, the name of the station along with the start and end dates should be specified:: - - station = 'fribourg01' - start_time = '2016-11-03-04' - end_time = '2016-11-03-04-2' - -where the start and end times should always have at least the year, month and day specified, and with the values separated by a dash symbol. Hour and minute can also be specified. - -If you are not working on the server and the data are located in a different repository than ``/GNOMEDrive/gnome/serverdata/``, a custom path can be defined. For instance:: - - datapath = '/Users/vincent/data/GNOMEDrive/gnome/serverdata/' - -The magnetic field data can then be retrieve as follows:: - - ts_data,ts_list,activity = gdas.magfield(station,start_time,end_time,rep=datapath) - -The ``gdas.magfield`` method will return 3 arrays of data that can then be used to produce different plots:: - - gdas.plot_activity(activity) - gdas.plot_time_series(station,ts_list,seglist=activity) - gdas.plot_asd(station,ts_list) - gdas.plot_whitening(station,ts_list,activity) - -This is a script to do Excess Power analysis:: - - psd_segment_length = 60 - psd_segment_stride = 30 - psd_estimation = 'median-mean' - window_fraction = 0 - tile_fap = 1e-5 - channels = 250 - - gdas.excess_power(ts_data,psd_segment_length,psd_segment_stride,psd_estimation,window_fraction,tile_fap,station,nchans=channels) - gdas.plot_triggers() diff --git a/docs/_sources/excess_power.rst.txt b/docs/_sources/excess_power.rst.txt deleted file mode 100644 index 840e8d3..0000000 --- a/docs/_sources/excess_power.rst.txt +++ /dev/null @@ -1,47 +0,0 @@ -Excess Power Overview -===================== - -The **Excess Power method** is known as the *optimal detection strategy* to search for burst signals for which only the duration and frequency band are known, which is basically the case for GNOME and its search of Axion-Like Particles (ALP). This method was developed and introduced by `Anderson et al. (200) `_ and has been extensively used in the detection of burst sources of gravitational radiation. A more technical documentation was written by `Brady et al. (2007) `_ describing how the algorithm used by the LIGO collaboration works and how the theory is translated into code. - -We present below a step-by-step procedure followed during the Excess Power search analysis. For a better representation of what is happening, the figure at the end shows how the data is being split and analysed to search for multiple signals of different bandwidth and duration in the time-frequency plane. - -- :ref:`Time domain segmentation and PSD estimate ` - - We first estimate the instrument's noise Power Spectral Density (PSD) by splitting the time-series data into multiple overlapping segments. A periodogram for each segment is calculated separately and then averaged, which will reduce the variance of the individual power measurements. The result is a frequency series where samples are separated in frequency space by :math:`\Delta f` equal to the inverse of a segment’s length and with a high end frequency limit equal to the Nyquist limit. The final power spectrum will help reveal the existence, or the absence, of repetitive patterns and correlation structures in a signal process. - -- :ref:`Comb of frequency channels ` - - We then split the PSD frequency series into multiple channels. For each channel, a frequency domain filter is created with a :math:`\Delta f` determined by the PSD and a total extent in Fourier space that is twice the stated bandwidth of a channel. The result is a list of each channel filter's frequency series. - -- :ref:`Creating analysing blocks ` - - The Excess Power method can lead to moderately-large computational requirements, and it has been found that the computational efficiency of this implementation can be improved upon by considering blocks of data that are much longer than the longest signal time duration. The entire time series is therefore split into separate blocks. We use the length of the segments used for PSD estimate to define the duration of each block. For each block, the time series is c0Aonverted into frequency series which is then filtered by the filter bank throughout all the channels. A time-frequency map is finally created which stores all the filtered frequency series from each channel. - -- :ref:`Creating tiles with different bandwidth ` - - We can now construct tiles with different bandwidth by summing multiple channels together. - -- :ref:`Exploring tiles with different duration ` - - For each given tile's bandwidth, one can investigate different tile's duration. This can be done by exploring different number of degrees of freedom, :math:`d`, which can be calculated as follows: :math:`d=2BT` where :math:`B` and :math:`T` are respectively the bandwidth and duration of the tile. Section 2.2.5 of `Brady et al. `_ gives a great description of how to interpret the number of degrees of freedom. Therefore, by changing the :math:`d`, one can explore multiple tile's duration for different bandwidth. - -- :ref:`Define triggering signal ` - - The energy of each tile in the time-frequency space is calculated and compare to a user-defined threshold value. After defining a tile false alarm probability threshold in Gaussian noise and using the number of degrees of freedom for each tile, one can define a energy threshold value above which a burst trigger can be identified by comparing the energy threshold with the tile's energy in the time-frequency map. A tile energy time frequency map plot similar to Figure 5 in `Pustelny et al. (2013) `_ can then be made which plots the outlying tile energies present in the data. - -.. figure:: ./img/overview.png - - Overview of the Excess Power method and difference between segments, channels, tiles and blocks. - -Code access ------------ - -.. currentmodule:: gdas.epower - -.. autosummary:: - :toctree: generated/ - - excess_power - - - diff --git a/docs/_sources/explore_duration.rst.txt b/docs/_sources/explore_duration.rst.txt deleted file mode 100644 index b27114a..0000000 --- a/docs/_sources/explore_duration.rst.txt +++ /dev/null @@ -1,54 +0,0 @@ -.. _tileduration: - -Explore multiple tile durations -=============================== - -Now that we create a tile with a specific bandwidth, we can start exploring different durations for the tile. We will start checking if the user manually defined a value for the longest duration tile to compute, which can be done using the ``--max-duration`` argument. If not, the value will be set to 32. :: - - if args.max_duration is not None: - max_dof = 2 * args.max_duration * (band * (nc_sum+1)) - else: - max_dof = 32 - assert max_dof >= 2 - -Since we produce (initially) tiles with 1 degree of freedom, the duration goes as one over twice the bandwidth. :: - - print "\t\t...getting longer durations..." - #for j in [2**l for l in xrange(1, int(math.log(max_dof, 2))+1)]: - for j in [2**l for l in xrange(0, int(math.log(max_dof, 2)))]: - sys.stderr.write("\t\tSumming DOF = %d ..." % (2*j)) - #tlen = tiles.shape[1] - j + 1 - tlen = tiles.shape[1] - 2*j + 1 + 1 - if tlen <= 0: - print >>sys.stderr, " ...not enough samples." - continue - dof_tiles = numpy.zeros((tiles.shape[0], tlen)) - #:sum_filter = numpy.ones(j) - # FIXME: This is the correct filter for 50% overlap - sum_filter = numpy.array([1,0] * (j-1) + [1]) - #sum_filter = numpy.array([1,0] * int(math.log(j, 2)-1) + [1]) - for f in range(tiles.shape[0]): - # Sum and drop correlate tiles - # FIXME: don't drop correlated tiles - #output = numpy.convolve(tiles[f,:], sum_filter, 'valid') - dof_tiles[f] = fftconvolve(tiles[f], sum_filter, 'valid') - print >>sys.stderr, " done" - print "Summed tile energy mean: %f, var %f" % (numpy.mean(dof_tiles), numpy.var(dof_tiles)) - level_tdiff = time.time() - tdiff - print >>sys.stderr, "Done with this resolution, total %f" % level_tdiff - -Finally, the bandwidth and duration of the tile can be defined as followed: :: - - # Current bandwidth of the time-frequency map tiles - current_band = band * (nc_sum + 1) - # How much each "step" is in the frequency domain -- almost - # assuredly the fundamental bandwidth - df = current_band - # How much each "step" is in the time domain -- under sampling rate - # FIXME: THis won't work if the sample rate isn't a power of 2 - dt = 1.0 / 2 / (2 * current_band) * 2 - full_band = 250 - dt = current_band / full_band * ts_data.sample_rate - dt = 1.0/dt - # Duration is fixed by the NDOF and bandwidth - duration = j / 2.0 / current_band diff --git a/docs/_sources/generated/gdas.epower.calculate_psd.rst.txt b/docs/_sources/generated/gdas.epower.calculate_psd.rst.txt deleted file mode 100644 index 859226f..0000000 --- a/docs/_sources/generated/gdas.epower.calculate_psd.rst.txt +++ /dev/null @@ -1,6 +0,0 @@ -gdas.epower.calculate_psd -========================= - -.. currentmodule:: gdas.epower - -.. autofunction:: calculate_psd \ No newline at end of file diff --git a/docs/_sources/generated/gdas.epower.calculate_spectral_correlation.rst.txt b/docs/_sources/generated/gdas.epower.calculate_spectral_correlation.rst.txt deleted file mode 100644 index de867fe..0000000 --- a/docs/_sources/generated/gdas.epower.calculate_spectral_correlation.rst.txt +++ /dev/null @@ -1,6 +0,0 @@ -gdas.epower.calculate_spectral_correlation -========================================== - -.. currentmodule:: gdas.epower - -.. autofunction:: calculate_spectral_correlation \ No newline at end of file diff --git a/docs/_sources/generated/gdas.epower.check_filtering_settings.rst.txt b/docs/_sources/generated/gdas.epower.check_filtering_settings.rst.txt deleted file mode 100644 index a648bc8..0000000 --- a/docs/_sources/generated/gdas.epower.check_filtering_settings.rst.txt +++ /dev/null @@ -1,6 +0,0 @@ -gdas.epower.check_filtering_settings -==================================== - -.. currentmodule:: gdas.epower - -.. autofunction:: check_filtering_settings \ No newline at end of file diff --git a/docs/_sources/generated/gdas.epower.compute_channel_renormalization.rst.txt b/docs/_sources/generated/gdas.epower.compute_channel_renormalization.rst.txt deleted file mode 100644 index ed456af..0000000 --- a/docs/_sources/generated/gdas.epower.compute_channel_renormalization.rst.txt +++ /dev/null @@ -1,6 +0,0 @@ -gdas.epower.compute_channel_renormalization -=========================================== - -.. currentmodule:: gdas.epower - -.. autofunction:: compute_channel_renormalization \ No newline at end of file diff --git a/docs/_sources/generated/gdas.epower.create_filter_bank.rst.txt b/docs/_sources/generated/gdas.epower.create_filter_bank.rst.txt deleted file mode 100644 index a43b152..0000000 --- a/docs/_sources/generated/gdas.epower.create_filter_bank.rst.txt +++ /dev/null @@ -1,6 +0,0 @@ -gdas.epower.create_filter_bank -============================== - -.. currentmodule:: gdas.epower - -.. autofunction:: create_filter_bank \ No newline at end of file diff --git a/docs/_sources/generated/gdas.epower.excess_power.rst.txt b/docs/_sources/generated/gdas.epower.excess_power.rst.txt deleted file mode 100644 index 69bcaea..0000000 --- a/docs/_sources/generated/gdas.epower.excess_power.rst.txt +++ /dev/null @@ -1,6 +0,0 @@ -gdas.epower.excess_power -======================== - -.. currentmodule:: gdas.epower - -.. autofunction:: excess_power \ No newline at end of file diff --git a/docs/_sources/identify_block.rst.txt b/docs/_sources/identify_block.rst.txt deleted file mode 100644 index b11537f..0000000 --- a/docs/_sources/identify_block.rst.txt +++ /dev/null @@ -1,25 +0,0 @@ -.. _analysingblocks: - -Define analysing blocks ------------------------ - -The first thing we do is to calculate the time series for the segment that is covered (``tmp_ts_data``) and redefined the metadata, especially the time of the first sample in seconds which is defined by the ``epoch`` argument and is different for every segment. After plotting the time series for that segment, the data are then converted into frequency series (``fs_data``) using the `to_frequencyseries `_ module from the ``pycbc.types.timeseries.TimeSeries`` library. Finally, the frequency data are then whitened. :: - - # Loop over each data within the user requested time period - while t_idx_max <= t_idx_max_off: - # Define starting and ending time of the segment in seconds - start_time = ts_data.start_time + t_idx_min/float(args.sample_rate) - end_time = ts_data.start_time + t_idx_max/float(args.sample_rate) - print tprint(t0,t1),"Analyzing block %i to %i (%.2f percent)"%(start_time,end_time,100*float(t_idx_max)/float(idx_max_off)) - # Model a withen time series for the block - tmp_ts_data = types.TimeSeries(ts_data[t_idx_min:t_idx_max]*window, 1.0/args.sample_rate,epoch=start_time) - # Save time series in segment repository - segfolder = 'segments/%i-%i'%(start_time,end_time) - os.system('mkdir -p '+segfolder) - plot_ts(tmp_ts_data,fname='%s/ts.png'%(segfolder)) - # Convert times series to frequency series - fs_data = tmp_ts_data.to_frequencyseries() - print tprint(t0,t1),"Frequency series data has variance: %s" % fs_data.data.std()**2 - # Whitening (FIXME: Whiten the filters, not the data) - fs_data.data /= numpy.sqrt(fd_psd) / numpy.sqrt(2 * fd_psd.delta_f) - print tprint(t0,t1),"Whitened frequency series data has variance: %s" % fs_data.data.std()**2 diff --git a/docs/_sources/index.rst.txt b/docs/_sources/index.rst.txt deleted file mode 100644 index 1cca81a..0000000 --- a/docs/_sources/index.rst.txt +++ /dev/null @@ -1,68 +0,0 @@ -Welcome! -======== - -This package contains functions useful for magnetic field signal processing, with a focus on Excess Power search analysis and application on the data for the GNOME collaboration, see `Pustelny et al. (2013) `_. This documentation details all the available functions and tasks available through this software. Here are some example tasks that can (or will soon to) be handled: - -* Plot usual time series and spectrogram of magnetic field data. -* Perform excess power analysis and plot detected triggers in time-frequency map. -* Create artificial data for testing data analysis. -* Inject fake signal of different bandwidth and durations. -* Cross-correlation of continuous sine wave signals. -* Perform Allan Standard deviation. - -Should you have any questions or suggested corrections to be made, do not hesitate to `contact me `_. - -.. raw:: html - - Fork me on GitHub - -Getting Started ---------------- - -.. toctree:: - :maxdepth: 1 - - installation - server - example - -Excess Power Search Analysis ----------------------------- - -.. toctree:: - :maxdepth: 1 - - excess_power - -Pre-calculations and initialization -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. toctree:: - :maxdepth: 1 - - check_filtering_settings - calculate_psd - calculate_spectral_correlation - create_filter_bank - compute_channel_renormalization - initialization - -Looping over each block -~~~~~~~~~~~~~~~~~~~~~~~ - -.. toctree:: - :maxdepth: 1 - - identify_block - create_tf_plane - construct_tiles - explore_duration - -Save results -~~~~~~~~~~~~ - -.. toctree:: - :maxdepth: 1 - - create_xml - diff --git a/docs/_sources/initialization.rst.txt b/docs/_sources/initialization.rst.txt deleted file mode 100644 index 02e17f4..0000000 --- a/docs/_sources/initialization.rst.txt +++ /dev/null @@ -1,41 +0,0 @@ -Initialise event list and determine stride boundaries -===================================================== - -First of all, we create a table similar than the one made by the LIGO Scientific Collaboration (LSC) where all the information will be stored. Such table is commonly know as ``lsctables``. A pre-defined LSC table can be constructed using ``New`` function from the `glue.ligolw.lsctables `_ module. We use the ``SnglBurstTable`` function for the type of data to be stored and define all the columns we wish to record. :: - - # Create event list for single burst table - event_list = lsctables.New(lsctables.SnglBurstTable, - ['start_time','start_time_ns','peak_time','peak_time_ns', - 'duration','bandwidth','central_freq','chisq_dof', - 'confidence','snr','amplitude','channel','ifo', - 'process_id','event_id','search','stop_time','stop_time_ns']) - -We also need to determine the indexes of both starting and ending times for the first segment to analyse, respectively ``t_idx_min`` and ``t_idx_max``. The default values are considered to be 0 for the starting index and the segment length in sample unit for the ending time index. Also, if the user defines a different starting time than the one from the loaded data, the offset index in sample unit is determined and added the both starting and ending time indexes. :: - - # Determine boundaries of stride in time domain - t_idx_min, t_idx_max = 0, seg_len - # Check if user requested starting time is defined - if args.analysis_start_time is not None: - # Define the time difference in seconds between data and user requested starting times - t_idx_off = args.analysis_start_time - ts_data.start_time - # Calculate the index of the user requested starting point in the data - t_idx_off = int(t_idx_off * args.sample_rate) - else: - # Define index of the starting point as first value in data - t_idx_off = 0 - # Initialise minimum index values as offset starting index - t_idx_min += t_idx_off - # Initialise maximum index values as offset starting index - t_idx_max += t_idx_off - -Finally, the index for the ending time after all the segments have been analysed can be estimated for the user-defined parameter or is defined as the length of the time series data ``ts_data``. :: - - # Check if user requested end time is defined - if args.analysis_end_time is not None: - # Define the time difference between data and user requested ending times - t_idx_max_off = args.analysis_end_time - ts_data.start_time - # Calculate the index of the user requested starting point in the data - t_idx_max_off = int(t_idx_max_off * args.sample_rate) - else: - # Define index of the ending point as the length of data array - t_idx_max_off = len(ts_data) diff --git a/docs/_sources/installation.rst.txt b/docs/_sources/installation.rst.txt deleted file mode 100644 index cb5ed4e..0000000 --- a/docs/_sources/installation.rst.txt +++ /dev/null @@ -1,57 +0,0 @@ -Installation -============ - -The program requires the following general packages to run: `Numpy `_, `Matplotlib `_, `Scipy `_ and `Astropy `_. The following LIGO-related packages are also required for full functionality: `Gwpy `_, `PyCBC `_, `Glue `_, `LAL `_, `LALburst `_ and `LALsimulation `_. - -While most of the packages can be installed automatically using `pip `_, some LIGO packages (Glue, LAL, LALburst and LALsimulation) must be installed separately beforehand as they contain several C routines that need specific compilation. However, these packages are already included in a bigger package called `LALsuite `_ which can be installed fairly easily on Debian (Linux) and Mac OS machines. - -LALsuite tools --------------- - -Some useful pages on how to download and install the LIGO software can be found `here `_. - -MacPorts (Mac) -~~~~~~~~~~~~~~ - -For Mac users, the installation is pretty easy, detailed information can be found on `this page `_. You need to have `MacPorts `_ installed. The following commands should suffice to install the LALsuite package on your machine:: - - sudo port install lscsoft-deps - sudo port install glue - sudo port install lalapps - -The first command will install all the dependencies needed for the LIGO software to be installed. The following 2 commands will install the actual packages. - -apt-get (Debian) -~~~~~~~~~~~~~~~~ - -Since the LIGO software is not a default package in the apt package manager system on Debian machine, additional steps will be needed. The first step is to add the following links to the source list located at ``/etc/apt/sources.list``:: - - deb [arch=amd64] http://software.ligo.org/lscsoft/debian jessie contrib - deb-src [arch=amd64] http://software.ligo.org/lscsoft/debian jessie contrib - -Note that the ``[arch=amd64]`` is needed to fix the architecture problem in case it tries to install i386 version on 64-bit Debian. Once the sources have been added, you must first install all the dependencies as follows:: - - apt-get install build-essential automake autoconf libtool devscripts - -The LIGO software can finally be installed using the following command:: - - apt-get install lscsoft-all - -Main Program ------------- - -The best way to install the GNOME software along with the rest of the dependencies is by using `pip`:: - - pip install gdas - -(You may need to put a ``sudo`` in front of this). For this to work -you need to have `pip -`_ installed. This -method allows for easy uninstallation. - -You can also simply download the tarball from the PyPI website, unpack it and then do:: - - python setup.py install - -The latest stable package can be downloaded from PyPI: https://pypi.python.org/pypi/gdas. -The development version can be downloaded from `here `_. diff --git a/docs/_sources/server.rst.txt b/docs/_sources/server.rst.txt deleted file mode 100644 index b8b5172..0000000 --- a/docs/_sources/server.rst.txt +++ /dev/null @@ -1,20 +0,0 @@ -Multi-user Server -================= - -A GNOME JupyterHub, or multi-user server has been created to allow each member to access the entire available dataset. Member who do not have access to the server but wish to access it should send a request to Dr. Sam Afach. Member who are not part of the GNOME collaboration will not be granted access to the dataset but are free to use our software on their own data. - -The server can be accessed in two ways, either by acceding the `server's webpage `_, or from your terminal through SSH:: - - ssh -X username@budker.uni-mainz.de -p 8022 - -While SSH is very handy for people using UNIX-like operating systems, this can become more complicated for those working on Windows machines. Fortunately, access to a terminal is also possible through the webpage, which means directly from your internet browser! This can be done by clicking on the New tab after login and select Terminal: - -.. figure:: img/jupyter1.png - :width: 70% - :align: center - -You can then use the terminal window to access files and create new Python scripts for your analysis. - -.. figure:: img/jupyter2.png - :width: 70% - :align: center diff --git a/docs/_static/ajax-loader.gif b/docs/_static/ajax-loader.gif deleted file mode 100644 index 61faf8cab23993bd3e1560bff0668bd628642330..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 673 zcmZ?wbhEHb6krfw_{6~Q|Nno%(3)e{?)x>&1u}A`t?OF7Z|1gRivOgXi&7IyQd1Pl zGfOfQ60;I3a`F>X^fL3(@);C=vM_KlFfb_o=k{|A33hf2a5d61U}gjg=>Rd%XaNQW zW@Cw{|b%Y*pl8F?4B9 zlo4Fz*0kZGJabY|>}Okf0}CCg{u4`zEPY^pV?j2@h+|igy0+Kz6p;@SpM4s6)XEMg z#3Y4GX>Hjlml5ftdH$4x0JGdn8~MX(U~_^d!Hi)=HU{V%g+mi8#UGbE-*ao8f#h+S z2a0-5+vc7MU$e-NhmBjLIC1v|)9+Im8x1yacJ7{^tLX(ZhYi^rpmXm0`@ku9b53aN zEXH@Y3JaztblgpxbJt{AtE1ad1Ca>{v$rwwvK(>{m~Gf_=-Ro7Fk{#;i~+{{>QtvI yb2P8Zac~?~=sRA>$6{!(^3;ZP0TPFR(G_-UDU(8Jl0?(IXu$~#4A!880|o%~Al1tN diff --git a/docs/_static/alert_info_32.png b/docs/_static/alert_info_32.png deleted file mode 100644 index ea4d1baf7001be1d988ca82c2ac4d65803589915..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1128 zcmV-u1eg1XP)bXT=W25&P)Zz^Neb|z!nwr$(CZQHhO+cV9xXHqYj${6+j$uBp} zd*1&v@rL6gx+gc@yEAOrVS#!kbOhN0QdGb)uN3KiOponP&j0mud1HAyO@vAF($_3_c|3!sUe*@Q5)ms1qbkr)uoE6klqqnOwjuT8Asf)krtm2u^-{tN zkd6cp+i5D^q-{hdXilA^UZx4`CY)IWx)Y|8X90F1$vB$GeOmc>nsQgElX^M$ z^mYV+_JnEfSp^MXN)Sor68_ah#tk~x1Yfoz33MP#SIOte7vZN;AI1`>M3~`(9Thy$ zN7}iUS0rpC0ql_S2;&^{SM0@NV=mDN)ONqs>booND9t6Glq6DYCY(tGAmJNEbdG1f zk#Q_G?jh6FUq)ZLI)rf~0pY7mIOB-ayNCn}sI7!QfUnkd+6HlS8pSYk*CG|m_TU8Hx|1C)g?J58Cxv^8UBD@W0mdrW`hM+|hkPk()VXC&xB zpo4Ukz5)sF{0&&z>bksQ6ivxTGzA~fY2L?P-7~G$jn|BxzlqfPGv5m7znk0th_DApD610$n$VWl(-(WXez*UOH>m(2{SS~) zVGHoNv@uR*W^cWY1xG|t>ksyy%k4ki4Y&W!(o+V>n6L#n;;%Z0B_`Zq$;ojnIwn@@ zfBfv*PwR(Y0nj1j2hb21FQAl^g3rk<|4Kmey8@C*zQ=Pzf9E(B92>{d)8bfcf&!Fy zu7CgakpBD1aKg+ctX_u%u>jUc8!03O-=Ki}g^;1GA4gj|mZ@7sGvCk{w|{s2>K_r; z-Tu2vf5OZooa022vpSCvK7}#W2;iC&d<%IHGRI81?zH93(^h`2|EzBRsjr3fzksj@ zi3AGZoKc8#LB1UXz_$#L>G{6{ssiS!NjH?H@TFk?kr3H-h7!eb+{!7o+pW-TgfrCs^@(i64XXz9@N2l0DCMbB3 zuDH?(40YN}umx=CArHDb4@226Q5o zzCS)ldg`Gm)P=h1|Gz ziRc8~iSyqA+Mqy5a9bcf3gYiV^f_2Qkhbq$COhmVD9r#t7y`;if?A1dD1mH;mNCfK z#{dWjOF(0aeM%m(XmCLr0ECAi)ERI=8Dt5AFXLhZi0Z%v?9@vuV16y->0iY_NCMjR zC`%N40R>=JArt|n{8GFA<;|!Swmq~>=-NV6^l^P8Heqc-d-Uwod!zTT?S`rl1nkZ? zc>l{nT9(U&M@Rz76R>N)63PPQ-tYuG34`7Jx?})^MTpA41)_I8HiT)jVy3$QvgnUq z8UXAj6arEmrN9L?yW@!ww{CmP$DDu57zU3|kjr^9U?sdvSq!H>9tF5CNP%P@51t_3O2Kx{aiK$d5aEwS~Kz~SQQSFNmP9qS8fV2-D?D4~Cor?pcmrf;8 zxyoPfgckxSU^D)nI4~8M1r+{Qz&?Duaw`GYS23URrTTmPV^#wW0rmrC15+ISJ@X%Y zeGZFPK zX)DkTkx66baKe*xwOj%p0?WJk5VayeBer}buoT!6SciYlPr#I*zMlKg!~71im+`Yt Sk$V3C0000 tbody > tr > td > ul { - padding-left: 0em; -} - -table.indextable tr.pcap { - height: 10px; -} - -table.indextable tr.cap { - margin-top: 10px; - background-color: #f2f2f2; -} - -img.toggler { - margin-right: 3px; - margin-top: 3px; - cursor: pointer; -} - -div.modindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -div.genindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -/* -- domain module index --------------------------------------------------- */ - -table.modindextable td { - padding: 2px; - border-collapse: collapse; -} - -/* -- general body styles --------------------------------------------------- */ - -div.body p, div.body dd, div.body li, div.body blockquote { - -moz-hyphens: auto; - -ms-hyphens: auto; - -webkit-hyphens: auto; - hyphens: auto; -} - -a.headerlink { - visibility: hidden; -} - -h1:hover > a.headerlink, -h2:hover > a.headerlink, -h3:hover > a.headerlink, -h4:hover > a.headerlink, -h5:hover > a.headerlink, -h6:hover > a.headerlink, -dt:hover > a.headerlink, -caption:hover > a.headerlink, -p.caption:hover > a.headerlink, -div.code-block-caption:hover > a.headerlink { - visibility: visible; -} - -div.body p.caption { - text-align: inherit; -} - -div.body td { - text-align: left; -} - -.first { - margin-top: 0 !important; -} - -p.rubric { - margin-top: 30px; - font-weight: bold; -} - -img.align-left, .figure.align-left, object.align-left { - clear: left; - float: left; - margin-right: 1em; -} - -img.align-right, .figure.align-right, object.align-right { - clear: right; - float: right; - margin-left: 1em; -} - -img.align-center, .figure.align-center, object.align-center { - display: block; - margin-left: auto; - margin-right: auto; -} - -.align-left { - text-align: left; -} - -.align-center { - text-align: center; -} - -.align-right { - text-align: right; -} - -/* -- sidebars -------------------------------------------------------------- */ - -div.sidebar { - margin: 0 0 0.5em 1em; - border: 1px solid #ddb; - padding: 7px 7px 0 7px; - background-color: #ffe; - width: 40%; - float: right; -} - -p.sidebar-title { - font-weight: bold; -} - -/* -- topics ---------------------------------------------------------------- */ - -div.topic { - border: 1px solid #ccc; - padding: 7px 7px 0 7px; - margin: 10px 0 10px 0; -} - -p.topic-title { - font-size: 1.1em; - font-weight: bold; - margin-top: 10px; -} - -/* -- admonitions ----------------------------------------------------------- */ - -div.admonition { - margin-top: 10px; - margin-bottom: 10px; - padding: 7px; -} - -div.admonition dt { - font-weight: bold; -} - -div.admonition dl { - margin-bottom: 0; -} - -p.admonition-title { - margin: 0px 10px 5px 0px; - font-weight: bold; -} - -div.body p.centered { - text-align: center; - margin-top: 25px; -} - -/* -- tables ---------------------------------------------------------------- */ - -table.docutils { - border: 0; - border-collapse: collapse; -} - -table caption span.caption-number { - font-style: italic; -} - -table caption span.caption-text { -} - -table.docutils td, table.docutils th { - padding: 1px 8px 1px 5px; - border-top: 0; - border-left: 0; - border-right: 0; - border-bottom: 1px solid #aaa; -} - -table.footnote td, table.footnote th { - border: 0 !important; -} - -th { - text-align: left; - padding-right: 5px; -} - -table.citation { - border-left: solid 1px gray; - margin-left: 1px; -} - -table.citation td { - border-bottom: none; -} - -/* -- figures --------------------------------------------------------------- */ - -div.figure { - margin: 0.5em; - padding: 0.5em; -} - -div.figure p.caption { - padding: 0.3em; -} - -div.figure p.caption span.caption-number { - font-style: italic; -} - -div.figure p.caption span.caption-text { -} - -/* -- field list styles ----------------------------------------------------- */ - -table.field-list td, table.field-list th { - border: 0 !important; -} - -.field-list ul { - margin: 0; - padding-left: 1em; -} - -.field-list p { - margin: 0; -} - -/* -- other body styles ----------------------------------------------------- */ - -ol.arabic { - list-style: decimal; -} - -ol.loweralpha { - list-style: lower-alpha; -} - -ol.upperalpha { - list-style: upper-alpha; -} - -ol.lowerroman { - list-style: lower-roman; -} - -ol.upperroman { - list-style: upper-roman; -} - -dl { - margin-bottom: 15px; -} - -dd p { - margin-top: 0px; -} - -dd ul, dd table { - margin-bottom: 10px; -} - -dd { - margin-top: 3px; - margin-bottom: 10px; - margin-left: 30px; -} - -dt:target, .highlighted { - background-color: #fbe54e; -} - -dl.glossary dt { - font-weight: bold; - font-size: 1.1em; -} - -.optional { - font-size: 1.3em; -} - -.sig-paren { - font-size: larger; -} - -.versionmodified { - font-style: italic; -} - -.system-message { - background-color: #fda; - padding: 5px; - border: 3px solid red; -} - -.footnote:target { - background-color: #ffa; -} - -.line-block { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} - -.line-block .line-block { - margin-top: 0; - margin-bottom: 0; - margin-left: 1.5em; -} - -.guilabel, .menuselection { - font-family: sans-serif; -} - -.accelerator { - text-decoration: underline; -} - -.classifier { - font-style: oblique; -} - -abbr, acronym { - border-bottom: dotted 1px; - cursor: help; -} - -/* -- code displays --------------------------------------------------------- */ - -pre { - overflow: auto; - overflow-y: hidden; /* fixes display issues on Chrome browsers */ -} - -span.pre { - -moz-hyphens: none; - -ms-hyphens: none; - -webkit-hyphens: none; - hyphens: none; -} - -td.linenos pre { - padding: 5px 0px; - border: 0; - background-color: transparent; - color: #aaa; -} - -table.highlighttable { - margin-left: 0.5em; -} - -table.highlighttable td { - padding: 0 0.5em 0 0.5em; -} - -div.code-block-caption { - padding: 2px 5px; - font-size: small; -} - -div.code-block-caption code { - background-color: transparent; -} - -div.code-block-caption + div > div.highlight > pre { - margin-top: 0; -} - -div.code-block-caption span.caption-number { - padding: 0.1em 0.3em; - font-style: italic; -} - -div.code-block-caption span.caption-text { -} - -div.literal-block-wrapper { - padding: 1em 1em 0; -} - -div.literal-block-wrapper div.highlight { - margin: 0; -} - -code.descname { - background-color: transparent; - font-weight: bold; - font-size: 1.2em; -} - -code.descclassname { - background-color: transparent; -} - -code.xref, a code { - background-color: transparent; - font-weight: bold; -} - -h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { - background-color: transparent; -} - -.viewcode-link { - float: right; -} - -.viewcode-back { - float: right; - font-family: sans-serif; -} - -div.viewcode-block:target { - margin: -1px -10px; - padding: 0 10px; -} - -/* -- math display ---------------------------------------------------------- */ - -img.math { - vertical-align: middle; -} - -div.body div.math p { - text-align: center; -} - -span.eqno { - float: right; -} - -span.eqno a.headerlink { - position: relative; - left: 0px; - z-index: 1; -} - -div.math:hover a.headerlink { - visibility: visible; -} - -/* -- printout stylesheet --------------------------------------------------- */ - -@media print { - div.document, - div.documentwrapper, - div.bodywrapper { - margin: 0 !important; - width: 100%; - } - - div.sphinxsidebar, - div.related, - div.footer, - #top-link { - display: none; - } -} \ No newline at end of file diff --git a/docs/_static/bg-page.png b/docs/_static/bg-page.png deleted file mode 100644 index fe0a6dc896e0e3a5b7a5cdf37d07bcbc5c9a00cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82 zcmeAS@N?(olHy`uVBq!ia0vp^JV2bm0VEh6RQr_!DM?Qk$B+ufgKEEmrS eJg4#epawewOK?KyydX0*kYZ0)KbLh*2~7alO%#{_ diff --git a/docs/_static/bullet_orange.png b/docs/_static/bullet_orange.png deleted file mode 100644 index 1cb8097ce9b7592811e6ca10397ffe913e62503a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 165 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_|R1SIpWoc_7Rc)|DFwIFq!ZFK(e?s Q2WT&Yr>mdKI;Vst0IY{fhyVZp diff --git a/docs/_static/comment-bright.png b/docs/_static/comment-bright.png deleted file mode 100644 index 15e27edb12ac25701ac0ac21b97b52bb4e45415e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 756 zcmVgfIX78 z$8Pzv({A~p%??+>KickCb#0FM1rYN=mBmQ&Nwp<#JXUhU;{|)}%&s>suq6lXw*~s{ zvHx}3C%<;wE5CH!BR{p5@ml9ws}y)=QN-kL2?#`S5d*6j zk`h<}j1>tD$b?4D^N9w}-k)bxXxFg>+#kme^xx#qg6FI-%iv2U{0h(Y)cs%5a|m%Pn_K3X_bDJ>EH#(Fb73Z zfUt2Q3B>N+ot3qb*DqbTZpFIn4a!#_R-}{?-~Hs=xSS6p&$sZ-k1zDdtqU`Y@`#qL z&zv-~)Q#JCU(dI)Hf;$CEnK=6CK50}q7~wdbI->?E07bJ0R;!GSQTs5Am`#;*WHjvHRvY?&$Lm-vq1a_BzocI^ULXV!lbMd%|^B#fY;XX)n<&R^L z=84u1e_3ziq;Hz-*k5~zwY3*oDKt0;bM@M@@89;@m*4RFgvvM_4;5LB!@OB@^WbVT zjl{t;a8_>od-~P4 m{5|DvB&z#xT;*OnJqG}gk~_7HcNkCr0000W zanA~u9RIXo;n7c96&U)YLgs-FGlx~*_c{Jgvesu1E5(8YEf&5wF=YFPcRe@1=MJmi zag(L*xc2r0(slpcN!vC5CUju;vHJkHc*&70_n2OZsK%O~A=!+YIw z7zLLl7~Z+~RgWOQ=MI6$#0pvpu$Q43 zP@36QAmu6!_9NPM?o<1_!+stoVRRZbW9#SPe!n;#A_6m8f}|xN1;H{`0RoXQ2LM47 zt(g;iZ6|pCb@h2xk&(}S3=EVBUO0e90m2Lp5CB<(SPIaB;n4))3JB87Or#XPOPcum z?<^(g+m9}VNn4Y&B`g8h{t_$+RB1%HKRY6fjtd-<7&EsU;vs0GM(Lmbhi%Gwcfs0FTF}T zL{_M6Go&E0Eg8FuB*(Yn+Z*RVTBE@10eIOb3El^MhO`GabDll(V0&FlJi2k^;q8af zkENdk2}x2)_KVp`5OAwXZM;dG0?M-S)xE1IKDi6BY@5%Or?#aZ9$gcX)dPZ&wA1a< z$rFXHPn|TBf`e?>Are8sKtKrKcjF$i^lp!zkL?C|y^vlHr1HXeVJd;1I~g&Ob-q)& z(fn7s-KI}G{wnKzg_U5G(V%bX6uk zIa+<@>rdmZYd!9Y=C0cuchrbIjuRB_Wq{-RXlic?flu1*_ux}x%(HDH&nT`k^xCeC ziHi1!ChH*sQ6|UqJpTTzX$aw8e(UfcS^f;6yBWd+(1-70zU(rtxtqR%j z-lsH|CKQJXqD{+F7V0OTv8@{~(wp(`oIP^ZykMWgR>&|RsklFMCnOo&Bd{le} zV5F6424Qzl;o2G%oVvmHgRDP9!=rK8fy^!yV8y*4p=??uIRrrr0?>O!(z*g5AvL2!4z0{sq%vhG*Po}`a<6%kTK5TNhtC8}rXNu&h^QH4A&Sk~Autm*s~45(H7+0bi^MraaRVzr05hQ3iK?j` zR#U@^i0WhkIHTg29u~|ypU?sXCQEQgXfObPW;+0YAF;|5XyaMAEM0sQ@4-xCZe=0e z7r$ofiAxn@O5#RodD8rh5D@nKQ;?lcf@tg4o+Wp44aMl~c47azN_(im0N)7OqdPBC zGw;353_o$DqGRDhuhU$Eaj!@m000000NkvXXu0mjfjZ7Z_ diff --git a/docs/_static/doctools.js b/docs/_static/doctools.js deleted file mode 100644 index 8163495..0000000 --- a/docs/_static/doctools.js +++ /dev/null @@ -1,287 +0,0 @@ -/* - * doctools.js - * ~~~~~~~~~~~ - * - * Sphinx JavaScript utilities for all documentation. - * - * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -/** - * select a different prefix for underscore - */ -$u = _.noConflict(); - -/** - * make the code below compatible with browsers without - * an installed firebug like debugger -if (!window.console || !console.firebug) { - var names = ["log", "debug", "info", "warn", "error", "assert", "dir", - "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", - "profile", "profileEnd"]; - window.console = {}; - for (var i = 0; i < names.length; ++i) - window.console[names[i]] = function() {}; -} - */ - -/** - * small helper function to urldecode strings - */ -jQuery.urldecode = function(x) { - return decodeURIComponent(x).replace(/\+/g, ' '); -}; - -/** - * small helper function to urlencode strings - */ -jQuery.urlencode = encodeURIComponent; - -/** - * This function returns the parsed url parameters of the - * current request. Multiple values per key are supported, - * it will always return arrays of strings for the value parts. - */ -jQuery.getQueryParameters = function(s) { - if (typeof s == 'undefined') - s = document.location.search; - var parts = s.substr(s.indexOf('?') + 1).split('&'); - var result = {}; - for (var i = 0; i < parts.length; i++) { - var tmp = parts[i].split('=', 2); - var key = jQuery.urldecode(tmp[0]); - var value = jQuery.urldecode(tmp[1]); - if (key in result) - result[key].push(value); - else - result[key] = [value]; - } - return result; -}; - -/** - * highlight a given string on a jquery object by wrapping it in - * span elements with the given class name. - */ -jQuery.fn.highlightText = function(text, className) { - function highlight(node) { - if (node.nodeType == 3) { - var val = node.nodeValue; - var pos = val.toLowerCase().indexOf(text); - if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) { - var span = document.createElement("span"); - span.className = className; - span.appendChild(document.createTextNode(val.substr(pos, text.length))); - node.parentNode.insertBefore(span, node.parentNode.insertBefore( - document.createTextNode(val.substr(pos + text.length)), - node.nextSibling)); - node.nodeValue = val.substr(0, pos); - } - } - else if (!jQuery(node).is("button, select, textarea")) { - jQuery.each(node.childNodes, function() { - highlight(this); - }); - } - } - return this.each(function() { - highlight(this); - }); -}; - -/* - * backward compatibility for jQuery.browser - * This will be supported until firefox bug is fixed. - */ -if (!jQuery.browser) { - jQuery.uaMatch = function(ua) { - ua = ua.toLowerCase(); - - var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || - /(webkit)[ \/]([\w.]+)/.exec(ua) || - /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || - /(msie) ([\w.]+)/.exec(ua) || - ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || - []; - - return { - browser: match[ 1 ] || "", - version: match[ 2 ] || "0" - }; - }; - jQuery.browser = {}; - jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; -} - -/** - * Small JavaScript module for the documentation. - */ -var Documentation = { - - init : function() { - this.fixFirefoxAnchorBug(); - this.highlightSearchWords(); - this.initIndexTable(); - - }, - - /** - * i18n support - */ - TRANSLATIONS : {}, - PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; }, - LOCALE : 'unknown', - - // gettext and ngettext don't access this so that the functions - // can safely bound to a different name (_ = Documentation.gettext) - gettext : function(string) { - var translated = Documentation.TRANSLATIONS[string]; - if (typeof translated == 'undefined') - return string; - return (typeof translated == 'string') ? translated : translated[0]; - }, - - ngettext : function(singular, plural, n) { - var translated = Documentation.TRANSLATIONS[singular]; - if (typeof translated == 'undefined') - return (n == 1) ? singular : plural; - return translated[Documentation.PLURALEXPR(n)]; - }, - - addTranslations : function(catalog) { - for (var key in catalog.messages) - this.TRANSLATIONS[key] = catalog.messages[key]; - this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); - this.LOCALE = catalog.locale; - }, - - /** - * add context elements like header anchor links - */ - addContextElements : function() { - $('div[id] > :header:first').each(function() { - $('\u00B6'). - attr('href', '#' + this.id). - attr('title', _('Permalink to this headline')). - appendTo(this); - }); - $('dt[id]').each(function() { - $('\u00B6'). - attr('href', '#' + this.id). - attr('title', _('Permalink to this definition')). - appendTo(this); - }); - }, - - /** - * workaround a firefox stupidity - * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 - */ - fixFirefoxAnchorBug : function() { - if (document.location.hash) - window.setTimeout(function() { - document.location.href += ''; - }, 10); - }, - - /** - * highlight the search words provided in the url in the text - */ - highlightSearchWords : function() { - var params = $.getQueryParameters(); - var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; - if (terms.length) { - var body = $('div.body'); - if (!body.length) { - body = $('body'); - } - window.setTimeout(function() { - $.each(terms, function() { - body.highlightText(this.toLowerCase(), 'highlighted'); - }); - }, 10); - $('') - .appendTo($('#searchbox')); - } - }, - - /** - * init the domain index toggle buttons - */ - initIndexTable : function() { - var togglers = $('img.toggler').click(function() { - var src = $(this).attr('src'); - var idnum = $(this).attr('id').substr(7); - $('tr.cg-' + idnum).toggle(); - if (src.substr(-9) == 'minus.png') - $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); - else - $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); - }).css('display', ''); - if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { - togglers.click(); - } - }, - - /** - * helper function to hide the search marks again - */ - hideSearchWords : function() { - $('#searchbox .highlight-link').fadeOut(300); - $('span.highlighted').removeClass('highlighted'); - }, - - /** - * make the url absolute - */ - makeURL : function(relativeURL) { - return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; - }, - - /** - * get the current relative url - */ - getCurrentURL : function() { - var path = document.location.pathname; - var parts = path.split(/\//); - $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { - if (this == '..') - parts.pop(); - }); - var url = parts.join('/'); - return path.substring(url.lastIndexOf('/') + 1, path.length - 1); - }, - - initOnKeyListeners: function() { - $(document).keyup(function(event) { - var activeElementType = document.activeElement.tagName; - // don't navigate when in search box or textarea - if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') { - switch (event.keyCode) { - case 37: // left - var prevHref = $('link[rel="prev"]').prop('href'); - if (prevHref) { - window.location.href = prevHref; - return false; - } - case 39: // right - var nextHref = $('link[rel="next"]').prop('href'); - if (nextHref) { - window.location.href = nextHref; - return false; - } - } - } - }); - } -}; - -// quick alias for translations -_ = Documentation.gettext; - -$(document).ready(function() { - Documentation.init(); -}); \ No newline at end of file diff --git a/docs/_static/down-pressed.png b/docs/_static/down-pressed.png deleted file mode 100644 index 5756c8cad8854722893dc70b9eb4bb0400343a39..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 222 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`OFdm2Ln;`PZ^+1>KjR?B@S0W7 z%OS_REiHONoJ6{+Ks@6k3590|7k9F+ddB6!zw3#&!aw#S`x}3V3&=A(a#84O-&F7T z^k3tZB;&iR9siw0|F|E|DAL<8r-F4!1H-;1{e*~yAKZN5f0|Ei6yUmR#Is)EM(Po_ zi`qJR6|P<~+)N+kSDgL7AjdIC_!O7Q?eGb+L+qOjm{~LLinM4NHn7U%HcK%uoMYO5 VJ~8zD2B3o(JYD@<);T3K0RV0%P>BEl diff --git a/docs/_static/down.png b/docs/_static/down.png deleted file mode 100644 index 1b3bdad2ceffae91cee61b32f3295f9bbe646e48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 202 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6CVIL!hEy=F?b*7pIY7kW{q%Rg zx!yQ<9v8bmJwa`TQk7YSw}WVQ()mRdQ;TC;* diff --git a/docs/_static/file.png b/docs/_static/file.png deleted file mode 100644 index a858a410e4faa62ce324d814e4b816fff83a6fb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( diff --git a/docs/_static/haiku.css b/docs/_static/haiku.css deleted file mode 100644 index d4615fa..0000000 --- a/docs/_static/haiku.css +++ /dev/null @@ -1,376 +0,0 @@ -/* - * haiku.css_t - * ~~~~~~~~~~~ - * - * Sphinx stylesheet -- haiku theme. - * - * Adapted from http://haiku-os.org/docs/Haiku-doc.css. - * Original copyright message: - * - * Copyright 2008-2009, Haiku. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Francois Revol - * Stephan Assmus - * Braden Ewing - * Humdinger - * - * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -@import url("basic.css"); - -html { - margin: 0px; - padding: 0px; - background: #FFF url(bg-page.png) top left repeat-x; -} - -body { - line-height: 1.5; - margin: auto; - padding: 0px; - font-family: "DejaVu Sans", Arial, Helvetica, sans-serif; - min-width: 59em; - max-width: 70em; - color: #333333; -} - -div.footer { - padding: 8px; - font-size: 11px; - text-align: center; - letter-spacing: 0.5px; -} - -/* link colors and text decoration */ - -a:link { - font-weight: bold; - text-decoration: none; - color: #dc3c01; -} - -a:visited { - font-weight: bold; - text-decoration: none; - color: #892601; -} - -a:hover, a:active { - text-decoration: underline; - color: #ff4500; -} - -/* Some headers act as anchors, don't give them a hover effect */ - -h1 a:hover, a:active { - text-decoration: none; - color: #0c3762; -} - -h2 a:hover, a:active { - text-decoration: none; - color: #0c3762; -} - -h3 a:hover, a:active { - text-decoration: none; - color: #0c3762; -} - -h4 a:hover, a:active { - text-decoration: none; - color: #0c3762; -} - -a.headerlink { - color: #a7ce38; - padding-left: 5px; -} - -a.headerlink:hover { - color: #a7ce38; -} - -/* basic text elements */ - -div.content { - margin-top: 20px; - margin-left: 40px; - margin-right: 40px; - margin-bottom: 50px; - font-size: 0.9em; -} - -/* heading and navigation */ - -div.header { - position: relative; - left: 0px; - top: 0px; - height: 85px; - /* background: #eeeeee; */ - padding: 0 40px; -} -div.header h1 { - font-size: 1.6em; - font-weight: normal; - letter-spacing: 1px; - color: #0c3762; - border: 0; - margin: 0; - padding-top: 15px; -} -div.header h1 a { - font-weight: normal; - color: #0c3762; -} -div.header h2 { - font-size: 1.3em; - font-weight: normal; - letter-spacing: 1px; - text-transform: uppercase; - color: #aaa; - border: 0; - margin-top: -3px; - padding: 0; -} - -div.header img.rightlogo { - float: right; -} - - -div.title { - font-size: 1.3em; - font-weight: bold; - color: #0c3762; - border-bottom: dotted thin #e0e0e0; - margin-bottom: 25px; -} -div.topnav { - /* background: #e0e0e0; */ -} -div.topnav p { - margin-top: 0; - margin-left: 40px; - margin-right: 40px; - margin-bottom: 0px; - text-align: right; - font-size: 0.8em; -} -div.bottomnav { - background: #eeeeee; -} -div.bottomnav p { - margin-right: 40px; - text-align: right; - font-size: 0.8em; -} - -a.uplink { - font-weight: normal; -} - - -/* contents box */ - -table.index { - margin: 0px 0px 30px 30px; - padding: 1px; - border-width: 1px; - border-style: dotted; - border-color: #e0e0e0; -} -table.index tr.heading { - background-color: #e0e0e0; - text-align: center; - font-weight: bold; - font-size: 1.1em; -} -table.index tr.index { - background-color: #eeeeee; -} -table.index td { - padding: 5px 20px; -} - -table.index a:link, table.index a:visited { - font-weight: normal; - text-decoration: none; - color: #dc3c01; -} -table.index a:hover, table.index a:active { - text-decoration: underline; - color: #ff4500; -} - - -/* Haiku User Guide styles and layout */ - -/* Rounded corner boxes */ -/* Common declarations */ -div.admonition { - -webkit-border-radius: 10px; - -khtml-border-radius: 10px; - -moz-border-radius: 10px; - border-radius: 10px; - border-style: dotted; - border-width: thin; - border-color: #dcdcdc; - padding: 10px 15px 10px 15px; - margin-bottom: 15px; - margin-top: 15px; -} -div.note { - padding: 10px 15px 10px 80px; - background: #e4ffde url(alert_info_32.png) 15px 15px no-repeat; - min-height: 42px; -} -div.warning { - padding: 10px 15px 10px 80px; - background: #fffbc6 url(alert_warning_32.png) 15px 15px no-repeat; - min-height: 42px; -} -div.seealso { - background: #e4ffde; -} - -/* More layout and styles */ -h1 { - font-size: 1.3em; - font-weight: bold; - color: #0c3762; - border-bottom: dotted thin #e0e0e0; - margin-top: 30px; -} - -h2 { - font-size: 1.2em; - font-weight: normal; - color: #0c3762; - border-bottom: dotted thin #e0e0e0; - margin-top: 30px; -} - -h3 { - font-size: 1.1em; - font-weight: normal; - color: #0c3762; - margin-top: 30px; -} - -h4 { - font-size: 1.0em; - font-weight: normal; - color: #0c3762; - margin-top: 30px; -} - -p { - text-align: justify; -} - -p.last { - margin-bottom: 0; -} - -ol { - padding-left: 20px; -} - -ul { - padding-left: 5px; - margin-top: 3px; -} - -li { - line-height: 1.3; -} - -div.content ul > li { - -moz-background-clip:border; - -moz-background-inline-policy:continuous; - -moz-background-origin:padding; - background: transparent url(bullet_orange.png) no-repeat scroll left 0.45em; - list-style-image: none; - list-style-type: none; - padding: 0 0 0 1.666em; - margin-bottom: 3px; -} - -td { - vertical-align: top; -} - -code { - background-color: #e2e2e2; - font-size: 1.0em; - font-family: monospace; -} - -pre { - border-color: #0c3762; - border-style: dotted; - border-width: thin; - margin: 0 0 12px 0; - padding: 0.8em; - background-color: #f0f0f0; -} - -hr { - border-top: 1px solid #ccc; - border-bottom: 0; - border-right: 0; - border-left: 0; - margin-bottom: 10px; - margin-top: 20px; -} - -/* printer only pretty stuff */ -@media print { - .noprint { - display: none; - } - /* for acronyms we want their definitions inlined at print time */ - acronym[title]:after { - font-size: small; - content: " (" attr(title) ")"; - font-style: italic; - } - /* and not have mozilla dotted underline */ - acronym { - border: none; - } - div.topnav, div.bottomnav, div.header, table.index { - display: none; - } - div.content { - margin: 0px; - padding: 0px; - } - html { - background: #FFF; - } -} - -.viewcode-back { - font-family: "DejaVu Sans", Arial, Helvetica, sans-serif; -} - -div.viewcode-block:target { - background-color: #f4debf; - border-top: 1px solid #ac9; - border-bottom: 1px solid #ac9; - margin: -1px -10px; - padding: 0 12px; -} - -/* math display */ -div.math p { - text-align: center; -} \ No newline at end of file diff --git a/docs/_static/jquery-3.1.0.js b/docs/_static/jquery-3.1.0.js deleted file mode 100644 index f2fc274..0000000 --- a/docs/_static/jquery-3.1.0.js +++ /dev/null @@ -1,10074 +0,0 @@ -/*eslint-disable no-unused-vars*/ -/*! - * jQuery JavaScript Library v3.1.0 - * https://jquery.com/ - * - * Includes Sizzle.js - * https://sizzlejs.com/ - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license - * https://jquery.org/license - * - * Date: 2016-07-07T21:44Z - */ -( function( global, factory ) { - - "use strict"; - - if ( typeof module === "object" && typeof module.exports === "object" ) { - - // For CommonJS and CommonJS-like environments where a proper `window` - // is present, execute the factory and get jQuery. - // For environments that do not have a `window` with a `document` - // (such as Node.js), expose a factory as module.exports. - // This accentuates the need for the creation of a real `window`. - // e.g. var jQuery = require("jquery")(window); - // See ticket #14549 for more info. - module.exports = global.document ? - factory( global, true ) : - function( w ) { - if ( !w.document ) { - throw new Error( "jQuery requires a window with a document" ); - } - return factory( w ); - }; - } else { - factory( global ); - } - -// Pass this if window is not defined yet -} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { - -// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 -// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode -// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common -// enough that all such attempts are guarded in a try block. -"use strict"; - -var arr = []; - -var document = window.document; - -var getProto = Object.getPrototypeOf; - -var slice = arr.slice; - -var concat = arr.concat; - -var push = arr.push; - -var indexOf = arr.indexOf; - -var class2type = {}; - -var toString = class2type.toString; - -var hasOwn = class2type.hasOwnProperty; - -var fnToString = hasOwn.toString; - -var ObjectFunctionString = fnToString.call( Object ); - -var support = {}; - - - - function DOMEval( code, doc ) { - doc = doc || document; - - var script = doc.createElement( "script" ); - - script.text = code; - doc.head.appendChild( script ).parentNode.removeChild( script ); - } -/* global Symbol */ -// Defining this global in .eslintrc would create a danger of using the global -// unguarded in another place, it seems safer to define global only for this module - - - -var - version = "3.1.0", - - // Define a local copy of jQuery - jQuery = function( selector, context ) { - - // The jQuery object is actually just the init constructor 'enhanced' - // Need init if jQuery is called (just allow error to be thrown if not included) - return new jQuery.fn.init( selector, context ); - }, - - // Support: Android <=4.0 only - // Make sure we trim BOM and NBSP - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, - - // Matches dashed string for camelizing - rmsPrefix = /^-ms-/, - rdashAlpha = /-([a-z])/g, - - // Used by jQuery.camelCase as callback to replace() - fcamelCase = function( all, letter ) { - return letter.toUpperCase(); - }; - -jQuery.fn = jQuery.prototype = { - - // The current version of jQuery being used - jquery: version, - - constructor: jQuery, - - // The default length of a jQuery object is 0 - length: 0, - - toArray: function() { - return slice.call( this ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num != null ? - - // Return just the one element from the set - ( num < 0 ? this[ num + this.length ] : this[ num ] ) : - - // Return all the elements in a clean array - slice.call( this ); - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems ) { - - // Build a new jQuery matched element set - var ret = jQuery.merge( this.constructor(), elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - each: function( callback ) { - return jQuery.each( this, callback ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map( this, function( elem, i ) { - return callback.call( elem, i, elem ); - } ) ); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ) ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - eq: function( i ) { - var len = this.length, - j = +i + ( i < 0 ? len : 0 ); - return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); - }, - - end: function() { - return this.prevObject || this.constructor(); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: arr.sort, - splice: arr.splice -}; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[ 0 ] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - - // Skip the boolean and the target - target = arguments[ i ] || {}; - i++; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { - target = {}; - } - - // Extend jQuery itself if only one argument is passed - if ( i === length ) { - target = this; - i--; - } - - for ( ; i < length; i++ ) { - - // Only deal with non-null/undefined values - if ( ( options = arguments[ i ] ) != null ) { - - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject( copy ) || - ( copyIsArray = jQuery.isArray( copy ) ) ) ) { - - if ( copyIsArray ) { - copyIsArray = false; - clone = src && jQuery.isArray( src ) ? src : []; - - } else { - clone = src && jQuery.isPlainObject( src ) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend( { - - // Unique for each copy of jQuery on the page - expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), - - // Assume jQuery is ready without the ready module - isReady: true, - - error: function( msg ) { - throw new Error( msg ); - }, - - noop: function() {}, - - isFunction: function( obj ) { - return jQuery.type( obj ) === "function"; - }, - - isArray: Array.isArray, - - isWindow: function( obj ) { - return obj != null && obj === obj.window; - }, - - isNumeric: function( obj ) { - - // As of jQuery 3.0, isNumeric is limited to - // strings and numbers (primitives or objects) - // that can be coerced to finite numbers (gh-2662) - var type = jQuery.type( obj ); - return ( type === "number" || type === "string" ) && - - // parseFloat NaNs numeric-cast false positives ("") - // ...but misinterprets leading-number strings, particularly hex literals ("0x...") - // subtraction forces infinities to NaN - !isNaN( obj - parseFloat( obj ) ); - }, - - isPlainObject: function( obj ) { - var proto, Ctor; - - // Detect obvious negatives - // Use toString instead of jQuery.type to catch host objects - if ( !obj || toString.call( obj ) !== "[object Object]" ) { - return false; - } - - proto = getProto( obj ); - - // Objects with no prototype (e.g., `Object.create( null )`) are plain - if ( !proto ) { - return true; - } - - // Objects with prototype are plain iff they were constructed by a global Object function - Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; - return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; - }, - - isEmptyObject: function( obj ) { - - /* eslint-disable no-unused-vars */ - // See https://github.com/eslint/eslint/issues/6125 - var name; - - for ( name in obj ) { - return false; - } - return true; - }, - - type: function( obj ) { - if ( obj == null ) { - return obj + ""; - } - - // Support: Android <=2.3 only (functionish RegExp) - return typeof obj === "object" || typeof obj === "function" ? - class2type[ toString.call( obj ) ] || "object" : - typeof obj; - }, - - // Evaluates a script in a global context - globalEval: function( code ) { - DOMEval( code ); - }, - - // Convert dashed to camelCase; used by the css and data modules - // Support: IE <=9 - 11, Edge 12 - 13 - // Microsoft forgot to hump their vendor prefix (#9572) - camelCase: function( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - }, - - each: function( obj, callback ) { - var length, i = 0; - - if ( isArrayLike( obj ) ) { - length = obj.length; - for ( ; i < length; i++ ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } else { - for ( i in obj ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } - - return obj; - }, - - // Support: Android <=4.0 only - trim: function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "" ); - }, - - // results is for internal usage only - makeArray: function( arr, results ) { - var ret = results || []; - - if ( arr != null ) { - if ( isArrayLike( Object( arr ) ) ) { - jQuery.merge( ret, - typeof arr === "string" ? - [ arr ] : arr - ); - } else { - push.call( ret, arr ); - } - } - - return ret; - }, - - inArray: function( elem, arr, i ) { - return arr == null ? -1 : indexOf.call( arr, elem, i ); - }, - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - merge: function( first, second ) { - var len = +second.length, - j = 0, - i = first.length; - - for ( ; j < len; j++ ) { - first[ i++ ] = second[ j ]; - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, invert ) { - var callbackInverse, - matches = [], - i = 0, - length = elems.length, - callbackExpect = !invert; - - // Go through the array, only saving the items - // that pass the validator function - for ( ; i < length; i++ ) { - callbackInverse = !callback( elems[ i ], i ); - if ( callbackInverse !== callbackExpect ) { - matches.push( elems[ i ] ); - } - } - - return matches; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var length, value, - i = 0, - ret = []; - - // Go through the array, translating each of the items to their new values - if ( isArrayLike( elems ) ) { - length = elems.length; - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - - // Go through every key on the object, - } else { - for ( i in elems ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - } - - // Flatten any nested arrays - return concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // Bind a function to a context, optionally partially applying any - // arguments. - proxy: function( fn, context ) { - var tmp, args, proxy; - - if ( typeof context === "string" ) { - tmp = fn[ context ]; - context = fn; - fn = tmp; - } - - // Quick check to determine if target is callable, in the spec - // this throws a TypeError, but we will just return undefined. - if ( !jQuery.isFunction( fn ) ) { - return undefined; - } - - // Simulated bind - args = slice.call( arguments, 2 ); - proxy = function() { - return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); - }; - - // Set the guid of unique handler to the same of original handler, so it can be removed - proxy.guid = fn.guid = fn.guid || jQuery.guid++; - - return proxy; - }, - - now: Date.now, - - // jQuery.support is not used in Core but other projects attach their - // properties to it so it needs to exist. - support: support -} ); - -if ( typeof Symbol === "function" ) { - jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; -} - -// Populate the class2type map -jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), -function( i, name ) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -} ); - -function isArrayLike( obj ) { - - // Support: real iOS 8.2 only (not reproducible in simulator) - // `in` check used to prevent JIT error (gh-2145) - // hasOwn isn't used here due to false negatives - // regarding Nodelist length in IE - var length = !!obj && "length" in obj && obj.length, - type = jQuery.type( obj ); - - if ( type === "function" || jQuery.isWindow( obj ) ) { - return false; - } - - return type === "array" || length === 0 || - typeof length === "number" && length > 0 && ( length - 1 ) in obj; -} -var Sizzle = -/*! - * Sizzle CSS Selector Engine v2.3.0 - * https://sizzlejs.com/ - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2016-01-04 - */ -(function( window ) { - -var i, - support, - Expr, - getText, - isXML, - tokenize, - compile, - select, - outermostContext, - sortInput, - hasDuplicate, - - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, - - // Instance-specific data - expando = "sizzle" + 1 * new Date(), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - } - return 0; - }, - - // Instance methods - hasOwn = ({}).hasOwnProperty, - arr = [], - pop = arr.pop, - push_native = arr.push, - push = arr.push, - slice = arr.slice, - // Use a stripped-down indexOf as it's faster than native - // https://jsperf.com/thor-indexof-vs-for/5 - indexOf = function( list, elem ) { - var i = 0, - len = list.length; - for ( ; i < len; i++ ) { - if ( list[i] === elem ) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", - - // Regular expressions - - // http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - - // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", - - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + - // Operator (capture 2) - "*([*^$|!~]?=)" + whitespace + - // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + - "*\\]", - - pseudos = ":(" + identifier + ")(?:\\((" + - // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: - // 1. quoted (capture 3; capture 4 or capture 5) - "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - // 2. simple (capture 6) - "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - // 3. anything else (capture 2) - ".*" + - ")\\)|)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rwhitespace = new RegExp( whitespace + "+", "g" ), - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), - - rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), - - rpseudo = new RegExp( pseudos ), - ridentifier = new RegExp( "^" + identifier + "$" ), - - matchExpr = { - "ID": new RegExp( "^#(" + identifier + ")" ), - "CLASS": new RegExp( "^\\.(" + identifier + ")" ), - "TAG": new RegExp( "^(" + identifier + "|[*])" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + - whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) - }, - - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, - - rnative = /^[^{]+\{\s*\[native \w/, - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - - rsibling = /[+~]/, - - // CSS escapes - // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), - funescape = function( _, escaped, escapedWhitespace ) { - var high = "0x" + escaped - 0x10000; - // NaN means non-codepoint - // Support: Firefox<24 - // Workaround erroneous numeric interpretation of +"0x" - return high !== high || escapedWhitespace ? - escaped : - high < 0 ? - // BMP codepoint - String.fromCharCode( high + 0x10000 ) : - // Supplemental Plane codepoint (surrogate pair) - String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); - }, - - // CSS string/identifier serialization - // https://drafts.csswg.org/cssom/#common-serializing-idioms - rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g, - fcssescape = function( ch, asCodePoint ) { - if ( asCodePoint ) { - - // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER - if ( ch === "\0" ) { - return "\uFFFD"; - } - - // Control characters and (dependent upon position) numbers get escaped as code points - return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; - } - - // Other potentially-special ASCII characters get backslash-escaped - return "\\" + ch; - }, - - // Used for iframes - // See setDocument() - // Removing the function wrapper causes a "Permission Denied" - // error in IE - unloadHandler = function() { - setDocument(); - }, - - disabledAncestor = addCombinator( - function( elem ) { - return elem.disabled === true; - }, - { dir: "parentNode", next: "legend" } - ); - -// Optimize for push.apply( _, NodeList ) -try { - push.apply( - (arr = slice.call( preferredDoc.childNodes )), - preferredDoc.childNodes - ); - // Support: Android<4.0 - // Detect silently failing push.apply - arr[ preferredDoc.childNodes.length ].nodeType; -} catch ( e ) { - push = { apply: arr.length ? - - // Leverage slice if possible - function( target, els ) { - push_native.apply( target, slice.call(els) ); - } : - - // Support: IE<9 - // Otherwise append directly - function( target, els ) { - var j = target.length, - i = 0; - // Can't trust NodeList.length - while ( (target[j++] = els[i++]) ) {} - target.length = j - 1; - } - }; -} - -function Sizzle( selector, context, results, seed ) { - var m, i, elem, nid, match, groups, newSelector, - newContext = context && context.ownerDocument, - - // nodeType defaults to 9, since context defaults to document - nodeType = context ? context.nodeType : 9; - - results = results || []; - - // Return early from calls with invalid selector or context - if ( typeof selector !== "string" || !selector || - nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { - - return results; - } - - // Try to shortcut find operations (as opposed to filters) in HTML documents - if ( !seed ) { - - if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { - setDocument( context ); - } - context = context || document; - - if ( documentIsHTML ) { - - // If the selector is sufficiently simple, try using a "get*By*" DOM method - // (excepting DocumentFragment context, where the methods don't exist) - if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { - - // ID selector - if ( (m = match[1]) ) { - - // Document context - if ( nodeType === 9 ) { - if ( (elem = context.getElementById( m )) ) { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - - // Element context - } else { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( newContext && (elem = newContext.getElementById( m )) && - contains( context, elem ) && - elem.id === m ) { - - results.push( elem ); - return results; - } - } - - // Type selector - } else if ( match[2] ) { - push.apply( results, context.getElementsByTagName( selector ) ); - return results; - - // Class selector - } else if ( (m = match[3]) && support.getElementsByClassName && - context.getElementsByClassName ) { - - push.apply( results, context.getElementsByClassName( m ) ); - return results; - } - } - - // Take advantage of querySelectorAll - if ( support.qsa && - !compilerCache[ selector + " " ] && - (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { - - if ( nodeType !== 1 ) { - newContext = context; - newSelector = selector; - - // qSA looks outside Element context, which is not what we want - // Thanks to Andrew Dupont for this workaround technique - // Support: IE <=8 - // Exclude object elements - } else if ( context.nodeName.toLowerCase() !== "object" ) { - - // Capture the context ID, setting it first if necessary - if ( (nid = context.getAttribute( "id" )) ) { - nid = nid.replace( rcssescape, fcssescape ); - } else { - context.setAttribute( "id", (nid = expando) ); - } - - // Prefix every selector in the list - groups = tokenize( selector ); - i = groups.length; - while ( i-- ) { - groups[i] = "#" + nid + " " + toSelector( groups[i] ); - } - newSelector = groups.join( "," ); - - // Expand context for sibling selectors - newContext = rsibling.test( selector ) && testContext( context.parentNode ) || - context; - } - - if ( newSelector ) { - try { - push.apply( results, - newContext.querySelectorAll( newSelector ) - ); - return results; - } catch ( qsaError ) { - } finally { - if ( nid === expando ) { - context.removeAttribute( "id" ); - } - } - } - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed ); -} - -/** - * Create key-value caches of limited size - * @returns {function(string, object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry - */ -function createCache() { - var keys = []; - - function cache( key, value ) { - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if ( keys.push( key + " " ) > Expr.cacheLength ) { - // Only keep the most recent entries - delete cache[ keys.shift() ]; - } - return (cache[ key + " " ] = value); - } - return cache; -} - -/** - * Mark a function for special use by Sizzle - * @param {Function} fn The function to mark - */ -function markFunction( fn ) { - fn[ expando ] = true; - return fn; -} - -/** - * Support testing using an element - * @param {Function} fn Passed the created element and returns a boolean result - */ -function assert( fn ) { - var el = document.createElement("fieldset"); - - try { - return !!fn( el ); - } catch (e) { - return false; - } finally { - // Remove from its parent by default - if ( el.parentNode ) { - el.parentNode.removeChild( el ); - } - // release memory in IE - el = null; - } -} - -/** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ -function addHandle( attrs, handler ) { - var arr = attrs.split("|"), - i = arr.length; - - while ( i-- ) { - Expr.attrHandle[ arr[i] ] = handler; - } -} - -/** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ -function siblingCheck( a, b ) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - a.sourceIndex - b.sourceIndex; - - // Use IE sourceIndex if available on both nodes - if ( diff ) { - return diff; - } - - // Check if b follows a - if ( cur ) { - while ( (cur = cur.nextSibling) ) { - if ( cur === b ) { - return -1; - } - } - } - - return a ? 1 : -1; -} - -/** - * Returns a function to use in pseudos for input types - * @param {String} type - */ -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for buttons - * @param {String} type - */ -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for :enabled/:disabled - * @param {Boolean} disabled true for :disabled; false for :enabled - */ -function createDisabledPseudo( disabled ) { - // Known :disabled false positives: - // IE: *[disabled]:not(button, input, select, textarea, optgroup, option, menuitem, fieldset) - // not IE: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable - return function( elem ) { - - // Check form elements and option elements for explicit disabling - return "label" in elem && elem.disabled === disabled || - "form" in elem && elem.disabled === disabled || - - // Check non-disabled form elements for fieldset[disabled] ancestors - "form" in elem && elem.disabled === false && ( - // Support: IE6-11+ - // Ancestry is covered for us - elem.isDisabled === disabled || - - // Otherwise, assume any non-