def yield_multiplex_network_in_layersets(imgdata,layerset_size,timewindow=100,overlap=0,nanlogfile=None):
    # Yields small networks which contain layerset_size layers each,
    # starting from the beginning of imgdata
    # This is for running subgraph enumeration without having to load entire network at once (only create one relevant subnet at a time)
    assert(layerset_size>0 and isinstance(layerset_size,int))
    k = get_number_of_layers(imgdata.shape,timewindow,overlap)
    start_times,end_times = get_start_and_end_times(k,timewindow,overlap)
    # get all consecutive subsequences of length layerset_size in the range of all layers:
    layersets = zip(*(range(k)[ii:] for ii in range(layerset_size)))
    for layerset in layersets:
        
        M = pn.MultiplexNetwork(couplings='ordinal',fullyInterconnected=True)
        
        for tw_no in layerset:
            A,voxellist = corrs_and_mask_calculations.make_adjacency_matrix(imgdata[:,:,:,start_times[tw_no]:end_times[tw_no]],exclude_masked=True)
            for ii in range(A.shape[0]):
                node1 = str(voxellist[ii])
                for jj in range(ii+1,A.shape[1]):
                    node2 = str(voxellist[jj])
                    if not np.isnan(A[ii,jj]):
                        M[node1,tw_no][node2,tw_no] = A[ii,jj]
                    else:
                        if nanlogfile != None:
                            with open(nanlogfile,'a+') as f:
                                f.write('NaN correlation at nodes '+node1+', '+node2+' at timewindow '+str(tw_no)+'\n')
                        else:
                            print('NaN correlation at nodes '+node1+', '+node2+' at timewindow '+str(tw_no)+'\n')
        yield M
        del(M)
def make_multiplex(imgdata,timewindow=100,overlap=0,nanlogfile=None):
    # ignore remainder of timepoints
    # maybe use nan-inclusive adjacency matrix to weed out masked voxels?
    #xdim = imgdata.shape[0]
    #ydim = imgdata.shape[1]
    #zdim = imgdata.shape[2]
    k = get_number_of_layers(imgdata.shape,timewindow,overlap)
    start_times,end_times = get_start_and_end_times(k,timewindow,overlap)
    
    M = pn.MultiplexNetwork(couplings='ordinal',fullyInterconnected=True)
    
    for tw_no in range(k):
        #start = tw_no*(timewindow-overlap)
        #end = timewindow + tw_no*(timewindow-overlap)
        A,voxellist = corrs_and_mask_calculations.make_adjacency_matrix(imgdata[:,:,:,start_times[tw_no]:end_times[tw_no]],exclude_masked=True)
        for ii in range(A.shape[0]):
            # magic tricks to get true index from linearized form (disclaimer: not actual magic)
            # node1 = str((ii//(ydim*zdim),(ii%(ydim*zdim))//zdim,(ii%(ydim*zdim))%zdim))
            node1 = str(voxellist[ii])
            for jj in range(ii+1,A.shape[1]):
                #node2 = str((jj//(ydim*zdim),(jj%(ydim*zdim))//zdim,(jj%(ydim*zdim))%zdim))
                node2 = str(voxellist[jj])
                # only get unmasked voxels
                if not np.isnan(A[ii,jj]):
                    M[node1,tw_no][node2,tw_no] = A[ii,jj]
                else:
                    if nanlogfile != None:
                        with open(nanlogfile,'a+') as f:
                            f.write('NaN correlation at nodes '+node1+', '+node2+' at timewindow '+str(tw_no)+'\n')
                    else:
                        print('NaN correlation at nodes '+node1+', '+node2+' at timewindow '+str(tw_no)+'\n')
    return M
示例#3
0
def read_weighted_network(filename):
    # There's no EOF in Python so we need to use clumsy flags (must iterate using 'for line in f'...)
    # The closest thing to EOF is the empty string '', but if there are empty lines in the file there's no way to know if it's the end or
    # a stripped newline
    # Edges should be the last entry in the file
    # Assuming layer names are integers (ordinally coupled multiplex)
    nodeflag = 0
    layerflag = 0
    edgeflag = 0
    with open(filename,'r') as f:
        # Read first line which should contain the type of the network (multilayer/multiplex)
        nettype = f.readline()
        if nettype[0] != '#':
            raise Exception('The first line should start with # and contain network type')
        nettype = nettype.strip(' #\n').lower()
        if nettype == 'multiplex':
            M = pn.MultiplexNetwork(couplings='ordinal',fullyInterconnected=True)
        else:
            # If network is not multiplex, we use the general multilayer class
            M = pn.MultilayerNetwork(aspects=1,fullyInterconnected=False)
        
        if nettype == 'multiplex':
            for line in f:
                line = line.strip()
                if line[0] == '#':
                    pass
                else:
                    if nodeflag == 1:
                        for node in line.split(';'):
                            M.add_node(node)
                        nodeflag = 0
                    if layerflag == 1:
                        for layer in line.split(';'):
                            M.add_layer(int(layer),1)
                        layerflag = 0
                    if edgeflag == 1:
                        edge = line.split(';')
                        if edge[2] == edge[3]:
                            M[edge[0],int(edge[2])][edge[1],int(edge[3])] = float(edge[4])
                        elif edge[0] == edge[1]:
                            pass
                        else:
                            raise Exception('Illegal inter-layer edges')
                    if line == 'nodes:':
                        nodeflag = 1
                    if line == 'layers:':
                        layerflag = 1
                    if line == 'edges:':
                        edgeflag = 1
        else:
            # If the network is a general multilayer one, we just need to set all the edges
            for line in f:
                line = line.strip()
                if edgeflag == 1:
                    edge = line.split(';')
                    M[edge[0],int(edge[2])][edge[1],int(edge[3])] = float(edge[4])
                if line == 'edges:':
                    edgeflag = 1
    
    return M
示例#4
0
def threshold(net, threshold, method=">=", ignoreCouplingEdges=False):
    def accept_edge(weight, threshold, rule):
        if rule == ">=":
            return weight >= threshold
        elif rule == "<=":
            return weight <= threshold
        elif rule == ">":
            return weight > threshold
        elif rule == "<":
            return weight < threshold
        else:
            raise Exception("Invalid method for thresholding: " + str(rule))

    mplex = (type(net) == netmodule.MultiplexNetwork)
    if mplex:
        for coupling in net.couplings:
            if coupling[0] != "none":
                mplex = False

    if mplex:
        newNet = netmodule.MultiplexNetwork(
            couplings=net.couplings,
            directed=net.directed,
            noEdge=net.noEdge,
            fullyInterconnected=net.fullyInterconnected)
    else:
        newNet = netmodule.MultilayerNetwork(
            aspects=net.aspects,
            noEdge=net.noEdge,
            directed=net.directed,
            fullyInterconnected=net.fullyInterconnected)

    #copy nodes,layers,node-layers
    for node in net:
        newNet.add_node(node)
    for aspect in range(net.aspects):
        for layer in net.slices[aspect + 1]:
            newNet.add_layer(layer, aspect=aspect + 1)
    if not net.fullyInterconnected:
        for nodelayer in net.iter_node_layers():
            layer = lnodelayer[1:]
            if net.aspects == 1:
                layer = layer[0]
            newNet.add_node(nodelayer[0], layer=layer)

    if mplex:
        for layer in net.iter_layers():
            for edge in net.A[layer].edges:
                if accept_edge(edge[-1], threshold, rule=method):
                    newNet.A[layer][edge[0]][edge[1]] = edge[-1]
    else:
        for edge in net.edges:
            if accept_edge(edge[-1], threshold, rule=method):
                newNet[edge[:-1]] = edge[-1]
    return newNet
