Passed
Pull Request — main (#26)
by
unknown
02:13
created

mutis.correlation   B

Complexity

Total Complexity 46

Size/Duplication

Total Lines 442
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 46
eloc 255
dl 0
loc 442
rs 8.72
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A Correlation.__init__() 0 43 1
A Correlation.plot_times() 0 50 3
B Correlation.plot_corr() 0 62 8
F Correlation.gen_corr() 0 127 21
A Correlation.gen_synth() 0 16 1
A Correlation.gen_times() 0 38 5
A Correlation.plot_signals() 0 27 2
B Correlation.peak_find() 0 37 5

How to fix   Complexity   

Complexity

Complex classes like mutis.correlation often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
# Licensed under a 3-clause BSD style license - see LICENSE
2
"""Analysis of correlation of light curves."""
3
4
import logging
5
6
import matplotlib.pyplot as plt
0 ignored issues
show
introduced by
Unable to import 'matplotlib.pyplot'
Loading history...
7
import numpy as np
0 ignored issues
show
introduced by
Unable to import 'numpy'
Loading history...
8
import scipy as sp
0 ignored issues
show
introduced by
Unable to import 'scipy'
Loading history...
9
10
from mutis.lib.correlation import *
0 ignored issues
show
Unused Code introduced by
get_grid was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
ndcf was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
welsh_ab_p was imported with wildcard, but is not used.
Loading history...
Unused Code introduced by
kroedel_ab_p was imported with wildcard, but is not used.
Loading history...
Coding Style introduced by
The usage of wildcard imports like mutis.lib.correlation should generally be avoided.
Loading history...
11
12
from mutis.lib.utils import interp_smooth_curve
13
14
15
__all__ = ["Correlation"]
16
17
log = logging.getLogger(__name__)
18
19
20
class Correlation:
0 ignored issues
show
best-practice introduced by
Too many instance attributes (22/7)
Loading history...
21
    """Analysis of the correlation of two signals.
22
23
    Parameters
24
    ----------
25
    signal1 : :class:`~mutis.signal.Signal`
26
        Values of the time axis.
27
    signal2 : :class:`~mutis.signal.Signal`
28
        Values of the signal axis.
29
    fcorr : :py:class:`~str`
30
        Method used to correlate the signals.
31
    """
32
33
    def __init__(self, signal1, signal2, fcorr):
34
        self.signal1 = signal1
35
        self.signal2 = signal2
36
        self.fcorr = fcorr
37
38
        self.times = np.array([])
39
        self.dts = np.array([])
40
        self.nb = np.array([])
0 ignored issues
show
Coding Style Naming introduced by
Attribute name "nb" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
41
        self.values = None
42
43
        # TODO: have a much smaller set of attributes
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
44
        self.samples = None
45
        # storage of the significance limits of the correlation
46
        self.l1s = None
47
        self.l2s = None
48
        self.l3s = None
49
        # storage of the uncertainties of the correlation
50
        self.s1s = None
51
        self.s2s = None
52
        self.s3s = None
53
54
        # attributes indicating the ranges where the correlations are defined
55
        t1, t2 = self.signal1.times, self.signal2.times
0 ignored issues
show
Coding Style Naming introduced by
Variable name "t2" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Coding Style Naming introduced by
Variable name "t1" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
56
        self.tmin_full = t2.min() - t1.max()
57
        self.tmax_full = t2.max() - t1.min()
58
        self.t0_full = (self.tmax_full + self.tmin_full) / 2
59
        self.tmin_same = -(np.max([t1.max() - t1.min(), t2.max() - t2.min()])) / 2 + self.t0_full
60
        self.tmax_same = (np.max([t1.max() - t1.min(), t2.max() - t2.min()])) / 2 + self.t0_full
61
        self.tmin_valid = (
62
            -(
63
                np.max([t1.max() - t1.min(), t2.max() - t2.min()])
64
                - np.min([t1.max() - t1.min(), t2.max() - t2.min()])
65
            )
66
            / 2
67
            + self.t0_full
68
        )
69
        self.tmax_valid = (
70
            +(
71
                np.max([t1.max() - t1.min(), t2.max() - t2.min()])
72
                - np.min([t1.max() - t1.min(), t2.max() - t2.min()])
73
            )
74
            / 2
75
            + self.t0_full
76
        )
77
78
    def peak_find(self, smooth=False, smooth_std=None, Ninterp=1000):
0 ignored issues
show
Coding Style Naming introduced by
Argument name "Ninterp" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Comprehensibility introduced by
This function exceeds the maximum number of variables (23/15).
Loading history...
79
        """Find the peaks of the correlation, optionally smoothing with a kernel of standard deviation `s`.
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (107/100).

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

Loading history...
80
        Returns dict with peak positions and significances, ordered from closest to farthest from zero.
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (103/100).

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

Loading history...
81
        """
82
        x, y = self.times, self.values
0 ignored issues
show
Coding Style Naming introduced by
Variable name "x" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Coding Style Naming introduced by
Variable name "y" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
83
84
        if smooth_std is None:
85
            dt1 = np.mean(self.signal1.times[1:]-self.signal1.times[:-1])
86
            std1 = np.std(self.signal1.times[1:]-self.signal1.times[:-1])
0 ignored issues
show
Unused Code introduced by
The variable std1 seems to be unused.
Loading history...
87
            dt2 = np.mean(self.signal2.times[1:]-self.signal2.times[:-1])
88
            std2 = np.std(self.signal2.times[1:]-self.signal2.times[:-1])
0 ignored issues
show
Unused Code introduced by
The variable std2 seems to be unused.
Loading history...
89
90
            smooth_std = 1*np.max([dt1,dt2])
0 ignored issues
show
Coding Style introduced by
Exactly one space required after comma
Loading history...
91
                
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
92
        if smooth:
93
            xs, ys = interp_smooth_curve(x, y, smooth_std, Ninterp)
0 ignored issues
show
Coding Style Naming introduced by
Variable name "ys" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Coding Style Naming introduced by
Variable name "xs" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
94
        else:
95
            xs, ys = x, y
0 ignored issues
show
Coding Style Naming introduced by
Variable name "ys" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Coding Style Naming introduced by
Variable name "xs" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
96
97
        idx, props = sp.signal.find_peaks(ys)
0 ignored issues
show
Unused Code introduced by
The variable props seems to be unused.
Loading history...
98
        
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
99
        if smooth:
100
            s1s_x, s1s_y = interp_smooth_curve(x, self.l1s[1], smooth_std, Ninterp)
0 ignored issues
show
Unused Code introduced by
The variable s1s_x seems to be unused.
Loading history...
101
        else:
102
            s1s_x, s1s_y = x, self.l1s[1]
103
104
        peak_idx = idx[np.argsort(np.abs(xs[idx]))]
105
        peak_x = xs[peak_idx]
106
        peak_y = ys[peak_idx]
107
        peak_signf1s = ys[peak_idx]/s1s_y[peak_idx]
108
        
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
109
        peak_signif_percent = list()
110
        for i in range(len(peak_x)):
0 ignored issues
show
unused-code introduced by
Consider using enumerate instead of iterating with range and len
Loading history...
111
            f = sp.interpolate.interp1d(self.times, self.mc_corr, axis=-1)
0 ignored issues
show
Coding Style Naming introduced by
Variable name "f" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
112
            peak_signif_percent.append( sp.stats.percentileofscore(f(peak_x[i]), peak_y[i], kind='strict') )
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (108/100).

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

Loading history...
Coding Style introduced by
No space allowed after bracket
Loading history...
Coding Style introduced by
No space allowed before bracket
Loading history...
113
114
        return {'x':peak_x, 's':smooth_std, 'y':peak_y, 'signf1s':peak_signf1s, 'signif_percent':np.array(peak_signif_percent)}
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (127/100).

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

Loading history...
115
116
    def gen_synth(self, samples):
117
        """Generates the synthetic light curves.
118
119
        Generates the specified number `samples` of synthetic light
120
        curves for each signal, to be used to compute the significance
121
        the correlation.
122
123
        Parameters
124
        ----------
125
        samples : :py:class:`~int`
126
            Number of synthetic light curves to be generated for each signal.
127
        """
128
129
        self.samples = samples
130
        self.signal1.gen_synth(samples)
131
        self.signal2.gen_synth(samples)
132
133
    def gen_corr(self, uncert=True, dsamples=500):
134
        """Generates the correlation of the signals.
135
136
        Generates the correlation of the signals, and computes their
137
        confidence level from the synthetic light curves, which must
138
        have been generated before.
139
        """
140
141
        if uncert and self.signal1.dvalues is None:
142
            log.error(
143
                "uncert is True but no uncertainties for Signal 1 were specified, setting uncert to False"
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (106/100).

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

Loading history...
144
            )
145
            uncert = False
146
        if uncert and self.signal2.dvalues is None:
147
            log.error(
148
                "uncert is True but no uncertainties for Signal 2 were specified, setting uncert to False"
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (106/100).

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

Loading history...
149
            )
150
            uncert = False
151
152
        if len(self.times) == 0 or len(self.dts) == 0:
153
            raise Exception(
154
                "You need to define the times on which to calculate the correlation."
155
                "Please use gen_times() or manually set them."
156
            )
157
158
        # TODO: refactor if/elif with a helper function
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
159
        mc_corr = np.empty((self.samples, self.times.size))
160
        if uncert:
161
            mc_sig = np.empty((dsamples, self.times.size))
162
163
        if self.fcorr == "welsh_ab":
164
            for idx in range(self.samples):
165
                mc_corr[idx] = welsh_ab(
166
                    self.signal1.times,
167
                    self.signal1.synth[idx],
168
                    self.signal2.times,
169
                    self.signal2.synth[idx],
170
                    self.times,
171
                    self.dts,
172
                )
173
            if uncert:
174
                for idx in range(dsamples):
175
                    mc_sig[idx] = welsh_ab(
176
                        self.signal1.times,
177
                        self.signal1.values
178
                        + self.signal1.dvalues * np.random.randn(self.signal1.values.size),
179
                        self.signal2.times,
180
                        self.signal2.values
181
                        + self.signal2.dvalues * np.random.randn(self.signal2.values.size),
182
                        self.times,
183
                        self.dts,
184
                    )
185
            self.values = welsh_ab(
186
                self.signal1.times,
187
                self.signal1.values,
188
                self.signal2.times,
189
                self.signal2.values,
190
                self.times,
191
                self.dts,
192
            )
193
        elif self.fcorr == "kroedel_ab":
194
            for idx in range(self.samples):
195
                mc_corr[idx] = kroedel_ab(
196
                    self.signal1.times,
197
                    self.signal1.synth[idx],
198
                    self.signal2.times,
199
                    self.signal2.synth[idx],
200
                    self.times,
201
                    self.dts,
202
                )
203
            if uncert:
204
                for idx in range(dsamples):
205
                    mc_sig[idx] = kroedel_ab(
206
                        self.signal1.times,
207
                        self.signal1.values
208
                        + self.signal1.dvalues * np.random.randn(self.signal1.values.size),
209
                        self.signal2.times,
210
                        self.signal2.values
211
                        + self.signal2.dvalues * np.random.randn(self.signal2.values.size),
212
                        self.times,
213
                        self.dts,
214
                    )
215
            self.values = kroedel_ab(
216
                self.signal1.times,
217
                self.signal1.values,
218
                self.signal2.times,
219
                self.signal2.values,
220
                self.times,
221
                self.dts,
222
            )
223
        elif self.fcorr == "numpy":
224
            for idx in range(self.samples):
225
                mc_corr[idx] = nindcf(
226
                    self.signal1.times,
227
                    self.signal1.synth[idx],
228
                    self.signal2.times,
229
                    self.signal2.synth[idx],
230
                )
231
            if uncert:
232
                for idx in range(dsamples):
233
                    mc_sig[idx] = nindcf(
234
                        self.signal1.times,
235
                        self.signal1.values
236
                        + self.signal1.dvalues * np.random.randn(self.signal1.values.size),
237
                        self.signal2.times,
238
                        self.signal2.values
239
                        + self.signal2.dvalues * np.random.randn(self.signal2.values.size),
240
                    )
241
            self.values = nindcf(
242
                self.signal1.times,
243
                self.signal1.values,
244
                self.signal2.times,
245
                self.signal2.values,
246
            )
247
        else:
248
            raise Exception("Unknown method " + self.fcorr + " for correlation.")
249
250
        self.l3s = np.percentile(mc_corr, [0.135, 99.865], axis=0)
251
        self.l2s = np.percentile(mc_corr, [2.28, 97.73], axis=0)
252
        self.l1s = np.percentile(mc_corr, [15.865, 84.135], axis=0)
253
254
        self.mc_corr = mc_corr # save them to be able to compute exact significance later...
0 ignored issues
show
Coding Style introduced by
The attribute mc_corr was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
255
        
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
256
        if uncert:
257
            self.s3s = np.percentile(mc_sig, [0.135, 99.865], axis=0)
0 ignored issues
show
introduced by
The variable mc_sig does not seem to be defined in case uncert on line 160 is False. Are you sure this can never be the case?
Loading history...
258
            self.s2s = np.percentile(mc_sig, [2.28, 97.73], axis=0)
259
            self.s1s = np.percentile(mc_sig, [15.865, 84.135], axis=0)
260
261
    def gen_times(self, ftimes="canopy", *args, **kwargs):
0 ignored issues
show
introduced by
Keyword argument before variable positional arguments list in the definition of gen_times function
Loading history...
262
        """Sets times and bins using the method defined by ftimes parameter.
263
264
        Parameters
265
        ----------
266
        ftimes : :py:class:`~str`
267
            Method used to bin the time interval of the correlation.
268
            Possible values are:
269
            - "canopy": Computes a binning as dense as possible, with
270
            variable bin width and (with a minimum and a maximum
271
            resolution) and a minimum statistic.
272
            - "rawab": Computes a binning with variable bin width,
273
            a given step, maximum bin size and a minimum statistic.
274
            - "uniform": Computes a binning with uniform bin width
275
            and a minimum statistic.
276
            - "numpy": Computes a binning suitable for method='numpy'.
277
        """
278
        if ftimes == "canopy":
279
            self.times, self.dts, self.nb = gen_times_canopy(
280
                self.signal1.times, self.signal2.times, *args, **kwargs
281
            )
282
        elif ftimes == "rawab":
283
            self.times, self.dts, self.nb = gen_times_rawab(
284
                self.signal1.times, self.signal2.times, *args, **kwargs
285
            )
286
        elif ftimes == "uniform":
287
            self.times, self.dts, self.nb = gen_times_uniform(
288
                self.signal1.times, self.signal2.times, *args, **kwargs
289
            )
290
        elif ftimes == "numpy":
291
            t1, t2 = self.signal1.times, self.signal1.times
0 ignored issues
show
Coding Style Naming introduced by
Variable name "t1" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Coding Style Naming introduced by
Variable name "t2" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
292
            dt = np.max([(t1.max() - t1.min()) / t1.size, (t2.max() - t2.min()) / t2.size])
0 ignored issues
show
Coding Style Naming introduced by
Variable name "dt" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
293
            n1 = int(np.ptp(t1) / dt * 10.0)
0 ignored issues
show
Coding Style Naming introduced by
Variable name "n1" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
294
            n2 = int(np.ptp(t1) / dt * 10.0)
0 ignored issues
show
Coding Style Naming introduced by
Variable name "n2" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
295
            self.times = np.linspace(self.tmin_full, self.tmax_full, n1 + n2 - 1)
296
            self.dts = np.full(self.times.size, (self.tmax_full - self.tmin_full) / (n1 + n2))
297
        else:
298
            raise Exception("Unknown method " + ftimes + ", please indicate how to generate times.")
299
300
    def plot_corr(self, uncert=True, ax=None, legend=False):
0 ignored issues
show
Coding Style Naming introduced by
Argument name "ax" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
301
        """Plots the correlation of the signals.
302
303
        Plots the correlation of the signal, and the confidence limits
304
        computed from the synthetic curves.
305
306
        Parameters
307
        ----------
308
        ax : :class:`matplotlib.axes.Axes`
309
            Axes to be used (default None, it creates a new axes).
310
        legend : :py:class:`~bool`
311
            Whether to add a legend indicating the confidence levels.
312
        """
313
314
        # TODO: develop a plotting object for plots
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
315
        #       this will considerably shorten the
316
        #       number of attributes of this class
317
318
        if uncert and self.signal1.dvalues is None:
319
            log.error(
320
                "uncert is True but no uncertainties for Signal 1 were specified, setting uncert to False"
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (106/100).

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

Loading history...
321
            )
322
            uncert = False
323
        if uncert and self.signal2.dvalues is None:
324
            log.error(
325
                "uncert is True but no uncertainties for Signal 2 were specified, setting uncert to False"
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (106/100).

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

Loading history...
326
            )
327
            uncert = False
328
329
        # plt.figure()
330
        if ax is None:
331
            ax = plt.gca()
332
333
        ax.plot(self.times, self.l1s[0], "c-.")
334
        ax.plot(self.times, self.l1s[1], "c-.", label=r"$1\sigma$")
335
        ax.plot(self.times, self.l2s[0], "k--")
336
        ax.plot(self.times, self.l2s[1], "k--", label=r"$2\sigma$")
337
        ax.plot(self.times, self.l3s[0], "r-")
338
        ax.plot(self.times, self.l3s[1], "r-", label=r"$3\sigma$")
339
        ax.plot(self.times, self.values, "b.--", lw=1)
340
341
        # full limit
342
        ax.axvline(x=self.tmin_full, ymin=-1, ymax=+1, color="red", linewidth=4, alpha=0.5)
343
        ax.axvline(x=self.tmax_full, ymin=-1, ymax=+1, color="red", linewidth=4, alpha=0.5)
344
        # same limit
345
        ax.axvline(x=self.tmin_same, ymin=-1, ymax=+1, color="black", linewidth=2, alpha=0.5)
346
        ax.axvline(x=self.tmax_same, ymin=-1, ymax=+1, color="black", linewidth=2, alpha=0.5)
347
        # valid limit
348
        ax.axvline(x=self.tmin_valid, ymin=-1, ymax=+1, color="cyan", linewidth=1, alpha=0.5)
349
        ax.axvline(x=self.tmax_valid, ymin=-1, ymax=+1, color="cyan", linewidth=1, alpha=0.5)
350
351
        if uncert:
352
            ax.fill_between(x=self.times, y1=self.s1s[0], y2=self.s1s[1], color="b", alpha=0.5)
353
            ax.fill_between(x=self.times, y1=self.s2s[0], y2=self.s2s[1], color="b", alpha=0.3)
354
            ax.fill_between(x=self.times, y1=self.s3s[0], y2=self.s3s[1], color="b", alpha=0.1)
355
            
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
356
            
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
357
        if legend:
358
            ax.legend()
359
360
        # plt.show()
361
        return ax
362
363
    def plot_times(self, rug=False):
364
        """Plots the time binning generated previously.
365
366
        Plots the number of total bins, their distribution and the
367
        number of points in each bin for the generated time binning,
368
        previously generated with Correlation().gen_times(...).
369
370
        Parameters
371
        ----------
372
        rug : :py:class:`~bool`
373
            Whether to make a rug plot just below the binning, to make
374
            it easier to visually understand the density and distribution
375
            of the generated bins.
376
377
        """
378
379
        # TODO: develop a plotting object for plots
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
380
        #       this will considerably shorten the
381
        #       number of attributes of this class
382
383
        fig, ax = plt.subplots(nrows=2, ncols=1, sharex=True)
0 ignored issues
show
Coding Style Naming introduced by
Variable name "ax" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
384
        tab, dtab, nab = self.times, self.dts, self.nb
385
386
        fig.suptitle("Total bins: {:d}".format(self.times.size))
387
        ax[0].plot(tab, nab, "b.")
388
        ax[0].errorbar(x=tab, y=nab, xerr=dtab / 2, fmt="none")
389
        ax[0].set_ylabel("$n_i$")
390
        ax[0].grid()
391
        ax[0].axvline(x=self.tmin_full, ymin=-1, ymax=+1, color="red", linewidth=4, alpha=0.5)
392
        ax[0].axvline(x=self.tmax_full, ymin=-1, ymax=+1, color="red", linewidth=4, alpha=0.5)
393
        ax[0].axvline(x=self.tmin_same, ymin=-1, ymax=+1, color="black", linewidth=2, alpha=0.5)
394
        ax[0].axvline(x=self.tmax_same, ymin=-1, ymax=+1, color="black", linewidth=2, alpha=0.5)
395
        ax[0].axvline(x=self.tmin_valid, ymin=-1, ymax=+1, color="cyan", linewidth=1, alpha=0.5)
396
        ax[0].axvline(x=self.tmax_valid, ymin=-1, ymax=+1, color="cyan", linewidth=1, alpha=0.5)
397
        ax[1].plot(tab, dtab, "b.")
398
        ax[1].set_ylabel("$dt_i$")
399
        # ax[1].grid()
400
        ax[1].axvline(x=self.tmin_full, ymin=-1, ymax=+1, color="red", linewidth=4, alpha=0.5)
401
        ax[1].axvline(x=self.tmax_full, ymin=-1, ymax=+1, color="red", linewidth=4, alpha=0.5)
402
        ax[1].axvline(x=self.tmin_same, ymin=-1, ymax=+1, color="black", linewidth=2, alpha=0.5)
403
        ax[1].axvline(x=self.tmax_same, ymin=-1, ymax=+1, color="black", linewidth=2, alpha=0.5)
404
        ax[1].axvline(x=self.tmin_valid, ymin=-1, ymax=+1, color="cyan", linewidth=1, alpha=0.5)
405
        ax[1].axvline(x=self.tmax_valid, ymin=-1, ymax=+1, color="cyan", linewidth=1, alpha=0.5)
406
407
        if rug:
408
            for time in self.times:
409
                ax[1].axvline(x=time, ymin=0, ymax=0.2, color="black", linewidth=0.8, alpha=1.0)
410
            # ax[1].plot(self.t, ax[1].get_ylim()[0]+np.zeros(self.t.size), 'k|', alpha=0.8, lw=1)
411
412
        ax[1].grid()
413
        # fig.show()
414
415
    def plot_signals(self, ax=None):
0 ignored issues
show
Coding Style Naming introduced by
Argument name "ax" doesn't conform to snake_case naming style ('([^\\W\\dA-Z][^\\WA-Z]2,|_[^\\WA-Z]*|__[^\\WA-Z\\d_][^\\WA-Z]+__)$' pattern)

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
416
        """Plots the signals involved in this correlation.
417
418
        Plots the signals involved in this correlation, in the same window
419
        but with different twin y-axes and different colors.
420
421
        Parameters
422
        ----------
423
        ax : :py:class:`~matplotlib.axes.Axes`
424
            Axes to be used for plotting.
425
        """
426
427
        # TODO: develop a plotting object for plots
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
428
        #       this will considerably shorten the
429
        #       number of attributes of this class
430
431
        if ax is None:
432
            ax = plt.gca()
433
434
        ax.plot(self.signal1.times, self.signal1.values, "b.-", lw=1, alpha=0.4)
435
        ax.tick_params(axis="y", labelcolor="b")
436
        ax.set_ylabel("sig 1", color="b")
437
438
        ax2 = ax.twinx()
439
        ax2.plot(self.signal2.times, self.signal2.values, "r.-", lw=1, alpha=0.4)
440
        ax2.tick_params(axis="y", labelcolor="r")
441
        ax2.set_ylabel("sig 2", color="r")
442