Workflow of MUTIS

Here we illustrate the workflow of MUTIS (class version) to analyze correlation between two signals. The general workflow is:

  • We load the data in a suitable way.

  • We generate the synthetic light curves, which are used to calculate the confidence levels of correlations.

    This is an automatic process if the method used for generating them is just sampling (lc_gen_samp), or flux randomization with the same psd (lc_gen_psd). If we simulate them as an stochastic process (lc_gen_ou) as suggested for example in Tavecchio, Bonnoli and Galanti, 2020 (doi:10.1093/mnras/staa2055) we need to carefully choose the parameters for this stochastic process (currently trying to optimize it).

  • We generate the correlations (the synthetic ones and the real one) and plot them together.

    For this we need to manually choose the time binning.

Juan Escudero

[1]:
# I'm doing a lot of changes to MUTIS while writting this, better reload automatically.
%load_ext autoreload
%autoreload 2
[2]:
import numpy as np
import scipy as sp

import pandas as pd
pd.set_option("display.max_columns", None)

from astropy.time import Time

import matplotlib as mplt
import matplotlib.pyplot as plt

import mutis

Load data

Load it with pandas becase I like the way pandas prints tables. Also useful accesing vars as strings!

[3]:
data = {}
[4]:
data['3mm'] = pd.read_csv('data/mm-I.dat', comment='!')
data['3mm']
[4]:
jyear I dI
0 2007.336684 4.038324 0.180
1 2007.384127 3.664838 0.200
2 2007.603228 1.487572 0.090
3 2007.665543 1.245085 0.070
4 2007.714794 0.600193 0.040
... ... ... ...
100 2020.429704 0.910855 0.052
101 2020.445397 1.940285 0.111
102 2020.507706 1.482400 0.111
103 2020.650145 2.236022 0.112
104 2020.750106 1.926506 0.113

105 rows × 3 columns

[5]:
data['gamma'] = pd.read_csv('data/gamma-I.dat', comment='!')
data['gamma']
[5]:
jyear CFlux CFluxErr
0 2008.605065 1.894027e-07 3.326300e-08
1 2008.624230 5.572932e-07 4.754800e-08
2 2008.643395 5.439230e-07 5.684800e-08
3 2008.662560 6.763391e-07 6.980500e-08
4 2008.681725 9.020173e-07 7.435100e-08
... ... ... ...
631 2020.763861 1.119233e-07 5.747500e-08
632 2020.783026 9.138770e-08 3.188800e-08
633 2020.802191 6.064478e-08 1.657600e-08
634 2020.821356 4.770228e-08 2.429000e-08
635 2020.840520 1.733534e-07 3.886500e-08

636 rows × 3 columns

Show data

[6]:
fig, ax = plt.subplots(nrows=2, figsize=(12,4), sharex=True, gridspec_kw={'hspace':0.00})


ax[0].errorbar(data['gamma']['jyear'], data['gamma']['CFlux'], data['gamma']['CFluxErr'], fmt='b.--', label='Gamma-ray flux (0.1 to 200 GeV)', lw=1) # freq?
ax[0].set_ylabel('$\gamma/\mathrm{cm}^2/\mathrm{s}?$')
ax[0].legend()
ax[0].grid()

ax[1].errorbar(data['3mm']['jyear'], data['3mm']['I'], data['3mm']['dI'], fmt='k.--', label='mm', lw=1)  #data['3mm'].plot(x='year', y='I')
ax[1].set_ylabel('Jy')
ax[1].legend()
ax[1].grid()

fig.suptitle('Test Source Flux Density')
plt.xlabel('years')
plt.show()
../_images/recipes_mutis_workflow_8_0.png

Correlate data

Choose data and methods

Choose the signals to correlate

[7]:
t1, s1, ds1 = data['3mm']['jyear'], data['3mm']['I'], data['3mm']['dI']
t2, s2, ds2 = data['gamma']['jyear'], 1e6*data['gamma']['CFlux'], 1e6*data['gamma']['CFluxErr'] ### ¡Use sensible units!

Create signals with the corresponding data and choose the method for generating the light curves.

[8]:
sig1 = mutis.Signal(t1, s1, ds1, 'lc_gen_psd_nft')
sig2 = mutis.Signal(t2, s2, ds2, 'lc_gen_ou')

Create the correlation with the corresponding signals and choose the method for generating the correltions.

[9]:
correlation = mutis.Correlation(sig1, sig2, 'welsh')

Generate synthetic light curves

HUMAN INTERVENTION

Chose good parameters for time binning!