示例#5
0
    def test_write_weighted_network(self):
        M_multiplex = pn.MultiplexNetwork(couplings='ordinal',
                                          fullyInterconnected=True)
        M_multiplex['(1, 2, 3)', 0]['(2, 3, 4)', 0] = 0.5
        M_multiplex['(2, 3, 4)', 1]['(3, 4, 5)', 1] = 0.999
        M_multiplex['(3, 4, 5)', 2]['(1, 2, 3)', 2] = 1
        possible_nodelines = set([
            '(1, 2, 3);(2, 3, 4);(3, 4, 5)\n',
            '(1, 2, 3);(3, 4, 5);(2, 3, 4)\n',
            '(2, 3, 4);(1, 2, 3);(3, 4, 5)\n',
            '(2, 3, 4);(3, 4, 5);(1, 2, 3)\n',
            '(3, 4, 5);(1, 2, 3);(2, 3, 4)\n',
            '(3, 4, 5);(2, 3, 4);(1, 2, 3)\n'
        ])
        possible_layerlines = set(
            ['0;1;2\n', '0;2;1\n', '1;0;2\n', '1;2;0\n', '2;0;1\n', '2;1;0\n'])
        edgeset = set([
            '(1, 2, 3);(2, 3, 4);0;0;0.5\n', '(1, 2, 3);(1, 2, 3);0;1;1.0\n',
            '(1, 2, 3);(1, 2, 3);1;2;1.0\n', '(1, 2, 3);(3, 4, 5);2;2;1\n',
            '(2, 3, 4);(2, 3, 4);0;1;1.0\n', '(2, 3, 4);(3, 4, 5);1;1;0.999\n',
            '(2, 3, 4);(2, 3, 4);1;2;1.0\n', '(3, 4, 5);(3, 4, 5);0;1;1.0\n',
            '(3, 4, 5);(3, 4, 5);1;2;1.0\n'
        ])
        network_io.write_weighted_network(
            M_multiplex, 'test_for_network_writing_WILL_BE_REMOVED.txt',
            'Created by test_write_weighted_network')
        try:
            with open('test_for_network_writing_WILL_BE_REMOVED.txt',
                      'r') as f:
                self.assertEqual(f.readline(), '# Multiplex\n')
                self.assertEqual(f.readline(),
                                 '# Created by test_write_weighted_network\n')
                self.assertEqual(f.readline(), 'nodes:\n')
                self.assertTrue(f.readline() in possible_nodelines)
                self.assertEqual(f.readline(), 'layers:\n')
                self.assertTrue(f.readline() in possible_layerlines)
                self.assertEqual(f.readline(), 'edges:\n')
                for line in f:
                    self.assertTrue(line in edgeset)
                    edgeset.remove(line)
                self.assertEqual(len(edgeset), 0)
                self.assertEqual(f.readline(), '')
        finally:
            os.remove('test_for_network_writing_WILL_BE_REMOVED.txt')

        M_multilayer = pn.MultilayerNetwork(aspects=1,
                                            fullyInterconnected=False)
        M_multilayer['[(1, 2, 3),(2, 3, 4)]', 0]['[(3, 4, 5)]', 0] = 0.123
        M_multilayer['[(1, 2, 3)]', 1]['[(2, 3, 4),(3, 4, 5)]', 1] = 0.456
        M_multilayer['[(1, 2, 3),(2, 3, 4)]', 0]['[(1, 2, 3)]', 1] = 0.5
        M_multilayer['[(1, 2, 3),(2, 3, 4)]', 0]['[(2, 3, 4),(3, 4, 5)]',
                                                 1] = 0.333
        M_multilayer['[(3, 4, 5)]', 0]['[(1, 2, 3)]', 1] = 0
        M_multilayer['[(3, 4, 5)]', 0]['[(2, 3, 4),(3, 4, 5)]', 1] = 0.5
        possible_nodelines = set([
            x[0] + ';' + x[1] + ';' + x[2] + ';' + x[3] + '\n'
            for x in itertools.permutations([
                '[(1, 2, 3)]', '[(1, 2, 3),(2, 3, 4)]',
                '[(2, 3, 4),(3, 4, 5)]', '[(3, 4, 5)]'
            ])
        ])
        possible_layerlines = set(['0;1\n', '1;0\n'])
        edgeset = set([
            '[(1, 2, 3),(2, 3, 4)];[(2, 3, 4),(3, 4, 5)];0;1;0.333\n',
            '[(1, 2, 3),(2, 3, 4)];[(3, 4, 5)];0;0;0.123\n',
            '[(1, 2, 3),(2, 3, 4)];[(1, 2, 3)];0;1;0.5\n',
            '[(3, 4, 5)];[(2, 3, 4),(3, 4, 5)];0;1;0.5\n',
            '[(1, 2, 3)];[(2, 3, 4),(3, 4, 5)];1;1;0.456\n'
        ])
        network_io.write_weighted_network(
            M_multilayer, 'test_for_network_writing_WILL_BE_REMOVED.txt',
            'Created by test_write_weighted_network')
        try:
            with open('test_for_network_writing_WILL_BE_REMOVED.txt',
                      'r') as f:
                self.assertEqual(f.readline(), '# Multilayer\n')
                self.assertEqual(f.readline(),
                                 '# Created by test_write_weighted_network\n')
                self.assertEqual(f.readline(), 'nodes:\n')
                self.assertTrue(f.readline() in possible_nodelines)
                self.assertEqual(f.readline(), 'layers:\n')
                self.assertTrue(f.readline() in possible_layerlines)
                self.assertEqual(f.readline(), 'edges:\n')
                for line in f:
                    self.assertTrue(line in edgeset)
                    edgeset.remove(line)
                self.assertEqual(len(edgeset), 0)
                self.assertEqual(f.readline(), '')
        finally:
            os.remove('test_for_network_writing_WILL_BE_REMOVED.txt')
def make_clustered_multilayer(imgdata,timewindow=100,overlap=0,n_clusters=100,method='sklearn',template=None,nanlogfile=None):
    '''
    Possible methods:
    'sklearn' : hierarchical clustering from sklearn, different for each time window
    'template' : preconstructed clustering, same for each time window (requires parameter template : 3d ndarray with the same shape
        as imgdata.shape[0:3] where 0 denotes masked voxel and other values denote cluster identity
        Using this, n_clusters is ignored
    '''
    k = get_number_of_layers(imgdata.shape,timewindow,overlap)
    start_times,end_times = get_start_and_end_times(k,timewindow,overlap)
    
    if method == 'sklearn':
        M = pn.MultilayerNetwork(aspects=1,fullyInterconnected=False)
        previous_voxels_in_clusters = dict()
        for tw_no in range(k):
            # Create new object and make voxels_in_clusters refer to it (doesn't change previous_voxels_in_clusters)
            voxels_in_clusters = dict()
            #start = tw_no*(timewindow-overlap)
            #end = timewindow + tw_no*(timewindow-overlap)
            model,voxellist = clustering.cluster_timewindow_scikit(imgdata[:,:,:,start_times[tw_no]:end_times[tw_no]],n_clusters=n_clusters)
            for ii,label in enumerate(model.labels_):
                voxels_in_clusters.setdefault(label,[]).append(voxellist[ii])
            R = calculate_cluster_correlation_matrix(imgdata[:,:,:,start_times[tw_no]:end_times[tw_no]],voxels_in_clusters)
            for ii in range(R.shape[0]):
                node1 = str(voxels_in_clusters[ii])
                for jj in range(ii+1,R.shape[1]):
                    node2 = str(voxels_in_clusters[jj])
                    if not np.isnan(R[ii,jj]):
                        M[node1,tw_no][node2,tw_no] = R[ii,jj]
                    else:
                        if nanlogfile != None:
                            with open(nanlogfile,'a+') as f:
                                f.write('NaN correlation at nodes '+node1+', '+node2+' at timewindow '+str(tw_no)+'\n')
                        else:
                            print('NaN correlation at nodes '+node1+', '+node2+' at timewindow '+str(tw_no)+'\n')
            for cluster_number in voxels_in_clusters:
                for previous_cluster_number in previous_voxels_in_clusters:
                    cluster_overlap = get_overlap(set(voxels_in_clusters[cluster_number]),set(previous_voxels_in_clusters[previous_cluster_number]))
                    M[str(previous_voxels_in_clusters[previous_cluster_number]),tw_no-1][str(voxels_in_clusters[cluster_number]),tw_no] = cluster_overlap
            previous_voxels_in_clusters = voxels_in_clusters # reference to the same object
            
    elif method == 'template':
        M = pn.MultiplexNetwork(couplings='ordinal',fullyInterconnected=True)
        voxels_in_clusters = get_voxels_in_clusters(template)
        for tw_no in range(k):
            R = calculate_cluster_correlation_matrix(imgdata[:,:,:,start_times[tw_no]:end_times[tw_no]],voxels_in_clusters)
            for ii in range(R.shape[0]):
                node1 = str(voxels_in_clusters[ii])
                for jj in range(ii+1,R.shape[1]):
                    node2 = str(voxels_in_clusters[jj])
                    if not np.isnan(R[ii,jj]):
                        M[node1,tw_no][node2,tw_no] = R[ii,jj]
                    else:
                        if nanlogfile != None:
                            with open(nanlogfile,'a+') as f:
                                f.write('NaN correlation at nodes '+node1+', '+node2+' at timewindow '+str(tw_no)+'\n')
                        else:
                            print('NaN correlation at nodes '+node1+', '+node2+' at timewindow '+str(tw_no)+'\n')
    
    else:
        raise NotImplementedError('This clustering not implemented')
    
    return M
