def test_get_column_string(self): rcParams['text.usetex'] = True self.assertEqual(get_column_string('snr'), 'SNR') self.assertEqual(get_column_string('reduced_chisq'), r'Reduced $\chi^2$') self.assertEqual(get_column_string('flow'), r'f$_{\mbox{\small low}}$') self.assertEqual(get_column_string('end_time_ns'), r'End Time $(ns)$')
def binned_event_rates(self, stride, column, bins, operator='>=', start=None, end=None, timecolumn='time'): """Calculate an event rate `~gwpy.timeseries.TimeSeriesDict` over a number of bins. Parameters ---------- stride : `float` size (seconds) of each time bin column : `str` name of column by which to bin. bins : `list` a list of `tuples <tuple>` marking containing bins, or a list of `floats <float>` defining bin edges against which an math operation is performed for each event. operator : `str`, `callable` one of: - ``'<'``, ``'<='``, ``'>'``, ``'>='``, ``'=='``, ``'!='``, for a standard mathematical operation, - ``'in'`` to use the list of bins as containing bin edges, or - a callable function that takes compares an event value against the bin value and returns a boolean. .. note:: If ``bins`` is given as a list of tuples, this argument is ignored. start : `float`, :class:`~gwpy.time.LIGOTimeGPS`, optional GPS start epoch of rate `~gwpy.timeseries.TimeSeries`. end : `float`, `~gwpy.time.LIGOTimeGPS`, optional GPS end time of rate `~gwpy.timeseries.TimeSeries`. This value will be rounded up to the nearest sample if needed. timecolumn : `str`, optional, default: ``time`` name of time-column to use when binning events Returns ------- rates : :class:`~gwpy.timeseries.TimeSeriesDict` a dict of (bin, `~gwpy.timeseries.TimeSeries`) pairs describing a rate of events per second (Hz) for each of the bins. """ from gwpy.timeseries import (TimeSeries, TimeSeriesDict) from gwpy.plotter.table import get_column_string # get time data times = get_table_column(self, timecolumn) # get channel try: channel = self[0].channel except (IndexError, AttributeError): channel = None # generate time bins if not start: start = times.min() if not end: end = times.max() nsamp = int(ceil((end - start) / stride)) timebins = numpy.arange(nsamp + 1) * stride + start # generate column bins if not bins: bins = [(-numpy.inf, numpy.inf)] if operator == 'in' and not isinstance(bins[0], tuple): bins2 = [] for i, bin_ in enumerate(bins[:-1]): bins2.append((bin_, bins[i+1])) bins = bins2 elif isinstance(operator, (unicode, str)): op = OPERATORS[operator] else: op = operator coldata = get_table_column(self, column) colstr = get_column_string(column) # generate one TimeSeries per bin out = TimeSeriesDict() for bin_ in bins: if isinstance(bin_, tuple): bintimes = times[(coldata >= bin_[0]) & (coldata < bin_[1])] else: bintimes = times[op(coldata, bin_)] out[bin_] = TimeSeries( numpy.histogram(bintimes, bins=timebins)[0] / float(stride), epoch=start, sample_rate=1/float(stride), unit='Hz', name='%s $%s$ %s' % (colstr, operator, bin_), channel=channel) return out
def test_get_column_string(self): with rc_context(rc={'text.usetex': True}): assert get_column_string('snr') == 'SNR' assert get_column_string('reduced_chisq') == r'Reduced $\chi^2$' assert get_column_string('flow') == r'f$_{\mbox{\small low}}$' assert get_column_string('end_time_ns') == r'End Time $(ns)$'
def draw(self): """Read in all necessary data, and generate the figure. """ # get rate arguments stride = self.pargs.pop('stride') if self.column: cname = get_column_string(self.column) bins = self.pargs.pop('bins') operator = self.pargs.pop('operator', '>=') try: opstr = LATEX_OPERATOR[operator] except KeyError: opstr = str(operator) else: bins = ['_'] # work out labels labels = self.pargs.pop('labels', None) if isinstance(labels, (unicode, str)): labels = labels.split(',') elif labels is None and self.column and len(self.channels) > 1: labels = [] for channel, bin in [(c, b) for c in self.channels for b in bins]: labels.append(r' '.join([channel, '$%s$' % opstr, str(b)])) self.pargs.setdefault('legend-title', cname) elif labels is None and self.column: labels = [r' '.join(['$%s$' % opstr, str(b)]) for b in bins] self.pargs.setdefault('legend-title', cname) elif labels is None: labels = self.channels self.pargs['labels'] = map(lambda s: str(s).strip('\n '), labels) # get time column try: tcol = self.pargs.pop('timecolumn') except KeyError: if self.etg in ['pycbc_live']: tcol = 'end_time' else: tcol = 'time' # generate data keys = [] for channel in self.channels: if self.state and not self.all_data: valid = self.state.active else: valid = SegmentList([self.span]) if '#' in str(channel) or '@' in str(channel): key = '%s,%s' % (str(channel), state and str(state) or 'All') else: key = str(channel) table_ = get_triggers(key, self.etg, valid, query=False) if self.column: rates = binned_event_rates( table_, stride, self.column, bins, operator, self.start, self.end, timecolumn=tcol).values() else: rates = [event_rate(table_, stride, self.start, self.end, timecolumn=tcol)] for bin, rate in zip(bins, rates): rate.channel = channel keys.append('%s_%s_EVENT_RATE_%s_%s' % (str(channel), str(self.etg), str(self.column), bin)) if keys[-1] not in globalv.DATA: add_timeseries(rate, keys[-1]) # reset channel lists and generate time-series plot channels = self.channels outputfile = self.outputfile self.channels = keys out = super(TriggerRateDataPlot, self).draw(outputfile=outputfile) self.channels = channels return out
def get_column_label(column): try: return COLUMN_LABEL.get(column) except KeyError: return get_column_string(column)
def process(self): """Read in all necessary data, and generate the figure. """ # get rate arguments stride = self.pargs.pop('stride') if self.column: cname = get_column_string(self.column) bins = self.pargs.pop('bins') operator = self.pargs.pop('operator', '>=') try: opstr = LATEX_OPERATOR[operator] except KeyError: opstr = str(operator) else: bins = ['_'] # work out labels labels = self.pargs.pop('labels', None) if isinstance(labels, (unicode, str)): labels = labels.split(',') elif labels is None and self.column and len(self.channels) > 1: labels = [] for channel, bin in [(c, b) for c in self.channels for b in bins]: labels.append(r' '.join( [channel, cname, '$%s$' % opstr, str(b)])) elif labels is None and self.column: labels = [r' '.join([cname, '$%s$' % opstr, str(b)]) for b in bins] elif labels is None: labels = self.channels self.pargs['labels'] = map(lambda s: str(s).strip('\n '), labels) # generate data keys = [] for channel in self.channels: if self.state and not self.all_data: valid = self.state.active else: valid = SegmentList([self.span]) if '#' in str(channel) or '@' in str(channel): key = '%s,%s' % (str(channel), state and str(state) or 'All') else: key = str(channel) table_ = get_triggers(key, self.etg, valid, query=False) if self.column: rates = binned_event_rates(table_, stride, self.column, bins, operator, self.start, self.end).values() else: rates = [event_rate(table_, stride, self.start, self.end)] for bin, rate in zip(bins, rates): rate.channel = channel keys.append( '%s_%s_EVENT_RATE_%s_%s' % (str(channel), str(self.etg), str(self.column), bin)) if keys[-1] not in globalv.DATA: add_timeseries(rate, keys[-1]) # reset channel lists and generate time-series plot channels = self.channels outputfile = self.outputfile self.channels = keys out = super(TriggerRateDataPlot, self).process(outputfile=outputfile) self.channels = channels return out
def binned_event_rates(self, stride, column, bins, operator='>=', start=None, end=None, timecolumn='time'): """Calculate an event rate `~gwpy.timeseries.TimeSeriesDict` over a number of bins. Parameters ---------- stride : `float` size (seconds) of each time bin column : `str` name of column by which to bin. bins : `list` a list of `tuples <tuple>` marking containing bins, or a list of `floats <float>` defining bin edges against which an math operation is performed for each event. operator : `str`, `callable` one of: - ``'<'``, ``'<='``, ``'>'``, ``'>='``, ``'=='``, ``'!='``, for a standard mathematical operation, - ``'in'`` to use the list of bins as containing bin edges, or - a callable function that takes compares an event value against the bin value and returns a boolean. .. note:: If ``bins`` is given as a list of tuples, this argument is ignored. start : `float`, :class:`~gwpy.time.LIGOTimeGPS`, optional GPS start epoch of rate `~gwpy.timeseries.TimeSeries`. end : `float`, `~gwpy.time.LIGOTimeGPS`, optional GPS end time of rate `~gwpy.timeseries.TimeSeries`. This value will be rounded up to the nearest sample if needed. timecolumn : `str`, optional, default: ``time`` name of time-column to use when binning events Returns ------- rates : :class:`~gwpy.timeseries.TimeSeriesDict` a dict of (bin, `~gwpy.timeseries.TimeSeries`) pairs describing a rate of events per second (Hz) for each of the bins. """ from gwpy.timeseries import (TimeSeries, TimeSeriesDict) from gwpy.plotter.table import get_column_string # get time data times = get_table_column(self, timecolumn) # get channel try: channel = self[0].channel except (IndexError, AttributeError): channel = None # generate time bins if not start: start = times.min() if not end: end = times.max() nsamp = int(ceil((end - start) / stride)) timebins = numpy.arange(nsamp + 1) * stride + start # generate column bins if not bins: bins = [(-numpy.inf, numpy.inf)] if operator == 'in' and not isinstance(bins[0], tuple): bins2 = [] for i, bin_ in enumerate(bins[:-1]): bins2.append((bin_, bins[i + 1])) bins = bins2 elif isinstance(operator, (unicode, str)): op = OPERATORS[operator] else: op = operator coldata = get_table_column(self, column) colstr = get_column_string(column) # generate one TimeSeries per bin out = TimeSeriesDict() for bin_ in bins: if isinstance(bin_, tuple): bintimes = times[(coldata >= bin_[0]) & (coldata < bin_[1])] else: bintimes = times[op(coldata, bin_)] out[bin_] = TimeSeries(numpy.histogram(bintimes, bins=timebins)[0] / float(stride), epoch=start, sample_rate=1 / float(stride), unit='Hz', name='%s $%s$ %s' % (colstr, operator, bin_), channel=channel) return out