diff --git a/gwsumm/config.py b/gwsumm/config.py index e5195bde..3a904e31 100644 --- a/gwsumm/config.py +++ b/gwsumm/config.py @@ -305,7 +305,7 @@ def load_states(self, section='states'): """Read and format a list of `SummaryState` definitions from the given :class:`~configparser.ConfigParser` """ - from .state import (register_state, SummaryState, + from .state import (register_state, SummaryState, SummaryMetaState, ALLSTATE, generate_all_state, get_state) # parse the [states] section into individual state definitions try: @@ -327,6 +327,9 @@ def load_states(self, section='states'): if re.match(r'state[-\s]', section): states.append(register_state( SummaryState.from_ini(self, section))) + elif re.match(r'metastate[-\s]', section): + states.append(register_state( + SummaryMetaState.from_ini(self, section))) # register All state start = self.getint(section, 'gps-start-time') diff --git a/gwsumm/plot/builtin.py b/gwsumm/plot/builtin.py index 54fa5020..3bbc922b 100644 --- a/gwsumm/plot/builtin.py +++ b/gwsumm/plot/builtin.py @@ -41,7 +41,7 @@ from ..data import (get_timeseries, get_spectrogram, get_coherence_spectrogram, get_range_spectrogram, get_spectrum, get_coherence_spectrum, get_range_spectrum) -from ..state import ALLSTATE +from ..state import ALLSTATE, SummaryMetaState from .registry import (get_plot, register_plot) from .mixins import DataLabelSvgMixin @@ -508,6 +508,9 @@ def _draw(self): else: valid = SegmentList([self.span]) + if isinstance(valid, SummaryMetaState): + valid = globalv.STATES[f'{channel.ifo}-{valid.uses[0][3:]}'.lower()] + if self.type == 'coherence-spectrum': data = get_coherence_spectrum( [str(channel), str(channel2)], valid, query=False) diff --git a/gwsumm/state/__init__.py b/gwsumm/state/__init__.py index 860f3dfe..250e0b53 100644 --- a/gwsumm/state/__init__.py +++ b/gwsumm/state/__init__.py @@ -55,9 +55,9 @@ """ -from .core import SummaryState +from .core import (SummaryState, SummaryMetaState) from .registry import (get_state, get_states, register_state) from .all import (ALLSTATE, generate_all_state) __all__ = ['ALLSTATE', 'SummaryState', 'get_state', 'get_states', - 'register_state', 'generate_all_state'] + 'register_state', 'generate_all_state', 'SummaryMetaState'] diff --git a/gwsumm/state/core.py b/gwsumm/state/core.py index f5c64310..7c64798d 100644 --- a/gwsumm/state/core.py +++ b/gwsumm/state/core.py @@ -349,3 +349,45 @@ def copy(self): def __str__(self): return self.name + + +class SummaryMetaState(SummaryState): + """A meta state where different states may be used""" + + def __init__(self, name, known=SegmentList(), active=SegmentList(), + description=None, definition=None, hours=None, key=None, + filename=None, url=None, uses=[]): + + super(SummaryMetaState, self).__init__( + name=name, known=known, active=active, + description=description, definition=definition, hours=hours, + key=key, filename=filename, url=url) + + self.uses = uses + + @classmethod + def from_ini(cls, config, section): + config = GWSummConfigParser.from_configparser(config) + # get parameters + params = dict(config.nditems(section)) + # parse name + name = params.pop('name', section) + if re.match(r'metastate[-\s]', name): + name = section[10:] + # list states this uses + uses = params.pop('uses', section).split(',') + + # generate metastate + return cls(name=name, uses=uses, **params) + + def fetch(self, config=GWSummConfigParser(), + segmentcache=None, segdb_error='raise', + datacache=None, datafind_error='raise', nproc=1, nds=None, + **kwargs): + + for idx, state in enumerate(self.uses): + globalv.STATES[state.lower()].fetch( + config=config, segmentcache=segmentcache, + segdb_error=segdb_error, datacache=datacache, + datafind_error=datafind_error, nproc=nproc, nds=nds, + **kwargs) diff --git a/gwsumm/tabs/data.py b/gwsumm/tabs/data.py index aec3e7d8..5933ed44 100644 --- a/gwsumm/tabs/data.py +++ b/gwsumm/tabs/data.py @@ -60,7 +60,8 @@ from ..data.utils import get_fftparams from ..plot import get_plot from ..segments import get_segments -from ..state import (generate_all_state, ALLSTATE, get_state) +from ..state import (generate_all_state, ALLSTATE, get_state, + SummaryMetaState) from ..triggers import get_triggers from ..utils import (re_flagdiv, vprint, safe_eval) @@ -357,11 +358,20 @@ def process(self, config=ConfigParser(), nproc=1, **stateargs): nproc=nproc, nds=stateargs.get('nds', None)) vprint("States finalised [%d total]\n" % len(self.states)) for state in self.states: - vprint(" {0.name}: {1} segments | {2} seconds".format( - state, len(state.active), abs(state.active))) + if isinstance(state, SummaryMetaState): + vprint( + f"Metastate {state.key} has {len(state.uses)} states") + else: + vprint(" {0.name}: {1} segments | {2} seconds".format( + state, len(state.active), abs(state.active))) if state is self.defaultstate: vprint(" [DEFAULT]") vprint('\n') + if isinstance(state, SummaryMetaState): + for idx, this_state in enumerate(state.uses): + vprint(f" {this_state}: ") + vprint(f"{len(globalv.STATES[this_state.lower()].active)} segments | ") + vprint(f"{abs(globalv.STATES[this_state.lower()].active)} seconds\n") # pre-process requests for 'all-data' plots all_data = any([(p.all_data & p.new) for p in self.plots])