def yield_clustered_multilayer_network_in_layersets(imgdata,layerset_size,timewindow=100,overlap=0,n_clusters=100,
                                                    method='sklearn',template=None,nanlogfile=None,
                                                    event_time_stamps=None,ROI_centroids=[],ROI_names=[],
                                                    consistency_threshold=-1,consistency_target_function='spatialConsistency',
                                                    f_transform_consistency=False,calculate_consistency_while_clustering=False,
                                                    n_consistency_CPUs=5,consistency_save_path='spatial-consistency.pkl',
                                                    n_consistency_iters=100,consistency_percentage_ROIs_for_thresholding=0,
                                                    n_ReHo_neighbors=6,percentage_min_centroid_distance=0,ReHo_measure='ReHo'):
    
    """
    Consistency-related inputs:
    ---------------------------
    ROI_centroids: n_ROIs x 3 np.array, coordinates (in voxels) of the ROI centroids, around which ROIs are grown in some clustering
                   methods (default=[]). Set to 'random' to use random seeds and to 'ReHo' to use seeds selected by maximal Regional 
                   Homogeneity.
    ROI_names: list of strs, names of ROIs (default=[])
    consistency_threshold: float or string. The lowest centroid-voxel correlation that leads to adding a voxel. All
                           thresholding approaches may lead to parcellation where some voxels don't belong to any ROI.
                           Options:
                           - -1: no thresholding (the default option)
                           - float: no voxel is added to a ROI if the value of consistency target function < threshold
                           - 'data-driven': no voxel is added to a ROI if after adding the voxel the mean correlation of the 
                           voxels of this ROI is lower than the mean correlation between the voxels of this ROI and the voxels
                           of any other ROI. However, the same voxel can be considered again later.
                           - 'strict data-driven': similar as above but when a voxel has been found to be sub-threshold
                           for a ROI, it is entirely removed from the base of possible voxels for this ROI
                           - 'voxel-wise': no voxel is added to a ROI if its average correlation to the voxels of this
                           ROI is lower than its average correlation at least consistency_percentage_ROIs_for_thresholding * n_ROIs
                           other ROIs
                           - 'voxel-neighbor': no voxel is added to a ROI if its average correlation to the voxels of this
                           ROI is lower than the average correlation of a voxel to its closest (6-voxel) neighborhood. This
                           threshold value is calculated as an average across all voxels before starting to build the ROIs.
    consistency_target_function: str, homogeneity  measure that will be optimized. Options: 
                                 'spatialConsistency': the mean Pearson correlation coefficient of the voxels already in the ROI and 
                                                       the candidate voxel (the default option)
                                 'correlationWithCentroid': the Pearson correlation between the ROI centroid time series and 
                                                            voxel time series
    f_transform_consistency: boolean; if True, Fischer z transform is applied to the correlations before averaging (default: False)
    calculate_consistency_while_clustering: boolean; if True, the consistency of each cluster is calculated and saved in a pickle
                                            file during the clustering. Note that setting this to True doesn't change clustering
                                            method. So, this can be applied together with 'template' or 'sklearn' methods. (default: False)
    n_consistency_CPUs: int, number of CPUs used for parallel consistency calculations if calculate_consistency_while_clustering == True.
                        (default: 5)
    consistency_save_path: str, a path to which the consistency pickle will be saved (default: 'spatial_consistency.pkl')
    n_consistency_iters: int, number of random seed sets to generate if ROI_centroids == 'random' (default = 100)
    consistency_percentage_ROIs_for_thresholding: float (from 0 to 1), used in thresholding (see above) (default = 0 that is interprested
                                                  as 1/n_ROIs)
    percentage_min_centroid_distance: float (from 0 to 1), the minimal distance between ReHo-based seeds is set as 
                                   percentageMinCentroidDistance times maximal dimension of imgdata (default = 0).
    n_ReHo_neighbors: int, number or neighbors used for calculating ReHo if ReHo-based seeds are to be used; options: 6 (faces),
                    18 (faces + edges), 26 (faces + edges + corners) (default = 6)
    ReHoMeasure: str, the measure of the neighbourhood similarity used to pick the ReHo-based seeds, options 'ReHo', 'spatialConsistency' (default = 'ReHo')
    """
    
    
    # If event_time_stamps is specified, then they are used to compute start_times, end_times and k (and timewindow and overlap are ignored).
    # Otherwise, timewindow and overlap are used ot compute start_times, end_times and k.
    if event_time_stamps == None:
        k = get_number_of_layers(imgdata.shape,timewindow,overlap)
        start_times,end_times = get_start_and_end_times(k,timewindow,overlap)
    else:
        assert isinstance(event_time_stamps,list)
        k = len(event_time_stamps) + 1
        start_times = [0] + event_time_stamps
        end_times = event_time_stamps + [imgdata.shape[3]]
    layersets = zip(*(range(k)[ii:] for ii in range(layerset_size)))
    
    if method == 'sklearn':
        voxels_in_clusters_by_timewindow = dict()
        for layerset in layersets:
            M = pn.MultilayerNetwork(aspects=1,fullyInterconnected=False)
            previous_voxels_in_clusters = dict()
            for tw_no in layerset:
                if not tw_no in voxels_in_clusters_by_timewindow:
                    voxels_in_clusters = dict()
                    model,voxellist = clustering.cluster_timewindow_scikit(imgdata[:,:,:,start_times[tw_no]:end_times[tw_no]],n_clusters=n_clusters)
                    for ii,label in enumerate(model.labels_):
                        voxels_in_clusters.setdefault(label,[]).append(voxellist[ii])
                    voxels_in_clusters_by_timewindow[tw_no] = voxels_in_clusters
                else:
                    voxels_in_clusters = voxels_in_clusters_by_timewindow[tw_no]
                R = calculate_cluster_correlation_matrix(imgdata[:,:,:,start_times[tw_no]:end_times[tw_no]],voxels_in_clusters)
                for ii in range(R.shape[0]):
                    node1 = str(voxels_in_clusters[ii])
                    for jj in range(ii+1,R.shape[1]):
                        node2 = str(voxels_in_clusters[jj])
                        if not np.isnan(R[ii,jj]):
                            M[node1,tw_no][node2,tw_no] = R[ii,jj]
                        else:
                            if nanlogfile != None:
                                with open(nanlogfile,'a+') as f:
                                    f.write('NaN correlation at nodes '+node1+', '+node2+' at timewindow '+str(tw_no)+'\n')
                            else:
                                print('NaN correlation at nodes '+node1+', '+node2+' at timewindow '+str(tw_no)+'\n')
                for cluster_number in voxels_in_clusters:
                    for previous_cluster_number in previous_voxels_in_clusters:
                        cluster_overlap = get_overlap(set(voxels_in_clusters[cluster_number]),set(previous_voxels_in_clusters[previous_cluster_number]))
                        M[str(previous_voxels_in_clusters[previous_cluster_number]),tw_no-1][str(voxels_in_clusters[cluster_number]),tw_no] = cluster_overlap
                previous_voxels_in_clusters = voxels_in_clusters # reference to the same object
                if calculate_consistency_while_clustering: # calculating spatial consistency of formed clusters
                    windowdata = imgdata[:,:,:,start_times[tw_no]:end_times[tw_no]]
                    if '.' in consistency_save_path:
                        name,extension = consistency_save_path.split('.')
                        consistency_save_path_final = name + '_' + str(tw_no) + '.' + extension
                    else:
                        consistency_save_path_final = name + '_' + str(tw_no) + '.pkl'
                    calculate_spatial_consistency(windowdata,voxels_in_clusters,f_transform_consistency,n_consistency_CPUs,consistency_save_path_final)
            del(voxels_in_clusters_by_timewindow[min(voxels_in_clusters_by_timewindow)])
            yield M
            del(M)
    
    elif method == 'template':
        voxels_in_clusters = get_voxels_in_clusters(template)
        for layerset in layersets:
            M = pn.MultiplexNetwork(couplings='ordinal',fullyInterconnected=True)
            for tw_no in layerset:
                R = calculate_cluster_correlation_matrix(imgdata[:,:,:,start_times[tw_no]:end_times[tw_no]],voxels_in_clusters)
                for ii in range(R.shape[0]):
                    node1 = str(voxels_in_clusters[ii])
                    for jj in range(ii+1,R.shape[1]):
                        node2 = str(voxels_in_clusters[jj])
                        if not np.isnan(R[ii,jj]):
                            M[node1,tw_no][node2,tw_no] = R[ii,jj]
                        else:
                            if nanlogfile != None:
                                with open(nanlogfile,'a+') as f:
                                    f.write('NaN correlation at nodes '+node1+', '+node2+' at timewindow '+str(tw_no)+'\n')
                            else:
                                print('NaN correlation at nodes '+node1+', '+node2+' at timewindow '+str(tw_no)+'\n')
                if calculate_consistency_while_clustering: #calculating spatial consistency of formed clusters
                    windowdata = imgdata[:,:,:,start_times[tw_no]:end_times[tw_no]]
                    if '.' in consistency_save_path:
                        name,extension = consistency_save_path.split('.')
                        consistency_save_path_final = name + '_' + str(tw_no) + '.' + extension
                    else:
                        consistency_save_path_final = name + '_' + str(tw_no) + '.pkl'
                    calculate_spatial_consistency(windowdata,voxels_in_clusters,f_transform_consistency,n_consistency_CPUs,consistency_save_path_final)
            yield M
            del(M)
    elif method == 'consistency_optimized':
        voxels_in_clusters_by_timewindow = dict()
        for layerset in layersets:
            M = pn.MultilayerNetwork(aspects=1,fullyInterconnected=False)
            previous_voxels_in_clusters = dict()
            for tw_no in layerset:
                cfg = {'ROICentroids':ROI_centroids,'names':ROI_names,'imgdata':imgdata[:,:,:,start_times[tw_no]:end_times[tw_no]],
                       'threshold':consistency_threshold,'targetFunction':consistency_target_function,
                       'fTransform':f_transform_consistency,'nROIs':n_clusters,'template':template,
                       'percentageROIsForThresholding':consistency_percentage_ROIs_for_thresholding,'nCPUs':n_consistency_CPUs,
                       'nReHoNeighbors':n_ReHo_neighbors,'percentageMinCentroidDistance':percentage_min_centroid_distance,
                       'ReHoMeasure':ReHo_measure}
                if not tw_no in voxels_in_clusters_by_timewindow:
                    voxels_in_clusters = dict()
                    if ROI_centroids == 'random':
                        voxel_labels, voxel_coordinates = cbc.growOptimizedROIsInParallel(cfg,n_consistency_iters,n_consistency_CPUs)
                    else:
                        voxel_labels, voxel_coordinates, _ = cbc.growOptimizedROIs(cfg)
                    for ii, label in enumerate(voxel_labels):
                        voxels_in_clusters.setdefault(label,[]).append(voxel_coordinates[ii]) # voxels_in_clusters will contain label:[voxels with label] pairs; here, coordinates of each voxel are added to the correct list
                    if -1 in voxels_in_clusters:
                        del voxels_in_clusters[-1] # Voxels that are not located in any ROI (because of thresholding) have label -1. These should not be considered further in the pipeline.
                    voxels_in_clusters_by_timewindow[tw_no] = voxels_in_clusters
                else:
                    voxels_in_clusters = voxels_in_clusters_by_timewindow[tw_no]
                R = calculate_cluster_correlation_matrix(imgdata[:,:,:,start_times[tw_no]:end_times[tw_no]],voxels_in_clusters)
                for ii in range(R.shape[0]):
                    node1 = str(voxels_in_clusters[ii])
                    for jj in range(ii+1,R.shape[1]):
                        node2 = str(voxels_in_clusters[jj])
                        if not np.isnan(R[ii,jj]):
                            M[node1,node2,tw_no] = R[ii,jj]
                        else:
                            if nanlogfile != None:
                                with open(nanlogfile,'a+') as f:
                                    f.write('NaN correlation at nodes ' + node1 + ',' + node2 + 'at timewindow ' + str(tw_no) + '/n')
                            else:
                                print('NaN correlation at nodes ' + node1 + ',' + node2 + 'at timewindow ' + str(tw_no) + '/n')
                for cluster_number in voxels_in_clusters:
                    for previous_cluster_number in previous_voxels_in_clusters:
                        # If previous_voxels_in_clusters is empty, this loop isn't performed at all
                        cluster_overlap = get_overlap(set(voxels_in_clusters[cluster_number]),set(previous_voxels_in_clusters[previous_cluster_number]))
                        M[str(previous_voxels_in_clusters[previous_cluster_number]),tw_no-1][str(voxels_in_clusters[cluster_number]),tw_no] = cluster_overlap
                previous_voxels_in_clusters = voxels_in_clusters
                if calculate_consistency_while_clustering:
                    windowdata = imgdata[:,:,:,start_times[tw_no]:end_times[tw_no]]
                    if '.' in consistency_save_path:
                        name,extension = consistency_save_path.split('.')
                        consistency_save_path_final = name + '_' + str(tw_no) + '.' + extension
                    else:
                        consistency_save_path_final = name + '_' + str(tw_no) + '.pkl'
                    calculate_spatial_consistency(windowdata,voxels_in_clusters,f_transform_consistency,n_consistency_CPUs,consistency_save_path_final)
            del(voxels_in_clusters_by_timewindow[min(voxels_in_clusters_by_timewindow)])
            yield M
            del(M)
    elif method=='random_balls':
        voxels_in_clusters_by_timewindow = dict()
        for layerset in layersets:
            M = pn.MultilayerNetwork(aspects=1,fullyInterconnected=False)
            previous_voxels_in_clusters = dict()
            for tw_no in layerset:
                if not tw_no in voxels_in_clusters_by_timewindow:
                    voxels_in_clusters = dict()
                    voxel_labels, voxel_coordinates, _ = cbc.growSphericalROIs('random',imgdata[:,:,:,start_times[tw_no]:end_times[tw_no]],nROIs=n_clusters,template=template)
                    for ii, label in enumerate(voxel_labels):
                        voxels_in_clusters.setdefault(label,[]).append(voxel_coordinates[ii]) # voxels_in_clusters will contain label:[voxels with label] pairs; here, coordinates of each voxel are added to the correct list
                    if -1 in voxels_in_clusters:
                        del voxels_in_clusters[-1] # Voxels that are not located in any ROI (because of thresholding) have label -1. These should not be considered further in the pipeline.
                    voxels_in_clusters_by_timewindow[tw_no] = voxels_in_clusters
                else:
                    voxels_in_clusters = voxels_in_clusters_by_timewindow[tw_no]
                R = calculate_cluster_correlation_matrix(imgdata[:,:,:,start_times[tw_no]:end_times[tw_no]],voxels_in_clusters)
                for ii in range(R.shape[0]):
                    node1 = str(voxels_in_clusters[ii])
                    for jj in range(ii+1,R.shape[1]):
                        node2 = str(voxels_in_clusters[jj])
                        if not np.isnan(R[ii,jj]):
                            M[node1,node2,tw_no] = R[ii,jj]
                        else:
                            if nanlogfile != None:
                                with open(nanlogfile,'a+') as f:
                                    f.write('NaN correlation at nodes ' + node1 + ',' + node2 + 'at timewindow ' + str(tw_no) + '/n')
                            else:
                                print('NaN correlation at nodes ' + node1 + ',' + node2 + 'at timewindow ' + str(tw_no) + '/n')
                for cluster_number in voxels_in_clusters:
                    for previous_cluster_number in previous_voxels_in_clusters:
                        # If previous_voxels_in_clusters is empty, this loop isn't performed at all
                        cluster_overlap = get_overlap(set(voxels_in_clusters[cluster_number]),set(previous_voxels_in_clusters[previous_cluster_number]))
                        M[str(previous_voxels_in_clusters[previous_cluster_number]),tw_no-1][str(voxels_in_clusters[cluster_number]),tw_no] = cluster_overlap
                previous_voxels_in_clusters = voxels_in_clusters
                if calculate_consistency_while_clustering:
                    windowdata = imgdata[:,:,:,start_times[tw_no]:end_times[tw_no]]
                    if '.' in consistency_save_path:
                        name,extension = consistency_save_path.split('.')
                        consistency_save_path_final = name + '_' + str(tw_no) + '.' + extension
                    else:
                        consistency_save_path_final = name + '_' + str(tw_no) + '.pkl'
                    calculate_spatial_consistency(windowdata,voxels_in_clusters,f_transform_consistency,n_consistency_CPUs,consistency_save_path_final)
            del(voxels_in_clusters_by_timewindow[min(voxels_in_clusters_by_timewindow)])
    elif method=='craddock':
        voxels_in_clusters_by_timewindow = dict()
        for layerset in layersets:
            M = pn.MultilayerNetwork(aspects=1,fullyInterconnected=False)
            previous_voxels_in_clusters = dict()
            for tw_no in layerset:
                cfg = {'imgdata':imgdata[:,:,:,start_times[tw_no]:end_times[tw_no]],'threshold':consistency_threshold,'nROIs':n_clusters}
                if not tw_no in voxels_in_clusters_by_timewindow:
                    voxels_in_clusters = dict()
                    voxel_labels,voxel_coordinates = cbc.spectralNCutClustering(cfg)
                    if min(np.abs(voxel_labels))>0: # if cluster indexing starts from a non-zero value, let's fix it to start from zero
                        voxel_labels[np.where(voxel_labels)>0] -= np.min(voxel_labels[np.where(voxel_labels)>0])
                    for ii, label in enumerate(voxel_labels):
                        voxels_in_clusters.setdefault(label,[]).append(voxel_coordinates[ii]) # voxels_in_clusters will contain label:[voxels with label] pairs; here, coordinates of each voxel are added to the correct list
                    if -1 in voxels_in_clusters:
                        del voxels_in_clusters[-1] # Voxels that are not located in any ROI (because of thresholding) have label -1. These should not be considered further in the pipeline.
                    voxels_in_clusters_by_timewindow[tw_no] = voxels_in_clusters
                else:
                    voxels_in_clusters = voxels_in_clusters_by_timewindow[tw_no]
                R = calculate_cluster_correlation_matrix(imgdata[:,:,:,start_times[tw_no]:end_times[tw_no]],voxels_in_clusters)
                for ii in range(R.shape[0]):
                    node1 = str(voxels_in_clusters[ii])
                    for jj in range(ii+1,R.shape[1]):
                        node2 = str(voxels_in_clusters[jj])
                        if not np.isnan(R[ii,jj]):
                            M[node1,node2,tw_no] = R[ii,jj]
                        else:
                            if nanlogfile != None:
                                with open(nanlogfile,'a+') as f:
                                    f.write('NaN correlation at nodes ' + node1 + ',' + node2 + 'at timewindow ' + str(tw_no) + '/n')
                            else:
                                print('NaN correlation at nodes ' + node1 + ',' + node2 + 'at timewindow ' + str(tw_no) + '/n')
                for cluster_number in voxels_in_clusters:
                    for previous_cluster_number in previous_voxels_in_clusters:
                        # If previous_voxels_in_clusters is empty, this loop isn't performed at all
                        cluster_overlap = get_overlap(set(voxels_in_clusters[cluster_number]),set(previous_voxels_in_clusters[previous_cluster_number]))
                        M[str(previous_voxels_in_clusters[previous_cluster_number]),tw_no-1][str(voxels_in_clusters[cluster_number]),tw_no] = cluster_overlap
                previous_voxels_in_clusters = voxels_in_clusters
                if calculate_consistency_while_clustering:
                    windowdata = imgdata[:,:,:,start_times[tw_no]:end_times[tw_no]]
                    if '.' in consistency_save_path:
                        name,extension = consistency_save_path.split('.')
                        consistency_save_path_final = name + '_' + str(tw_no) + '.' + extension
                    else:
                        consistency_save_path_final = name + '_' + str(tw_no) + '.pkl'
                    calculate_spatial_consistency(windowdata,voxels_in_clusters,f_transform_consistency,n_consistency_CPUs,consistency_save_path_final)
            yield M
            del(M)
    else:
        raise NotImplementedError('Not implemented')
