Source code for monalisa.binning._mitosis
"""Port of src/arrayUtility/bmMitosis.m."""
import numpy as np
from monalisa._mat import cell_from_items, cell_items, iscell, msize, reshape
from monalisa.array._index_to_multi_index import index_to_multi_index
[docs]
def mitosis(*varargin, nargout=2):
"""Split ``nargout`` tables (last dimension = samples) into bins.
The remaining arguments are 2D logical masks ``[nPhase, nSample]`` (or one
cell of them); every combination of one phase per mask is a bin. Returns
one ``[N_tot, 1]`` cell per table.
"""
nTable = nargout
nMask = len(varargin) - nTable
if nTable < 1 or nMask < 1:
raise ValueError("Wrong list of argumnts")
tables = [np.asarray(a) for a in varargin[:nTable]]
nOfCol = msize(tables[0])[-1]
in_size, new_size = [], []
for tab in tables:
s = msize(tab)
if s[-1] != nOfCol:
raise ValueError("The last dimension is not the same for every input array. ")
in_size.append(list(s[:-1]))
new_size.append((int(np.prod(s[:-1])), s[-1]))
if iscell(varargin[nTable]):
mask_list = cell_items(varargin[nTable])
else:
mask_list = list(varargin[nTable:])
for m in mask_list:
if msize(m)[-1] != nOfCol:
raise ValueError("The last dimension is not the same for every input array. ")
if len(msize(m)) != 2:
raise ValueError("The masks must be 2Dim. ")
inTable = [np.reshape(t, ns, order="F") for t, ns in zip(tables, new_size, strict=True)]
masks = [np.asarray(m, dtype=bool) for m in mask_list]
nPhase = np.array([m.shape[0] for m in masks], dtype=np.float64)
N_tot = int(np.prod(nPhase))
out = [[None] * N_tot for _ in range(nTable)]
for i in range(N_tot):
myIndex = index_to_multi_index(i + 1, nPhase).ravel().astype(np.int64) - 1
myMask = np.ones(nOfCol, dtype=bool)
for k, m in enumerate(masks):
myMask &= m[myIndex[k], :]
for j in range(nTable):
out[j][i] = reshape(inTable[j][:, myMask], [*in_size[j], int(myMask.sum())])
cells = tuple(cell_from_items(o, (N_tot, 1)) for o in out)
return cells[0] if nTable == 1 else cells