Passed
Pull Request — master (#1929)
by
unknown
02:32
created

gammapy/background/phase.py (4 issues)

1
# Licensed under a 3-clause BSD style license - see LICENSE.rst
2
from __future__ import absolute_import, division, print_function, unicode_literals
3
from .background_estimate import BackgroundEstimate
4
from gammapy.data import EventList
0 ignored issues
show
external import "from gammapy.data import EventList" should be placed before "from .background_estimate import BackgroundEstimate"
Loading history...
5
import numpy as np
0 ignored issues
show
external import "import numpy as np" should be placed before "from .background_estimate import BackgroundEstimate"
Loading history...
6
7
__all__ = ["PhaseBackgroundEstimator"]
8
9
10
class PhaseBackgroundEstimator(object):
0 ignored issues
show
The variable __class__ seems to be unused.
Loading history...
11
    """Background estimation with on and off phases.
12
13
    This class is responsible for creating a
14
    `~gammapy.background.BackgroundEstimate` by counting events
15
    in the on-phase-zone and off-phase-zone in an ON-region,
16
    given an observation, an on_region, an on-phase-zone, an off-phase-zone.
17
18
    For a usage example see future notebook.
19
20
    TODO: The phase interval has to be between 0 and 1.
21
    Cases like [-0.1, 0.1], for example, are still not supported.
22
23
    Parameters
24
    ----------
25
    on_region : `~regions.CircleSkyRegion`
26
        Target region in the sky
27
    observations : `~gammapy.data.Observations`
28
        Observations to process
29
    on_phase : `tuple` or list of tuples
30
        on-phase defined by the two edges of each interval (edges are excluded)
31
    off_phase : `tuple` or list of tuples
32
        off-phase defined by the two edges of each interval (edges are excluded)
33
    """
34
35
    def __init__(self, on_region, on_phase, off_phase, observations):
36
        self.on_region = on_region
37
        self.observations = observations
38
        self.on_phase = np.atleast_2d(on_phase)
39
        self.off_phase = np.atleast_2d(off_phase)
40
        self.result = None
41
42
    def __str__(self):
43
        s = self.__class__.__name__
44
        s += "\n{}".format(self.on_region)
45
        s += "\n{}".format(self.on_phase)
46
        s += "\n{}".format(self.off_phase)
47
        s += "\n{}".format(self.observations)
48
        return s
49
50
    def run(self):
51
        """Run all steps."""
52
        result = []
53
        for obs in self.observations:
54
            temp = self.process(obs=obs)
55
            result.append(temp)
56
57
        self.result = result
58
59
    @staticmethod
60
    def filter_events(events, tuple_phase_zone):
61
        """Select events depending on their phases."""
62
        p = events.table["PHASE"]
63
        mask = (tuple_phase_zone[0] < p) & (p < tuple_phase_zone[1])
64
        return events.select_row_subset(mask)
65
66
    @staticmethod
67
    def _check_intervals(intervals):
68
        """Split phase intervals that go beyond phase 1"""
69
        for phase_interval in intervals:
70
            if phase_interval[0] > phase_interval[1]:
71
                intervals.remove(phase_interval)
72
                intervals.append([phase_interval[0], 1])
73
                intervals.append([0, phase_interval[1]])
74
        return intervals
75
76
    def process(self, obs):
77
        """Estimate background for one observation."""
78
        all_events = obs.events.select_circular_region(self.on_region)
79
80
        self.on_phase = self._check_intervals(self.on_phase)
81
        self.off_phase = self._check_intervals(self.off_phase)
82
83
        # Loop over all ON- and OFF- phase intervals to filter the ON- and OFF- events
84
        list_on_events = [
85
            self.filter_events(all_events, each_on_phase)
86
            for each_on_phase in self.on_phase
87
        ]
88
        list_off_events = [
89
            self.filter_events(all_events, each_off_phase)
90
            for each_off_phase in self.off_phase
91
        ]
92
93
        # Loop over all ON- and OFF- phase intervals to compute the normalization factors a_on and a_off
0 ignored issues
show
This line is too long as per the coding-style (104/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
94
        a_on = np.sum([_[1] - _[0] for _ in self.on_phase])
95
        a_off = np.sum([_[1] - _[0] for _ in self.off_phase])
96
97
        on_events = EventList.stack(list_on_events)
98
        off_events = EventList.stack(list_off_events)
99
100
        return BackgroundEstimate(
101
            on_region=self.on_region,
102
            on_events=on_events,
103
            off_region=None,
104
            off_events=off_events,
105
            a_on=a_on,
106
            a_off=a_off,
107
            method="Phase Bkg Estimator",
108
        )
109