示例#8
0
def relabel(net,nodeNames=None,layerNames=None):
    """Returns a copy of the network with nodes and layers relabeled.
    
     Parameters
     ----------
     net : MultilayerNetwork, or MultiplexNetwork 
        The original network.
     nodeNames : None, or dict
        The map from node names to node indices.
     layerNames : None, dict, or sequence of dicts
        The map(s) from (elementary) layer names to (elementary) layer indices.
        Note that you can add empty dicts for aspects you do not want to relabel.

     Return
     ------
     newnet : type(net)
         The normalized network.
    """
    def dget(d,e):
        if e in d:
            return d[e]
        else:
            return e

    def layer_to_indexlayer(layer,layerNames):
        return tuple([dget(layerNames[i],elayer) for i,elayer in enumerate(layer)])

    if nodeNames==None:
        nodeNames={}

    if layerNames==None:
        layerNames=[]

    if net.aspects==1:
        if isinstance(layerNames,dict):
            layerNames=[layerNames]

    for aspect in range(net.aspects):
        if len(layerNames)<aspect+1:
            layerNames.append({})
     
    if type(net)==netmodule.MultilayerNetwork:
        newNet=netmodule.MultilayerNetwork(aspects=net.aspects,
                                 noEdge=net.noEdge,
                                 directed=net.directed,
                                 fullyInterconnected=net.fullyInterconnected)
    elif type(net)==netmodule.MultiplexNetwork:
        newNet=netmodule.MultiplexNetwork(couplings=net.couplings,
                                directed=net.directed,
                                noEdge=net.noEdge,
                                fullyInterconnected=net.fullyInterconnected)
    else:
        raise Exception("Invalid type of net",type(net))

    for node in net:
        newNet.add_node(dget(nodeNames,node))
    for aspect in range(net.aspects):
        for layer in net.slices[aspect+1]:
            newNet.add_layer(dget(layerNames[aspect],layer),aspect=aspect+1) 

    if not net.fullyInterconnected:
        for nodelayer in net.iter_node_layers():
            layer=layer_to_indexlayer(nodelayer[1:],layerNames)
            if net.aspects==1:
                layer=layer[0]
            newNet.add_node(dget(nodeNames,nodelayer[0]),layer=layer)

    if type(net)==netmodule.MultilayerNetwork:
        for edge in net.edges:
            newedge=[dget(nodeNames,edge[0]),dget(nodeNames,edge[1])]
            for aspect in range(net.aspects):
                newedge.append(dget(layerNames[aspect],edge[2+aspect*2]))
                newedge.append(dget(layerNames[aspect],edge[2+aspect*2+1]))
            newNet[tuple(newedge)]=edge[-1]
    elif type(net)==netmodule.MultiplexNetwork:
            for layer in net.iter_layers():
                if net.aspects==1:
                    layertuple=(layer,)
                else:
                    layertuple=layer
                for node in net.A[layer]:
                    for neigh in net.A[layer][node]:
                        newNet[(dget(nodeNames,node),dget(nodeNames,neigh))+layer_to_indexlayer(layertuple,layerNames)]=net[(node,neigh)+layertuple]

                            
    return newNet
示例#9
0
def subnet(net,nodes,*layers,**kwargs):
    """Returns an induced subgraph with given set of nodes and layers.

    Parameters
    ----------
    net : MultilayerNetwork, MultiplexNetwork 
        The original network.
    nodes : sequence
        The nodes that span the induces subgraph.
    *layers : *sequence
        (Elementary) layers included in the subgraph. One parameter for each aspect.
    newNet : None, MultilayerNetwork, MultiplexNetwork    
        An empty new network or None. If None, the new network is created as a
        an empty copy of the net. The edges and nodes are copied to this network.
    nolinks : bool
        If set True, this function does not copy any links. That is, the returned
        network is _not_ an induced subnetwork but an empty network.

    Return
    ------
    subnet : type(net), or type(newNet)
        The induced subgraph that contains only nodes given in
        `nodes` and the edges between those nodes that are
        present in `net`. Node properties etc are left untouched.
    """

    if "newNet" in kwargs:
        newNet=kwargs["newNet"]
    else:
        newNet=None

    if "nolinks" in kwargs:
        nolinks=kwargs["nolinks"]
    else:
        nolinks=False

    assert len(layers)==net.aspects, "Please give layers for each aspect."
    nodelayers=[]
    for a,elayers in enumerate(itertools.chain([nodes],layers)):
        if elayers==None:
            nodelayers.append(set(net.get_layers(a)))
        else:
            nodelayers.append(set(elayers))

    if newNet==None:
        if isinstance(net,netmodule.MultiplexNetwork):
            newNet=netmodule.MultiplexNetwork(couplings=net.couplings,
                                    directed=net.directed,
                                    noEdge=net.noEdge,
                                    fullyInterconnected=net.fullyInterconnected)
        elif isinstance(net,netmodule.MultilayerNetwork):
            newNet=netmodule.MultilayerNetwork(aspects=net.aspects,
                                     noEdge=net.noEdge,
                                     directed=net.directed,
                                     fullyInterconnected=net.fullyInterconnected)
        else:
            raise Exception("Invalid net type: "+str(type(net)))

    addedElementaryLayers=[]
    for a,elayers in enumerate(nodelayers):#enumerate(itertools.chain((nodes,),layers)):
        if net.fullyInterconnected or a!=0:
            addedElementaryLayers.append(0)
            oldElementaryLayers=net.get_layers(a)
            for elayer in elayers:
                if elayer in oldElementaryLayers:
                    newNet.add_layer(elayer,a)
                    addedElementaryLayers[-1]+=1

    if not net.fullyInterconnected:
        totalNodeLayers=0
        for nl in net.iter_node_layers():
            if reduce(lambda x,y:x and y, (e in nodelayers[a] for a,e in enumerate(nl))):
                if net.aspects==1:
                    newNet.add_node(nl[0],layer=nl[1])
                else:
                    newNet.add_node(nl[0],layer=nl[1:])
                totalNodeLayers+=1
    else:
        totalNodeLayers=reduce(lambda x,y:x*y,addedElementaryLayers)


    #copy the links
    if not nolinks:
        if isinstance(net,netmodule.MultiplexNetwork):
            #Go through all the combinations of new layers
            for layer in itertools.product(*nodelayers[1:]):
                layer=layer[0] if net.aspects==1 else layer
                subnet(net.A[layer],nodelayers[0],newNet=newNet.A[layer],nolinks=nolinks)
        elif isinstance(net,netmodule.MultilayerNetwork):
            for nl1 in itertools.product(*nodelayers):
                nl1 = nl1[0] if net.aspects==0 else nl1
                if net[nl1].deg()>=totalNodeLayers:
                    for nl2 in itertools.product(*nodelayers):
                        nl2 = nl2[0] if net.aspects==0 else nl2
                        if net[nl1][nl2]!=net.noEdge:
                            newNet[nl1][nl2]=net[nl1][nl2]
                else:
                    if net.aspects==0:
                        for nl2 in net[nl1]:
                            if nl2 in nodelayers[0]:
                                newNet[nl1][nl2]=net[nl1][nl2]
                    else:
                        for nl2 in net[nl1]:
                            if reduce(lambda x,y:x and y, (e in nodelayers[a] for a,e in enumerate(nl2))):
                                newNet[nl1][nl2]=net[nl1][nl2]
        else:
            raise Exception("Invalid net type: "+str(type(net)))

    return newNet
def graphlets(n, layers, n_l=None, couplings=None, allowed_aspects="all"):
    '''
    Generate graphlets up to n nodes
    
    Parameters
    ----------
    n : int
        maximum number of nodes
    layers : list of layers
    n_l : int
        Number of layers in the generated graphlets, can be smaller than or equal
        to the number of elements in layers
    couplings : list, str, tuple, None, MultilayerNetwork
        Parameter determining how the layers are coupled, i.e. what 
        inter-layer edges are present.
    allowed_aspects : list, string
        the aspects that can be permutated when computing isomorphisms
    
    Returns
    -------
    nets : dict (key: n_nodes, value: list of MultiplexNetwork objects)
        graphlets
    invariants : dict (key: str(complete invariant), value: tuple(index in 'nets': n_nodes, index in the list of multiplex networks))
        complete invariants of the graphlets, the values can be used to match the graphlets in 'nets'
    '''
    if n_l == None:
        n_l = len(layers)

    nets = {}
    invariants = {}
    nets2 = []

    for net_layers in itertools.combinations(layers, n_l):
        layer_combs = layer_combinations(net_layers)
        for layer_comb in layer_combs:
            net = pymnet.MultiplexNetwork(couplings=couplings,
                                          fullyInterconnected=True)
            for layer in layer_comb:
                net[0, 1, layer] = 1

            for layer in net_layers:
                net.add_layer(layer)

            ci = pymnet.get_complete_invariant(net,
                                               allowed_aspects=allowed_aspects)
            ci_s = str(ci)
            if not ci_s in invariants:
                invariants[ci_s] = (2, len(nets2))
                nets2.append(net)

    nets[2] = nets2

    for i in range(2, n):
        nets_i = nets[i]
        nets_i_1 = []
        for net in nets_i:
            net_nodes = net.slices[0]
            net_layers = list(net.slices[1])
            net_layers.sort()
            layer_combs = layer_combinations(net_layers)
            for n_n in range(1, i + 1):
                for node_comb in itertools.combinations(range(i), n_n):
                    node_layers = [layer_combs] * n_n
                    for node_layer_comb in itertools.product(*node_layers):
                        new_net = pymnet.subnet(net, net_nodes, net_layers)
                        for node_i in range(n_n):
                            node = node_comb[node_i]
                            for layer in node_layer_comb[node_i]:
                                new_net[node, i, layer] = 1

                        for layer in net_layers:
                            new_net.add_layer(layer)
                        # check if isomorphic with a previous graph & add only if not isomorphic
                        ci = pymnet.get_complete_invariant(
                            new_net, allowed_aspects=allowed_aspects)
                        ci_s = str(ci)
                        if not ci_s in invariants:
                            invariants[ci_s] = (i + 1, len(nets_i_1))
                            nets_i_1.append(new_net)

        nets[i + 1] = nets_i_1

    return nets, invariants
示例#11
0
class test_network_io(unittest.TestCase):

    timeseries0 = np.array(range(-10, 11), dtype=np.float64)
    timeseries1 = np.array([
        -0.46362334, -0.56982772, 0.06455791, -0.44209878, -0.31068497,
        0.05360425, -0.41299186, -0.29082169, -0.07190158, -0.12474256,
        -0.24997589, 0.01267206, 0.03601663, 0.29330202, -0.12646342,
        0.13130587, 0.57496159, 0.77851974, 0.12816724, 0.63563011, 0.35058168
    ],
                           dtype=np.float64)
    timeseries2 = np.array(range(100, 121), dtype=np.float64)
    timeseries3 = np.zeros((21, ))
    timeseries4 = np.array(
        [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
        dtype=np.float64)
    timeseries5 = np.array(range(0, -21, -1))

    timeseries6 = np.copy(timeseries0)
    timeseries7 = np.copy(timeseries1)
    timeseries8 = np.copy(timeseries2)
    timeseries9 = np.copy(timeseries3)
    timeseries10 = np.copy(timeseries4)
    timeseries11 = np.copy(timeseries5)

    imgdata = np.block([[[[timeseries0], [timeseries1]],
                         [[timeseries2], [timeseries3]],
                         [[timeseries4], [timeseries5]]],
                        [[[timeseries6], [timeseries7]],
                         [[timeseries8], [timeseries9]],
                         [[timeseries10], [timeseries11]]]])

    pickle_test_mplex = pn.MultiplexNetwork(couplings='ordinal',
                                            fullyInterconnected=True)
    pickle_test_mplex['(1, 2, 3)', 0]['(2, 3, 4)', 0] = 0.5
    pickle_test_mplex['(2, 3, 4)', 1]['(3, 4, 5)', 1] = 0.999
    pickle_test_mplex['(1, 2, 3)', 1]['(2, 3, 4)', 1] = 0.001
    pickle_test_mplex['(1, 2, 3)', 1]['(3, 4, 5)', 1] = 0.234
    pickle_test_mplex['(3, 4, 5)', 2]['(1, 2, 3)', 2] = 1

    pickle_test_mlayer = pn.MultilayerNetwork(aspects=1,
                                              fullyInterconnected=False)
    pickle_test_mlayer['[(1, 2, 3),(2, 3, 4)]', 9]['[(3, 4, 5)]', 9] = 0.123
    pickle_test_mlayer['[(1, 2, 3)]', 10]['[(2, 3, 4),(3, 4, 5)]', 10] = 0.456
    pickle_test_mlayer['[(1, 2, 3),(2, 3, 4)]', 9]['[(1, 2, 3)]', 10] = 0.5
    pickle_test_mlayer['[(1, 2, 3),(2, 3, 4)]', 9]['[(2, 3, 4),(3, 4, 5)]',
                                                   10] = 0.333
    pickle_test_mlayer['[(3, 4, 5)]', 9]['[(1, 2, 3)]', 10] = 0
    pickle_test_mlayer['[(3, 4, 5)]', 9]['[(2, 3, 4),(3, 4, 5)]', 10] = 0.5
    pickle_test_mlayer['[(4,5,6)]', 10]['[(2, 3, 4),(3, 4, 5)]', 10] = 0.01
    pickle_test_mlayer['[(2, 3, 4)]', 11]['[(2, 3, 4),(3, 4, 5)]', 10] = 0.999

    def round_edge_weights(self, M):
        # rounds edge weights to 10 decimals
        if isinstance(M, pn.net.MultiplexNetwork):
            for edge in M.edges:
                if edge[2] == edge[3]:
                    M[edge[0], edge[2]][edge[1], edge[3]] = round(edge[4], 10)
            return M
        else:
            for edge in M.edges:
                M[edge[0], edge[2]][edge[1], edge[3]] = round(edge[4], 10)
            return M

    def test_write_weighted_network(self):
        M_multiplex = pn.MultiplexNetwork(couplings='ordinal',
                                          fullyInterconnected=True)
        M_multiplex['(1, 2, 3)', 0]['(2, 3, 4)', 0] = 0.5
        M_multiplex['(2, 3, 4)', 1]['(3, 4, 5)', 1] = 0.999
        M_multiplex['(3, 4, 5)', 2]['(1, 2, 3)', 2] = 1
        possible_nodelines = set([
            '(1, 2, 3);(2, 3, 4);(3, 4, 5)\n',
            '(1, 2, 3);(3, 4, 5);(2, 3, 4)\n',
            '(2, 3, 4);(1, 2, 3);(3, 4, 5)\n',
            '(2, 3, 4);(3, 4, 5);(1, 2, 3)\n',
            '(3, 4, 5);(1, 2, 3);(2, 3, 4)\n',
            '(3, 4, 5);(2, 3, 4);(1, 2, 3)\n'
        ])
        possible_layerlines = set(
            ['0;1;2\n', '0;2;1\n', '1;0;2\n', '1;2;0\n', '2;0;1\n', '2;1;0\n'])
        edgeset = set([
            '(1, 2, 3);(2, 3, 4);0;0;0.5\n', '(1, 2, 3);(1, 2, 3);0;1;1.0\n',
            '(1, 2, 3);(1, 2, 3);1;2;1.0\n', '(1, 2, 3);(3, 4, 5);2;2;1\n',
            '(2, 3, 4);(2, 3, 4);0;1;1.0\n', '(2, 3, 4);(3, 4, 5);1;1;0.999\n',
            '(2, 3, 4);(2, 3, 4);1;2;1.0\n', '(3, 4, 5);(3, 4, 5);0;1;1.0\n',
            '(3, 4, 5);(3, 4, 5);1;2;1.0\n'
        ])
        network_io.write_weighted_network(
            M_multiplex, 'test_for_network_writing_WILL_BE_REMOVED.txt',
            'Created by test_write_weighted_network')
        try:
            with open('test_for_network_writing_WILL_BE_REMOVED.txt',
                      'r') as f:
                self.assertEqual(f.readline(), '# Multiplex\n')
                self.assertEqual(f.readline(),
                                 '# Created by test_write_weighted_network\n')
                self.assertEqual(f.readline(), 'nodes:\n')
                self.assertTrue(f.readline() in possible_nodelines)
                self.assertEqual(f.readline(), 'layers:\n')
                self.assertTrue(f.readline() in possible_layerlines)
                self.assertEqual(f.readline(), 'edges:\n')
                for line in f:
                    self.assertTrue(line in edgeset)
                    edgeset.remove(line)
                self.assertEqual(len(edgeset), 0)
                self.assertEqual(f.readline(), '')
        finally:
            os.remove('test_for_network_writing_WILL_BE_REMOVED.txt')

        M_multilayer = pn.MultilayerNetwork(aspects=1,
                                            fullyInterconnected=False)
        M_multilayer['[(1, 2, 3),(2, 3, 4)]', 0]['[(3, 4, 5)]', 0] = 0.123
        M_multilayer['[(1, 2, 3)]', 1]['[(2, 3, 4),(3, 4, 5)]', 1] = 0.456
        M_multilayer['[(1, 2, 3),(2, 3, 4)]', 0]['[(1, 2, 3)]', 1] = 0.5
        M_multilayer['[(1, 2, 3),(2, 3, 4)]', 0]['[(2, 3, 4),(3, 4, 5)]',
                                                 1] = 0.333
        M_multilayer['[(3, 4, 5)]', 0]['[(1, 2, 3)]', 1] = 0
        M_multilayer['[(3, 4, 5)]', 0]['[(2, 3, 4),(3, 4, 5)]', 1] = 0.5
        possible_nodelines = set([
            x[0] + ';' + x[1] + ';' + x[2] + ';' + x[3] + '\n'
            for x in itertools.permutations([
                '[(1, 2, 3)]', '[(1, 2, 3),(2, 3, 4)]',
                '[(2, 3, 4),(3, 4, 5)]', '[(3, 4, 5)]'
            ])
        ])
        possible_layerlines = set(['0;1\n', '1;0\n'])
        edgeset = set([
            '[(1, 2, 3),(2, 3, 4)];[(2, 3, 4),(3, 4, 5)];0;1;0.333\n',
            '[(1, 2, 3),(2, 3, 4)];[(3, 4, 5)];0;0;0.123\n',
            '[(1, 2, 3),(2, 3, 4)];[(1, 2, 3)];0;1;0.5\n',
            '[(3, 4, 5)];[(2, 3, 4),(3, 4, 5)];0;1;0.5\n',
            '[(1, 2, 3)];[(2, 3, 4),(3, 4, 5)];1;1;0.456\n'
        ])
        network_io.write_weighted_network(
            M_multilayer, 'test_for_network_writing_WILL_BE_REMOVED.txt',
            'Created by test_write_weighted_network')
        try:
            with open('test_for_network_writing_WILL_BE_REMOVED.txt',
                      'r') as f:
                self.assertEqual(f.readline(), '# Multilayer\n')
                self.assertEqual(f.readline(),
                                 '# Created by test_write_weighted_network\n')
                self.assertEqual(f.readline(), 'nodes:\n')
                self.assertTrue(f.readline() in possible_nodelines)
                self.assertEqual(f.readline(), 'layers:\n')
                self.assertTrue(f.readline() in possible_layerlines)
                self.assertEqual(f.readline(), 'edges:\n')
                for line in f:
                    self.assertTrue(line in edgeset)
                    edgeset.remove(line)
                self.assertEqual(len(edgeset), 0)
                self.assertEqual(f.readline(), '')
        finally:
            os.remove('test_for_network_writing_WILL_BE_REMOVED.txt')

    def test_read_weighted_network(self):
        M_multiplex = network_construction.make_multiplex(self.imgdata,
                                                          timewindow=7,
                                                          overlap=2)
        network_io.write_weighted_network(
            M_multiplex, 'test_for_network_reading_WILL_BE_REMOVED.txt',
            'Created by test_read_weighted_network')
        M_multiplex_read = network_io.read_weighted_network(
            'test_for_network_reading_WILL_BE_REMOVED.txt')
        try:
            self.assertEqual(self.round_edge_weights(M_multiplex),
                             self.round_edge_weights(M_multiplex_read))
        finally:
            os.remove('test_for_network_reading_WILL_BE_REMOVED.txt')

        M_multilayer = network_construction.make_clustered_multilayer(
            self.imgdata, timewindow=7, overlap=2, n_clusters=3)
        network_io.write_weighted_network(
            M_multilayer, 'test_for_network_reading_WILL_BE_REMOVED.txt',
            'Created by test_read_weighted_network')
        M_multilayer_read = network_io.read_weighted_network(
            'test_for_network_reading_WILL_BE_REMOVED.txt')
        try:
            self.assertEqual(self.round_edge_weights(M_multilayer),
                             self.round_edge_weights(M_multilayer_read))
        finally:
            os.remove('test_for_network_reading_WILL_BE_REMOVED.txt')

    def test_pickle_file_io_for_networks(self):
        try:
            network_io.write_pickle_file(
                self.pickle_test_mplex,
                'test_for_pickle_io_mplex_network_WILL_BE_REMOVED.pkl')
            network_io.write_pickle_file(
                self.pickle_test_mlayer,
                'test_for_pickle_io_mlayer_network_WILL_BE_REMOVED.pkl')
            pickle_test_mplex_read = network_io.read_pickle_file(
                'test_for_pickle_io_mplex_network_WILL_BE_REMOVED.pkl')
            pickle_test_mlayer_read = network_io.read_pickle_file(
                'test_for_pickle_io_mlayer_network_WILL_BE_REMOVED.pkl')
            self.assertEqual(self.pickle_test_mplex, pickle_test_mplex_read)
            self.assertEqual(self.pickle_test_mlayer, pickle_test_mlayer_read)
        finally:
            if os.path.exists(
                    'test_for_pickle_io_mplex_network_WILL_BE_REMOVED.pkl'):
                os.remove(
                    'test_for_pickle_io_mplex_network_WILL_BE_REMOVED.pkl')
            if os.path.exists(
                    'test_for_pickle_io_mlayer_network_WILL_BE_REMOVED.pkl'):
                os.remove(
                    'test_for_pickle_io_mlayer_network_WILL_BE_REMOVED.pkl')

    def test_write_layersetwise_network(self):
        try:
            os.mkdir('dir_for_test_write_layersetwise_network_WILL_BE_REMOVED')
            network_io.write_layersetwise_network(
                self.pickle_test_mplex,
                'dir_for_test_write_layersetwise_network_WILL_BE_REMOVED')
            network_io.write_layersetwise_network(
                self.pickle_test_mlayer,
                'dir_for_test_write_layersetwise_network_WILL_BE_REMOVED')
            self.assertEqual(
                sorted(
                    os.listdir(
                        'dir_for_test_write_layersetwise_network_WILL_BE_REMOVED'
                    )), ['0_1_2', '9_10_11'])
            mplex = network_io.read_pickle_file(
                'dir_for_test_write_layersetwise_network_WILL_BE_REMOVED/0_1_2'
            )
            mlayer = network_io.read_pickle_file(
                'dir_for_test_write_layersetwise_network_WILL_BE_REMOVED/9_10_11'
            )
            self.assertEqual(self.pickle_test_mplex, mplex)
            self.assertEqual(self.pickle_test_mlayer, mlayer)
        finally:
            if os.path.exists(
                    'dir_for_test_write_layersetwise_network_WILL_BE_REMOVED/0_1_2'
            ):
                os.remove(
                    'dir_for_test_write_layersetwise_network_WILL_BE_REMOVED/0_1_2'
                )
            if os.path.exists(
                    'dir_for_test_write_layersetwise_network_WILL_BE_REMOVED/9_10_11'
            ):
                os.remove(
                    'dir_for_test_write_layersetwise_network_WILL_BE_REMOVED/9_10_11'
                )
            if os.path.exists(
                    'dir_for_test_write_layersetwise_network_WILL_BE_REMOVED'):
                os.rmdir(
                    'dir_for_test_write_layersetwise_network_WILL_BE_REMOVED')
def get_fruchterman_reingold_multilayer_layout(net,
                                               nodeDist="auto",
                                               boxSize=1.0,
                                               alignedNodes=True,
                                               nodelayerCoords=None,
                                               nodeCoords=None,
                                               fixedNodes=None,
                                               fixedNodeLayers=None,
                                               iterations=100):
    """A multilayer version of the Fructherman-Reingold algorithm for network layouts.

    This is a mulitlayer variation of the standard FR algorithm, where the layout is 
    produced by simulating springs between linked nodes and repulsive forces between all 
    nodes. The main difference to the normal version of the algorithm is that the nodes 
    which are on different layers do not repulse each other.

    Parameters
    ----------
    net : MultilayerNetwork
       The network for which the coordinates are calculated
    nodeDist : float, string
       The desired distance between pairs of nodes. If "auto", then inverse of the 
       square root of the number of nodes is used.
    boxSize : float, tuple of floats
       The size of the bounding box for the coordinates. If float is given then a square
       box is used. Otherwise, provide a tuple with two floats.
    alignedNodes : bool
       Determines if the nodes-layer tuples with the same node should have the same 
       coordinates. 
    nodelayerCoords : dict, None
       Initial coordinates for node-layer tuples. If None, random coordinates are used.
       If alignedNodes is set to True these coordinates are not used.
    nodeCoords : dict, None    
       Initial coordinates for nodes. If None, random coordinates are used. If a coordinate
       for node-layer tuple is defined then that is used instead of the node coordinate.
    fixedNodes : set, None
       The set of nodes that are not moved from the initial coordinates. If None, then 
       all nodes are allowed to move. You can also use list or similar data structures, but
       set is recommended for speed when the number of elements is large.
    fixedNodeLayers : set, None
       The set of nodes-layers that are not moved from the initial coordinates. If None, then 
       all node-layers are allowed to move. You can also use list or similar data structures, but
       set is recommended for speed when the number of elements is large.
    iterations : int
       The number of times the nodes/node-layer tuples are moved.
    """

    #Parsing parameters and sanity check for them
    #net
    assert isinstance(net, pymnet.MultilayerNetwork), "Invalid network type"
    assert net.aspects >= 1, "No monoplex networks"

    #If the network is fully interconnected, we just create network with one layer
    if net.fullyInterconnected:
        assert nodelayerCoords == None, "Only node coordinates for fully interconnected networks"
        magg = pymnet.MultiplexNetwork(fullyInterconnected=False)
        magg.add_layer("all")
        magg.A["all"] = pymnet.transforms.aggregate(net, 1)
        net = magg

    #nodeDist
    if nodeDist == "auto":
        nodeDist = 1. / math.sqrt(len(net.slices[0]))
    else:
        nodeDist = float(nodeDist)
        assert nodeDist > 0

    #boxSize
    if isinstance(boxSize, tuple) or isinstance(boxSize, list):
        assert len(boxSize) == 2
    else:
        boxSize = float(boxSize)
        boxSize = (boxSize, boxSize)

    #nodeCoords
    if nodeCoords == None:
        nodeCoords = {}

    #nodelayerCoords
    if nodelayerCoords == None:
        nodelayerCoords = {}

    if alignedNodes:  #use node coordinates
        nc = {}
        for node in net:
            if node in nodeCoords:
                nc[node] = nodeCoords[node]
            else:
                nc[node] = (boxSize[0] * random.random(),
                            boxSize[1] * random.random())
    else:  #use node-layer tuple coordinates
        nlc = {}
        for nl in net.iter_node_layers():
            if nl in nodelayerCoords:
                nlc[nl] = nodelayerCoords[nl]
            elif nl[0] in nodeCoords:
                nlc[nl] = nodeCoords[nl[0]]
            else:
                nlc[nl] = (boxSize[0] * random.random(),
                           boxSize[1] * random.random())

    if fixedNodes == None:
        fixedNodes = set()
    if fixedNodeLayers == None:
        fixedNodeLayers = set()

    #Parsing complete

    #Some internal parameters
    temperature = 0.1 * max(boxSize)
    delta_temperature = temperature / float(iterations)
    min_dist = 0.01

    for iteration in range(iterations):
        if alignedNodes:  #we have coordinates for nodes
            delta_nc = dict(((k, (0., 0.)) for k in nc))
            #Spring forces
            for edge in net.edges:
                node1 = edge[0]
                node2 = edge[1]
                if node1 != node2:
                    diff = (nc[node1][0] - nc[node2][0],
                            nc[node1][1] - nc[node2][1])
                    dist = math.sqrt(diff[0]**2 + diff[1]**2)
                    c = dist / float(nodeDist)
                    delta_nc[node1] = (delta_nc[node1][0] - c * diff[0],
                                       delta_nc[node1][1] - c * diff[1])
                    delta_nc[node2] = (delta_nc[node2][0] + c * diff[0],
                                       delta_nc[node2][1] + c * diff[1])

            #Repulsive forces
            for node1 in net:
                for node2 in net:
                    if node1 != node2:
                        layer_overlap = len(
                            net._nodeToLayers[node1].intersection(
                                net._nodeToLayers[node2]))
                        diff = (nc[node1][0] - nc[node2][0],
                                nc[node1][1] - nc[node2][1])
                        dist = math.sqrt(diff[0]**2 + diff[1]**2)
                        dist = max(dist, min_dist)
                        c = layer_overlap * nodeDist**2 / float(dist**2)
                        delta_nc[node1] = (delta_nc[node1][0] + c * diff[0],
                                           delta_nc[node1][1] + c * diff[1])
                        delta_nc[node2] = (delta_nc[node2][0] - c * diff[0],
                                           delta_nc[node2][1] - c * diff[1])

            #Normalize coordinate, and apply them
            #for node,(x,y) in delta_nc.iteritems():
            for node in delta_nc:
                x, y = delta_nc[node]
                if node not in fixedNodes:
                    delta_len = math.sqrt(x**2 + y**2)
                    nc[node] = (nc[node][0] + temperature * delta_len * x,
                                nc[node][1] + temperature * delta_len * y)
            normalize_coordinates(nc, boxSize, inplace=True)

        else:  #we have coordinates for node-layer tuples

            #There is currently a lot of code dublication here when compared to the
            #case where nodes are aligned. Some of this should be removed, and some
            #of it will probably disappear once the code is optimized a bit.

            delta_nlc = dict(((k, (0., 0.)) for k in nlc))
            #Spring forces
            for edge in net.edges:
                nl1, nl2 = net._link_to_nodes(edge[:-1])
                diff = (nlc[nl1][0] - nlc[nl2][0], nlc[nl1][1] - nlc[nl2][1])
                dist = math.sqrt(diff[0]**2 + diff[1]**2)
                dist = max(dist, min_dist)
                c = dist / float(nodeDist)
                delta_nlc[nl1] = (delta_nlc[nl1][0] - c * diff[0],
                                  delta_nlc[nl1][1] - c * diff[1])
                delta_nlc[nl2] = (delta_nlc[nl2][0] + c * diff[0],
                                  delta_nlc[nl2][1] + c * diff[1])

            #Repulsive forces
            for nl1 in net.iter_node_layers():
                layer = nl1[1:][0] if net.aspects == 1 else nl1[1:]
                for node2 in net.iter_nodes(layer=layer):
                    nl2 = (node2, ) + nl1[1:]
                    if nl1 != nl2:
                        diff = (nlc[nl1][0] - nlc[nl2][0],
                                nlc[nl1][1] - nlc[nl2][1])
                        dist = math.sqrt(diff[0]**2 + diff[1]**2)
                        dist = max(dist, min_dist)
                        c = nodeDist**2 / float(dist**2)
                        delta_nlc[nl1] = (delta_nlc[nl1][0] + c * diff[0],
                                          delta_nlc[nl1][1] + c * diff[1])
                        delta_nlc[nl2] = (delta_nlc[nl2][0] - c * diff[0],
                                          delta_nlc[nl2][1] - c * diff[1])

            #Normalize coordinate, and apply them
            #for nl,(x,y) in delta_nlc.iteritems():
            for nl in delta_nlc:
                x, y = delta_nlc[nl]
                if nl not in fixedNodeLayers:
                    delta_len = math.sqrt(x**2 + y**2)
                    nlc[nl] = (nlc[nl][0] + temperature * delta_len * x,
                               nlc[nl][1] + temperature * delta_len * y)
            normalize_coordinates(nlc, boxSize, inplace=True)

        temperature -= delta_temperature

    if alignedNodes:
        return nc
    else:
        return nlc
def yield_clustered_multilayer_network_in_layersets(imgdata,
                                                    layerset_size,
                                                    timewindow=100,
                                                    overlap=0,
                                                    n_clusters=100,
                                                    method='sklearn',
                                                    template=None,
                                                    nanlogfile=None,
                                                    event_time_stamps=None):
    # If event_time_stamps is specified, then they are used to compute start_times, end_times and k (and timewindow and overlap are ignored).
    # Otherwise, timewindow and overlap are used ot compute start_times, end_times and k.
    if event_time_stamps == None:
        k = get_number_of_layers(imgdata.shape, timewindow, overlap)
        start_times, end_times = get_start_and_end_times(
            k, timewindow, overlap)
    else:
        assert isinstance(event_time_stamps, list)
        k = len(event_time_stamps) + 1
        start_times = [0] + event_time_stamps
        end_times = event_time_stamps + [imgdata.shape[3]]
    layersets = zip(*(range(k)[ii:] for ii in range(layerset_size)))

    if method == 'sklearn':
        voxels_in_clusters_by_timewindow = dict()
        for layerset in layersets:
            M = pn.MultilayerNetwork(aspects=1, fullyInterconnected=False)
            previous_voxels_in_clusters = dict()
            for tw_no in layerset:
                if not tw_no in voxels_in_clusters_by_timewindow:
                    voxels_in_clusters = dict()
                    model, voxellist = clustering.cluster_timewindow_scikit(
                        imgdata[:, :, :, start_times[tw_no]:end_times[tw_no]],
                        n_clusters=n_clusters)
                    for ii, label in enumerate(model.labels_):
                        voxels_in_clusters.setdefault(label,
                                                      []).append(voxellist[ii])
                    voxels_in_clusters_by_timewindow[
                        tw_no] = voxels_in_clusters
                else:
                    voxels_in_clusters = voxels_in_clusters_by_timewindow[
                        tw_no]
                R = calculate_cluster_correlation_matrix(
                    imgdata[:, :, :, start_times[tw_no]:end_times[tw_no]],
                    voxels_in_clusters)
                for ii in range(R.shape[0]):
                    node1 = str(voxels_in_clusters[ii])
                    for jj in range(ii + 1, R.shape[1]):
                        node2 = str(voxels_in_clusters[jj])
                        if not np.isnan(R[ii, jj]):
                            M[node1, tw_no][node2, tw_no] = R[ii, jj]
                        else:
                            if nanlogfile != None:
                                with open(nanlogfile, 'a+') as f:
                                    f.write('NaN correlation at nodes ' +
                                            node1 + ', ' + node2 +
                                            ' at timewindow ' + str(tw_no) +
                                            '\n')
                            else:
                                print('NaN correlation at nodes ' + node1 +
                                      ', ' + node2 + ' at timewindow ' +
                                      str(tw_no) + '\n')
                for cluster_number in voxels_in_clusters:
                    for previous_cluster_number in previous_voxels_in_clusters:
                        cluster_overlap = get_overlap(
                            set(voxels_in_clusters[cluster_number]),
                            set(previous_voxels_in_clusters[
                                previous_cluster_number]))
                        M[str(previous_voxels_in_clusters[
                            previous_cluster_number]),
                          tw_no - 1][str(voxels_in_clusters[cluster_number]),
                                     tw_no] = cluster_overlap
                previous_voxels_in_clusters = voxels_in_clusters  # reference to the same object
            del (voxels_in_clusters_by_timewindow[min(
                voxels_in_clusters_by_timewindow)])
            yield M
            del (M)

    elif method == 'template':
        voxels_in_clusters = get_voxels_in_clusters(template)
        for layerset in layersets:
            M = pn.MultiplexNetwork(couplings='ordinal',
                                    fullyInterconnected=True)
            for tw_no in layerset:
                R = calculate_cluster_correlation_matrix(
                    imgdata[:, :, :, start_times[tw_no]:end_times[tw_no]],
                    voxels_in_clusters)
                for ii in range(R.shape[0]):
                    node1 = str(voxels_in_clusters[ii])
                    for jj in range(ii + 1, R.shape[1]):
                        node2 = str(voxels_in_clusters[jj])
                        if not np.isnan(R[ii, jj]):
                            M[node1, tw_no][node2, tw_no] = R[ii, jj]
                        else:
                            if nanlogfile != None:
                                with open(nanlogfile, 'a+') as f:
                                    f.write('NaN correlation at nodes ' +
                                            node1 + ', ' + node2 +
                                            ' at timewindow ' + str(tw_no) +
                                            '\n')
                            else:
                                print('NaN correlation at nodes ' + node1 +
                                      ', ' + node2 + ' at timewindow ' +
                                      str(tw_no) + '\n')
            yield M
            del (M)
    else:
        raise NotImplementedError('Not implemented')
def load_mplex(filenames, netnames, threshold=0):
    net = pymnet.MultiplexNetwork(couplings='none')
    for fn, nn in zip(filenames, netnames):
        net.add_layer(nn)
        load_layer(net.A[nn], fn, threshold=threshold)
    return net