Passed
Pull Request — main (#26)
by
unknown
01:57
created

mutis.correlation   B

Complexity

Total Complexity 45

Size/Duplication

Total Lines 435
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 45
eloc 250
dl 0
loc 435
rs 8.8
c 0
b 0
f 0

8 Methods

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

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 (21/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 (20/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
109
        return {'x':peak_x, 's':smooth_std, 'y':peak_y, 'signf1s':peak_signf1s}
110
111
    def gen_synth(self, samples):
112
        """Generates the synthetic light curves.
113
114
        Generates the specified number `samples` of synthetic light
115
        curves for each signal, to be used to compute the significance
116
        the correlation.
117
118
        Parameters
119
        ----------
120
        samples : :py:class:`~int`
121
            Number of synthetic light curves to be generated for each signal.
122
        """
123
124
        self.samples = samples
125
        self.signal1.gen_synth(samples)
126
        self.signal2.gen_synth(samples)
127
128
    def gen_corr(self, uncert=True, dsamples=500):
129
        """Generates the correlation of the signals.
130
131
        Generates the correlation of the signals, and computes their
132
        confidence level from the synthetic light curves, which must
133
        have been generated before.
134
        """
135
136
        if uncert and self.signal1.dvalues is None:
137
            log.error(
138
                "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...
139
            )
140
            uncert = False
141
        if uncert and self.signal2.dvalues is None:
142
            log.error(
143
                "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...
144
            )
145
            uncert = False
146
147
        if len(self.times) == 0 or len(self.dts) == 0:
148
            raise Exception(
149
                "You need to define the times on which to calculate the correlation."
150
                "Please use gen_times() or manually set them."
151
            )
152
153
        # 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...
154
        mc_corr = np.empty((self.samples, self.times.size))
155
        if uncert:
156
            mc_sig = np.empty((dsamples, self.times.size))
157
158
        if self.fcorr == "welsh_ab":
159
            for idx in range(self.samples):
160
                mc_corr[idx] = welsh_ab(
161
                    self.signal1.times,
162
                    self.signal1.synth[idx],
163
                    self.signal2.times,
164
                    self.signal2.synth[idx],
165
                    self.times,
166
                    self.dts,
167
                )
168
            if uncert:
169
                for idx in range(dsamples):
170
                    mc_sig[idx] = welsh_ab(
171
                        self.signal1.times,
172
                        self.signal1.values
173
                        + self.signal1.dvalues * np.random.randn(self.signal1.values.size),
174
                        self.signal2.times,
175
                        self.signal2.values
176
                        + self.signal2.dvalues * np.random.randn(self.signal2.values.size),
177
                        self.times,
178
                        self.dts,
179
                    )
180
            self.values = welsh_ab(
181
                self.signal1.times,
182
                self.signal1.values,
183
                self.signal2.times,
184
                self.signal2.values,
185
                self.times,
186
                self.dts,
187
            )
188
        elif self.fcorr == "kroedel_ab":
189
            for idx in range(self.samples):
190
                mc_corr[idx] = kroedel_ab(
191
                    self.signal1.times,
192
                    self.signal1.synth[idx],
193
                    self.signal2.times,
194
                    self.signal2.synth[idx],
195
                    self.times,
196
                    self.dts,
197
                )
198
            if uncert:
199
                for idx in range(dsamples):
200
                    mc_sig[idx] = kroedel_ab(
201
                        self.signal1.times,
202
                        self.signal1.values
203
                        + self.signal1.dvalues * np.random.randn(self.signal1.values.size),
204
                        self.signal2.times,
205
                        self.signal2.values
206
                        + self.signal2.dvalues * np.random.randn(self.signal2.values.size),
207
                        self.times,
208
                        self.dts,
209
                    )
210
            self.values = kroedel_ab(
211
                self.signal1.times,
212
                self.signal1.values,
213
                self.signal2.times,
214
                self.signal2.values,
215
                self.times,
216
                self.dts,
217
            )
218
        elif self.fcorr == "numpy":
219
            for idx in range(self.samples):
220
                mc_corr[idx] = nindcf(
221
                    self.signal1.times,
222
                    self.signal1.synth[idx],
223
                    self.signal2.times,
224
                    self.signal2.synth[idx],
225
                )
226
            if uncert:
227
                for idx in range(dsamples):
228
                    mc_sig[idx] = nindcf(
229
                        self.signal1.times,
230
                        self.signal1.values
231
                        + self.signal1.dvalues * np.random.randn(self.signal1.values.size),
232
                        self.signal2.times,
233
                        self.signal2.values
234
                        + self.signal2.dvalues * np.random.randn(self.signal2.values.size),
235
                    )
236
            self.values = nindcf(
237
                self.signal1.times,
238
                self.signal1.values,
239
                self.signal2.times,
240
                self.signal2.values,
241
            )
242
        else:
243
            raise Exception("Unknown method " + self.fcorr + " for correlation.")
244
245
        self.l3s = np.percentile(mc_corr, [0.135, 99.865], axis=0)
246
        self.l2s = np.percentile(mc_corr, [2.28, 97.73], axis=0)
247
        self.l1s = np.percentile(mc_corr, [15.865, 84.135], axis=0)
248
249
        if uncert:
250
            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 155 is False. Are you sure this can never be the case?
Loading history...
251
            self.s2s = np.percentile(mc_sig, [2.28, 97.73], axis=0)
252
            self.s1s = np.percentile(mc_sig, [15.865, 84.135], axis=0)
253
254
    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...
255
        """Sets times and bins using the method defined by ftimes parameter.
256
257
        Parameters
258
        ----------
259
        ftimes : :py:class:`~str`
260
            Method used to bin the time interval of the correlation.
261
            Possible values are:
262
            - "canopy": Computes a binning as dense as possible, with
263
            variable bin width and (with a minimum and a maximum
264
            resolution) and a minimum statistic.
265
            - "rawab": Computes a binning with variable bin width,
266
            a given step, maximum bin size and a minimum statistic.
267
            - "uniform": Computes a binning with uniform bin width
268
            and a minimum statistic.
269
            - "numpy": Computes a binning suitable for method='numpy'.
270
        """
271
        if ftimes == "canopy":
272
            self.times, self.dts, self.nb = gen_times_canopy(
273
                self.signal1.times, self.signal2.times, *args, **kwargs
274
            )
275
        elif ftimes == "rawab":
276
            self.times, self.dts, self.nb = gen_times_rawab(
277
                self.signal1.times, self.signal2.times, *args, **kwargs
278
            )
279
        elif ftimes == "uniform":
280
            self.times, self.dts, self.nb = gen_times_uniform(
281
                self.signal1.times, self.signal2.times, *args, **kwargs
282
            )
283
        elif ftimes == "numpy":
284
            t1, t2 = self.signal1.times, self.signal1.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...
285
            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...
286
            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...
287
            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...
288
            self.times = np.linspace(self.tmin_full, self.tmax_full, n1 + n2 - 1)
289
            self.dts = np.full(self.times.size, (self.tmax_full - self.tmin_full) / (n1 + n2))
290
        else:
291
            raise Exception("Unknown method " + ftimes + ", please indicate how to generate times.")
292
293
    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...
294
        """Plots the correlation of the signals.
295
296
        Plots the correlation of the signal, and the confidence limits
297
        computed from the synthetic curves.
298
299
        Parameters
300
        ----------
301
        ax : :class:`matplotlib.axes.Axes`
302
            Axes to be used (default None, it creates a new axes).
303
        legend : :py:class:`~bool`
304
            Whether to add a legend indicating the confidence levels.
305
        """
306
307
        # 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...
308
        #       this will considerably shorten the
309
        #       number of attributes of this class
310
311
        if uncert and self.signal1.dvalues is None:
312
            log.error(
313
                "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...
314
            )
315
            uncert = False
316
        if uncert and self.signal2.dvalues is None:
317
            log.error(
318
                "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...
319
            )
320
            uncert = False
321
322
        # plt.figure()
323
        if ax is None:
324
            ax = plt.gca()
325
326
        ax.plot(self.times, self.l1s[0], "c-.")
327
        ax.plot(self.times, self.l1s[1], "c-.", label=r"$1\sigma$")
328
        ax.plot(self.times, self.l2s[0], "k--")
329
        ax.plot(self.times, self.l2s[1], "k--", label=r"$2\sigma$")
330
        ax.plot(self.times, self.l3s[0], "r-")
331
        ax.plot(self.times, self.l3s[1], "r-", label=r"$3\sigma$")
332
        ax.plot(self.times, self.values, "b.--", lw=1)
333
334
        # full limit
335
        ax.axvline(x=self.tmin_full, ymin=-1, ymax=+1, color="red", linewidth=4, alpha=0.5)
336
        ax.axvline(x=self.tmax_full, ymin=-1, ymax=+1, color="red", linewidth=4, alpha=0.5)
337
        # same limit
338
        ax.axvline(x=self.tmin_same, ymin=-1, ymax=+1, color="black", linewidth=2, alpha=0.5)
339
        ax.axvline(x=self.tmax_same, ymin=-1, ymax=+1, color="black", linewidth=2, alpha=0.5)
340
        # valid limit
341
        ax.axvline(x=self.tmin_valid, ymin=-1, ymax=+1, color="cyan", linewidth=1, alpha=0.5)
342
        ax.axvline(x=self.tmax_valid, ymin=-1, ymax=+1, color="cyan", linewidth=1, alpha=0.5)
343
344
        if uncert:
345
            ax.fill_between(x=self.times, y1=self.s1s[0], y2=self.s1s[1], color="b", alpha=0.5)
346
            ax.fill_between(x=self.times, y1=self.s2s[0], y2=self.s2s[1], color="b", alpha=0.3)
347
            ax.fill_between(x=self.times, y1=self.s3s[0], y2=self.s3s[1], color="b", alpha=0.1)
348
            
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
349
            
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
350
        if legend:
351
            ax.legend()
352
353
        # plt.show()
354
        return ax
355
356
    def plot_times(self, rug=False):
357
        """Plots the time binning generated previously.
358
359
        Plots the number of total bins, their distribution and the
360
        number of points in each bin for the generated time binning,
361
        previously generated with Correlation().gen_times(...).
362
363
        Parameters
364
        ----------
365
        rug : :py:class:`~bool`
366
            Whether to make a rug plot just below the binning, to make
367
            it easier to visually understand the density and distribution
368
            of the generated bins.
369
370
        """
371
372
        # 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...
373
        #       this will considerably shorten the
374
        #       number of attributes of this class
375
376
        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...
377
        tab, dtab, nab = self.times, self.dts, self.nb
378
379
        fig.suptitle("Total bins: {:d}".format(self.times.size))
380
        ax[0].plot(tab, nab, "b.")
381
        ax[0].errorbar(x=tab, y=nab, xerr=dtab / 2, fmt="none")
382
        ax[0].set_ylabel("$n_i$")
383
        ax[0].grid()
384
        ax[0].axvline(x=self.tmin_full, ymin=-1, ymax=+1, color="red", linewidth=4, alpha=0.5)
385
        ax[0].axvline(x=self.tmax_full, ymin=-1, ymax=+1, color="red", linewidth=4, alpha=0.5)
386
        ax[0].axvline(x=self.tmin_same, ymin=-1, ymax=+1, color="black", linewidth=2, alpha=0.5)
387
        ax[0].axvline(x=self.tmax_same, ymin=-1, ymax=+1, color="black", linewidth=2, alpha=0.5)
388
        ax[0].axvline(x=self.tmin_valid, ymin=-1, ymax=+1, color="cyan", linewidth=1, alpha=0.5)
389
        ax[0].axvline(x=self.tmax_valid, ymin=-1, ymax=+1, color="cyan", linewidth=1, alpha=0.5)
390
        ax[1].plot(tab, dtab, "b.")
391
        ax[1].set_ylabel("$dt_i$")
392
        # ax[1].grid()
393
        ax[1].axvline(x=self.tmin_full, ymin=-1, ymax=+1, color="red", linewidth=4, alpha=0.5)
394
        ax[1].axvline(x=self.tmax_full, ymin=-1, ymax=+1, color="red", linewidth=4, alpha=0.5)
395
        ax[1].axvline(x=self.tmin_same, ymin=-1, ymax=+1, color="black", linewidth=2, alpha=0.5)
396
        ax[1].axvline(x=self.tmax_same, ymin=-1, ymax=+1, color="black", linewidth=2, alpha=0.5)
397
        ax[1].axvline(x=self.tmin_valid, ymin=-1, ymax=+1, color="cyan", linewidth=1, alpha=0.5)
398
        ax[1].axvline(x=self.tmax_valid, ymin=-1, ymax=+1, color="cyan", linewidth=1, alpha=0.5)
399
400
        if rug:
401
            for time in self.times:
402
                ax[1].axvline(x=time, ymin=0, ymax=0.2, color="black", linewidth=0.8, alpha=1.0)
403
            # ax[1].plot(self.t, ax[1].get_ylim()[0]+np.zeros(self.t.size), 'k|', alpha=0.8, lw=1)
404
405
        ax[1].grid()
406
        # fig.show()
407
408
    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...
409
        """Plots the signals involved in this correlation.
410
411
        Plots the signals involved in this correlation, in the same window
412
        but with different twin y-axes and different colors.
413
414
        Parameters
415
        ----------
416
        ax : :py:class:`~matplotlib.axes.Axes`
417
            Axes to be used for plotting.
418
        """
419
420
        # 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...
421
        #       this will considerably shorten the
422
        #       number of attributes of this class
423
424
        if ax is None:
425
            ax = plt.gca()
426
427
        ax.plot(self.signal1.times, self.signal1.values, "b.-", lw=1, alpha=0.4)
428
        ax.tick_params(axis="y", labelcolor="b")
429
        ax.set_ylabel("sig 1", color="b")
430
431
        ax2 = ax.twinx()
432
        ax2.plot(self.signal2.times, self.signal2.values, "r.-", lw=1, alpha=0.4)
433
        ax2.tick_params(axis="y", labelcolor="r")
434
        ax2.set_ylabel("sig 2", color="r")
435