Good parameters will have a high and similar \(n_i\) for all bins, with bins covering most of the time range.

[10]:
correlation.gen_times(dtmin=0.25)
[11]:
correlation.plot_times()
../_images/recipes_mutis_workflow_20_0.png

HUMAN INTERVENTION

If the method for generating the synthetic light curves is lc_gen_ou we need to chose a good set of parameters.

In this case we have set only sig2’s method to be lc_gen_ou because lc_gen_psd is more or less okey for sig1.

The Signal class includes methods to deal with this OU parameter extraction. This could be more or less an authomathic process, but for some (not a negible number of) cases degenerancy of these OU parameter makes human intervention necessary. We need: 1. To plot the histogram and check if the supposed probability density function (pdf) fits nicely (several ways: curve fitting or MLE). 2. To check if the stimates are reasonable and produce nice light curves. 3. Actually generate the light curves.

Plot the histogram and get extracted parameters

[12]:
%%time
fits = sig2.OU_fit()
/home/docs/checkouts/readthedocs.org/user_builds/mutis/envs/latest/lib/python3.7/site-packages/mutis/signal.py:252: RuntimeWarning: invalid value encountered in double_scalars
  / xx ** (ll + 2)
CPU times: user 16.8 s, sys: 36.9 ms, total: 16.9 s
Wall time: 16.8 s
/home/docs/checkouts/readthedocs.org/user_builds/mutis/envs/latest/lib/python3.7/site-packages/mutis/signal.py:252: RuntimeWarning: divide by zero encountered in true_divide
  / xx ** (ll + 2)
/home/docs/checkouts/readthedocs.org/user_builds/mutis/envs/latest/lib/python3.7/site-packages/mutis/signal.py:252: RuntimeWarning: invalid value encountered in true_divide
  / xx ** (ll + 2)
../_images/recipes_mutis_workflow_23_3.png
[13]:
fits
[13]:
{'sigma_est': 5.94771645934871,
 'curve_fit': (array([1.00758681, 0.12887555]),
  array([0.17348078, 0.01219195])),
 'MLE_fit': (0.5523802491183334, 0.14125117915448523),
 'th_est1': 9.77031709753,
 'th_est2': 17.821858473859322}
Check if this parameters generate nice light curves.
[14]:
#%matplotlib inline
sig2.check_gen(fgen='lc_gen_ou', fgen_params=dict(theta=17.8, mu=0.14, sigma=5.9))
Original vs Synthethic:
mean: 0.11241061716509433 / 0.11872079739831864
std: 0.14036970709552712 / 0.1692722331611489
[14]:
{'ax1': <AxesSubplot:title={'center':'light curves'}>,
 'ax2': <AxesSubplot:title={'center':'pdf'}>,
 'ax3': <AxesSubplot:title={'center':'PSD'}>}
../_images/recipes_mutis_workflow_26_2.png

Set the parameters

[15]:
sig2.OU_theta, sig2.OU_mu, sig2.OU_sigma = 17.8, 0.13, 5.9
Actually generate the synthetic light curves
[16]:
%%time
correlation.gen_synth(400)
CPU times: user 1.58 s, sys: 0 ns, total: 1.58 s
Wall time: 1.58 s

Generate and plot correlations

[17]:
%%time
correlation.gen_corr();
CPU times: user 7.91 s, sys: 0 ns, total: 7.91 s
Wall time: 7.91 s
[18]:
correlation.plot_corr()
[18]:
<AxesSubplot:>
../_images/recipes_mutis_workflow_33_1.png

Find the peaks

[19]:
pd.DataFrame(correlation.peak_find())
[19]:
x s y signf1s signif_percent
0 0.126204 0.128975 0.635940 7.398281 100.00
1 1.388245 0.128975 0.073888 1.025973 85.25
2 2.397877 0.128975 -0.251714 -3.049960 0.25
3 -2.650286 0.128975 -0.109054 -1.255481 8.75
4 -3.155102 0.128975 -0.122123 -1.358888 6.75
5 -4.164735 0.128975 -0.288604 -3.042922 0.00
6 -5.174367 0.128975 -0.223148 -2.639614 1.75
7 5.174367 0.128975 -0.003976 -0.037662 43.75
8 6.184000 0.128975 0.117359 1.147013 86.00
9 -6.941224 0.128975 0.653198 6.733913 100.00
10 7.193632 0.128975 0.563514 4.479770 100.00
11 -8.455673 0.128975 0.315707 3.368703 99.75
12 9.297034 0.128975 0.054819 0.535690 71.75
[ ]: