def gccmi_nd_ccc(x, y, z, mvaxis=None, traxis=-1, shape_checking=True, gcrn=True): """GCCMI between two continuous variables conditioned on a third. Parameters ---------- x, y, z : array_like Continuous variables. z is the continuous variable that is considered as the condition mvaxis : int | None Spatial location of the axis to consider if multi-variate analysis is needed traxis : int | -1 Spatial location of the trial axis. By default the last axis is considered shape_checking : bool | True Perform a reshape and check that x and y shapes are consistents. For high performances and to avoid extensive memory usage, it's better to already have x and y with a shape of (..., mvaxis, traxis) and to set this parameter to False gcrn : bool | True Apply a Gaussian Copula rank normalization. This operation is relatively slow for big arrays. Returns ------- mi : array_like The mutual information with the same shape as x and y, without the mvaxis and traxis """ # Multi-dimentional shape checking if shape_checking: x = nd_reshape(x, mvaxis=mvaxis, traxis=traxis) y = nd_reshape(y, mvaxis=mvaxis, traxis=traxis) z = nd_reshape(z, mvaxis=mvaxis, traxis=traxis) nd_shape_checking(x, y, mvaxis, traxis) nd_shape_checking(x, z, mvaxis, traxis) # x.shape == y.shape == z.shape (..., x_mvaxis, traxis) if gcrn: cx, cy = copnorm_nd(x, axis=-1), copnorm_nd(y, axis=-1) cz = copnorm_nd(z, axis=-1) else: cx, cy, cz = x, y, z return cmi_nd_ggg(cx, cy, cz, mvaxis=-2, traxis=-1, biascorrect=True, demeaned=True, shape_checking=False)
def _cond_gccovgc(data, s, t, ind_tx, t0, conditional=True): """Compute the Gaussian-Copula based covGC for a single pair. This function computes the covGC for a single pair, across multiple trials, at different time indices. """ conditional = conditional if data.shape[1] > 2 else False kw = CONFIG["KW_GCMI"] d_s, d_t = data[:, s, :], data[:, t, :] n_lags, n_dt = ind_tx.shape n_trials, n_times = d_s.shape[0], len(t0) gc = np.empty((n_trials, n_times, 3), dtype=d_s.dtype, order='C') # define z past roi_range = np.array([k for k in range(data.shape[1]) if k not in [s, t]]) z_roi = data[:, roi_range, :] # other roi selection rsh = int(len(roi_range) * (n_lags - 1)) for n_ti, ti in enumerate(t0): # force starting indices at t0 + force row-major slicing ind_t0 = np.ascontiguousarray(ind_tx + ti) x = d_s[:, ind_t0] y = d_t[:, ind_t0] # temporal selection x_pres, x_past = x[:, [0], :], x[:, 1:, :] y_pres, y_past = y[:, [0], :], y[:, 1:, :] xy_past = np.concatenate((x[:, 1:, :], y[:, 1:, :]), axis=1) # conditional granger causality case if conditional: # condition by the past of every other possible sources z_past = z_roi[..., ind_t0[1:, :]] # (lag_past, dt) selection z_past = z_past.reshape(n_trials, rsh, n_dt) # cat with past yz_past = np.concatenate((y_past, z_past), axis=1) xz_past = np.concatenate((x_past, z_past), axis=1) xyz_past = np.concatenate((xy_past, z_past), axis=1) else: yz_past, xz_past, xyz_past = y_past, x_past, xy_past # copnorm over the last axis (avoid copnorming several times) x_pres = copnorm_nd(x_pres, axis=-1) x_past = copnorm_nd(x_past, axis=-1) y_pres = copnorm_nd(y_pres, axis=-1) y_past = copnorm_nd(y_past, axis=-1) yz_past = copnorm_nd(yz_past, axis=-1) xz_past = copnorm_nd(xz_past, axis=-1) xyz_past = copnorm_nd(xyz_past, axis=-1) # ----------------------------------------------------------------- # Granger Causality measures # ----------------------------------------------------------------- # gc(pairs(:,1) -> pairs(:,2)) gc[:, n_ti, 0] = cmi_nd_ggg(y_pres, x_past, yz_past, **kw) # gc(pairs(:,2) -> pairs(:,1)) gc[:, n_ti, 1] = cmi_nd_ggg(x_pres, y_past, xz_past, **kw) # gc(pairs(:,2) . pairs(:,1)) gc[:, n_ti, 2] = cmi_nd_ggg(x_pres, y_pres, xyz_past, **kw) return gc
def gcmi_model_nd_cd(x, y, mvaxis=None, traxis=-1, shape_checking=True, gcrn=True): """GCMI between a continuous and discret variables. The only difference with `mi_gg` is that a normalization is performed for each continuous variable. Parameters ---------- x : array_like Continuous variable y : array_like Discret variable of shape (n_trials,) mvaxis : int | None Spatial location of the axis to consider if multi-variate analysis is needed traxis : int | -1 Spatial location of the trial axis. By default the last axis is considered shape_checking : bool | True Perform a reshape and check that x is consistents. For high performances and to avoid extensive memory usage, it's better to already have x with a shape of (..., mvaxis, traxis) and to set this parameter to False gcrn : bool | True Apply a Gaussian Copula rank normalization. This operation is relatively slow for big arrays. Returns ------- mi : array_like The mutual information with the same shape as x, without the mvaxis and traxis """ # Multi-dimentional shape checking if shape_checking: x = nd_reshape(x, mvaxis=mvaxis, traxis=traxis) # x.shape (..., x_mvaxis, traxis) # y.shape (traxis) cx = copnorm_nd(x, axis=-1) if gcrn else x return mi_model_nd_gd(cx, y, mvaxis=-2, traxis=-1, biascorrect=True, demeaned=True, shape_checking=False)
def _gccovgc(d_s, d_t, ind_tx, t0): """Compute the Gaussian-Copula based covGC for a single pair. This function computes the covGC for a single pair, across multiple trials, at different time indices. """ kw = CONFIG["KW_GCMI"] n_trials, n_times = d_s.shape[0], len(t0) gc = np.empty((n_trials, n_times, 3), dtype=d_s.dtype, order='C') for n_ti, ti in enumerate(t0): # force starting indices at t0 + force row-major slicing ind_t0 = np.ascontiguousarray(ind_tx + ti) x = d_s[:, ind_t0] y = d_t[:, ind_t0] # temporal selection x_pres, x_past = x[:, [0], :], x[:, 1:, :] y_pres, y_past = y[:, [0], :], y[:, 1:, :] xy_past = np.concatenate((x[:, 1:, :], y[:, 1:, :]), axis=1) # copnorm over the last axis (avoid copnorming several times) x_pres = copnorm_nd(x_pres, axis=-1) x_past = copnorm_nd(x_past, axis=-1) y_pres = copnorm_nd(y_pres, axis=-1) y_past = copnorm_nd(y_past, axis=-1) xy_past = copnorm_nd(xy_past, axis=-1) # ----------------------------------------------------------------- # Granger Causality measures # ----------------------------------------------------------------- # gc(pairs(:,1) -> pairs(:,2)) gc[:, n_ti, 0] = cmi_nd_ggg(y_pres, x_past, y_past, **kw) # gc(pairs(:,2) -> pairs(:,1)) gc[:, n_ti, 1] = cmi_nd_ggg(x_pres, y_past, x_past, **kw) # gc(pairs(:,2) . pairs(:,1)) gc[:, n_ti, 2] = cmi_nd_ggg(x_pres, y_pres, xy_past, **kw) return gc
def gccmi_model_nd_cdnd(x, y, *z, mvaxis=None, traxis=-1, gcrn=True, shape_checking=True): """Conditional GCMI between a continuous and a discret variable. This function performs a GC-CMI between a continuous and a discret variable conditioned with multiple discrete variables. Parameters ---------- x : array_like Continuous variable y : array_like Discret variable z : list | array_like Array that describes the conditions across the trial axis. Should be a list of arrays of shape (n_trials,) of integers (e.g. [0, 0, ..., 1, 1, 2, 2]) mvaxis : int | None Spatial location of the axis to consider if multi-variate analysis is needed traxis : int | -1 Spatial location of the trial axis. By default the last axis is considered gcrn : bool | True Apply a Gaussian Copula rank normalization. This operation is relatively slow for big arrays. shape_checking : bool | True Perform a reshape and check that x and y shapes are consistents. For high performances and to avoid extensive memory usage, it's better to already have x and y with a shape of (..., mvaxis, traxis) and to set this parameter to False Returns ------- cmi : array_like Conditional mutual-information with the same shape as x and y without the mvaxis and traxis """ # Multi-dimentional shape checking if shape_checking: x = nd_reshape(x, mvaxis=mvaxis, traxis=traxis) assert isinstance(y, np.ndarray) and (y.ndim == 1) assert x.shape[-1] == len(y) ntrl = x.shape[-1] # Find unique values of each discret array prod_idx = discret_to_index(*z) # sh = x.shape[:-3] if isinstance(mvaxis, int) else x.shape[:-2] sh = x.shape[:-2] zm_shape = list(sh) + [len(prod_idx)] # calculate gcmi for each z value pz = np.zeros((len(prod_idx), ), dtype=float) icond = np.zeros(zm_shape, dtype=float) for num, idx in enumerate(prod_idx): pz[num] = idx.sum() if gcrn: thsx = copnorm_nd(x[..., idx], axis=-1) else: thsx = x[..., idx] thsy = y[idx] icond[..., num] = mi_model_nd_gd(thsx, thsy, mvaxis=-2, traxis=-1, biascorrect=True, demeaned=True, shape_checking=False) pz /= ntrl # conditional mutual information cmi = np.sum(pz * icond, axis=-1) return cmi